History

Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf updates from Ingo Molnar: "Kernel side changes: - Ftrace is one of the last W^X violators (after this only KLP is left). These patches move it over to the generic text_poke() interface and thereby get rid of this oddity. This requires a surprising amount of surgery, by Peter Zijlstra. - x86/AMD PMUs: add support for 'Large Increment per Cycle Events' to count certain types of events that have a special, quirky hw ABI (by Kim Phillips) - kprobes fixes by Masami Hiramatsu Lots of tooling updates as well, the following subcommands were updated: annotate/report/top, c2c, clang, record, report/top TUI, sched timehist, tests; plus updates were done to the gtk ui, libperf, headers and the parser" * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (57 commits) perf/x86/amd: Add support for Large Increment per Cycle Events perf/x86/amd: Constrain Large Increment per Cycle events perf/x86/intel/rapl: Add Comet Lake support tracing: Initialize ret in syscall_enter_define_fields() perf header: Use last modification time for timestamp perf c2c: Fix return type for histogram sorting comparision functions perf beauty sockaddr: Fix augmented syscall format warning perf/ui/gtk: Fix gtk2 build perf ui gtk: Add missing zalloc object perf tools: Use %define api.pure full instead of %pure-parser libperf: Setup initial evlist::all_cpus value perf report: Fix no libunwind compiled warning break s390 issue perf tools: Support --prefix/--prefix-strip perf report: Clarify in help that --children is default tools build: Fix test-clang.cpp with Clang 8+ perf clang: Fix build with Clang 9 kprobes: Fix optimize_kprobe()/unoptimize_kprobe() cancellation logic tools lib: Fix builds when glibc contains strlcpy() perf report/top: Make 'e' visible in the help and make it toggle showing callchains perf report/top: Do not offer annotation for symbols without samples ...

Linus Torvalds committed 6 years ago

Commit c0e809e2 parents 2180f21 0cc4bd8128 files · +2515 −1591Browse files

Unified · Split

128 files
  1. arch/arm/kernel/Makefile +2 −2
  2. arch/arm/kernel/ftrace.c +2 −8
  3. arch/nds32/kernel/ftrace.c +0 −12
  4. arch/x86/events/amd/core.c +79 −30
  5. arch/x86/events/core.c +59 −15
  6. arch/x86/events/intel/rapl.c +2 −0
  7. arch/x86/events/perf_event.h +20 −0
  8. arch/x86/include/asm/ftrace.h +0 −2
  9. arch/x86/include/asm/kprobes.h +5 −9
  10. arch/x86/include/asm/set_memory.h +0 −2
  11. arch/x86/include/asm/text-patching.h +67 −19
  12. arch/x86/kernel/alternative.c +150 −48
  13. arch/x86/kernel/ftrace.c +126 −562
  14. arch/x86/kernel/jump_label.c +38 −78
  15. arch/x86/kernel/kprobes/core.c +11 −9
  16. arch/x86/kernel/kprobes/opt.c +33 −34
  17. arch/x86/kernel/traps.c +0 −9
  18. arch/x86/mm/init_32.c +0 −28
  19. arch/x86/mm/init_64.c +0 −36
  20. drivers/infiniband/hw/hfi1/trace_tid.h +4 −4
  21. drivers/infiniband/hw/hfi1/trace_tx.h +1 −1
  22. drivers/lightnvm/pblk-trace.h +4 −4
  23. drivers/net/fjes/fjes_trace.h +1 −1
  24. drivers/net/wireless/ath/ath10k/trace.h +3 −3
  25. fs/xfs/scrub/trace.h +3 −3
  26. fs/xfs/xfs_trace.h +2 −2
  27. include/linux/module.h +0 −4
  28. include/linux/trace_events.h +17 −1
  29. include/trace/events/filemap.h +1 −1
  30. include/trace/trace_events.h +21 −43
  31. kernel/kprobes.c +46 −25
  32. kernel/module.c +0 −43
  33. kernel/trace/trace.h +14 −17
  34. kernel/trace/trace_entries.h +18 −48
  35. kernel/trace/trace_events.c +19 −1
  36. kernel/trace/trace_events_hist.c +7 −1
  37. kernel/trace/trace_export.c +39 −67
  38. kernel/trace/trace_kprobe.c +14 −2
  39. kernel/trace/trace_syscalls.c +21 −30
  40. kernel/trace/trace_uprobe.c +7 −2
  41. net/mac80211/trace.h +14 −14
  42. net/wireless/trace.h +3 −3
  43. tools/build/feature/Makefile +1 −1
  44. tools/build/feature/test-clang.cpp +6 −0
  45. tools/include/linux/bitmap.h +30 −0
  46. tools/include/linux/string.h +8 −0
  47. tools/lib/api/fs/fs.c +3 −1
  48. tools/lib/bitmap.c +15 −0
  49. tools/lib/perf/Build +0 −0
  50. tools/lib/perf/Documentation/Makefile +156 −0
  51. tools/lib/perf/Documentation/asciidoc.conf +120 −0
  52. tools/lib/perf/Documentation/examples/sampling.c +119 −0
  53. tools/lib/perf/Documentation/libperf-counting.txt +211 −0
  54. tools/lib/perf/Documentation/libperf-sampling.txt +243 −0
  55. tools/lib/perf/Documentation/libperf.txt +246 −0
  56. tools/lib/perf/Documentation/manpage-1.72.xsl +14 −0
  57. tools/lib/perf/Documentation/manpage-base.xsl +35 −0
  58. tools/lib/perf/Documentation/manpage-bold-literal.xsl +17 −0
  59. tools/lib/perf/Documentation/manpage-normal.xsl +13 −0
  60. tools/lib/perf/Documentation/manpage-suppress-sp.xsl +21 −0
  61. tools/lib/perf/Makefile +5 −2
  62. tools/lib/perf/core.c +0 −0
  63. tools/lib/perf/cpumap.c +0 −0
  64. tools/lib/perf/evlist.c +3 −0
  65. tools/lib/perf/evsel.c +0 −0
  66. tools/lib/perf/include/internal/cpumap.h +0 −0
  67. tools/lib/perf/include/internal/evlist.h +0 −0
  68. tools/lib/perf/include/internal/evsel.h +0 −0
  69. tools/lib/perf/include/internal/lib.h +0 −0
  70. tools/lib/perf/include/internal/mmap.h +0 −0
  71. tools/lib/perf/include/internal/tests.h +0 −0
  72. tools/lib/perf/include/internal/threadmap.h +0 −0
  73. tools/lib/perf/include/internal/xyarray.h +0 −0
  74. tools/lib/perf/include/perf/core.h +0 −0
  75. tools/lib/perf/include/perf/cpumap.h +0 −0
  76. tools/lib/perf/include/perf/event.h +0 −0
  77. tools/lib/perf/include/perf/evlist.h +0 −0
  78. tools/lib/perf/include/perf/evsel.h +0 −0
  79. tools/lib/perf/include/perf/mmap.h +0 −0
  80. tools/lib/perf/include/perf/threadmap.h +0 −0
  81. tools/lib/perf/internal.h +0 −0
  82. tools/lib/perf/lib.c +0 −0
  83. tools/lib/perf/libperf.map +0 −0
  84. tools/lib/perf/libperf.pc.template +0 −0
  85. tools/lib/perf/mmap.c +0 −0
  86. tools/lib/perf/tests/Makefile +1 −1
  87. tools/lib/perf/tests/test-cpumap.c +0 −0
  88. tools/lib/perf/tests/test-evlist.c +0 −0
  89. tools/lib/perf/tests/test-evsel.c +0 −0
  90. tools/lib/perf/tests/test-threadmap.c +0 −0
  91. tools/lib/perf/threadmap.c +0 −0
  92. tools/lib/perf/xyarray.c +0 −0
  93. tools/lib/string.c +7 −0
  94. tools/perf/Documentation/perf-annotate.txt +6 −0
  95. tools/perf/Documentation/perf-report.txt +6 −0
  96. tools/perf/Documentation/perf-sched.txt +4 −0
  97. tools/perf/Documentation/perf-top.txt +6 −0
  98. tools/perf/MANIFEST +1 −0
  99. tools/perf/Makefile.config +1 −1
  100. tools/perf/Makefile.perf +1 −1
  101. tools/perf/builtin-annotate.c +7 −0
  102. tools/perf/builtin-c2c.c +8 −6
  103. tools/perf/builtin-record.c +22 −6
  104. tools/perf/builtin-report.c +12 −4
  105. tools/perf/builtin-sched.c +13 −0
  106. tools/perf/builtin-top.c +7 −0
  107. tools/perf/lib/Documentation/Makefile +0 −7
  108. tools/perf/lib/Documentation/man/libperf.rst +0 −100
  109. tools/perf/lib/Documentation/tutorial/tutorial.rst +0 −123
  110. tools/perf/tests/bp_signal.c +5 −5
  111. tools/perf/trace/beauty/sockaddr.c +1 −1
  112. tools/perf/ui/browsers/hists.c +191 −86
  113. tools/perf/ui/browsers/hists.h +1 −1
  114. tools/perf/ui/browsers/res_sample.c +1 −1
  115. tools/perf/ui/browsers/scripts.c +1 −1
  116. tools/perf/ui/gtk/Build +6 −1
  117. tools/perf/ui/tui/util.c +8 −4
  118. tools/perf/ui/util.h +1 −1
  119. tools/perf/util/annotate.c +17 −2
  120. tools/perf/util/annotate.h +5 −0
  121. tools/perf/util/c++/clang.cpp +4 −0
  122. tools/perf/util/expr.y +2 −1
  123. tools/perf/util/header.c +1 −1
  124. tools/perf/util/mmap.c +34 −6
  125. tools/perf/util/mmap.h +12 −1
  126. tools/perf/util/parse-events.y +1 −1
  127. tools/perf/util/sort.c +1 −2
  128. tools/perf/util/sort.h +2 −0
arch/arm/kernel/Makefile+2−2
@@ -53,8 +53,8 @@ obj-$(CONFIG_HAVE_ARM_SCU) += smp_scu.o · 52 unmodified lines
5353 obj-$(CONFIG_HAVE_ARM_TWD) += smp_twd.o
5454 obj-$(CONFIG_ARM_ARCH_TIMER) += arch_timer.o
5555 obj-$(CONFIG_FUNCTION_TRACER) += entry-ftrace.o
56−obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o
57−obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o
56+obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o insn.o patch.o
57+obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o insn.o patch.o
5858 obj-$(CONFIG_JUMP_LABEL) += jump_label.o insn.o patch.o
5959 obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
6060 # Main staffs in KPROBES are in arch/arm/probes/ .
arch/arm/kernel/ftrace.c+2−8
@@ -22,6 +22,7 @@ · 21 unmodified lines
2222 #include <asm/ftrace.h>
2323 #include <asm/insn.h>
2424 #include <asm/set_memory.h>
25+#include <asm/patch.h>
2526
2627 #ifdef CONFIG_THUMB2_KERNEL
2728 #define NOP 0xf85deb04 /* pop.w {lr} */
@@ -35,9 +36,7 @@ static int __ftrace_modify_code(void *data) · 7 unmodified lines
3536 {
3637 int *command = data;
3738
38− set_kernel_text_rw();
3939 ftrace_modify_all_code(*command);
40− set_kernel_text_ro();
4140
4241 return 0;
4342 }
@@ -59,13 +58,11 @@ static unsigned long adjust_address(struct dyn_ftrace *rec, unsigned long addr) · 15 unmodified lines
5958
6059 int ftrace_arch_code_modify_prepare(void)
6160 {
62− set_all_modules_text_rw();
6361 return 0;
6462 }
6563
6664 int ftrace_arch_code_modify_post_process(void)
6765 {
68− set_all_modules_text_ro();
6966 /* Make sure any TLB misses during machine stop are cleared. */
7067 flush_tlb_all();
7168 return 0;
@@ -97,10 +94,7 @@ static int ftrace_modify_code(unsigned long pc, unsigned long old, · 25 unmodified lines
9794 return -EINVAL;
9895 }
9996
100− if (probe_kernel_write((void *)pc, &new, MCOUNT_INSN_SIZE))
101− return -EPERM;
102−
103− flush_icache_range(pc, pc + MCOUNT_INSN_SIZE);
97+ __patch_text((void *)pc, new);
10498
10599 return 0;
106100 }
arch/nds32/kernel/ftrace.c+0−12
@@ -89,18 +89,6 @@ int __init ftrace_dyn_arch_init(void) · 88 unmodified lines
8989 return 0;
9090 }
9191
92−int ftrace_arch_code_modify_prepare(void)
93−{
94− set_all_modules_text_rw();
95− return 0;
96−}
97−
98−int ftrace_arch_code_modify_post_process(void)
99−{
100− set_all_modules_text_ro();
101− return 0;
102−}
103−
10492 static unsigned long gen_sethi_insn(unsigned long addr)
10593 {
10694 unsigned long opcode = 0x46000000;
arch/x86/events/amd/core.c+79−30
@@ -14,6 +14,10 @@ · 13 unmodified lines
1414 static DEFINE_PER_CPU(unsigned long, perf_nmi_tstamp);
1515 static unsigned long perf_nmi_window;
1616
17+/* AMD Event 0xFFF: Merge. Used with Large Increment per Cycle events */
18+#define AMD_MERGE_EVENT ((0xFULL << 32) | 0xFFULL)
19+#define AMD_MERGE_EVENT_ENABLE (AMD_MERGE_EVENT | ARCH_PERFMON_EVENTSEL_ENABLE)
20+
1721 static __initconst const u64 amd_hw_cache_event_ids
1822 [PERF_COUNT_HW_CACHE_MAX]
1923 [PERF_COUNT_HW_CACHE_OP_MAX]
@@ -301,6 +305,25 @@ static inline int amd_pmu_addr_offset(int index, bool eventsel) · 281 unmodified lines
301305 return offset;
302306 }
303307
308+/*
309+ * AMD64 events are detected based on their event codes.
310+ */
311+static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
312+{
313+ return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
314+}
315+
316+static inline bool amd_is_pair_event_code(struct hw_perf_event *hwc)
317+{
318+ if (!(x86_pmu.flags & PMU_FL_PAIR))
319+ return false;
320+
321+ switch (amd_get_event_code(hwc)) {
322+ case 0x003: return true; /* Retired SSE/AVX FLOPs */
323+ default: return false;
324+ }
325+}
326+
304327 static int amd_core_hw_config(struct perf_event *event)
305328 {
306329 if (event->attr.exclude_host && event->attr.exclude_guest)
@@ -316,15 +339,10 @@ static int amd_core_hw_config(struct perf_event *event) · 9 unmodified lines
316339 else if (event->attr.exclude_guest)
317340 event->hw.config |= AMD64_EVENTSEL_HOSTONLY;
318341
319− return 0;
320−}
342+ if ((x86_pmu.flags & PMU_FL_PAIR) && amd_is_pair_event_code(&event->hw))
343+ event->hw.flags |= PERF_X86_EVENT_PAIR;
321344
322−/*
323− * AMD64 events are detected based on their event codes.
324− */
325−static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
326−{
327− return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
345+ return 0;
328346 }
329347
330348 static inline int amd_is_nb_event(struct hw_perf_event *hwc)
@@ -855,6 +873,29 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, int idx, · 524 unmodified lines
855873 }
856874 }
857875
876+static struct event_constraint pair_constraint;
877+
878+static struct event_constraint *
879+amd_get_event_constraints_f17h(struct cpu_hw_events *cpuc, int idx,
880+ struct perf_event *event)
881+{
882+ struct hw_perf_event *hwc = &event->hw;
883+
884+ if (amd_is_pair_event_code(hwc))
885+ return &pair_constraint;
886+
887+ return &unconstrained;
888+}
889+
890+static void amd_put_event_constraints_f17h(struct cpu_hw_events *cpuc,
891+ struct perf_event *event)
892+{
893+ struct hw_perf_event *hwc = &event->hw;
894+
895+ if (is_counter_pair(hwc))
896+ --cpuc->n_pair;
897+}
898+
858899 static ssize_t amd_event_sysfs_show(char *page, u64 config)
859900 {
860901 u64 event = (config & ARCH_PERFMON_EVENTSEL_EVENT) |
@@ -898,33 +939,15 @@ static __initconst const struct x86_pmu amd_pmu = { · 37 unmodified lines
898939
899940 static int __init amd_core_pmu_init(void)
900941 {
942+ u64 even_ctr_mask = 0ULL;
943+ int i;
944+
901945 if (!boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
902946 return 0;
903947
904− /* Avoid calulating the value each time in the NMI handler */
948+ /* Avoid calculating the value each time in the NMI handler */
905949 perf_nmi_window = msecs_to_jiffies(100);
906950
907− switch (boot_cpu_data.x86) {
908− case 0x15:
909− pr_cont("Fam15h ");
910− x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
911− break;
912− case 0x17:
913− pr_cont("Fam17h ");
914− /*
915− * In family 17h, there are no event constraints in the PMC hardware.
916− * We fallback to using default amd_get_event_constraints.
917− */
918− break;
919− case 0x18:
920− pr_cont("Fam18h ");
921− /* Using default amd_get_event_constraints. */
922− break;
923− default:
924− pr_err("core perfctr but no constraints; unknown hardware!\n");
925− return -ENODEV;
926− }
927−
928951 /*
929952 * If core performance counter extensions exists, we must use
930953 * MSR_F15H_PERF_CTL/MSR_F15H_PERF_CTR msrs. See also
@@ -939,6 +962,32 @@ static int __init amd_core_pmu_init(void) · 8 unmodified lines
939962 */
940963 x86_pmu.amd_nb_constraints = 0;
941964
965+ if (boot_cpu_data.x86 == 0x15) {
966+ pr_cont("Fam15h ");
967+ x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
968+ }
969+ if (boot_cpu_data.x86 >= 0x17) {
970+ pr_cont("Fam17h+ ");
971+ /*
972+ * Family 17h and compatibles have constraints for Large
973+ * Increment per Cycle events: they may only be assigned an
974+ * even numbered counter that has a consecutive adjacent odd
975+ * numbered counter following it.
976+ */
977+ for (i = 0; i < x86_pmu.num_counters - 1; i += 2)
978+ even_ctr_mask |= 1 << i;
979+
980+ pair_constraint = (struct event_constraint)
981+ __EVENT_CONSTRAINT(0, even_ctr_mask, 0,
982+ x86_pmu.num_counters / 2, 0,
983+ PERF_X86_EVENT_PAIR);
984+
985+ x86_pmu.get_event_constraints = amd_get_event_constraints_f17h;
986+ x86_pmu.put_event_constraints = amd_put_event_constraints_f17h;
987+ x86_pmu.perf_ctr_pair_en = AMD_MERGE_EVENT_ENABLE;
988+ x86_pmu.flags |= PMU_FL_PAIR;
989+ }
990+
942991 pr_cont("core perfctr, ");
943992 return 0;
944993 }
arch/x86/events/core.c+59−15
@@ -618,6 +618,7 @@ void x86_pmu_disable_all(void) · 617 unmodified lines
618618 int idx;
619619
620620 for (idx = 0; idx < x86_pmu.num_counters; idx++) {
621+ struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
621622 u64 val;
622623
623624 if (!test_bit(idx, cpuc->active_mask))
@@ -627,6 +628,8 @@ void x86_pmu_disable_all(void) · 3 unmodified lines
627628 continue;
628629 val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
629630 wrmsrl(x86_pmu_config_addr(idx), val);
631+ if (is_counter_pair(hwc))
632+ wrmsrl(x86_pmu_config_addr(idx + 1), 0);
630633 }
631634 }
632635
@@ -699,7 +702,7 @@ struct sched_state { · 66 unmodified lines
699702 int counter; /* counter index */
700703 int unassigned; /* number of events to be assigned left */
701704 int nr_gp; /* number of GP counters used */
702− unsigned long used[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
705+ u64 used;
703706 };
704707
705708 /* Total max is X86_PMC_IDX_MAX, but we are O(n!) limited */
@@ -756,8 +759,12 @@ static bool perf_sched_restore_state(struct perf_sched *sched) · 50 unmodified lines
756759 sched->saved_states--;
757760 sched->state = sched->saved[sched->saved_states];
758761
759− /* continue with next counter: */
760− clear_bit(sched->state.counter++, sched->state.used);
762+ /* this assignment didn't work out */
763+ /* XXX broken vs EVENT_PAIR */
764+ sched->state.used &= ~BIT_ULL(sched->state.counter);
765+
766+ /* try the next one */
767+ sched->state.counter++;
761768
762769 return true;
763770 }
@@ -782,20 +789,32 @@ static bool __perf_sched_find_counter(struct perf_sched *sched) · 18 unmodified lines
782789 if (c->idxmsk64 & (~0ULL << INTEL_PMC_IDX_FIXED)) {
783790 idx = INTEL_PMC_IDX_FIXED;
784791 for_each_set_bit_from(idx, c->idxmsk, X86_PMC_IDX_MAX) {
785− if (!__test_and_set_bit(idx, sched->state.used))
786− goto done;
792+ u64 mask = BIT_ULL(idx);
793+
794+ if (sched->state.used & mask)
795+ continue;
796+
797+ sched->state.used |= mask;
798+ goto done;
787799 }
788800 }
789801
790802 /* Grab the first unused counter starting with idx */
791803 idx = sched->state.counter;
792804 for_each_set_bit_from(idx, c->idxmsk, INTEL_PMC_IDX_FIXED) {
793− if (!__test_and_set_bit(idx, sched->state.used)) {
794− if (sched->state.nr_gp++ >= sched->max_gp)
795− return false;
805+ u64 mask = BIT_ULL(idx);
796806
797− goto done;
798− }
807+ if (c->flags & PERF_X86_EVENT_PAIR)
808+ mask |= mask << 1;
809+
810+ if (sched->state.used & mask)
811+ continue;
812+
813+ if (sched->state.nr_gp++ >= sched->max_gp)
814+ return false;
815+
816+ sched->state.used |= mask;
817+ goto done;
799818 }
800819
801820 return false;
@@ -872,12 +891,10 @@ EXPORT_SYMBOL_GPL(perf_assign_events); · 70 unmodified lines
872891 int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
873892 {
874893 struct event_constraint *c;
875− unsigned long used_mask[BITS_TO_LONGS(X86_PMC_IDX_MAX)];
876894 struct perf_event *e;
877895 int n0, i, wmin, wmax, unsched = 0;
878896 struct hw_perf_event *hwc;
879−
880− bitmap_zero(used_mask, X86_PMC_IDX_MAX);
897+ u64 used_mask = 0;
881898
882899 /*
883900 * Compute the number of events already present; see x86_pmu_add(),
@@ -920,6 +937,8 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) · 36 unmodified lines
920937 * fastpath, try to reuse previous register
921938 */
922939 for (i = 0; i < n; i++) {
940+ u64 mask;
941+
923942 hwc = &cpuc->event_list[i]->hw;
924943 c = cpuc->event_constraint[i];
925944
@@ -931,11 +950,16 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) · 5 unmodified lines
931950 if (!test_bit(hwc->idx, c->idxmsk))
932951 break;
933952
953+ mask = BIT_ULL(hwc->idx);
954+ if (is_counter_pair(hwc))
955+ mask |= mask << 1;
956+
934957 /* not already used */
935− if (test_bit(hwc->idx, used_mask))
958+ if (used_mask & mask)
936959 break;
937960
938− __set_bit(hwc->idx, used_mask);
961+ used_mask |= mask;
962+
939963 if (assign)
940964 assign[i] = hwc->idx;
941965 }
@@ -958,6 +982,15 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign) · 16 unmodified lines
958982 READ_ONCE(cpuc->excl_cntrs->exclusive_present))
959983 gpmax /= 2;
960984
985+ /*
986+ * Reduce the amount of available counters to allow fitting
987+ * the extra Merge events needed by large increment events.
988+ */
989+ if (x86_pmu.flags & PMU_FL_PAIR) {
990+ gpmax = x86_pmu.num_counters - cpuc->n_pair;
991+ WARN_ON(gpmax <= 0);
992+ }
993+
961994 unsched = perf_assign_events(cpuc->event_constraint, n, wmin,
962995 wmax, gpmax, assign);
963996 }
@@ -1038,6 +1071,8 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader, · 74 unmodified lines
10381071 return -EINVAL;
10391072 cpuc->event_list[n] = leader;
10401073 n++;
1074+ if (is_counter_pair(&leader->hw))
1075+ cpuc->n_pair++;
10411076 }
10421077 if (!dogrp)
10431078 return n;
@@ -1052,6 +1087,8 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader, · 8 unmodified lines
10521087
10531088 cpuc->event_list[n] = event;
10541089 n++;
1090+ if (is_counter_pair(&event->hw))
1091+ cpuc->n_pair++;
10551092 }
10561093 return n;
10571094 }
@@ -1237,6 +1274,13 @@ int x86_perf_event_set_period(struct perf_event *event) · 179 unmodified lines
12371274
12381275 wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask);
12391276
1277+ /*
1278+ * Clear the Merge event counter's upper 16 bits since
1279+ * we currently declare a 48-bit counter width
1280+ */
1281+ if (is_counter_pair(hwc))
1282+ wrmsrl(x86_pmu_event_addr(idx + 1), 0);
1283+
12401284 /*
12411285 * Due to erratum on certan cpu we need
12421286 * a second write to be sure the register
arch/x86/events/intel/rapl.c+2−0
@@ -741,6 +741,8 @@ static const struct x86_cpu_id rapl_model_match[] __initconst = { · 740 unmodified lines
741741 X86_RAPL_MODEL_MATCH(INTEL_FAM6_ATOM_GOLDMONT_PLUS, model_hsw),
742742 X86_RAPL_MODEL_MATCH(INTEL_FAM6_ICELAKE_L, model_skl),
743743 X86_RAPL_MODEL_MATCH(INTEL_FAM6_ICELAKE, model_skl),
744+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_COMETLAKE_L, model_skl),
745+ X86_RAPL_MODEL_MATCH(INTEL_FAM6_COMETLAKE, model_skl),
744746 {},
745747 };
746748
arch/x86/events/perf_event.h+20−0
@@ -77,6 +77,7 @@ static inline bool constraint_match(struct event_constraint *c, u64 ecode) · 76 unmodified lines
7777 #define PERF_X86_EVENT_AUTO_RELOAD 0x0200 /* use PEBS auto-reload */
7878 #define PERF_X86_EVENT_LARGE_PEBS 0x0400 /* use large PEBS */
7979 #define PERF_X86_EVENT_PEBS_VIA_PT 0x0800 /* use PT buffer for PEBS */
80+#define PERF_X86_EVENT_PAIR 0x1000 /* Large Increment per Cycle */
8081
8182 struct amd_nb {
8283 int nb_id; /* NorthBridge id */
@@ -272,6 +273,7 @@ struct cpu_hw_events { · 189 unmodified lines
272273 struct amd_nb *amd_nb;
273274 /* Inverted mask of bits to clear in the perf_ctr ctrl registers */
274275 u64 perf_ctr_virt_mask;
276+ int n_pair; /* Large increment events */
275277
276278 void *kfree_on_online[X86_PERF_KFREE_MAX];
277279 };
@@ -694,6 +696,7 @@ struct x86_pmu { · 416 unmodified lines
694696 * AMD bits
695697 */
696698 unsigned int amd_nb_constraints : 1;
699+ u64 perf_ctr_pair_en;
697700
698701 /*
699702 * Extra registers for events
@@ -743,6 +746,7 @@ do { \ · 43 unmodified lines
743746 #define PMU_FL_EXCL_ENABLED 0x8 /* exclusive counter active */
744747 #define PMU_FL_PEBS_ALL 0x10 /* all events are valid PEBS events */
745748 #define PMU_FL_TFA 0x20 /* deal with TSX force abort */
749+#define PMU_FL_PAIR 0x40 /* merge counters for large incr. events */
746750
747751 #define EVENT_VAR(_id) event_attr_##_id
748752 #define EVENT_PTR(_id) &event_attr_##_id.attr.attr
@@ -838,6 +842,11 @@ int x86_pmu_hw_config(struct perf_event *event); · 89 unmodified lines
838842
839843 void x86_pmu_disable_all(void);
840844
845+static inline bool is_counter_pair(struct hw_perf_event *hwc)
846+{
847+ return hwc->flags & PERF_X86_EVENT_PAIR;
848+}
849+
841850 static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
842851 u64 enable_mask)
843852 {
@@ -845,6 +854,14 @@ static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, · 1 unmodified line
845854
846855 if (hwc->extra_reg.reg)
847856 wrmsrl(hwc->extra_reg.reg, hwc->extra_reg.config);
857+
858+ /*
859+ * Add enabled Merge event on next counter
860+ * if large increment event being enabled on this counter
861+ */
862+ if (is_counter_pair(hwc))
863+ wrmsrl(x86_pmu_config_addr(hwc->idx + 1), x86_pmu.perf_ctr_pair_en);
864+
848865 wrmsrl(hwc->config_base, (hwc->config | enable_mask) & ~disable_mask);
849866 }
850867
@@ -861,6 +878,9 @@ static inline void x86_pmu_disable_event(struct perf_event *event) · 10 unmodified lines
861878 struct hw_perf_event *hwc = &event->hw;
862879
863880 wrmsrl(hwc->config_base, hwc->config);
881+
882+ if (is_counter_pair(hwc))
883+ wrmsrl(x86_pmu_config_addr(hwc->idx + 1), 0);
864884 }
865885
866886 void x86_pmu_enable_event(struct perf_event *event);
arch/x86/include/asm/ftrace.h+0−2
@@ -47,8 +47,6 @@ struct dyn_arch_ftrace { · 46 unmodified lines
4747 /* No extra data needed for x86 */
4848 };
4949
50−int ftrace_int3_handler(struct pt_regs *regs);
51−
5250 #define FTRACE_GRAPH_TRAMP_ADDR FTRACE_GRAPH_ADDR
5351
5452 #endif /* CONFIG_DYNAMIC_FTRACE */
arch/x86/include/asm/kprobes.h+5−9
@@ -11,12 +11,11 @@ · 10 unmodified lines
1111
1212 #include <asm-generic/kprobes.h>
1313
14−#define BREAKPOINT_INSTRUCTION 0xcc
15−
1614 #ifdef CONFIG_KPROBES
1715 #include <linux/types.h>
1816 #include <linux/ptrace.h>
1917 #include <linux/percpu.h>
18+#include <asm/text-patching.h>
2019 #include <asm/insn.h>
2120
2221 #define __ARCH_WANT_KPROBES_INSN_SLOT
@@ -25,10 +24,7 @@ struct pt_regs; · 2 unmodified lines
2524 struct kprobe;
2625
2726 typedef u8 kprobe_opcode_t;
28−#define RELATIVEJUMP_OPCODE 0xe9
29−#define RELATIVEJUMP_SIZE 5
30−#define RELATIVECALL_OPCODE 0xe8
31−#define RELATIVE_ADDR_SIZE 4
27+
3228 #define MAX_STACK_SIZE 64
3329 #define CUR_STACK_SIZE(ADDR) \
3430 (current_top_of_stack() - (unsigned long)(ADDR))
@@ -43,11 +39,11 @@ extern __visible kprobe_opcode_t optprobe_template_entry[]; · 8 unmodified lines
4339 extern __visible kprobe_opcode_t optprobe_template_val[];
4440 extern __visible kprobe_opcode_t optprobe_template_call[];
4541 extern __visible kprobe_opcode_t optprobe_template_end[];
46−#define MAX_OPTIMIZED_LENGTH (MAX_INSN_SIZE + RELATIVE_ADDR_SIZE)
42+#define MAX_OPTIMIZED_LENGTH (MAX_INSN_SIZE + DISP32_SIZE)
4743 #define MAX_OPTINSN_SIZE \
4844 (((unsigned long)optprobe_template_end - \
4945 (unsigned long)optprobe_template_entry) + \
50− MAX_OPTIMIZED_LENGTH + RELATIVEJUMP_SIZE)
46+ MAX_OPTIMIZED_LENGTH + JMP32_INSN_SIZE)
5147
5248 extern const int kretprobe_blacklist_size;
5349
@@ -73,7 +69,7 @@ struct arch_specific_insn { · 19 unmodified lines
7369
7470 struct arch_optimized_insn {
7571 /* copy of the original instructions */
76− kprobe_opcode_t copied_insn[RELATIVE_ADDR_SIZE];
72+ kprobe_opcode_t copied_insn[DISP32_SIZE];
7773 /* detour code buffer */
7874 kprobe_opcode_t *insn;
7975 /* the size of instructions copied to detour code buffer */
arch/x86/include/asm/set_memory.h+0−2
@@ -81,8 +81,6 @@ int set_direct_map_invalid_noflush(struct page *page); · 80 unmodified lines
8181 int set_direct_map_default_noflush(struct page *page);
8282
8383 extern int kernel_set_to_readonly;
84−void set_kernel_text_rw(void);
85−void set_kernel_text_ro(void);
8684
8785 #ifdef CONFIG_X86_64
8886 static inline int set_mce_nospec(unsigned long pfn)
arch/x86/include/asm/text-patching.h+67−19
@@ -25,14 +25,6 @@ static inline void apply_paravirt(struct paravirt_patch_site *start, · 24 unmodified lines
2525 */
2626 #define POKE_MAX_OPCODE_SIZE 5
2727
28−struct text_poke_loc {
29− void *addr;
30− int len;
31− s32 rel32;
32− u8 opcode;
33− const u8 text[POKE_MAX_OPCODE_SIZE];
34−};
35−
3628 extern void text_poke_early(void *addr, const void *opcode, size_t len);
3729
3830 /*
@@ -50,21 +42,13 @@ extern void text_poke_early(void *addr, const void *opcode, size_t len); · 11 unmodified lines
5042 * an inconsistent instruction while you patch.
5143 */
5244 extern void *text_poke(void *addr, const void *opcode, size_t len);
45+extern void text_poke_sync(void);
5346 extern void *text_poke_kgdb(void *addr, const void *opcode, size_t len);
5447 extern int poke_int3_handler(struct pt_regs *regs);
5548 extern void text_poke_bp(void *addr, const void *opcode, size_t len, const void *emulate);
56−extern void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries);
57−extern void text_poke_loc_init(struct text_poke_loc *tp, void *addr,
58− const void *opcode, size_t len, const void *emulate);
59−extern int after_bootmem;
60−extern __ro_after_init struct mm_struct *poking_mm;
61−extern __ro_after_init unsigned long poking_addr;
6249
63−#ifndef CONFIG_UML_X86
64−static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip)
65−{
66− regs->ip = ip;
67−}
50+extern void text_poke_queue(void *addr, const void *opcode, size_t len, const void *emulate);
51+extern void text_poke_finish(void);
6852
6953 #define INT3_INSN_SIZE 1
7054 #define INT3_INSN_OPCODE 0xCC
@@ -78,6 +62,67 @@ static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip) · 7 unmodified lines
7862 #define JMP8_INSN_SIZE 2
7963 #define JMP8_INSN_OPCODE 0xEB
8064
65+#define DISP32_SIZE 4
66+
67+static inline int text_opcode_size(u8 opcode)
68+{
69+ int size = 0;
70+
71+#define __CASE(insn) \
72+ case insn##_INSN_OPCODE: size = insn##_INSN_SIZE; break
73+
74+ switch(opcode) {
75+ __CASE(INT3);
76+ __CASE(CALL);
77+ __CASE(JMP32);
78+ __CASE(JMP8);
79+ }
80+
81+#undef __CASE
82+
83+ return size;
84+}
85+
86+union text_poke_insn {
87+ u8 text[POKE_MAX_OPCODE_SIZE];
88+ struct {
89+ u8 opcode;
90+ s32 disp;
91+ } __attribute__((packed));
92+};
93+
94+static __always_inline
95+void *text_gen_insn(u8 opcode, const void *addr, const void *dest)
96+{
97+ static union text_poke_insn insn; /* per instance */
98+ int size = text_opcode_size(opcode);
99+
100+ insn.opcode = opcode;
101+
102+ if (size > 1) {
103+ insn.disp = (long)dest - (long)(addr + size);
104+ if (size == 2) {
105+ /*
106+ * Ensure that for JMP9 the displacement
107+ * actually fits the signed byte.
108+ */
109+ BUG_ON((insn.disp >> 31) != (insn.disp >> 7));
110+ }
111+ }
112+
113+ return &insn.text;
114+}
115+
116+extern int after_bootmem;
117+extern __ro_after_init struct mm_struct *poking_mm;
118+extern __ro_after_init unsigned long poking_addr;
119+
120+#ifndef CONFIG_UML_X86
121+static inline void int3_emulate_jmp(struct pt_regs *regs, unsigned long ip)
122+{
123+ regs->ip = ip;
124+}
125+
81126 static inline void int3_emulate_push(struct pt_regs *regs, unsigned long val)
82127 {
83128 /*
@@ -85,6 +130,9 @@ static inline void int3_emulate_push(struct pt_regs *regs, unsigned long val) · 1 unmodified line
85130 * stack where the break point happened, and the saving of
86131 * pt_regs. We can extend the original stack because of
87132 * this gap. See the idtentry macro's create_gap option.
133+ *
134+ * Similarly entry_32.S will have a gap on the stack for (any) hardware
135+ * exception and pt_regs; see FIXUP_FRAME.
88136 */
89137 regs->sp -= sizeof(unsigned long);
90138 *(unsigned long *)regs->sp = val;
arch/x86/kernel/alternative.c+150−48
@@ -936,44 +936,81 @@ static void do_sync_core(void *info) · 935 unmodified lines
936936 sync_core();
937937 }
938938
939−static struct bp_patching_desc {
939+void text_poke_sync(void)
940+{
941+ on_each_cpu(do_sync_core, NULL, 1);
942+}
943+
944+struct text_poke_loc {
945+ s32 rel_addr; /* addr := _stext + rel_addr */
946+ s32 rel32;
947+ u8 opcode;
948+ const u8 text[POKE_MAX_OPCODE_SIZE];
949+};
950+
951+struct bp_patching_desc {
940952 struct text_poke_loc *vec;
941953 int nr_entries;
942−} bp_patching;
954+ atomic_t refs;
955+};
956+
957+static struct bp_patching_desc *bp_desc;
958+
959+static inline struct bp_patching_desc *try_get_desc(struct bp_patching_desc **descp)
960+{
961+ struct bp_patching_desc *desc = READ_ONCE(*descp); /* rcu_dereference */
962+
963+ if (!desc || !atomic_inc_not_zero(&desc->refs))
964+ return NULL;
965+
966+ return desc;
967+}
968+
969+static inline void put_desc(struct bp_patching_desc *desc)
970+{
971+ smp_mb__before_atomic();
972+ atomic_dec(&desc->refs);
973+}
943974
944−static int patch_cmp(const void *key, const void *elt)
975+static inline void *text_poke_addr(struct text_poke_loc *tp)
976+{
977+ return _stext + tp->rel_addr;
978+}
979+
980+static int notrace patch_cmp(const void *key, const void *elt)
945981 {
946982 struct text_poke_loc *tp = (struct text_poke_loc *) elt;
947983
948− if (key < tp->addr)
984+ if (key < text_poke_addr(tp))
949985 return -1;
950− if (key > tp->addr)
986+ if (key > text_poke_addr(tp))
951987 return 1;
952988 return 0;
953989 }
954990 NOKPROBE_SYMBOL(patch_cmp);
955991
956−int poke_int3_handler(struct pt_regs *regs)
992+int notrace poke_int3_handler(struct pt_regs *regs)
957993 {
994+ struct bp_patching_desc *desc;
958995 struct text_poke_loc *tp;
996+ int len, ret = 0;
959997 void *ip;
960998
999+ if (user_mode(regs))
1000+ return 0;
1001+
9611002 /*
9621003 * Having observed our INT3 instruction, we now must observe
963− * bp_patching.nr_entries.
1004+ * bp_desc:
9641005 *
965− * nr_entries != 0 INT3
1006+ * bp_desc = desc INT3
9661007 * WMB RMB
967− * write INT3 if (nr_entries)
968− *
969− * Idem for other elements in bp_patching.
1008+ * write INT3 if (desc)
9701009 */
9711010 smp_rmb();
9721011
973− if (likely(!bp_patching.nr_entries))
974− return 0;
975−
976− if (user_mode(regs))
1012+ desc = try_get_desc(&bp_desc);
1013+ if (!desc)
9771014 return 0;
9781015
9791016 /*
@@ -984,19 +1021,20 @@ int poke_int3_handler(struct pt_regs *regs) · 4 unmodified lines
9841021 /*
9851022 * Skip the binary search if there is a single member in the vector.
9861023 */
987− if (unlikely(bp_patching.nr_entries > 1)) {
988− tp = bsearch(ip, bp_patching.vec, bp_patching.nr_entries,
1024+ if (unlikely(desc->nr_entries > 1)) {
1025+ tp = bsearch(ip, desc->vec, desc->nr_entries,
9891026 sizeof(struct text_poke_loc),
9901027 patch_cmp);
9911028 if (!tp)
992− return 0;
1029+ goto out_put;
9931030 } else {
994− tp = bp_patching.vec;
995− if (tp->addr != ip)
996− return 0;
1031+ tp = desc->vec;
1032+ if (text_poke_addr(tp) != ip)
1033+ goto out_put;
9971034 }
9981035
999− ip += tp->len;
1036+ len = text_opcode_size(tp->opcode);
1037+ ip += len;
10001038
10011039 switch (tp->opcode) {
10021040 case INT3_INSN_OPCODE:
@@ -1004,7 +1042,7 @@ int poke_int3_handler(struct pt_regs *regs) · 1 unmodified line
10041042 * Someone poked an explicit INT3, they'll want to handle it,
10051043 * do not consume.
10061044 */
1007− return 0;
1045+ goto out_put;
10081046
10091047 case CALL_INSN_OPCODE:
10101048 int3_emulate_call(regs, (long)ip + tp->rel32);
@@ -1019,10 +1057,18 @@ int poke_int3_handler(struct pt_regs *regs) · 8 unmodified lines
10191057 BUG();
10201058 }
10211059
1022− return 1;
1060+ ret = 1;
1061+
1062+out_put:
1063+ put_desc(desc);
1064+ return ret;
10231065 }
10241066 NOKPROBE_SYMBOL(poke_int3_handler);
10251067
1068+#define TP_VEC_MAX (PAGE_SIZE / sizeof(struct text_poke_loc))
1069+static struct text_poke_loc tp_vec[TP_VEC_MAX];
1070+static int tp_vec_nr;
1071+
10261072 /**
10271073 * text_poke_bp_batch() -- update instructions on live kernel on SMP
10281074 * @tp: vector of instructions to patch
@@ -1044,16 +1090,20 @@ NOKPROBE_SYMBOL(poke_int3_handler); · 15 unmodified lines
10441090 * replacing opcode
10451091 * - sync cores
10461092 */
1047−void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries)
1093+static void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries)
10481094 {
1095+ struct bp_patching_desc desc = {
1096+ .vec = tp,
1097+ .nr_entries = nr_entries,
1098+ .refs = ATOMIC_INIT(1),
1099+ };
10491100 unsigned char int3 = INT3_INSN_OPCODE;
10501101 unsigned int i;
10511102 int do_sync;
10521103
10531104 lockdep_assert_held(&text_mutex);
10541105
1055− bp_patching.vec = tp;
1056− bp_patching.nr_entries = nr_entries;
1106+ smp_store_release(&bp_desc, &desc); /* rcu_assign_pointer */
10571107
10581108 /*
10591109 * Corresponding read barrier in int3 notifier for making sure the
@@ -1065,18 +1115,20 @@ void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries) · 5 unmodified lines
10651115 * First step: add a int3 trap to the address that will be patched.
10661116 */
10671117 for (i = 0; i < nr_entries; i++)
1068− text_poke(tp[i].addr, &int3, sizeof(int3));
1118+ text_poke(text_poke_addr(&tp[i]), &int3, INT3_INSN_SIZE);
10691119
1070− on_each_cpu(do_sync_core, NULL, 1);
1120+ text_poke_sync();
10711121
10721122 /*
10731123 * Second step: update all but the first byte of the patched range.
10741124 */
10751125 for (do_sync = 0, i = 0; i < nr_entries; i++) {
1076− if (tp[i].len - sizeof(int3) > 0) {
1077− text_poke((char *)tp[i].addr + sizeof(int3),
1078− (const char *)tp[i].text + sizeof(int3),
1079− tp[i].len - sizeof(int3));
1126+ int len = text_opcode_size(tp[i].opcode);
1127+
1128+ if (len - INT3_INSN_SIZE > 0) {
1129+ text_poke(text_poke_addr(&tp[i]) + INT3_INSN_SIZE,
1130+ (const char *)tp[i].text + INT3_INSN_SIZE,
1131+ len - INT3_INSN_SIZE);
10801132 do_sync++;
10811133 }
10821134 }
@@ -1087,7 +1139,7 @@ void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries) · 4 unmodified lines
10871139 * not necessary and we'd be safe even without it. But
10881140 * better safe than sorry (plus there's not only Intel).
10891141 */
1090− on_each_cpu(do_sync_core, NULL, 1);
1142+ text_poke_sync();
10911143 }
10921144
10931145 /*
@@ -1098,19 +1150,20 @@ void text_poke_bp_batch(struct text_poke_loc *tp, unsigned int nr_entries) · 4 unmodified lines
10981150 if (tp[i].text[0] == INT3_INSN_OPCODE)
10991151 continue;
11001152
1101− text_poke(tp[i].addr, tp[i].text, sizeof(int3));
1153+ text_poke(text_poke_addr(&tp[i]), tp[i].text, INT3_INSN_SIZE);
11021154 do_sync++;
11031155 }
11041156
11051157 if (do_sync)
1106− on_each_cpu(do_sync_core, NULL, 1);
1158+ text_poke_sync();
11071159
11081160 /*
1109− * sync_core() implies an smp_mb() and orders this store against
1110− * the writing of the new instruction.
1161+ * Remove and synchronize_rcu(), except we have a very primitive
1162+ * refcount based completion.
11111163 */
1112− bp_patching.vec = NULL;
1113− bp_patching.nr_entries = 0;
1164+ WRITE_ONCE(bp_desc, NULL); /* RCU_INIT_POINTER */
1165+ if (!atomic_dec_and_test(&desc.refs))
1166+ atomic_cond_read_acquire(&desc.refs, !VAL);
11141167 }
11151168
11161169 void text_poke_loc_init(struct text_poke_loc *tp, void *addr,
@@ -1118,11 +1171,7 @@ void text_poke_loc_init(struct text_poke_loc *tp, void *addr, · 1 unmodified line
11181171 {
11191172 struct insn insn;
11201173
1121− if (!opcode)
1122− opcode = (void *)tp->text;
1123− else
1124− memcpy((void *)tp->text, opcode, len);
1125−
1174+ memcpy((void *)tp->text, opcode, len);
11261175 if (!emulate)
11271176 emulate = opcode;
11281177
@@ -1132,8 +1181,7 @@ void text_poke_loc_init(struct text_poke_loc *tp, void *addr, · 3 unmodified lines
11321181 BUG_ON(!insn_complete(&insn));
11331182 BUG_ON(len != insn.length);
11341183
1135− tp->addr = addr;
1136− tp->len = len;
1184+ tp->rel_addr = addr - (void *)_stext;
11371185 tp->opcode = insn.opcode.bytes[0];
11381186
11391187 switch (tp->opcode) {
@@ -1167,6 +1215,55 @@ void text_poke_loc_init(struct text_poke_loc *tp, void *addr, · 27 unmodified lines
11671215 }
11681216 }
11691217
1218+/*
1219+ * We hard rely on the tp_vec being ordered; ensure this is so by flushing
1220+ * early if needed.
1221+ */
1222+static bool tp_order_fail(void *addr)
1223+{
1224+ struct text_poke_loc *tp;
1225+
1226+ if (!tp_vec_nr)
1227+ return false;
1228+
1229+ if (!addr) /* force */
1230+ return true;
1231+
1232+ tp = &tp_vec[tp_vec_nr - 1];
1233+ if ((unsigned long)text_poke_addr(tp) > (unsigned long)addr)
1234+ return true;
1235+
1236+ return false;
1237+}
1238+
1239+static void text_poke_flush(void *addr)
1240+{
1241+ if (tp_vec_nr == TP_VEC_MAX || tp_order_fail(addr)) {
1242+ text_poke_bp_batch(tp_vec, tp_vec_nr);
1243+ tp_vec_nr = 0;
1244+ }
1245+}
1246+
1247+void text_poke_finish(void)
1248+{
1249+ text_poke_flush(NULL);
1250+}
1251+
1252+void __ref text_poke_queue(void *addr, const void *opcode, size_t len, const void *emulate)
1253+{
1254+ struct text_poke_loc *tp;
1255+
1256+ if (unlikely(system_state == SYSTEM_BOOTING)) {
1257+ text_poke_early(addr, opcode, len);
1258+ return;
1259+ }
1260+
1261+ text_poke_flush(addr);
1262+
1263+ tp = &tp_vec[tp_vec_nr++];
1264+ text_poke_loc_init(tp, addr, opcode, len, emulate);
1265+}
1266+
11701267 /**
11711268 * text_poke_bp() -- update instructions on live kernel on SMP
11721269 * @addr: address to patch
@@ -1178,10 +1275,15 @@ void text_poke_loc_init(struct text_poke_loc *tp, void *addr, · 5 unmodified lines
11781275 * dynamically allocated memory. This function should be used when it is
11791276 * not possible to allocate memory.
11801277 */
1181−void text_poke_bp(void *addr, const void *opcode, size_t len, const void *emulate)
1278+void __ref text_poke_bp(void *addr, const void *opcode, size_t len, const void *emulate)
11821279 {
11831280 struct text_poke_loc tp;
11841281
1282+ if (unlikely(system_state == SYSTEM_BOOTING)) {
1283+ text_poke_early(addr, opcode, len);
1284+ return;
1285+ }
1286+
11851287 text_poke_loc_init(&tp, addr, opcode, len, emulate);
11861288 text_poke_bp_batch(&tp, 1);
11871289 }
arch/x86/kernel/ftrace.c+126−562
@@ -35,6 +35,8 @@ · 34 unmodified lines
3535
3636 #ifdef CONFIG_DYNAMIC_FTRACE
3737
38+static int ftrace_poke_late = 0;
39+
3840 int ftrace_arch_code_modify_prepare(void)
3941 __acquires(&text_mutex)
4042 {
@@ -44,84 +46,37 @@ int ftrace_arch_code_modify_prepare(void) · 3 unmodified lines
4446 * ftrace has it set to "read/write".
4547 */
4648 mutex_lock(&text_mutex);
47− set_kernel_text_rw();
48− set_all_modules_text_rw();
49+ ftrace_poke_late = 1;
4950 return 0;
5051 }
5152
5253 int ftrace_arch_code_modify_post_process(void)
5354 __releases(&text_mutex)
5455 {
55− set_all_modules_text_ro();
56− set_kernel_text_ro();
56+ /*
57+ * ftrace_make_{call,nop}() may be called during
58+ * module load, and we need to finish the text_poke_queue()
59+ * that they do, here.
60+ */
61+ text_poke_finish();
62+ ftrace_poke_late = 0;
5763 mutex_unlock(&text_mutex);
5864 return 0;
5965 }
6066
61−union ftrace_code_union {
62− char code[MCOUNT_INSN_SIZE];
63− struct {
64− unsigned char op;
65− int offset;
66− } __attribute__((packed));
67−};
68−
69−static int ftrace_calc_offset(long ip, long addr)
70−{
71− return (int)(addr - ip);
72−}
73−
74−static unsigned char *
75−ftrace_text_replace(unsigned char op, unsigned long ip, unsigned long addr)
67+static const char *ftrace_nop_replace(void)
7668 {
77− static union ftrace_code_union calc;
78−
79− calc.op = op;
80− calc.offset = ftrace_calc_offset(ip + MCOUNT_INSN_SIZE, addr);
81−
82− return calc.code;
83−}
84−
85−static unsigned char *
86−ftrace_call_replace(unsigned long ip, unsigned long addr)
87−{
88− return ftrace_text_replace(0xe8, ip, addr);
89−}
90−
91−static inline int
92−within(unsigned long addr, unsigned long start, unsigned long end)
93−{
94− return addr >= start && addr < end;
69+ return ideal_nops[NOP_ATOMIC5];
9570 }
9671
97−static unsigned long text_ip_addr(unsigned long ip)
72+static const char *ftrace_call_replace(unsigned long ip, unsigned long addr)
9873 {
99− /*
100− * On x86_64, kernel text mappings are mapped read-only, so we use
101− * the kernel identity mapping instead of the kernel text mapping
102− * to modify the kernel text.
103− *
104− * For 32bit kernels, these mappings are same and we can use
105− * kernel identity mapping to modify code.
106− */
107− if (within(ip, (unsigned long)_text, (unsigned long)_etext))
108− ip = (unsigned long)__va(__pa_symbol(ip));
109−
110− return ip;
74+ return text_gen_insn(CALL_INSN_OPCODE, (void *)ip, (void *)addr);
11175 }
11276
113−static const unsigned char *ftrace_nop_replace(void)
77+static int ftrace_verify_code(unsigned long ip, const char *old_code)
11478 {
115− return ideal_nops[NOP_ATOMIC5];
116−}
117−
118−static int
119−ftrace_modify_code_direct(unsigned long ip, unsigned const char *old_code,
120− unsigned const char *new_code)
121−{
122− unsigned char replaced[MCOUNT_INSN_SIZE];
123−
124− ftrace_expected = old_code;
79+ char cur_code[MCOUNT_INSN_SIZE];
12580
12681 /*
12782 * Note:
@@ -130,31 +85,46 @@ ftrace_modify_code_direct(unsigned long ip, unsigned const char *old_code, · 2 unmodified lines
13085 * Carefully read and modify the code with probe_kernel_*(), and make
13186 * sure what we read is what we expected it to be before modifying it.
13287 */
133−
13488 /* read the text we want to modify */
135− if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
89+ if (probe_kernel_read(cur_code, (void *)ip, MCOUNT_INSN_SIZE)) {
90+ WARN_ON(1);
13691 return -EFAULT;
92+ }
13793
13894 /* Make sure it is what we expect it to be */
139− if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0)
95+ if (memcmp(cur_code, old_code, MCOUNT_INSN_SIZE) != 0) {
96+ WARN_ON(1);
14097 return -EINVAL;
98+ }
14199
142− ip = text_ip_addr(ip);
143−
144− /* replace the text with the new text */
145− if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE))
146− return -EPERM;
100+ return 0;
101+}
147102
148− sync_core();
103+/*
104+ * Marked __ref because it calls text_poke_early() which is .init.text. That is
105+ * ok because that call will happen early, during boot, when .init sections are
106+ * still present.
107+ */
108+static int __ref
109+ftrace_modify_code_direct(unsigned long ip, const char *old_code,
110+ const char *new_code)
111+{
112+ int ret = ftrace_verify_code(ip, old_code);
113+ if (ret)
114+ return ret;
149115
116+ /* replace the text with the new text */
117+ if (ftrace_poke_late)
118+ text_poke_queue((void *)ip, new_code, MCOUNT_INSN_SIZE, NULL);
119+ else
120+ text_poke_early((void *)ip, new_code, MCOUNT_INSN_SIZE);
150121 return 0;
151122 }
152123
153−int ftrace_make_nop(struct module *mod,
154− struct dyn_ftrace *rec, unsigned long addr)
124+int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr)
155125 {
156− unsigned const char *new, *old;
157126 unsigned long ip = rec->ip;
127+ const char *new, *old;
158128
159129 old = ftrace_call_replace(ip, addr);
160130 new = ftrace_nop_replace();
@@ -168,19 +138,20 @@ int ftrace_make_nop(struct module *mod, · 7 unmodified lines
168138 * just modify the code directly.
169139 */
170140 if (addr == MCOUNT_ADDR)
171− return ftrace_modify_code_direct(rec->ip, old, new);
141+ return ftrace_modify_code_direct(ip, old, new);
172142
173− ftrace_expected = NULL;
174−
175− /* Normal cases use add_brk_on_nop */
143+ /*
144+ * x86 overrides ftrace_replace_code -- this function will never be used
145+ * in this case.
146+ */
176147 WARN_ONCE(1, "invalid use of ftrace_make_nop");
177148 return -EINVAL;
178149 }
179150
180151 int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
181152 {
182− unsigned const char *new, *old;
183153 unsigned long ip = rec->ip;
154+ const char *new, *old;
184155
185156 old = ftrace_nop_replace();
186157 new = ftrace_call_replace(ip, addr);
@@ -189,43 +160,6 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) · 2 unmodified lines
189160 return ftrace_modify_code_direct(rec->ip, old, new);
190161 }
191162
192−/*
193− * The modifying_ftrace_code is used to tell the breakpoint
194− * handler to call ftrace_int3_handler(). If it fails to
195− * call this handler for a breakpoint added by ftrace, then
196− * the kernel may crash.
197− *
198− * As atomic_writes on x86 do not need a barrier, we do not
199− * need to add smp_mb()s for this to work. It is also considered
200− * that we can not read the modifying_ftrace_code before
201− * executing the breakpoint. That would be quite remarkable if
202− * it could do that. Here's the flow that is required:
203− *
204− * CPU-0 CPU-1
205− *
206− * atomic_inc(mfc);
207− * write int3s
208− * <trap-int3> // implicit (r)mb
209− * if (atomic_read(mfc))
210− * call ftrace_int3_handler()
211− *
212− * Then when we are finished:
213− *
214− * atomic_dec(mfc);
215− *
216− * If we hit a breakpoint that was not set by ftrace, it does not
217− * matter if ftrace_int3_handler() is called or not. It will
218− * simply be ignored. But it is crucial that a ftrace nop/caller
219− * breakpoint is handled. No other user should ever place a
220− * breakpoint on an ftrace nop/caller location. It must only
221− * be done by this code.
222− */
223−atomic_t modifying_ftrace_code __read_mostly;
224−
225−static int
226−ftrace_modify_code(unsigned long ip, unsigned const char *old_code,
227− unsigned const char *new_code);
228−
229163 /*
230164 * Should never be called:
231165 * As it is only called by __ftrace_replace_code() which is called by
@@ -238,452 +172,84 @@ int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, · 6 unmodified lines
238172 unsigned long addr)
239173 {
240174 WARN_ON(1);
241− ftrace_expected = NULL;
242175 return -EINVAL;
243176 }
244177
245−static unsigned long ftrace_update_func;
246−static unsigned long ftrace_update_func_call;
247−
248−static int update_ftrace_func(unsigned long ip, void *new)
249−{
250− unsigned char old[MCOUNT_INSN_SIZE];
251− int ret;
252−
253− memcpy(old, (void *)ip, MCOUNT_INSN_SIZE);
254−
255− ftrace_update_func = ip;
256− /* Make sure the breakpoints see the ftrace_update_func update */
257− smp_wmb();
258−
259− /* See comment above by declaration of modifying_ftrace_code */
260− atomic_inc(&modifying_ftrace_code);
261−
262− ret = ftrace_modify_code(ip, old, new);
263−
264− atomic_dec(&modifying_ftrace_code);
265−
266− return ret;
267−}
268−
269178 int ftrace_update_ftrace_func(ftrace_func_t func)
270−{
271− unsigned long ip = (unsigned long)(&ftrace_call);
272− unsigned char *new;
273− int ret;
274−
275− ftrace_update_func_call = (unsigned long)func;
276−
277− new = ftrace_call_replace(ip, (unsigned long)func);
278− ret = update_ftrace_func(ip, new);
279−
280− /* Also update the regs callback function */
281− if (!ret) {
282− ip = (unsigned long)(&ftrace_regs_call);
283− new = ftrace_call_replace(ip, (unsigned long)func);
284− ret = update_ftrace_func(ip, new);
285− }
286−
287− return ret;
288−}
289−
290−static nokprobe_inline int is_ftrace_caller(unsigned long ip)
291−{
292− if (ip == ftrace_update_func)
293− return 1;
294−
295− return 0;
296−}
297−
298−/*
299− * A breakpoint was added to the code address we are about to
300− * modify, and this is the handle that will just skip over it.
301− * We are either changing a nop into a trace call, or a trace
302− * call to a nop. While the change is taking place, we treat
303− * it just like it was a nop.
304− */
305−int ftrace_int3_handler(struct pt_regs *regs)
306179 {
307180 unsigned long ip;
181+ const char *new;
308182
309− if (WARN_ON_ONCE(!regs))
310− return 0;
311−
312− ip = regs->ip - INT3_INSN_SIZE;
313−
314− if (ftrace_location(ip)) {
315− int3_emulate_call(regs, (unsigned long)ftrace_regs_caller);
316− return 1;
317− } else if (is_ftrace_caller(ip)) {
318− if (!ftrace_update_func_call) {
319− int3_emulate_jmp(regs, ip + CALL_INSN_SIZE);
320− return 1;
321− }
322− int3_emulate_call(regs, ftrace_update_func_call);
323− return 1;
324− }
325−
326− return 0;
327−}
328−NOKPROBE_SYMBOL(ftrace_int3_handler);
329−
330−static int ftrace_write(unsigned long ip, const char *val, int size)
331−{
332− ip = text_ip_addr(ip);
333−
334− if (probe_kernel_write((void *)ip, val, size))
335− return -EPERM;
336−
337− return 0;
338−}
339−
340−static int add_break(unsigned long ip, const char *old)
341−{
342− unsigned char replaced[MCOUNT_INSN_SIZE];
343− unsigned char brk = BREAKPOINT_INSTRUCTION;
344−
345− if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE))
346− return -EFAULT;
347−
348− ftrace_expected = old;
349−
350− /* Make sure it is what we expect it to be */
351− if (memcmp(replaced, old, MCOUNT_INSN_SIZE) != 0)
352− return -EINVAL;
353−
354− return ftrace_write(ip, &brk, 1);
355−}
356−
357−static int add_brk_on_call(struct dyn_ftrace *rec, unsigned long addr)
358−{
359− unsigned const char *old;
360− unsigned long ip = rec->ip;
361−
362− old = ftrace_call_replace(ip, addr);
363−
364− return add_break(rec->ip, old);
365−}
366−
367−
368−static int add_brk_on_nop(struct dyn_ftrace *rec)
369−{
370− unsigned const char *old;
371−
372− old = ftrace_nop_replace();
373−
374− return add_break(rec->ip, old);
375−}
376−
377−static int add_breakpoints(struct dyn_ftrace *rec, bool enable)
378−{
379− unsigned long ftrace_addr;
380− int ret;
381−
382− ftrace_addr = ftrace_get_addr_curr(rec);
383−
384− ret = ftrace_test_record(rec, enable);
385−
386− switch (ret) {
387− case FTRACE_UPDATE_IGNORE:
388− return 0;
389−
390− case FTRACE_UPDATE_MAKE_CALL:
391− /* converting nop to call */
392− return add_brk_on_nop(rec);
393−
394− case FTRACE_UPDATE_MODIFY_CALL:
395− case FTRACE_UPDATE_MAKE_NOP:
396− /* converting a call to a nop */
397− return add_brk_on_call(rec, ftrace_addr);
398− }
399− return 0;
400−}
401−
402−/*
403− * On error, we need to remove breakpoints. This needs to
404− * be done caefully. If the address does not currently have a
405− * breakpoint, we know we are done. Otherwise, we look at the
406− * remaining 4 bytes of the instruction. If it matches a nop
407− * we replace the breakpoint with the nop. Otherwise we replace
408− * it with the call instruction.
409− */
410−static int remove_breakpoint(struct dyn_ftrace *rec)
411−{
412− unsigned char ins[MCOUNT_INSN_SIZE];
413− unsigned char brk = BREAKPOINT_INSTRUCTION;
414− const unsigned char *nop;
415− unsigned long ftrace_addr;
416− unsigned long ip = rec->ip;
417−
418− /* If we fail the read, just give up */
419− if (probe_kernel_read(ins, (void *)ip, MCOUNT_INSN_SIZE))
420− return -EFAULT;
421−
422− /* If this does not have a breakpoint, we are done */
423− if (ins[0] != brk)
424− return 0;
425−
426− nop = ftrace_nop_replace();
427−
428− /*
429− * If the last 4 bytes of the instruction do not match
430− * a nop, then we assume that this is a call to ftrace_addr.
431− */
432− if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) != 0) {
433− /*
434− * For extra paranoidism, we check if the breakpoint is on
435− * a call that would actually jump to the ftrace_addr.
436− * If not, don't touch the breakpoint, we make just create
437− * a disaster.
438− */
439− ftrace_addr = ftrace_get_addr_new(rec);
440− nop = ftrace_call_replace(ip, ftrace_addr);
441−
442− if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) == 0)
443− goto update;
444−
445− /* Check both ftrace_addr and ftrace_old_addr */
446− ftrace_addr = ftrace_get_addr_curr(rec);
447− nop = ftrace_call_replace(ip, ftrace_addr);
448−
449− ftrace_expected = nop;
450−
451− if (memcmp(&ins[1], &nop[1], MCOUNT_INSN_SIZE - 1) != 0)
452− return -EINVAL;
453− }
454−
455− update:
456− return ftrace_write(ip, nop, 1);
457−}
458−
459−static int add_update_code(unsigned long ip, unsigned const char *new)
460−{
461− /* skip breakpoint */
462− ip++;
463− new++;
464− return ftrace_write(ip, new, MCOUNT_INSN_SIZE - 1);
465−}
466−
467−static int add_update_call(struct dyn_ftrace *rec, unsigned long addr)
468−{
469− unsigned long ip = rec->ip;
470− unsigned const char *new;
471−
472− new = ftrace_call_replace(ip, addr);
473− return add_update_code(ip, new);
474−}
475−
476−static int add_update_nop(struct dyn_ftrace *rec)
477−{
478− unsigned long ip = rec->ip;
479− unsigned const char *new;
480−
481− new = ftrace_nop_replace();
482− return add_update_code(ip, new);
483−}
484−
485−static int add_update(struct dyn_ftrace *rec, bool enable)
486−{
487− unsigned long ftrace_addr;
488− int ret;
489−
490− ret = ftrace_test_record(rec, enable);
491−
492− ftrace_addr = ftrace_get_addr_new(rec);
493−
494− switch (ret) {
495− case FTRACE_UPDATE_IGNORE:
496− return 0;
497−
498− case FTRACE_UPDATE_MODIFY_CALL:
499− case FTRACE_UPDATE_MAKE_CALL:
500− /* converting nop to call */
501− return add_update_call(rec, ftrace_addr);
502−
503− case FTRACE_UPDATE_MAKE_NOP:
504− /* converting a call to a nop */
505− return add_update_nop(rec);
506− }
507−
508− return 0;
509−}
510−
511−static int finish_update_call(struct dyn_ftrace *rec, unsigned long addr)
512−{
513− unsigned long ip = rec->ip;
514− unsigned const char *new;
515−
516− new = ftrace_call_replace(ip, addr);
517−
518− return ftrace_write(ip, new, 1);
519−}
520−
521−static int finish_update_nop(struct dyn_ftrace *rec)
522−{
523− unsigned long ip = rec->ip;
524− unsigned const char *new;
525−
526− new = ftrace_nop_replace();
527−
528− return ftrace_write(ip, new, 1);
529−}
530−
531−static int finish_update(struct dyn_ftrace *rec, bool enable)
532−{
533− unsigned long ftrace_addr;
534− int ret;
535−
536− ret = ftrace_update_record(rec, enable);
537−
538− ftrace_addr = ftrace_get_addr_new(rec);
539−
540− switch (ret) {
541− case FTRACE_UPDATE_IGNORE:
542− return 0;
543−
544− case FTRACE_UPDATE_MODIFY_CALL:
545− case FTRACE_UPDATE_MAKE_CALL:
546− /* converting nop to call */
547− return finish_update_call(rec, ftrace_addr);
183+ ip = (unsigned long)(&ftrace_call);
184+ new = ftrace_call_replace(ip, (unsigned long)func);
185+ text_poke_bp((void *)ip, new, MCOUNT_INSN_SIZE, NULL);
548186
549− case FTRACE_UPDATE_MAKE_NOP:
550− /* converting a call to a nop */
551− return finish_update_nop(rec);
552− }
187+ ip = (unsigned long)(&ftrace_regs_call);
188+ new = ftrace_call_replace(ip, (unsigned long)func);
189+ text_poke_bp((void *)ip, new, MCOUNT_INSN_SIZE, NULL);
553190
554191 return 0;
555192 }
556193
557−static void do_sync_core(void *data)
558−{
559− sync_core();
560−}
561−
562−static void run_sync(void)
563−{
564− int enable_irqs;
565−
566− /* No need to sync if there's only one CPU */
567− if (num_online_cpus() == 1)
568− return;
569−
570− enable_irqs = irqs_disabled();
571−
572− /* We may be called with interrupts disabled (on bootup). */
573− if (enable_irqs)
574− local_irq_enable();
575− on_each_cpu(do_sync_core, NULL, 1);
576− if (enable_irqs)
577− local_irq_disable();
578−}
579−
580194 void ftrace_replace_code(int enable)
581195 {
582196 struct ftrace_rec_iter *iter;
583197 struct dyn_ftrace *rec;
584− const char *report = "adding breakpoints";
585− int count = 0;
198+ const char *new, *old;
586199 int ret;
587200
588201 for_ftrace_rec_iter(iter) {
589202 rec = ftrace_rec_iter_record(iter);
590203
591− ret = add_breakpoints(rec, enable);
592− if (ret)
593− goto remove_breakpoints;
594− count++;
595− }
596−
597− run_sync();
204+ switch (ftrace_test_record(rec, enable)) {
205+ case FTRACE_UPDATE_IGNORE:
206+ default:
207+ continue;
598208
599− report = "updating code";
600− count = 0;
209+ case FTRACE_UPDATE_MAKE_CALL:
210+ old = ftrace_nop_replace();
211+ break;
601212
602− for_ftrace_rec_iter(iter) {
603− rec = ftrace_rec_iter_record(iter);
213+ case FTRACE_UPDATE_MODIFY_CALL:
214+ case FTRACE_UPDATE_MAKE_NOP:
215+ old = ftrace_call_replace(rec->ip, ftrace_get_addr_curr(rec));
216+ break;
217+ }
604218
605− ret = add_update(rec, enable);
606− if (ret)
607− goto remove_breakpoints;
608− count++;
219+ ret = ftrace_verify_code(rec->ip, old);
220+ if (ret) {
221+ ftrace_bug(ret, rec);
222+ return;
223+ }
609224 }
610225
611− run_sync();
612−
613− report = "removing breakpoints";
614− count = 0;
615−
616226 for_ftrace_rec_iter(iter) {
617227 rec = ftrace_rec_iter_record(iter);
618228
619− ret = finish_update(rec, enable);
620− if (ret)
621− goto remove_breakpoints;
622− count++;
623− }
229+ switch (ftrace_test_record(rec, enable)) {
230+ case FTRACE_UPDATE_IGNORE:
231+ default:
232+ continue;
624233
625− run_sync();
234+ case FTRACE_UPDATE_MAKE_CALL:
235+ case FTRACE_UPDATE_MODIFY_CALL:
236+ new = ftrace_call_replace(rec->ip, ftrace_get_addr_new(rec));
237+ break;
626238
627− return;
239+ case FTRACE_UPDATE_MAKE_NOP:
240+ new = ftrace_nop_replace();
241+ break;
242+ }
628243
629− remove_breakpoints:
630− pr_warn("Failed on %s (%d):\n", report, count);
631− ftrace_bug(ret, rec);
632− for_ftrace_rec_iter(iter) {
633− rec = ftrace_rec_iter_record(iter);
634− /*
635− * Breakpoints are handled only when this function is in
636− * progress. The system could not work with them.
637− */
638− if (remove_breakpoint(rec))
639− BUG();
244+ text_poke_queue((void *)rec->ip, new, MCOUNT_INSN_SIZE, NULL);
245+ ftrace_update_record(rec, enable);
640246 }
641− run_sync();
642−}
643−
644−static int
645−ftrace_modify_code(unsigned long ip, unsigned const char *old_code,
646− unsigned const char *new_code)
647−{
648− int ret;
649−
650− ret = add_break(ip, old_code);
651− if (ret)
652− goto out;
653−
654− run_sync();
655−
656− ret = add_update_code(ip, new_code);
657− if (ret)
658− goto fail_update;
659−
660− run_sync();
661−
662− ret = ftrace_write(ip, new_code, 1);
663− /*
664− * The breakpoint is handled only when this function is in progress.
665− * The system could not work if we could not remove it.
666− */
667− BUG_ON(ret);
668− out:
669− run_sync();
670− return ret;
671−
672− fail_update:
673− /* Also here the system could not work with the breakpoint */
674− if (ftrace_write(ip, old_code, 1))
675− BUG();
676− goto out;
247+ text_poke_finish();
677248 }
678249
679250 void arch_ftrace_update_code(int command)
680251 {
681− /* See comment above by declaration of modifying_ftrace_code */
682− atomic_inc(&modifying_ftrace_code);
683−
684252 ftrace_modify_all_code(command);
685−
686− atomic_dec(&modifying_ftrace_code);
687253 }
688254
689255 int __init ftrace_dyn_arch_init(void)
@@ -748,6 +314,7 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size) · 58 unmodified lines
748314 unsigned long start_offset;
749315 unsigned long end_offset;
750316 unsigned long op_offset;
317+ unsigned long call_offset;
751318 unsigned long offset;
752319 unsigned long npages;
753320 unsigned long size;
@@ -764,10 +331,12 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size) · 10 unmodified lines
764331 start_offset = (unsigned long)ftrace_regs_caller;
765332 end_offset = (unsigned long)ftrace_regs_caller_end;
766333 op_offset = (unsigned long)ftrace_regs_caller_op_ptr;
334+ call_offset = (unsigned long)ftrace_regs_call;
767335 } else {
768336 start_offset = (unsigned long)ftrace_caller;
769337 end_offset = (unsigned long)ftrace_epilogue;
770338 op_offset = (unsigned long)ftrace_caller_op_ptr;
339+ call_offset = (unsigned long)ftrace_call;
771340 }
772341
773342 size = end_offset - start_offset;
@@ -824,16 +393,21 @@ create_trampoline(struct ftrace_ops *ops, unsigned int *tramp_size) · 50 unmodified lines
824393 /* put in the new offset to the ftrace_ops */
825394 memcpy(trampoline + op_offset, &op_ptr, OP_REF_SIZE);
826395
396+ /* put in the call to the function */
397+ mutex_lock(&text_mutex);
398+ call_offset -= start_offset;
399+ memcpy(trampoline + call_offset,
400+ text_gen_insn(CALL_INSN_OPCODE,
401+ trampoline + call_offset,
402+ ftrace_ops_get_func(ops)), CALL_INSN_SIZE);
403+ mutex_unlock(&text_mutex);
404+
827405 /* ALLOC_TRAMP flags lets us know we created it */
828406 ops->flags |= FTRACE_OPS_FL_ALLOC_TRAMP;
829407
830408 set_vm_flush_reset_perms(trampoline);
831409
832− /*
833− * Module allocation needs to be completed by making the page
834− * executable. The page is still writable, which is a security hazard,
835− * but anyhow ftrace breaks W^X completely.
836− */
410+ set_memory_ro((unsigned long)trampoline, npages);
837411 set_memory_x((unsigned long)trampoline, npages);
838412 return (unsigned long)trampoline;
839413 fail:
@@ -860,62 +434,54 @@ static unsigned long calc_trampoline_call_offset(bool save_regs) · 20 unmodified lines
860434 void arch_ftrace_update_trampoline(struct ftrace_ops *ops)
861435 {
862436 ftrace_func_t func;
863− unsigned char *new;
864437 unsigned long offset;
865438 unsigned long ip;
866439 unsigned int size;
867− int ret, npages;
440+ const char *new;
868441
869− if (ops->trampoline) {
870− /*
871− * The ftrace_ops caller may set up its own trampoline.
872− * In such a case, this code must not modify it.
873− */
874− if (!(ops->flags & FTRACE_OPS_FL_ALLOC_TRAMP))
875− return;
876− npages = PAGE_ALIGN(ops->trampoline_size) >> PAGE_SHIFT;
877− set_memory_rw(ops->trampoline, npages);
878− } else {
442+ if (!ops->trampoline) {
879443 ops->trampoline = create_trampoline(ops, &size);
880444 if (!ops->trampoline)
881445 return;
882446 ops->trampoline_size = size;
883− npages = PAGE_ALIGN(size) >> PAGE_SHIFT;
447+ return;
884448 }
885449
450+ /*
451+ * The ftrace_ops caller may set up its own trampoline.
452+ * In such a case, this code must not modify it.
453+ */
454+ if (!(ops->flags & FTRACE_OPS_FL_ALLOC_TRAMP))
455+ return;
456+
886457 offset = calc_trampoline_call_offset(ops->flags & FTRACE_OPS_FL_SAVE_REGS);
887458 ip = ops->trampoline + offset;
888−
889459 func = ftrace_ops_get_func(ops);
890460
891− ftrace_update_func_call = (unsigned long)func;
892−
461+ mutex_lock(&text_mutex);
893462 /* Do a safe modify in case the trampoline is executing */
894463 new = ftrace_call_replace(ip, (unsigned long)func);
895− ret = update_ftrace_func(ip, new);
896− set_memory_ro(ops->trampoline, npages);
897−
898− /* The update should never fail */
899− WARN_ON(ret);
464+ text_poke_bp((void *)ip, new, MCOUNT_INSN_SIZE, NULL);
465+ mutex_unlock(&text_mutex);
900466 }
901467
902468 /* Return the address of the function the trampoline calls */
903469 static void *addr_from_call(void *ptr)
904470 {
905− union ftrace_code_union calc;
471+ union text_poke_insn call;
906472 int ret;
907473
908− ret = probe_kernel_read(&calc, ptr, MCOUNT_INSN_SIZE);
474+ ret = probe_kernel_read(&call, ptr, CALL_INSN_SIZE);
909475 if (WARN_ON_ONCE(ret < 0))
910476 return NULL;
911477
912478 /* Make sure this is a call */
913− if (WARN_ON_ONCE(calc.op != 0xe8)) {
914− pr_warn("Expected e8, got %x\n", calc.op);
479+ if (WARN_ON_ONCE(call.opcode != CALL_INSN_OPCODE)) {
480+ pr_warn("Expected E8, got %x\n", call.opcode);
915481 return NULL;
916482 }
917483
918− return ptr + MCOUNT_INSN_SIZE + calc.offset;
484+ return ptr + CALL_INSN_SIZE + call.disp;
919485 }
920486
921487 void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
@@ -982,19 +548,18 @@ void arch_ftrace_trampoline_free(struct ftrace_ops *ops) · 60 unmodified lines
982548 #ifdef CONFIG_DYNAMIC_FTRACE
983549 extern void ftrace_graph_call(void);
984550
985−static unsigned char *ftrace_jmp_replace(unsigned long ip, unsigned long addr)
551+static const char *ftrace_jmp_replace(unsigned long ip, unsigned long addr)
986552 {
987− return ftrace_text_replace(0xe9, ip, addr);
553+ return text_gen_insn(JMP32_INSN_OPCODE, (void *)ip, (void *)addr);
988554 }
989555
990556 static int ftrace_mod_jmp(unsigned long ip, void *func)
991557 {
992− unsigned char *new;
558+ const char *new;
993559
994− ftrace_update_func_call = 0UL;
995560 new = ftrace_jmp_replace(ip, (unsigned long)func);
996−
997− return update_ftrace_func(ip, new);
561+ text_poke_bp((void *)ip, new, MCOUNT_INSN_SIZE, NULL);
562+ return 0;
998563 }
999564
1000565 int ftrace_enable_ftrace_graph_caller(void)
@@ -1020,10 +585,9 @@ int ftrace_disable_ftrace_graph_caller(void) · 19 unmodified lines
1020585 void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
1021586 unsigned long frame_pointer)
1022587 {
588+ unsigned long return_hooker = (unsigned long)&return_to_handler;
1023589 unsigned long old;
1024590 int faulted;
1025− unsigned long return_hooker = (unsigned long)
1026− &return_to_handler;
1027591
1028592 /*
1029593 * When resuming from suspend-to-ram, this function can be indirectly
arch/x86/kernel/jump_label.c+38−78
@@ -16,15 +16,7 @@ · 15 unmodified lines
1616 #include <asm/alternative.h>
1717 #include <asm/text-patching.h>
1818
19−union jump_code_union {
20− char code[JUMP_LABEL_NOP_SIZE];
21− struct {
22− char jump;
23− int offset;
24− } __attribute__((packed));
25−};
26−
27−static void bug_at(unsigned char *ip, int line)
19+static void bug_at(const void *ip, int line)
2820 {
2921 /*
3022 * The location is not an op that we were expecting.
@@ -35,42 +27,42 @@ static void bug_at(unsigned char *ip, int line) · 4 unmodified lines
3527 BUG();
3628 }
3729
38−static void __jump_label_set_jump_code(struct jump_entry *entry,
39− enum jump_label_type type,
40− union jump_code_union *code,
41− int init)
30+static const void *
31+__jump_label_set_jump_code(struct jump_entry *entry, enum jump_label_type type, int init)
4232 {
4333 const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP };
4434 const unsigned char *ideal_nop = ideal_nops[NOP_ATOMIC5];
45− const void *expect;
35+ const void *expect, *code;
36+ const void *addr, *dest;
4637 int line;
4738
48− code->jump = 0xe9;
49− code->offset = jump_entry_target(entry) -
50− (jump_entry_code(entry) + JUMP_LABEL_NOP_SIZE);
39+ addr = (void *)jump_entry_code(entry);
40+ dest = (void *)jump_entry_target(entry);
41+
42+ code = text_gen_insn(JMP32_INSN_OPCODE, addr, dest);
5143
5244 if (init) {
5345 expect = default_nop; line = __LINE__;
5446 } else if (type == JUMP_LABEL_JMP) {
5547 expect = ideal_nop; line = __LINE__;
5648 } else {
57− expect = code->code; line = __LINE__;
49+ expect = code; line = __LINE__;
5850 }
5951
60− if (memcmp((void *)jump_entry_code(entry), expect, JUMP_LABEL_NOP_SIZE))
61− bug_at((void *)jump_entry_code(entry), line);
52+ if (memcmp(addr, expect, JUMP_LABEL_NOP_SIZE))
53+ bug_at(addr, line);
6254
6355 if (type == JUMP_LABEL_NOP)
64− memcpy(code, ideal_nop, JUMP_LABEL_NOP_SIZE);
56+ code = ideal_nop;
57+
58+ return code;
6559 }
6660
67−static void __ref __jump_label_transform(struct jump_entry *entry,
68− enum jump_label_type type,
69− int init)
61+static void inline __jump_label_transform(struct jump_entry *entry,
62+ enum jump_label_type type,
63+ int init)
7064 {
71− union jump_code_union code;
72−
73− __jump_label_set_jump_code(entry, type, &code, init);
65+ const void *opcode = __jump_label_set_jump_code(entry, type, init);
7466
7567 /*
7668 * As long as only a single processor is running and the code is still
@@ -84,31 +76,33 @@ static void __ref __jump_label_transform(struct jump_entry *entry, · 7 unmodified lines
8476 * always nop being the 'currently valid' instruction
8577 */
8678 if (init || system_state == SYSTEM_BOOTING) {
87− text_poke_early((void *)jump_entry_code(entry), &code,
79+ text_poke_early((void *)jump_entry_code(entry), opcode,
8880 JUMP_LABEL_NOP_SIZE);
8981 return;
9082 }
9183
92− text_poke_bp((void *)jump_entry_code(entry), &code, JUMP_LABEL_NOP_SIZE, NULL);
84+ text_poke_bp((void *)jump_entry_code(entry), opcode, JUMP_LABEL_NOP_SIZE, NULL);
9385 }
9486
95−void arch_jump_label_transform(struct jump_entry *entry,
96− enum jump_label_type type)
87+static void __ref jump_label_transform(struct jump_entry *entry,
88+ enum jump_label_type type,
89+ int init)
9790 {
9891 mutex_lock(&text_mutex);
99− __jump_label_transform(entry, type, 0);
92+ __jump_label_transform(entry, type, init);
10093 mutex_unlock(&text_mutex);
10194 }
10295
103−#define TP_VEC_MAX (PAGE_SIZE / sizeof(struct text_poke_loc))
104−static struct text_poke_loc tp_vec[TP_VEC_MAX];
105−static int tp_vec_nr;
96+void arch_jump_label_transform(struct jump_entry *entry,
97+ enum jump_label_type type)
98+{
99+ jump_label_transform(entry, type, 0);
100+}
106101
107102 bool arch_jump_label_transform_queue(struct jump_entry *entry,
108103 enum jump_label_type type)
109104 {
110− struct text_poke_loc *tp;
111− void *entry_code;
105+ const void *opcode;
112106
113107 if (system_state == SYSTEM_BOOTING) {
114108 /*
@@ -118,53 +112,19 @@ bool arch_jump_label_transform_queue(struct jump_entry *entry, · 3 unmodified lines
118112 return true;
119113 }
120114
121− /*
122− * No more space in the vector, tell upper layer to apply
123− * the queue before continuing.
124− */
125− if (tp_vec_nr == TP_VEC_MAX)
126− return false;
127−
128− tp = &tp_vec[tp_vec_nr];
129−
130− entry_code = (void *)jump_entry_code(entry);
131−
132− /*
133− * The INT3 handler will do a bsearch in the queue, so we need entries
134− * to be sorted. We can survive an unsorted list by rejecting the entry,
135− * forcing the generic jump_label code to apply the queue. Warning once,
136− * to raise the attention to the case of an unsorted entry that is
137− * better not happen, because, in the worst case we will perform in the
138− * same way as we do without batching - with some more overhead.
139− */
140− if (tp_vec_nr > 0) {
141− int prev = tp_vec_nr - 1;
142− struct text_poke_loc *prev_tp = &tp_vec[prev];
143−
144− if (WARN_ON_ONCE(prev_tp->addr > entry_code))
145− return false;
146− }
147−
148− __jump_label_set_jump_code(entry, type,
149− (union jump_code_union *)&tp->text, 0);
150−
151− text_poke_loc_init(tp, entry_code, NULL, JUMP_LABEL_NOP_SIZE, NULL);
152−
153− tp_vec_nr++;
154−
115+ mutex_lock(&text_mutex);
116+ opcode = __jump_label_set_jump_code(entry, type, 0);
117+ text_poke_queue((void *)jump_entry_code(entry),
118+ opcode, JUMP_LABEL_NOP_SIZE, NULL);
119+ mutex_unlock(&text_mutex);
155120 return true;
156121 }
157122
158123 void arch_jump_label_transform_apply(void)
159124 {
160− if (!tp_vec_nr)
161− return;
162−
163125 mutex_lock(&text_mutex);
164− text_poke_bp_batch(tp_vec, tp_vec_nr);
126+ text_poke_finish();
165127 mutex_unlock(&text_mutex);
166−
167− tp_vec_nr = 0;
168128 }
169129
170130 static enum {
@@ -193,5 +153,5 @@ __init_or_module void arch_jump_label_transform_static(struct jump_entry *entry, · 22 unmodified lines
193153 jlstate = JL_STATE_NO_UPDATE;
194154 }
195155 if (jlstate == JL_STATE_UPDATE)
196− __jump_label_transform(entry, type, 1);
156+ jump_label_transform(entry, type, 1);
197157 }
arch/x86/kernel/kprobes/core.c+11−9
@@ -120,14 +120,14 @@ __synthesize_relative_insn(void *dest, void *from, void *to, u8 op) · 119 unmodified lines
120120 /* Insert a jump instruction at address 'from', which jumps to address 'to'.*/
121121 void synthesize_reljump(void *dest, void *from, void *to)
122122 {
123− __synthesize_relative_insn(dest, from, to, RELATIVEJUMP_OPCODE);
123+ __synthesize_relative_insn(dest, from, to, JMP32_INSN_OPCODE);
124124 }
125125 NOKPROBE_SYMBOL(synthesize_reljump);
126126
127127 /* Insert a call instruction at address 'from', which calls address 'to'.*/
128128 void synthesize_relcall(void *dest, void *from, void *to)
129129 {
130− __synthesize_relative_insn(dest, from, to, RELATIVECALL_OPCODE);
130+ __synthesize_relative_insn(dest, from, to, CALL_INSN_OPCODE);
131131 }
132132 NOKPROBE_SYMBOL(synthesize_relcall);
133133
@@ -302,7 +302,7 @@ static int can_probe(unsigned long paddr) · 168 unmodified lines
302302 * Another debugging subsystem might insert this breakpoint.
303303 * In that case, we can't recover it.
304304 */
305− if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
305+ if (insn.opcode.bytes[0] == INT3_INSN_OPCODE)
306306 return 0;
307307 addr += insn.length;
308308 }
@@ -357,7 +357,7 @@ int __copy_instruction(u8 *dest, u8 *src, u8 *real, struct insn *insn) · 48 unmodified lines
357357 return 0;
358358
359359 /* Another subsystem puts a breakpoint, failed to recover */
360− if (insn->opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
360+ if (insn->opcode.bytes[0] == INT3_INSN_OPCODE)
361361 return 0;
362362
363363 /* We should not singlestep on the exception masking instructions */
@@ -401,14 +401,14 @@ static int prepare_boost(kprobe_opcode_t *buf, struct kprobe *p, · 37 unmodified lines
401401 int len = insn->length;
402402
403403 if (can_boost(insn, p->addr) &&
404− MAX_INSN_SIZE - len >= RELATIVEJUMP_SIZE) {
404+ MAX_INSN_SIZE - len >= JMP32_INSN_SIZE) {
405405 /*
406406 * These instructions can be executed directly if it
407407 * jumps back to correct address.
408408 */
409409 synthesize_reljump(buf + len, p->ainsn.insn + len,
410410 p->addr + insn->length);
411− len += RELATIVEJUMP_SIZE;
411+ len += JMP32_INSN_SIZE;
412412 p->ainsn.boostable = true;
413413 } else {
414414 p->ainsn.boostable = false;
@@ -502,12 +502,14 @@ int arch_prepare_kprobe(struct kprobe *p) · 87 unmodified lines
502502
503503 void arch_arm_kprobe(struct kprobe *p)
504504 {
505− text_poke(p->addr, ((unsigned char []){BREAKPOINT_INSTRUCTION}), 1);
505+ text_poke(p->addr, ((unsigned char []){INT3_INSN_OPCODE}), 1);
506+ text_poke_sync();
506507 }
507508
508509 void arch_disarm_kprobe(struct kprobe *p)
509510 {
510511 text_poke(p->addr, &p->opcode, 1);
512+ text_poke_sync();
511513 }
512514
513515 void arch_remove_kprobe(struct kprobe *p)
@@ -610,7 +612,7 @@ static void setup_singlestep(struct kprobe *p, struct pt_regs *regs, · 96 unmodified lines
610612 regs->flags |= X86_EFLAGS_TF;
611613 regs->flags &= ~X86_EFLAGS_IF;
612614 /* single step inline if the instruction is an int3 */
613− if (p->opcode == BREAKPOINT_INSTRUCTION)
615+ if (p->opcode == INT3_INSN_OPCODE)
614616 regs->ip = (unsigned long)p->addr;
615617 else
616618 regs->ip = (unsigned long)p->ainsn.insn;
@@ -696,7 +698,7 @@ int kprobe_int3_handler(struct pt_regs *regs) · 79 unmodified lines
696698 reset_current_kprobe();
697699 return 1;
698700 }
699− } else if (*addr != BREAKPOINT_INSTRUCTION) {
701+ } else if (*addr != INT3_INSN_OPCODE) {
700702 /*
701703 * The breakpoint instruction was removed right
702704 * after we hit it. Another cpu has removed
arch/x86/kernel/kprobes/opt.c+33−34
@@ -38,7 +38,7 @@ unsigned long __recover_optprobed_insn(kprobe_opcode_t *buf, unsigned long addr) · 37 unmodified lines
3838 long offs;
3939 int i;
4040
41− for (i = 0; i < RELATIVEJUMP_SIZE; i++) {
41+ for (i = 0; i < JMP32_INSN_SIZE; i++) {
4242 kp = get_kprobe((void *)addr - i);
4343 /* This function only handles jump-optimized kprobe */
4444 if (kp && kprobe_optimized(kp)) {
@@ -62,10 +62,10 @@ found: · 17 unmodified lines
6262
6363 if (addr == (unsigned long)kp->addr) {
6464 buf[0] = kp->opcode;
65− memcpy(buf + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
65+ memcpy(buf + 1, op->optinsn.copied_insn, DISP32_SIZE);
6666 } else {
6767 offs = addr - (unsigned long)kp->addr - 1;
68− memcpy(buf, op->optinsn.copied_insn + offs, RELATIVE_ADDR_SIZE - offs);
68+ memcpy(buf, op->optinsn.copied_insn + offs, DISP32_SIZE - offs);
6969 }
7070
7171 return (unsigned long)buf;
@@ -141,8 +141,6 @@ STACK_FRAME_NON_STANDARD(optprobe_template_func); · 69 unmodified lines
141141 #define TMPL_END_IDX \
142142 ((long)optprobe_template_end - (long)optprobe_template_entry)
143143
144−#define INT3_SIZE sizeof(kprobe_opcode_t)
145−
146144 /* Optimized kprobe call back function: called from optinsn */
147145 static void
148146 optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs)
@@ -162,7 +160,7 @@ optimized_callback(struct optimized_kprobe *op, struct pt_regs *regs) · 13 unmodified lines
162160 regs->cs |= get_kernel_rpl();
163161 regs->gs = 0;
164162 #endif
165− regs->ip = (unsigned long)op->kp.addr + INT3_SIZE;
163+ regs->ip = (unsigned long)op->kp.addr + INT3_INSN_SIZE;
166164 regs->orig_ax = ~0UL;
167165
168166 __this_cpu_write(current_kprobe, &op->kp);
@@ -179,7 +177,7 @@ static int copy_optimized_instructions(u8 *dest, u8 *src, u8 *real) · 10 unmodified lines
179177 struct insn insn;
180178 int len = 0, ret;
181179
182− while (len < RELATIVEJUMP_SIZE) {
180+ while (len < JMP32_INSN_SIZE) {
183181 ret = __copy_instruction(dest + len, src + len, real + len, &insn);
184182 if (!ret || !can_boost(&insn, src + len))
185183 return -EINVAL;
@@ -271,7 +269,7 @@ static int can_optimize(unsigned long paddr) · 85 unmodified lines
271269 return 0;
272270
273271 /* Check there is enough space for a relative jump. */
274− if (size - offset < RELATIVEJUMP_SIZE)
272+ if (size - offset < JMP32_INSN_SIZE)
275273 return 0;
276274
277275 /* Decode instructions */
@@ -290,15 +288,15 @@ static int can_optimize(unsigned long paddr) · 12 unmodified lines
290288 kernel_insn_init(&insn, (void *)recovered_insn, MAX_INSN_SIZE);
291289 insn_get_length(&insn);
292290 /* Another subsystem puts a breakpoint */
293− if (insn.opcode.bytes[0] == BREAKPOINT_INSTRUCTION)
291+ if (insn.opcode.bytes[0] == INT3_INSN_OPCODE)
294292 return 0;
295293 /* Recover address */
296294 insn.kaddr = (void *)addr;
297295 insn.next_byte = (void *)(addr + insn.length);
298296 /* Check any instructions don't jump into target */
299297 if (insn_is_indirect_jump(&insn) ||
300− insn_jump_into_range(&insn, paddr + INT3_SIZE,
301− RELATIVE_ADDR_SIZE))
298+ insn_jump_into_range(&insn, paddr + INT3_INSN_SIZE,
299+ DISP32_SIZE))
302300 return 0;
303301 addr += insn.length;
304302 }
@@ -374,7 +372,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, · 69 unmodified lines
374372 * Verify if the address gap is in 2GB range, because this uses
375373 * a relative jump.
376374 */
377− rel = (long)slot - (long)op->kp.addr + RELATIVEJUMP_SIZE;
375+ rel = (long)slot - (long)op->kp.addr + JMP32_INSN_SIZE;
378376 if (abs(rel) > 0x7fffffff) {
379377 ret = -ERANGE;
380378 goto err;
@@ -401,7 +399,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, · 20 unmodified lines
401399 /* Set returning jmp instruction at the tail of out-of-line buffer */
402400 synthesize_reljump(buf + len, slot + len,
403401 (u8 *)op->kp.addr + op->optinsn.size);
404− len += RELATIVEJUMP_SIZE;
402+ len += JMP32_INSN_SIZE;
405403
406404 /* We have to use text_poke() for instruction buffer because it is RO */
407405 text_poke(slot, buf, len);
@@ -416,49 +414,50 @@ err: · 8 unmodified lines
416414 }
417415
418416 /*
419− * Replace breakpoints (int3) with relative jumps.
417+ * Replace breakpoints (INT3) with relative jumps (JMP.d32).
420418 * Caller must call with locking kprobe_mutex and text_mutex.
419+ *
420+ * The caller will have installed a regular kprobe and after that issued
421+ * syncrhonize_rcu_tasks(), this ensures that the instruction(s) that live in
422+ * the 4 bytes after the INT3 are unused and can now be overwritten.
421423 */
422424 void arch_optimize_kprobes(struct list_head *oplist)
423425 {
424426 struct optimized_kprobe *op, *tmp;
425− u8 insn_buff[RELATIVEJUMP_SIZE];
427+ u8 insn_buff[JMP32_INSN_SIZE];
426428
427429 list_for_each_entry_safe(op, tmp, oplist, list) {
428430 s32 rel = (s32)((long)op->optinsn.insn -
429− ((long)op->kp.addr + RELATIVEJUMP_SIZE));
431+ ((long)op->kp.addr + JMP32_INSN_SIZE));
430432
431433 WARN_ON(kprobe_disabled(&op->kp));
432434
433435 /* Backup instructions which will be replaced by jump address */
434− memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_SIZE,
435− RELATIVE_ADDR_SIZE);
436+ memcpy(op->optinsn.copied_insn, op->kp.addr + INT3_INSN_SIZE,
437+ DISP32_SIZE);
436438
437− insn_buff[0] = RELATIVEJUMP_OPCODE;
439+ insn_buff[0] = JMP32_INSN_OPCODE;
438440 *(s32 *)(&insn_buff[1]) = rel;
439441
440− text_poke_bp(op->kp.addr, insn_buff, RELATIVEJUMP_SIZE, NULL);
442+ text_poke_bp(op->kp.addr, insn_buff, JMP32_INSN_SIZE, NULL);
441443
442444 list_del_init(&op->list);
443445 }
444446 }
445447
446−/* Replace a relative jump with a breakpoint (int3). */
448+/*
449+ * Replace a relative jump (JMP.d32) with a breakpoint (INT3).
450+ *
451+ * After that, we can restore the 4 bytes after the INT3 to undo what
452+ * arch_optimize_kprobes() scribbled. This is safe since those bytes will be
453+ * unused once the INT3 lands.
454+ */
447455 void arch_unoptimize_kprobe(struct optimized_kprobe *op)
448456 {
449− u8 insn_buff[RELATIVEJUMP_SIZE];
450− u8 emulate_buff[RELATIVEJUMP_SIZE];
451−
452− /* Set int3 to first byte for kprobes */
453− insn_buff[0] = BREAKPOINT_INSTRUCTION;
454− memcpy(insn_buff + 1, op->optinsn.copied_insn, RELATIVE_ADDR_SIZE);
455−
456− emulate_buff[0] = RELATIVEJUMP_OPCODE;
457− *(s32 *)(&emulate_buff[1]) = (s32)((long)op->optinsn.insn -
458− ((long)op->kp.addr + RELATIVEJUMP_SIZE));
459−
460− text_poke_bp(op->kp.addr, insn_buff, RELATIVEJUMP_SIZE,
461− emulate_buff);
457+ arch_arm_kprobe(&op->kp);
458+ text_poke(op->kp.addr + INT3_INSN_SIZE,
459+ op->optinsn.copied_insn, DISP32_SIZE);
460+ text_poke_sync();
462461 }
463462
464463 /*
arch/x86/kernel/traps.c+0−9
@@ -572,15 +572,6 @@ NOKPROBE_SYMBOL(do_general_protection); · 571 unmodified lines
572572
573573 dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code)
574574 {
575−#ifdef CONFIG_DYNAMIC_FTRACE
576− /*
577− * ftrace must be first, everything else may cause a recursive crash.
578− * See note by declaration of modifying_ftrace_code in ftrace.c
579− */
580− if (unlikely(atomic_read(&modifying_ftrace_code)) &&
581− ftrace_int3_handler(regs))
582− return;
583−#endif
584575 if (poke_int3_handler(regs))
585576 return;
586577
arch/x86/mm/init_32.c+0−28
@@ -873,34 +873,6 @@ void arch_remove_memory(int nid, u64 start, u64 size, · 872 unmodified lines
873873
874874 int kernel_set_to_readonly __read_mostly;
875875
876−void set_kernel_text_rw(void)
877−{
878− unsigned long start = PFN_ALIGN(_text);
879− unsigned long size = PFN_ALIGN(_etext) - start;
880−
881− if (!kernel_set_to_readonly)
882− return;
883−
884− pr_debug("Set kernel text: %lx - %lx for read write\n",
885− start, start+size);
886−
887− set_pages_rw(virt_to_page(start), size >> PAGE_SHIFT);
888−}
889−
890−void set_kernel_text_ro(void)
891−{
892− unsigned long start = PFN_ALIGN(_text);
893− unsigned long size = PFN_ALIGN(_etext) - start;
894−
895− if (!kernel_set_to_readonly)
896− return;
897−
898− pr_debug("Set kernel text: %lx - %lx for read only\n",
899− start, start+size);
900−
901− set_pages_ro(virt_to_page(start), size >> PAGE_SHIFT);
902−}
903−
904876 static void mark_nxdata_nx(void)
905877 {
906878 /*
arch/x86/mm/init_64.c+0−36
@@ -1258,42 +1258,6 @@ void __init mem_init(void) · 1257 unmodified lines
12581258
12591259 int kernel_set_to_readonly;
12601260
1261−void set_kernel_text_rw(void)
1262−{
1263− unsigned long start = PFN_ALIGN(_text);
1264− unsigned long end = PFN_ALIGN(_etext);
1265−
1266− if (!kernel_set_to_readonly)
1267− return;
1268−
1269− pr_debug("Set kernel text: %lx - %lx for read write\n",
1270− start, end);
1271−
1272− /*
1273− * Make the kernel identity mapping for text RW. Kernel text
1274− * mapping will always be RO. Refer to the comment in
1275− * static_protections() in pageattr.c
1276− */
1277− set_memory_rw(start, (end - start) >> PAGE_SHIFT);
1278−}
1279−
1280−void set_kernel_text_ro(void)
1281−{
1282− unsigned long start = PFN_ALIGN(_text);
1283− unsigned long end = PFN_ALIGN(_etext);
1284−
1285− if (!kernel_set_to_readonly)
1286− return;
1287−
1288− pr_debug("Set kernel text: %lx - %lx for read only\n",
1289− start, end);
1290−
1291− /*
1292− * Set the kernel identity mapping for text RO.
1293− */
1294− set_memory_ro(start, (end - start) >> PAGE_SHIFT);
1295−}
1296−
12971261 void mark_rodata_ro(void)
12981262 {
12991263 unsigned long start = PFN_ALIGN(_text);
drivers/infiniband/hw/hfi1/trace_tid.h+4−4
@@ -138,10 +138,10 @@ TRACE_EVENT(/* put_tid */ · 137 unmodified lines
138138 TP_ARGS(dd, index, type, pa, order),
139139 TP_STRUCT__entry(/* entry */
140140 DD_DEV_ENTRY(dd)
141− __field(unsigned long, pa);
142− __field(u32, index);
143− __field(u32, type);
144− __field(u16, order);
141+ __field(unsigned long, pa)
142+ __field(u32, index)
143+ __field(u32, type)
144+ __field(u16, order)
145145 ),
146146 TP_fast_assign(/* assign */
147147 DD_DEV_ASSIGN(dd);
drivers/infiniband/hw/hfi1/trace_tx.h+1−1
@@ -588,7 +588,7 @@ TRACE_EVENT(hfi1_sdma_user_reqinfo, · 587 unmodified lines
588588 TP_PROTO(struct hfi1_devdata *dd, u16 ctxt, u8 subctxt, u16 *i),
589589 TP_ARGS(dd, ctxt, subctxt, i),
590590 TP_STRUCT__entry(
591− DD_DEV_ENTRY(dd);
591+ DD_DEV_ENTRY(dd)
592592 __field(u16, ctxt)
593593 __field(u8, subctxt)
594594 __field(u8, ver_opcode)
drivers/lightnvm/pblk-trace.h+4−4
@@ -46,7 +46,7 @@ TRACE_EVENT(pblk_chunk_reset, · 45 unmodified lines
4646 TP_STRUCT__entry(
4747 __string(name, name)
4848 __field(u64, ppa)
49− __field(int, state);
49+ __field(int, state)
5050 ),
5151
5252 TP_fast_assign(
@@ -72,7 +72,7 @@ TRACE_EVENT(pblk_chunk_state, · 19 unmodified lines
7272 TP_STRUCT__entry(
7373 __string(name, name)
7474 __field(u64, ppa)
75− __field(int, state);
75+ __field(int, state)
7676 ),
7777
7878 TP_fast_assign(
@@ -98,7 +98,7 @@ TRACE_EVENT(pblk_line_state, · 19 unmodified lines
9898 TP_STRUCT__entry(
9999 __string(name, name)
100100 __field(int, line)
101− __field(int, state);
101+ __field(int, state)
102102 ),
103103
104104 TP_fast_assign(
@@ -121,7 +121,7 @@ TRACE_EVENT(pblk_state, · 16 unmodified lines
121121
122122 TP_STRUCT__entry(
123123 __string(name, name)
124− __field(int, state);
124+ __field(int, state)
125125 ),
126126
127127 TP_fast_assign(
drivers/net/fjes/fjes_trace.h+1−1
@@ -28,7 +28,7 @@ TRACE_EVENT(fjes_hw_issue_request_command, · 27 unmodified lines
2828 __field(u8, cs_busy)
2929 __field(u8, cs_complete)
3030 __field(int, timeout)
31− __field(int, ret);
31+ __field(int, ret)
3232 ),
3333 TP_fast_assign(
3434 __entry->cr_req = cr->bits.req_code;
drivers/net/wireless/ath/ath10k/trace.h+3−3
@@ -239,7 +239,7 @@ TRACE_EVENT(ath10k_wmi_dbglog, · 238 unmodified lines
239239 TP_STRUCT__entry(
240240 __string(device, dev_name(ar->dev))
241241 __string(driver, dev_driver_string(ar->dev))
242− __field(u8, hw_type);
242+ __field(u8, hw_type)
243243 __field(size_t, buf_len)
244244 __dynamic_array(u8, buf, buf_len)
245245 ),
@@ -269,7 +269,7 @@ TRACE_EVENT(ath10k_htt_pktlog, · 23 unmodified lines
269269 TP_STRUCT__entry(
270270 __string(device, dev_name(ar->dev))
271271 __string(driver, dev_driver_string(ar->dev))
272− __field(u8, hw_type);
272+ __field(u8, hw_type)
273273 __field(u16, buf_len)
274274 __dynamic_array(u8, pktlog, buf_len)
275275 ),
@@ -435,7 +435,7 @@ TRACE_EVENT(ath10k_htt_rx_desc, · 159 unmodified lines
435435 TP_STRUCT__entry(
436436 __string(device, dev_name(ar->dev))
437437 __string(driver, dev_driver_string(ar->dev))
438− __field(u8, hw_type);
438+ __field(u8, hw_type)
439439 __field(u16, len)
440440 __dynamic_array(u8, rxdesc, len)
441441 ),
fs/xfs/scrub/trace.h+3−3
@@ -329,7 +329,7 @@ TRACE_EVENT(xchk_btree_op_error, · 328 unmodified lines
329329 __field(int, level)
330330 __field(xfs_agnumber_t, agno)
331331 __field(xfs_agblock_t, bno)
332− __field(int, ptr);
332+ __field(int, ptr)
333333 __field(int, error)
334334 __field(void *, ret_ip)
335335 ),
@@ -414,7 +414,7 @@ TRACE_EVENT(xchk_btree_error, · 78 unmodified lines
414414 __field(int, level)
415415 __field(xfs_agnumber_t, agno)
416416 __field(xfs_agblock_t, bno)
417− __field(int, ptr);
417+ __field(int, ptr)
418418 __field(void *, ret_ip)
419419 ),
420420 TP_fast_assign(
@@ -452,7 +452,7 @@ TRACE_EVENT(xchk_ifork_btree_error, · 31 unmodified lines
452452 __field(int, level)
453453 __field(xfs_agnumber_t, agno)
454454 __field(xfs_agblock_t, bno)
455− __field(int, ptr);
455+ __field(int, ptr)
456456 __field(void *, ret_ip)
457457 ),
458458 TP_fast_assign(
fs/xfs/xfs_trace.h+2−2
@@ -218,8 +218,8 @@ DECLARE_EVENT_CLASS(xfs_bmap_class, · 217 unmodified lines
218218 TP_STRUCT__entry(
219219 __field(dev_t, dev)
220220 __field(xfs_ino_t, ino)
221− __field(void *, leaf);
222− __field(int, pos);
221+ __field(void *, leaf)
222+ __field(int, pos)
223223 __field(xfs_fileoff_t, startoff)
224224 __field(xfs_fsblock_t, startblock)
225225 __field(xfs_filblks_t, blockcount)
include/linux/module.h+0−4
@@ -849,13 +849,9 @@ extern int module_sysfs_initialized; · 848 unmodified lines
849849 #define __MODULE_STRING(x) __stringify(x)
850850
851851 #ifdef CONFIG_STRICT_MODULE_RWX
852−extern void set_all_modules_text_rw(void);
853−extern void set_all_modules_text_ro(void);
854852 extern void module_enable_ro(const struct module *mod, bool after_init);
855853 extern void module_disable_ro(const struct module *mod);
856854 #else
857−static inline void set_all_modules_text_rw(void) { }
858−static inline void set_all_modules_text_ro(void) { }
859855 static inline void module_enable_ro(const struct module *mod, bool after_init) { }
860856 static inline void module_disable_ro(const struct module *mod) { }
861857 #endif
include/linux/trace_events.h+17−1
@@ -192,6 +192,22 @@ enum trace_reg { · 191 unmodified lines
192192
193193 struct trace_event_call;
194194
195+#define TRACE_FUNCTION_TYPE ((const char *)~0UL)
196+
197+struct trace_event_fields {
198+ const char *type;
199+ union {
200+ struct {
201+ const char *name;
202+ const int size;
203+ const int align;
204+ const int is_signed;
205+ const int filter_type;
206+ };
207+ int (*define_fields)(struct trace_event_call *);
208+ };
209+};
210+
195211 struct trace_event_class {
196212 const char *system;
197213 void *probe;
@@ -200,7 +216,7 @@ struct trace_event_class { · 2 unmodified lines
200216 #endif
201217 int (*reg)(struct trace_event_call *event,
202218 enum trace_reg type, void *data);
203− int (*define_fields)(struct trace_event_call *);
219+ struct trace_event_fields *fields_array;
204220 struct list_head *(*get_fields)(struct trace_event_call *);
205221 struct list_head fields;
206222 int (*raw_init)(struct trace_event_call *);
include/trace/events/filemap.h+1−1
@@ -85,7 +85,7 @@ TRACE_EVENT(file_check_and_advance_wb_err, · 84 unmodified lines
8585 TP_ARGS(file, old),
8686
8787 TP_STRUCT__entry(
88− __field(struct file *, file);
88+ __field(struct file *, file)
8989 __field(unsigned long, i_ino)
9090 __field(dev_t, s_dev)
9191 __field(errseq_t, old)
include/trace/trace_events.h+21−43
@@ -400,22 +400,16 @@ static struct trace_event_functions trace_event_type_funcs_##call = { \ · 399 unmodified lines
400400 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
401401
402402 #undef __field_ext
403−#define __field_ext(type, item, filter_type) \
404− ret = trace_define_field(event_call, #type, #item, \
405− offsetof(typeof(field), item), \
406− sizeof(field.item), \
407− is_signed_type(type), filter_type); \
408− if (ret) \
409− return ret;
403+#define __field_ext(_type, _item, _filter_type) { \
404+ .type = #_type, .name = #_item, \
405+ .size = sizeof(_type), .align = __alignof__(_type), \
406+ .is_signed = is_signed_type(_type), .filter_type = _filter_type },
410407
411408 #undef __field_struct_ext
412−#define __field_struct_ext(type, item, filter_type) \
413− ret = trace_define_field(event_call, #type, #item, \
414− offsetof(typeof(field), item), \
415− sizeof(field.item), \
416− 0, filter_type); \
417− if (ret) \
418− return ret;
409+#define __field_struct_ext(_type, _item, _filter_type) { \
410+ .type = #_type, .name = #_item, \
411+ .size = sizeof(_type), .align = __alignof__(_type), \
412+ 0, .filter_type = _filter_type },
419413
420414 #undef __field
421415 #define __field(type, item) __field_ext(type, item, FILTER_OTHER)
@@ -424,25 +418,16 @@ static struct trace_event_functions trace_event_type_funcs_##call = { \ · 2 unmodified lines
424418 #define __field_struct(type, item) __field_struct_ext(type, item, FILTER_OTHER)
425419
426420 #undef __array
427−#define __array(type, item, len) \
428− do { \
429− char *type_str = #type"["__stringify(len)"]"; \
430− BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \
431− BUILD_BUG_ON(len <= 0); \
432− ret = trace_define_field(event_call, type_str, #item, \
433− offsetof(typeof(field), item), \
434− sizeof(field.item), \
435− is_signed_type(type), FILTER_OTHER); \
436− if (ret) \
437− return ret; \
438− } while (0);
421+#define __array(_type, _item, _len) { \
422+ .type = #_type"["__stringify(_len)"]", .name = #_item, \
423+ .size = sizeof(_type[_len]), .align = __alignof__(_type), \
424+ .is_signed = is_signed_type(_type), .filter_type = FILTER_OTHER },
439425
440426 #undef __dynamic_array
441−#define __dynamic_array(type, item, len) \
442− ret = trace_define_field(event_call, "__data_loc " #type "[]", #item, \
443− offsetof(typeof(field), __data_loc_##item), \
444− sizeof(field.__data_loc_##item), \
445− is_signed_type(type), FILTER_OTHER);
427+#define __dynamic_array(_type, _item, _len) { \
428+ .type = "__data_loc " #_type "[]", .name = #_item, \
429+ .size = 4, .align = 4, \
430+ .is_signed = is_signed_type(_type), .filter_type = FILTER_OTHER },
446431
447432 #undef __string
448433 #define __string(item, src) __dynamic_array(char, item, -1)
@@ -452,16 +437,9 @@ static struct trace_event_functions trace_event_type_funcs_##call = { \ · 3 unmodified lines
452437
453438 #undef DECLARE_EVENT_CLASS
454439 #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, func, print) \
455−static int notrace __init \
456−trace_event_define_fields_##call(struct trace_event_call *event_call) \
457−{ \
458− struct trace_event_raw_##call field; \
459− int ret; \
460− \
461− tstruct; \
462− \
463− return ret; \
464−}
440+static struct trace_event_fields trace_event_fields_##call[] = { \
441+ tstruct \
442+ {} };
465443
466444 #undef DEFINE_EVENT
467445 #define DEFINE_EVENT(template, name, proto, args)
@@ -619,7 +597,7 @@ static inline notrace int trace_event_get_offsets_##call( \ · 151 unmodified lines
619597 *
620598 * static struct trace_event_class __used event_class_<template> = {
621599 * .system = "<system>",
622− * .define_fields = trace_event_define_fields_<call>,
600+ * .fields_array = trace_event_fields_<call>,
623601 * .fields = LIST_HEAD_INIT(event_class_##call.fields),
624602 * .raw_init = trace_event_raw_init,
625603 * .probe = trace_event_raw_event_##call,
@@ -768,7 +746,7 @@ _TRACE_PERF_PROTO(call, PARAMS(proto)); \ · 142 unmodified lines
768746 static char print_fmt_##call[] = print; \
769747 static struct trace_event_class __used __refdata event_class_##call = { \
770748 .system = TRACE_SYSTEM_STRING, \
771− .define_fields = trace_event_define_fields_##call, \
749+ .fields_array = trace_event_fields_##call, \
772750 .fields = LIST_HEAD_INIT(event_class_##call.fields),\
773751 .raw_init = trace_event_raw_init, \
774752 .probe = trace_event_raw_event_##call, \
kernel/kprobes.c+46−25
@@ -510,6 +510,8 @@ static void do_unoptimize_kprobes(void) · 509 unmodified lines
510510 arch_unoptimize_kprobes(&unoptimizing_list, &freeing_list);
511511 /* Loop free_list for disarming */
512512 list_for_each_entry_safe(op, tmp, &freeing_list, list) {
513+ /* Switching from detour code to origin */
514+ op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
513515 /* Disarm probes if marked disabled */
514516 if (kprobe_disabled(&op->kp))
515517 arch_disarm_kprobe(&op->kp);
@@ -610,6 +612,18 @@ void wait_for_kprobe_optimizer(void) · 94 unmodified lines
610612 mutex_unlock(&kprobe_mutex);
611613 }
612614
615+static bool optprobe_queued_unopt(struct optimized_kprobe *op)
616+{
617+ struct optimized_kprobe *_op;
618+
619+ list_for_each_entry(_op, &unoptimizing_list, list) {
620+ if (op == _op)
621+ return true;
622+ }
623+
624+ return false;
625+}
626+
613627 /* Optimize kprobe if p is ready to be optimized */
614628 static void optimize_kprobe(struct kprobe *p)
615629 {
@@ -631,17 +645,21 @@ static void optimize_kprobe(struct kprobe *p) · 15 unmodified lines
631645 return;
632646
633647 /* Check if it is already optimized. */
634− if (op->kp.flags & KPROBE_FLAG_OPTIMIZED)
648+ if (op->kp.flags & KPROBE_FLAG_OPTIMIZED) {
649+ if (optprobe_queued_unopt(op)) {
650+ /* This is under unoptimizing. Just dequeue the probe */
651+ list_del_init(&op->list);
652+ }
635653 return;
654+ }
636655 op->kp.flags |= KPROBE_FLAG_OPTIMIZED;
637656
638− if (!list_empty(&op->list))
639− /* This is under unoptimizing. Just dequeue the probe */
640− list_del_init(&op->list);
641− else {
642− list_add(&op->list, &optimizing_list);
643− kick_kprobe_optimizer();
644− }
657+ /* On unoptimizing/optimizing_list, op must have OPTIMIZED flag */
658+ if (WARN_ON_ONCE(!list_empty(&op->list)))
659+ return;
660+
661+ list_add(&op->list, &optimizing_list);
662+ kick_kprobe_optimizer();
645663 }
646664
647665 /* Short cut to direct unoptimizing */
@@ -649,6 +667,7 @@ static void force_unoptimize_kprobe(struct optimized_kprobe *op) · 1 unmodified line
649667 {
650668 lockdep_assert_cpus_held();
651669 arch_unoptimize_kprobe(op);
670+ op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
652671 if (kprobe_disabled(&op->kp))
653672 arch_disarm_kprobe(&op->kp);
654673 }
@@ -662,31 +681,33 @@ static void unoptimize_kprobe(struct kprobe *p, bool force) · 7 unmodified lines
662681 return; /* This is not an optprobe nor optimized */
663682
664683 op = container_of(p, struct optimized_kprobe, kp);
665− if (!kprobe_optimized(p)) {
666− /* Unoptimized or unoptimizing case */
667− if (force && !list_empty(&op->list)) {
668− /*
669− * Only if this is unoptimizing kprobe and forced,
670− * forcibly unoptimize it. (No need to unoptimize
671− * unoptimized kprobe again :)
672− */
673− list_del_init(&op->list);
674− force_unoptimize_kprobe(op);
675− }
684+ if (!kprobe_optimized(p))
676685 return;
677− }
678686
679− op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
680687 if (!list_empty(&op->list)) {
681− /* Dequeue from the optimization queue */
682− list_del_init(&op->list);
688+ if (optprobe_queued_unopt(op)) {
689+ /* Queued in unoptimizing queue */
690+ if (force) {
691+ /*
692+ * Forcibly unoptimize the kprobe here, and queue it
693+ * in the freeing list for release afterwards.
694+ */
695+ force_unoptimize_kprobe(op);
696+ list_move(&op->list, &freeing_list);
697+ }
698+ } else {
699+ /* Dequeue from the optimizing queue */
700+ list_del_init(&op->list);
701+ op->kp.flags &= ~KPROBE_FLAG_OPTIMIZED;
702+ }
683703 return;
684704 }
705+
685706 /* Optimized kprobe case */
686− if (force)
707+ if (force) {
687708 /* Forcibly update the code: this is a special case */
688709 force_unoptimize_kprobe(op);
689− else {
710+ } else {
690711 list_add(&op->list, &unoptimizing_list);
691712 kick_kprobe_optimizer();
692713 }
kernel/module.c+0−43
@@ -2031,49 +2031,6 @@ static void module_enable_nx(const struct module *mod) · 2030 unmodified lines
20312031 frob_writable_data(&mod->init_layout, set_memory_nx);
20322032 }
20332033
2034−/* Iterate through all modules and set each module's text as RW */
2035−void set_all_modules_text_rw(void)
2036−{
2037− struct module *mod;
2038−
2039− if (!rodata_enabled)
2040− return;
2041−
2042− mutex_lock(&module_mutex);
2043− list_for_each_entry_rcu(mod, &modules, list) {
2044− if (mod->state == MODULE_STATE_UNFORMED)
2045− continue;
2046−
2047− frob_text(&mod->core_layout, set_memory_rw);
2048− frob_text(&mod->init_layout, set_memory_rw);
2049− }
2050− mutex_unlock(&module_mutex);
2051−}
2052−
2053−/* Iterate through all modules and set each module's text as RO */
2054−void set_all_modules_text_ro(void)
2055−{
2056− struct module *mod;
2057−
2058− if (!rodata_enabled)
2059− return;
2060−
2061− mutex_lock(&module_mutex);
2062− list_for_each_entry_rcu(mod, &modules, list) {
2063− /*
2064− * Ignore going modules since it's possible that ro
2065− * protection has already been disabled, otherwise we'll
2066− * run into protection faults at module deallocation.
2067− */
2068− if (mod->state == MODULE_STATE_UNFORMED ||
2069− mod->state == MODULE_STATE_GOING)
2070− continue;
2071−
2072− frob_text(&mod->core_layout, set_memory_ro);
2073− frob_text(&mod->init_layout, set_memory_ro);
2074− }
2075− mutex_unlock(&module_mutex);
2076−}
20772034 #else /* !CONFIG_STRICT_MODULE_RWX */
20782035 static void module_enable_nx(const struct module *mod) { }
20792036 #endif /* CONFIG_STRICT_MODULE_RWX */
kernel/trace/trace.h+14−17
@@ -52,6 +52,9 @@ enum trace_type { · 51 unmodified lines
5252 #undef __field
5353 #define __field(type, item) type item;
5454
55+#undef __field_fn
56+#define __field_fn(type, item) type item;
57+
5558 #undef __field_struct
5659 #define __field_struct(type, item) __field(type, item)
5760
@@ -71,26 +74,22 @@ enum trace_type { · 13 unmodified lines
7174 #define F_STRUCT(args...) args
7275
7376 #undef FTRACE_ENTRY
74−#define FTRACE_ENTRY(name, struct_name, id, tstruct, print, filter) \
77+#define FTRACE_ENTRY(name, struct_name, id, tstruct, print) \
7578 struct struct_name { \
7679 struct trace_entry ent; \
7780 tstruct \
7881 }
7982
8083 #undef FTRACE_ENTRY_DUP
81−#define FTRACE_ENTRY_DUP(name, name_struct, id, tstruct, printk, filter)
84+#define FTRACE_ENTRY_DUP(name, name_struct, id, tstruct, printk)
8285
8386 #undef FTRACE_ENTRY_REG
84−#define FTRACE_ENTRY_REG(name, struct_name, id, tstruct, print, \
85− filter, regfn) \
86− FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print), \
87− filter)
87+#define FTRACE_ENTRY_REG(name, struct_name, id, tstruct, print, regfn) \
88+ FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print))
8889
8990 #undef FTRACE_ENTRY_PACKED
90−#define FTRACE_ENTRY_PACKED(name, struct_name, id, tstruct, print, \
91− filter) \
92− FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print), \
93− filter) __packed
91+#define FTRACE_ENTRY_PACKED(name, struct_name, id, tstruct, print) \
92+ FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print)) __packed
9493
9594 #include "trace_entries.h"
9695
@@ -1917,17 +1916,15 @@ extern void tracing_log_err(struct trace_array *tr, · 1820 unmodified lines
19171916 #define internal_trace_puts(str) __trace_puts(_THIS_IP_, str, strlen(str))
19181917
19191918 #undef FTRACE_ENTRY
1920−#define FTRACE_ENTRY(call, struct_name, id, tstruct, print, filter) \
1919+#define FTRACE_ENTRY(call, struct_name, id, tstruct, print) \
19211920 extern struct trace_event_call \
19221921 __aligned(4) event_##call;
19231922 #undef FTRACE_ENTRY_DUP
1924−#define FTRACE_ENTRY_DUP(call, struct_name, id, tstruct, print, filter) \
1925− FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print), \
1926− filter)
1923+#define FTRACE_ENTRY_DUP(call, struct_name, id, tstruct, print) \
1924+ FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print))
19271925 #undef FTRACE_ENTRY_PACKED
1928−#define FTRACE_ENTRY_PACKED(call, struct_name, id, tstruct, print, filter) \
1929− FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print), \
1930− filter)
1926+#define FTRACE_ENTRY_PACKED(call, struct_name, id, tstruct, print) \
1927+ FTRACE_ENTRY(call, struct_name, id, PARAMS(tstruct), PARAMS(print))
19311928
19321929 #include "trace_entries.h"
19331930
kernel/trace/trace_entries.h+18−48
@@ -61,15 +61,13 @@ FTRACE_ENTRY_REG(function, ftrace_entry, · 60 unmodified lines
6161 TRACE_FN,
6262
6363 F_STRUCT(
64− __field( unsigned long, ip )
65− __field( unsigned long, parent_ip )
64+ __field_fn( unsigned long, ip )
65+ __field_fn( unsigned long, parent_ip )
6666 ),
6767
6868 F_printk(" %ps <-- %ps",
6969 (void *)__entry->ip, (void *)__entry->parent_ip),
7070
71− FILTER_TRACE_FN,
72−
7371 perf_ftrace_event_register
7472 );
7573
@@ -84,9 +82,7 @@ FTRACE_ENTRY_PACKED(funcgraph_entry, ftrace_graph_ent_entry, · 8 unmodified lines
8482 __field_desc( int, graph_ent, depth )
8583 ),
8684
87− F_printk("--> %ps (%d)", (void *)__entry->func, __entry->depth),
88−
89− FILTER_OTHER
85+ F_printk("--> %ps (%d)", (void *)__entry->func, __entry->depth)
9086 );
9187
9288 /* Function return entry */
@@ -97,18 +93,16 @@ FTRACE_ENTRY_PACKED(funcgraph_exit, ftrace_graph_ret_entry, · 4 unmodified lines
9793 F_STRUCT(
9894 __field_struct( struct ftrace_graph_ret, ret )
9995 __field_desc( unsigned long, ret, func )
96+ __field_desc( unsigned long, ret, overrun )
10097 __field_desc( unsigned long long, ret, calltime)
10198 __field_desc( unsigned long long, ret, rettime )
102− __field_desc( unsigned long, ret, overrun )
10399 __field_desc( int, ret, depth )
104100 ),
105101
106102 F_printk("<-- %ps (%d) (start: %llx end: %llx) over: %d",
107103 (void *)__entry->func, __entry->depth,
108104 __entry->calltime, __entry->rettime,
109− __entry->depth),
110−
111− FILTER_OTHER
105+ __entry->depth)
112106 );
113107
114108 /*
@@ -137,9 +131,7 @@ FTRACE_ENTRY(context_switch, ctx_switch_entry, · 22 unmodified lines
137131 F_printk("%u:%u:%u ==> %u:%u:%u [%03u]",
138132 __entry->prev_pid, __entry->prev_prio, __entry->prev_state,
139133 __entry->next_pid, __entry->next_prio, __entry->next_state,
140− __entry->next_cpu),
141−
142− FILTER_OTHER
134+ __entry->next_cpu)
143135 );
144136
145137 /*
@@ -157,9 +149,7 @@ FTRACE_ENTRY_DUP(wakeup, ctx_switch_entry, · 11 unmodified lines
157149 F_printk("%u:%u:%u ==+ %u:%u:%u [%03u]",
158150 __entry->prev_pid, __entry->prev_prio, __entry->prev_state,
159151 __entry->next_pid, __entry->next_prio, __entry->next_state,
160− __entry->next_cpu),
161−
162− FILTER_OTHER
152+ __entry->next_cpu)
163153 );
164154
165155 /*
@@ -183,9 +173,7 @@ FTRACE_ENTRY(kernel_stack, stack_entry, · 17 unmodified lines
183173 (void *)__entry->caller[0], (void *)__entry->caller[1],
184174 (void *)__entry->caller[2], (void *)__entry->caller[3],
185175 (void *)__entry->caller[4], (void *)__entry->caller[5],
186− (void *)__entry->caller[6], (void *)__entry->caller[7]),
187−
188− FILTER_OTHER
176+ (void *)__entry->caller[6], (void *)__entry->caller[7])
189177 );
190178
191179 FTRACE_ENTRY(user_stack, userstack_entry,
@@ -203,9 +191,7 @@ FTRACE_ENTRY(user_stack, userstack_entry, · 11 unmodified lines
203191 (void *)__entry->caller[0], (void *)__entry->caller[1],
204192 (void *)__entry->caller[2], (void *)__entry->caller[3],
205193 (void *)__entry->caller[4], (void *)__entry->caller[5],
206− (void *)__entry->caller[6], (void *)__entry->caller[7]),
207−
208− FILTER_OTHER
194+ (void *)__entry->caller[6], (void *)__entry->caller[7])
209195 );
210196
211197 /*
@@ -222,9 +208,7 @@ FTRACE_ENTRY(bprint, bprint_entry, · 10 unmodified lines
222208 ),
223209
224210 F_printk("%ps: %s",
225− (void *)__entry->ip, __entry->fmt),
226−
227− FILTER_OTHER
211+ (void *)__entry->ip, __entry->fmt)
228212 );
229213
230214 FTRACE_ENTRY_REG(print, print_entry,
@@ -239,8 +223,6 @@ FTRACE_ENTRY_REG(print, print_entry, · 8 unmodified lines
239223 F_printk("%ps: %s",
240224 (void *)__entry->ip, __entry->buf),
241225
242− FILTER_OTHER,
243−
244226 ftrace_event_register
245227 );
246228
@@ -254,9 +236,7 @@ FTRACE_ENTRY(raw_data, raw_data_entry, · 7 unmodified lines
254236 ),
255237
256238 F_printk("id:%04x %08x",
257− __entry->id, (int)__entry->buf[0]),
258−
259− FILTER_OTHER
239+ __entry->id, (int)__entry->buf[0])
260240 );
261241
262242 FTRACE_ENTRY(bputs, bputs_entry,
@@ -269,9 +249,7 @@ FTRACE_ENTRY(bputs, bputs_entry, · 6 unmodified lines
269249 ),
270250
271251 F_printk("%ps: %s",
272− (void *)__entry->ip, __entry->str),
273−
274− FILTER_OTHER
252+ (void *)__entry->ip, __entry->str)
275253 );
276254
277255 FTRACE_ENTRY(mmiotrace_rw, trace_mmiotrace_rw,
@@ -283,16 +261,14 @@ FTRACE_ENTRY(mmiotrace_rw, trace_mmiotrace_rw, · 5 unmodified lines
283261 __field_desc( resource_size_t, rw, phys )
284262 __field_desc( unsigned long, rw, value )
285263 __field_desc( unsigned long, rw, pc )
286− __field_desc( int, rw, map_id )
264+ __field_desc( int, rw, map_id )
287265 __field_desc( unsigned char, rw, opcode )
288266 __field_desc( unsigned char, rw, width )
289267 ),
290268
291269 F_printk("%lx %lx %lx %d %x %x",
292270 (unsigned long)__entry->phys, __entry->value, __entry->pc,
293− __entry->map_id, __entry->opcode, __entry->width),
294−
295− FILTER_OTHER
271+ __entry->map_id, __entry->opcode, __entry->width)
296272 );
297273
298274 FTRACE_ENTRY(mmiotrace_map, trace_mmiotrace_map,
@@ -304,15 +280,13 @@ FTRACE_ENTRY(mmiotrace_map, trace_mmiotrace_map, · 5 unmodified lines
304280 __field_desc( resource_size_t, map, phys )
305281 __field_desc( unsigned long, map, virt )
306282 __field_desc( unsigned long, map, len )
307− __field_desc( int, map, map_id )
283+ __field_desc( int, map, map_id )
308284 __field_desc( unsigned char, map, opcode )
309285 ),
310286
311287 F_printk("%lx %lx %lx %d %x",
312288 (unsigned long)__entry->phys, __entry->virt, __entry->len,
313− __entry->map_id, __entry->opcode),
314−
315− FILTER_OTHER
289+ __entry->map_id, __entry->opcode)
316290 );
317291
318292
@@ -334,9 +308,7 @@ FTRACE_ENTRY(branch, trace_branch, · 15 unmodified lines
334308 F_printk("%u:%s:%s (%u)%s",
335309 __entry->line,
336310 __entry->func, __entry->file, __entry->correct,
337− __entry->constant ? " CONSTANT" : ""),
338−
339− FILTER_OTHER
311+ __entry->constant ? " CONSTANT" : "")
340312 );
341313
342314
@@ -362,7 +334,5 @@ FTRACE_ENTRY(hwlat, hwlat_entry, · 19 unmodified lines
362334 __entry->duration,
363335 __entry->outer_duration,
364336 __entry->nmi_total_ts,
365− __entry->nmi_count),
366−
367− FILTER_OTHER
337+ __entry->nmi_count)
368338 );
kernel/trace/trace_events.c+19−1
@@ -24,6 +24,7 @@ · 23 unmodified lines
2424 #include <linux/delay.h>
2525
2626 #include <trace/events/sched.h>
27+#include <trace/syscall.h>
2728
2829 #include <asm/setup.h>
2930
@@ -2017,7 +2018,24 @@ event_create_dir(struct dentry *parent, struct trace_event_file *file) · 1987 unmodified lines
20172018 */
20182019 head = trace_get_fields(call);
20192020 if (list_empty(head)) {
2020− ret = call->class->define_fields(call);
2021+ struct trace_event_fields *field = call->class->fields_array;
2022+ unsigned int offset = sizeof(struct trace_entry);
2023+
2024+ for (; field->type; field++) {
2025+ if (field->type == TRACE_FUNCTION_TYPE) {
2026+ ret = field->define_fields(call);
2027+ break;
2028+ }
2029+
2030+ offset = ALIGN(offset, field->align);
2031+ ret = trace_define_field(call, field->type, field->name,
2032+ offset, field->size,
2033+ field->is_signed, field->filter_type);
2034+ if (ret)
2035+ break;
2036+
2037+ offset += field->size;
2038+ }
20212039 if (ret < 0) {
20222040 pr_warn("Could not initialize trace point events/%s\n",
20232041 name);
kernel/trace/trace_events_hist.c+7−1
@@ -1155,6 +1155,12 @@ static struct synth_event *find_synth_event(const char *name) · 1154 unmodified lines
11551155 return NULL;
11561156 }
11571157
1158+static struct trace_event_fields synth_event_fields_array[] = {
1159+ { .type = TRACE_FUNCTION_TYPE,
1160+ .define_fields = synth_event_define_fields },
1161+ {}
1162+};
1163+
11581164 static int register_synth_event(struct synth_event *event)
11591165 {
11601166 struct trace_event_call *call = &event->call;
@@ -1176,7 +1182,7 @@ static int register_synth_event(struct synth_event *event) · 15 unmodified lines
11761182
11771183 INIT_LIST_HEAD(&call->class->fields);
11781184 call->event.funcs = &synth_event_funcs;
1179− call->class->define_fields = synth_event_define_fields;
1185+ call->class->fields_array = synth_event_fields_array;
11801186
11811187 ret = register_trace_event(&call->event);
11821188 if (!ret) {
kernel/trace/trace_export.c+39−67
@@ -29,10 +29,8 @@ static int ftrace_event_register(struct trace_event_call *call, · 28 unmodified lines
2929 * function and thus become accesible via perf.
3030 */
3131 #undef FTRACE_ENTRY_REG
32−#define FTRACE_ENTRY_REG(name, struct_name, id, tstruct, print, \
33− filter, regfn) \
34− FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print), \
35− filter)
32+#define FTRACE_ENTRY_REG(name, struct_name, id, tstruct, print, regfn) \
33+ FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print))
3634
3735 /* not needed for this file */
3836 #undef __field_struct
@@ -41,6 +39,9 @@ static int ftrace_event_register(struct trace_event_call *call, · 2 unmodified lines
4139 #undef __field
4240 #define __field(type, item) type item;
4341
42+#undef __field_fn
43+#define __field_fn(type, item) type item;
44+
4445 #undef __field_desc
4546 #define __field_desc(type, container, item) type item;
4647
@@ -60,7 +61,7 @@ static int ftrace_event_register(struct trace_event_call *call, · 13 unmodified lines
6061 #define F_printk(fmt, args...) fmt, args
6162
6263 #undef FTRACE_ENTRY
63−#define FTRACE_ENTRY(name, struct_name, id, tstruct, print, filter) \
64+#define FTRACE_ENTRY(name, struct_name, id, tstruct, print) \
6465 struct ____ftrace_##name { \
6566 tstruct \
6667 }; \
@@ -73,76 +74,46 @@ static void __always_unused ____ftrace_check_##name(void) \ · 6 unmodified lines
7374 }
7475
7576 #undef FTRACE_ENTRY_DUP
76−#define FTRACE_ENTRY_DUP(name, struct_name, id, tstruct, print, filter) \
77− FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print), \
78− filter)
77+#define FTRACE_ENTRY_DUP(name, struct_name, id, tstruct, print) \
78+ FTRACE_ENTRY(name, struct_name, id, PARAMS(tstruct), PARAMS(print))
7979
8080 #include "trace_entries.h"
8181
82+#undef __field_ext
83+#define __field_ext(_type, _item, _filter_type) { \
84+ .type = #_type, .name = #_item, \
85+ .size = sizeof(_type), .align = __alignof__(_type), \
86+ is_signed_type(_type), .filter_type = _filter_type },
87+
8288 #undef __field
83−#define __field(type, item) \
84− ret = trace_define_field(event_call, #type, #item, \
85− offsetof(typeof(field), item), \
86− sizeof(field.item), \
87− is_signed_type(type), filter_type); \
88− if (ret) \
89− return ret;
89+#define __field(_type, _item) __field_ext(_type, _item, FILTER_OTHER)
90+
91+#undef __field_fn
92+#define __field_fn(_type, _item) __field_ext(_type, _item, FILTER_TRACE_FN)
9093
9194 #undef __field_desc
92−#define __field_desc(type, container, item) \
93− ret = trace_define_field(event_call, #type, #item, \
94− offsetof(typeof(field), \
95− container.item), \
96− sizeof(field.container.item), \
97− is_signed_type(type), filter_type); \
98− if (ret) \
99− return ret;
95+#define __field_desc(_type, _container, _item) __field_ext(_type, _item, FILTER_OTHER)
10096
10197 #undef __array
102−#define __array(type, item, len) \
103− do { \
104− char *type_str = #type"["__stringify(len)"]"; \
105− BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \
106− ret = trace_define_field(event_call, type_str, #item, \
107− offsetof(typeof(field), item), \
108− sizeof(field.item), \
109− is_signed_type(type), filter_type); \
110− if (ret) \
111− return ret; \
112− } while (0);
98+#define __array(_type, _item, _len) { \
99+ .type = #_type"["__stringify(_len)"]", .name = #_item, \
100+ .size = sizeof(_type[_len]), .align = __alignof__(_type), \
101+ is_signed_type(_type), .filter_type = FILTER_OTHER },
113102
114103 #undef __array_desc
115−#define __array_desc(type, container, item, len) \
116− BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \
117− ret = trace_define_field(event_call, #type "[" #len "]", #item, \
118− offsetof(typeof(field), \
119− container.item), \
120− sizeof(field.container.item), \
121− is_signed_type(type), filter_type); \
122− if (ret) \
123− return ret;
104+#define __array_desc(_type, _container, _item, _len) __array(_type, _item, _len)
124105
125106 #undef __dynamic_array
126−#define __dynamic_array(type, item) \
127− ret = trace_define_field(event_call, #type "[]", #item, \
128− offsetof(typeof(field), item), \
129− 0, is_signed_type(type), filter_type);\
130− if (ret) \
131− return ret;
107+#define __dynamic_array(_type, _item) { \
108+ .type = #_type "[]", .name = #_item, \
109+ .size = 0, .align = __alignof__(_type), \
110+ is_signed_type(_type), .filter_type = FILTER_OTHER },
132111
133112 #undef FTRACE_ENTRY
134−#define FTRACE_ENTRY(name, struct_name, id, tstruct, print, filter) \
135−static int __init \
136−ftrace_define_fields_##name(struct trace_event_call *event_call) \
137−{ \
138− struct struct_name field; \
139− int ret; \
140− int filter_type = filter; \
141− \
142− tstruct; \
143− \
144− return ret; \
145−}
113+#define FTRACE_ENTRY(name, struct_name, id, tstruct, print) \
114+static struct trace_event_fields ftrace_event_fields_##name[] = { \
115+ tstruct \
116+ {} };
146117
147118 #include "trace_entries.h"
148119
@@ -152,6 +123,9 @@ ftrace_define_fields_##name(struct trace_event_call *event_call) \ · 3 unmodified lines
152123 #undef __field
153124 #define __field(type, item)
154125
126+#undef __field_fn
127+#define __field_fn(type, item)
128+
155129 #undef __field_desc
156130 #define __field_desc(type, container, item)
157131
@@ -168,12 +142,10 @@ ftrace_define_fields_##name(struct trace_event_call *event_call) \ · 10 unmodified lines
168142 #define F_printk(fmt, args...) __stringify(fmt) ", " __stringify(args)
169143
170144 #undef FTRACE_ENTRY_REG
171−#define FTRACE_ENTRY_REG(call, struct_name, etype, tstruct, print, filter,\
172− regfn) \
173− \
145+#define FTRACE_ENTRY_REG(call, struct_name, etype, tstruct, print, regfn) \
174146 static struct trace_event_class __refdata event_class_ftrace_##call = { \
175147 .system = __stringify(TRACE_SYSTEM), \
176− .define_fields = ftrace_define_fields_##call, \
148+ .fields_array = ftrace_event_fields_##call, \
177149 .fields = LIST_HEAD_INIT(event_class_ftrace_##call.fields),\
178150 .reg = regfn, \
179151 }; \
@@ -191,9 +163,9 @@ static struct trace_event_call __used \ · 11 unmodified lines
191163 __attribute__((section("_ftrace_events"))) *__event_##call = &event_##call;
192164
193165 #undef FTRACE_ENTRY
194−#define FTRACE_ENTRY(call, struct_name, etype, tstruct, print, filter) \
166+#define FTRACE_ENTRY(call, struct_name, etype, tstruct, print) \
195167 FTRACE_ENTRY_REG(call, struct_name, etype, \
196− PARAMS(tstruct), PARAMS(print), filter, NULL)
168+ PARAMS(tstruct), PARAMS(print), NULL)
197169
198170 bool ftrace_event_is_function(struct trace_event_call *call)
199171 {
kernel/trace/trace_kprobe.c+14−2
@@ -1555,16 +1555,28 @@ static struct trace_event_functions kprobe_funcs = { · 1554 unmodified lines
15551555 .trace = print_kprobe_event
15561556 };
15571557
1558+static struct trace_event_fields kretprobe_fields_array[] = {
1559+ { .type = TRACE_FUNCTION_TYPE,
1560+ .define_fields = kretprobe_event_define_fields },
1561+ {}
1562+};
1563+
1564+static struct trace_event_fields kprobe_fields_array[] = {
1565+ { .type = TRACE_FUNCTION_TYPE,
1566+ .define_fields = kprobe_event_define_fields },
1567+ {}
1568+};
1569+
15581570 static inline void init_trace_event_call(struct trace_kprobe *tk)
15591571 {
15601572 struct trace_event_call *call = trace_probe_event_call(&tk->tp);
15611573
15621574 if (trace_kprobe_is_return(tk)) {
15631575 call->event.funcs = &kretprobe_funcs;
1564− call->class->define_fields = kretprobe_event_define_fields;
1576+ call->class->fields_array = kretprobe_fields_array;
15651577 } else {
15661578 call->event.funcs = &kprobe_funcs;
1567− call->class->define_fields = kprobe_event_define_fields;
1579+ call->class->fields_array = kprobe_fields_array;
15681580 }
15691581
15701582 call->flags = TRACE_EVENT_FL_KPROBE;
kernel/trace/trace_syscalls.c+21−30
@@ -203,11 +203,10 @@ print_syscall_exit(struct trace_iterator *iter, int flags, · 202 unmodified lines
203203
204204 extern char *__bad_type_size(void);
205205
206−#define SYSCALL_FIELD(type, field, name) \
207− sizeof(type) != sizeof(trace.field) ? \
208− __bad_type_size() : \
209− #type, #name, offsetof(typeof(trace), field), \
210− sizeof(trace.field), is_signed_type(type)
206+#define SYSCALL_FIELD(_type, _name) { \
207+ .type = #_type, .name = #_name, \
208+ .size = sizeof(_type), .align = __alignof__(_type), \
209+ .is_signed = is_signed_type(_type), .filter_type = FILTER_OTHER }
211210
212211 static int __init
213212 __set_enter_print_fmt(struct syscall_metadata *entry, char *buf, int len)
@@ -274,42 +273,23 @@ static int __init syscall_enter_define_fields(struct trace_event_call *call) · 60 unmodified lines
274273 {
275274 struct syscall_trace_enter trace;
276275 struct syscall_metadata *meta = call->data;
277− int ret;
278− int i;
279276 int offset = offsetof(typeof(trace), args);
280−
281− ret = trace_define_field(call, SYSCALL_FIELD(int, nr, __syscall_nr),
282− FILTER_OTHER);
283− if (ret)
284− return ret;
277+ int ret = 0;
278+ int i;
285279
286280 for (i = 0; i < meta->nb_args; i++) {
287281 ret = trace_define_field(call, meta->types[i],
288282 meta->args[i], offset,
289283 sizeof(unsigned long), 0,
290284 FILTER_OTHER);
285+ if (ret)
286+ break;
291287 offset += sizeof(unsigned long);
292288 }
293289
294290 return ret;
295291 }
296292
297−static int __init syscall_exit_define_fields(struct trace_event_call *call)
298−{
299− struct syscall_trace_exit trace;
300− int ret;
301−
302− ret = trace_define_field(call, SYSCALL_FIELD(int, nr, __syscall_nr),
303− FILTER_OTHER);
304− if (ret)
305− return ret;
306−
307− ret = trace_define_field(call, SYSCALL_FIELD(long, ret, ret),
308− FILTER_OTHER);
309−
310− return ret;
311−}
312−
313293 static void ftrace_syscall_enter(void *data, struct pt_regs *regs, long id)
314294 {
315295 struct trace_array *tr = data;
@@ -507,6 +487,13 @@ static int __init init_syscall_trace(struct trace_event_call *call) · 191 unmodified lines
507487 return id;
508488 }
509489
490+static struct trace_event_fields __refdata syscall_enter_fields_array[] = {
491+ SYSCALL_FIELD(int, __syscall_nr),
492+ { .type = TRACE_FUNCTION_TYPE,
493+ .define_fields = syscall_enter_define_fields },
494+ {}
495+};
496+
510497 struct trace_event_functions enter_syscall_print_funcs = {
511498 .trace = print_syscall_enter,
512499 };
@@ -518,7 +505,7 @@ struct trace_event_functions exit_syscall_print_funcs = { · 5 unmodified lines
518505 struct trace_event_class __refdata event_class_syscall_enter = {
519506 .system = "syscalls",
520507 .reg = syscall_enter_register,
521− .define_fields = syscall_enter_define_fields,
508+ .fields_array = syscall_enter_fields_array,
522509 .get_fields = syscall_get_enter_fields,
523510 .raw_init = init_syscall_trace,
524511 };
@@ -526,7 +513,11 @@ struct trace_event_class __refdata event_class_syscall_enter = { · 1 unmodified line
526513 struct trace_event_class __refdata event_class_syscall_exit = {
527514 .system = "syscalls",
528515 .reg = syscall_exit_register,
529− .define_fields = syscall_exit_define_fields,
516+ .fields_array = (struct trace_event_fields[]){
517+ SYSCALL_FIELD(int, __syscall_nr),
518+ SYSCALL_FIELD(long, ret),
519+ {}
520+ },
530521 .fields = LIST_HEAD_INIT(event_class_syscall_exit.fields),
531522 .raw_init = init_syscall_trace,
532523 };
kernel/trace/trace_uprobe.c+7−2
@@ -1528,12 +1528,17 @@ static struct trace_event_functions uprobe_funcs = { · 1527 unmodified lines
15281528 .trace = print_uprobe_event
15291529 };
15301530
1531+static struct trace_event_fields uprobe_fields_array[] = {
1532+ { .type = TRACE_FUNCTION_TYPE,
1533+ .define_fields = uprobe_event_define_fields },
1534+ {}
1535+};
1536+
15311537 static inline void init_trace_event_call(struct trace_uprobe *tu)
15321538 {
15331539 struct trace_event_call *call = trace_probe_event_call(&tu->tp);
1534−
15351540 call->event.funcs = &uprobe_funcs;
1536− call->class->define_fields = uprobe_event_define_fields;
1541+ call->class->fields_array = uprobe_fields_array;
15371542
15381543 call->flags = TRACE_EVENT_FL_UPROBE | TRACE_EVENT_FL_CAP_ANY;
15391544 call->class->reg = trace_uprobe_register;
net/mac80211/trace.h+14−14
@@ -408,20 +408,20 @@ TRACE_EVENT(drv_bss_info_changed, · 407 unmodified lines
408408 __field(u32, basic_rates)
409409 __array(int, mcast_rate, NUM_NL80211_BANDS)
410410 __field(u16, ht_operation_mode)
411− __field(s32, cqm_rssi_thold);
412− __field(s32, cqm_rssi_hyst);
413− __field(u32, channel_width);
414− __field(u32, channel_cfreq1);
411+ __field(s32, cqm_rssi_thold)
412+ __field(s32, cqm_rssi_hyst)
413+ __field(u32, channel_width)
414+ __field(u32, channel_cfreq1)
415415 __dynamic_array(u32, arp_addr_list,
416416 info->arp_addr_cnt > IEEE80211_BSS_ARP_ADDR_LIST_LEN ?
417417 IEEE80211_BSS_ARP_ADDR_LIST_LEN :
418− info->arp_addr_cnt);
419− __field(int, arp_addr_cnt);
420− __field(bool, qos);
421− __field(bool, idle);
422− __field(bool, ps);
423− __dynamic_array(u8, ssid, info->ssid_len);
424− __field(bool, hidden_ssid);
418+ info->arp_addr_cnt)
419+ __field(int, arp_addr_cnt)
420+ __field(bool, qos)
421+ __field(bool, idle)
422+ __field(bool, ps)
423+ __dynamic_array(u8, ssid, info->ssid_len)
424+ __field(bool, hidden_ssid)
425425 __field(int, txpower)
426426 __field(u8, p2p_oppps_ctwindow)
427427 ),
@@ -1672,8 +1672,8 @@ TRACE_EVENT(drv_start_ap, · 1244 unmodified lines
16721672 VIF_ENTRY
16731673 __field(u8, dtimper)
16741674 __field(u16, bcnint)
1675− __dynamic_array(u8, ssid, info->ssid_len);
1676− __field(bool, hidden_ssid);
1675+ __dynamic_array(u8, ssid, info->ssid_len)
1676+ __field(bool, hidden_ssid)
16771677 ),
16781678
16791679 TP_fast_assign(
@@ -1739,7 +1739,7 @@ TRACE_EVENT(drv_join_ibss, · 59 unmodified lines
17391739 VIF_ENTRY
17401740 __field(u8, dtimper)
17411741 __field(u16, bcnint)
1742− __dynamic_array(u8, ssid, info->ssid_len);
1742+ __dynamic_array(u8, ssid, info->ssid_len)
17431743 ),
17441744
17451745 TP_fast_assign(
net/wireless/trace.h+3−3
@@ -2014,7 +2014,7 @@ TRACE_EVENT(rdev_start_nan, · 2013 unmodified lines
20142014 WIPHY_ENTRY
20152015 WDEV_ENTRY
20162016 __field(u8, master_pref)
2017− __field(u8, bands);
2017+ __field(u8, bands)
20182018 ),
20192019 TP_fast_assign(
20202020 WIPHY_ASSIGN;
@@ -2036,8 +2036,8 @@ TRACE_EVENT(rdev_nan_change_conf, · 15 unmodified lines
20362036 WIPHY_ENTRY
20372037 WDEV_ENTRY
20382038 __field(u8, master_pref)
2039− __field(u8, bands);
2040− __field(u32, changes);
2039+ __field(u8, bands)
2040+ __field(u32, changes)
20412041 ),
20422042 TP_fast_assign(
20432043 WIPHY_ASSIGN;
tools/build/feature/Makefile+1−1
@@ -197,7 +197,7 @@ $(OUTPUT)test-libcrypto.bin: · 196 unmodified lines
197197 $(BUILD) -lcrypto
198198
199199 $(OUTPUT)test-gtk2.bin:
200− $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
200+ $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) -Wno-deprecated-declarations
201201
202202 $(OUTPUT)test-gtk2-infobar.bin:
203203 $(BUILD) $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null)
tools/build/feature/test-clang.cpp+6−0
@@ -1,9 +1,15 @@
11 // SPDX-License-Identifier: GPL-2.0
2+#include "clang/Basic/Version.h"
3+#if CLANG_VERSION_MAJOR < 8
24 #include "clang/Basic/VirtualFileSystem.h"
5+#endif
36 #include "clang/Driver/Driver.h"
47 #include "clang/Frontend/TextDiagnosticPrinter.h"
58 #include "llvm/ADT/IntrusiveRefCntPtr.h"
69 #include "llvm/Support/ManagedStatic.h"
10+#if CLANG_VERSION_MAJOR >= 8
11+#include "llvm/Support/VirtualFileSystem.h"
12+#endif
713 #include "llvm/Support/raw_ostream.h"
814
915 using namespace clang;
tools/include/linux/bitmap.h+30−0
@@ -15,6 +15,8 @@ void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, · 14 unmodified lines
1515 const unsigned long *bitmap2, int bits);
1616 int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
1717 const unsigned long *bitmap2, unsigned int bits);
18+int __bitmap_equal(const unsigned long *bitmap1,
19+ const unsigned long *bitmap2, unsigned int bits);
1820 void bitmap_clear(unsigned long *map, unsigned int start, int len);
1921
2022 #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
@@ -123,6 +125,15 @@ static inline unsigned long *bitmap_alloc(int nbits) · 102 unmodified lines
123125 return calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long));
124126 }
125127
128+/*
129+ * bitmap_free - Free bitmap
130+ * @bitmap: pointer to bitmap
131+ */
132+static inline void bitmap_free(unsigned long *bitmap)
133+{
134+ free(bitmap);
135+}
136+
126137 /*
127138 * bitmap_scnprintf - print bitmap list into buffer
128139 * @bitmap: bitmap
@@ -148,4 +159,23 @@ static inline int bitmap_and(unsigned long *dst, const unsigned long *src1, · 19 unmodified lines
148159 return __bitmap_and(dst, src1, src2, nbits);
149160 }
150161
162+#ifdef __LITTLE_ENDIAN
163+#define BITMAP_MEM_ALIGNMENT 8
164+#else
165+#define BITMAP_MEM_ALIGNMENT (8 * sizeof(unsigned long))
166+#endif
167+#define BITMAP_MEM_MASK (BITMAP_MEM_ALIGNMENT - 1)
168+#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)
169+
170+static inline int bitmap_equal(const unsigned long *src1,
171+ const unsigned long *src2, unsigned int nbits)
172+{
173+ if (small_const_nbits(nbits))
174+ return !((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
175+ if (__builtin_constant_p(nbits & BITMAP_MEM_MASK) &&
176+ IS_ALIGNED(nbits, BITMAP_MEM_ALIGNMENT))
177+ return !memcmp(src1, src2, nbits / 8);
178+ return __bitmap_equal(src1, src2, nbits);
179+}
180+
151181 #endif /* _PERF_BITOPS_H */
tools/include/linux/string.h+8−0
@@ -17,7 +17,15 @@ int strtobool(const char *s, bool *res); · 16 unmodified lines
1717 * However uClibc headers also define __GLIBC__ hence the hack below
1818 */
1919 #if defined(__GLIBC__) && !defined(__UCLIBC__)
20+// pragma diagnostic was introduced in gcc 4.6
21+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
22+#pragma GCC diagnostic push
23+#pragma GCC diagnostic ignored "-Wredundant-decls"
24+#endif
2025 extern size_t strlcpy(char *dest, const char *src, size_t size);
26+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
27+#pragma GCC diagnostic pop
28+#endif
2129 #endif
2230
2331 char *str_error_r(int errnum, char *buf, size_t buflen);
tools/lib/api/fs/fs.c+3−1
@@ -210,6 +210,7 @@ static bool fs__env_override(struct fs *fs) · 209 unmodified lines
210210 size_t name_len = strlen(fs->name);
211211 /* name + "_PATH" + '\0' */
212212 char upper_name[name_len + 5 + 1];
213+
213214 memcpy(upper_name, fs->name, name_len);
214215 mem_toupper(upper_name, name_len);
215216 strcpy(&upper_name[name_len], "_PATH");
@@ -219,7 +220,8 @@ static bool fs__env_override(struct fs *fs) · 3 unmodified lines
219220 return false;
220221
221222 fs->found = true;
222− strncpy(fs->path, override_path, sizeof(fs->path));
223+ strncpy(fs->path, override_path, sizeof(fs->path) - 1);
224+ fs->path[sizeof(fs->path) - 1] = '\0';
223225 return true;
224226 }
225227
tools/lib/bitmap.c+15−0
@@ -71,3 +71,18 @@ int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1, · 70 unmodified lines
7171 BITMAP_LAST_WORD_MASK(bits));
7272 return result != 0;
7373 }
74+
75+int __bitmap_equal(const unsigned long *bitmap1,
76+ const unsigned long *bitmap2, unsigned int bits)
77+{
78+ unsigned int k, lim = bits/BITS_PER_LONG;
79+ for (k = 0; k < lim; ++k)
80+ if (bitmap1[k] != bitmap2[k])
81+ return 0;
82+
83+ if (bits % BITS_PER_LONG)
84+ if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
85+ return 0;
86+
87+ return 1;
88+}
tools/lib/perf/Buildrenamed from tools/perf/lib/Build+0−0

File renamed without changes.

tools/lib/perf/Documentation/Makefile+156−0
@@ -0,0 +1,156 @@
1+# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2+# Most of this file is copied from tools/perf/Documentation/Makefile
3+
4+include ../../../scripts/Makefile.include
5+include ../../../scripts/utilities.mak
6+
7+MAN3_TXT = libperf.txt
8+MAN7_TXT = libperf-counting.txt libperf-sampling.txt
9+MAN_EX = examples/*.c
10+
11+MAN_TXT = $(MAN3_TXT) $(MAN7_TXT)
12+
13+_MAN_XML = $(patsubst %.txt,%.xml,$(MAN_TXT))
14+_MAN_HTML = $(patsubst %.txt,%.html,$(MAN_TXT))
15+_MAN_3 = $(patsubst %.txt,%.3,$(MAN3_TXT))
16+_MAN_7 = $(patsubst %.txt,%.7,$(MAN7_TXT))
17+
18+MAN_XML = $(addprefix $(OUTPUT),$(_MAN_XML))
19+MAN_HTML = $(addprefix $(OUTPUT),$(_MAN_HTML))
20+MAN_3 = $(addprefix $(OUTPUT),$(_MAN_3))
21+MAN_7 = $(addprefix $(OUTPUT),$(_MAN_7))
22+MAN_X = $(MAN_3) $(MAN_7)
23+
24+# Make the path relative to DESTDIR, not prefix
25+ifndef DESTDIR
26+ prefix ?=$(HOME)
27+endif
28+
29+mandir ?= $(prefix)/share/man
30+man3dir = $(mandir)/man3
31+man7dir = $(mandir)/man7
32+
33+docdir ?= $(prefix)/share/doc/libperf
34+htmldir = $(docdir)/html
35+exdir = $(docdir)/examples
36+
37+ASCIIDOC = asciidoc
38+ASCIIDOC_EXTRA = --unsafe -f asciidoc.conf
39+ASCIIDOC_HTML = xhtml11
40+MANPAGE_XSL = manpage-normal.xsl
41+XMLTO_EXTRA =
42+XMLTO =xmlto
43+
44+INSTALL ?= install
45+RM ?= rm -f
46+
47+# For asciidoc ...
48+# -7.1.2, no extra settings are needed.
49+# 8.0-, set ASCIIDOC8.
50+#
51+
52+# For docbook-xsl ...
53+# -1.68.1, set ASCIIDOC_NO_ROFF? (based on changelog from 1.73.0)
54+# 1.69.0, no extra settings are needed?
55+# 1.69.1-1.71.0, set DOCBOOK_SUPPRESS_SP?
56+# 1.71.1, no extra settings are needed?
57+# 1.72.0, set DOCBOOK_XSL_172.
58+# 1.73.0-, set ASCIIDOC_NO_ROFF
59+
60+# If you had been using DOCBOOK_XSL_172 in an attempt to get rid
61+# of 'the ".ft C" problem' in your generated manpages, and you
62+# instead ended up with weird characters around callouts, try
63+# using ASCIIDOC_NO_ROFF instead (it works fine with ASCIIDOC8).
64+
65+ifdef ASCIIDOC8
66+ ASCIIDOC_EXTRA += -a asciidoc7compatible
67+endif
68+ifdef DOCBOOK_XSL_172
69+ ASCIIDOC_EXTRA += -a libperf-asciidoc-no-roff
70+ MANPAGE_XSL = manpage-1.72.xsl
71+else
72+ ifdef ASCIIDOC_NO_ROFF
73+ # docbook-xsl after 1.72 needs the regular XSL, but will not
74+ # pass-thru raw roff codes from asciidoc.conf, so turn them off.
75+ ASCIIDOC_EXTRA += -a libperf-asciidoc-no-roff
76+ endif
77+endif
78+ifdef MAN_BOLD_LITERAL
79+ XMLTO_EXTRA += -m manpage-bold-literal.xsl
80+endif
81+ifdef DOCBOOK_SUPPRESS_SP
82+ XMLTO_EXTRA += -m manpage-suppress-sp.xsl
83+endif
84+
85+DESTDIR ?=
86+DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
87+
88+export DESTDIR DESTDIR_SQ
89+
90+# Please note that there is a minor bug in asciidoc.
91+# The version after 6.0.3 _will_ include the patch found here:
92+# http://marc.theaimsgroup.com/?l=libtraceevent&m=111558757202243&w=2
93+#
94+# Until that version is released you may have to apply the patch
95+# yourself - yes, all 6 characters of it!
96+
97+QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
98+QUIET_SUBDIR1 =
99+
100+ifneq ($(findstring $(MAKEFLAGS),w),w)
101+ PRINT_DIR = --no-print-directory
102+else # "make -w"
103+ NO_SUBDIR = :
104+endif
105+
106+ifneq ($(findstring $(MAKEFLAGS),s),s)
107+ ifneq ($(V),1)
108+ QUIET_ASCIIDOC = @echo ' ASCIIDOC '$@;
109+ QUIET_XMLTO = @echo ' XMLTO '$@;
110+ endif
111+endif
112+
113+all: $(MAN_X) $(MAN_HTML)
114+
115+$(MAN_HTML) $(MAN_X): asciidoc.conf
116+
117+install-man: all
118+ $(call QUIET_INSTALL, man) \
119+ $(INSTALL) -d -m 755 $(DESTDIR)$(man3dir); \
120+ $(INSTALL) -m 644 $(MAN_3) $(DESTDIR)$(man3dir); \
121+ $(INSTALL) -d -m 755 $(DESTDIR)$(man7dir); \
122+ $(INSTALL) -m 644 $(MAN_7) $(DESTDIR)$(man7dir);
123+
124+install-html:
125+ $(call QUIET_INSTALL, html) \
126+ $(INSTALL) -d -m 755 $(DESTDIR)$(htmldir); \
127+ $(INSTALL) -m 644 $(MAN_HTML) $(DESTDIR)$(htmldir); \
128+
129+install-examples:
130+ $(call QUIET_INSTALL, examples) \
131+ $(INSTALL) -d -m 755 $(DESTDIR)$(exdir); \
132+ $(INSTALL) -m 644 $(MAN_EX) $(DESTDIR)$(exdir); \
133+
134+CLEAN_FILES = \
135+ $(MAN_XML) $(addsuffix +,$(MAN_XML)) \
136+ $(MAN_HTML) $(addsuffix +,$(MAN_HTML)) \
137+ $(MAN_X)
138+
139+clean:
140+ $(call QUIET_CLEAN, Documentation) $(RM) $(CLEAN_FILES)
141+
142+$(MAN_3): $(OUTPUT)%.3: %.xml
143+ $(QUIET_XMLTO)$(XMLTO) -o $(OUTPUT). -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
144+
145+$(MAN_7): $(OUTPUT)%.7: %.xml
146+ $(QUIET_XMLTO)$(XMLTO) -o $(OUTPUT). -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $<
147+
148+$(MAN_XML): $(OUTPUT)%.xml: %.txt
149+ $(QUIET_ASCIIDOC)$(ASCIIDOC) -b docbook -d manpage \
150+ $(ASCIIDOC_EXTRA) -alibperf_version=$(EVENT_PARSE_VERSION) -o $@+ $< && \
151+ mv $@+ $@
152+
153+$(MAN_HTML): $(OUTPUT)%.html: %.txt
154+ $(QUIET_ASCIIDOC)$(ASCIIDOC) -b $(ASCIIDOC_HTML) -d manpage \
155+ $(ASCIIDOC_EXTRA) -aperf_version=$(EVENT_PARSE_VERSION) -o $@+ $< && \
156+ mv $@+ $@
tools/lib/perf/Documentation/asciidoc.conf+120−0
@@ -0,0 +1,120 @@
1+## linktep: macro
2+#
3+# Usage: linktep:command[manpage-section]
4+#
5+# Note, {0} is the manpage section, while {target} is the command.
6+#
7+# Show TEP link as: <command>(<section>); if section is defined, else just show
8+# the command.
9+
10+[macros]
11+(?su)[\\]?(?P<name>linktep):(?P<target>\S*?)\[(?P<attrlist>.*?)\]=
12+
13+[attributes]
14+asterisk=&#42;
15+plus=&#43;
16+caret=&#94;
17+startsb=&#91;
18+endsb=&#93;
19+tilde=&#126;
20+
21+ifdef::backend-docbook[]
22+[linktep-inlinemacro]
23+{0%{target}}
24+{0#<citerefentry>}
25+{0#<refentrytitle>{target}</refentrytitle><manvolnum>{0}</manvolnum>}
26+{0#</citerefentry>}
27+endif::backend-docbook[]
28+
29+ifdef::backend-docbook[]
30+ifndef::tep-asciidoc-no-roff[]
31+# "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this.
32+# v1.72 breaks with this because it replaces dots not in roff requests.
33+[listingblock]
34+<example><title>{title}</title>
35+<literallayout>
36+ifdef::doctype-manpage[]
37+&#10;.ft C&#10;
38+endif::doctype-manpage[]
39+|
40+ifdef::doctype-manpage[]
41+&#10;.ft&#10;
42+endif::doctype-manpage[]
43+</literallayout>
44+{title#}</example>
45+endif::tep-asciidoc-no-roff[]
46+
47+ifdef::tep-asciidoc-no-roff[]
48+ifdef::doctype-manpage[]
49+# The following two small workarounds insert a simple paragraph after screen
50+[listingblock]
51+<example><title>{title}</title>
52+<literallayout>
53+|
54+</literallayout><simpara></simpara>
55+{title#}</example>
56+
57+[verseblock]
58+<formalpara{id? id="{id}"}><title>{title}</title><para>
59+{title%}<literallayout{id? id="{id}"}>
60+{title#}<literallayout>
61+|
62+</literallayout>
63+{title#}</para></formalpara>
64+{title%}<simpara></simpara>
65+endif::doctype-manpage[]
66+endif::tep-asciidoc-no-roff[]
67+endif::backend-docbook[]
68+
69+ifdef::doctype-manpage[]
70+ifdef::backend-docbook[]
71+[header]
72+template::[header-declarations]
73+<refentry>
74+<refmeta>
75+<refentrytitle>{mantitle}</refentrytitle>
76+<manvolnum>{manvolnum}</manvolnum>
77+<refmiscinfo class="source">libperf</refmiscinfo>
78+<refmiscinfo class="version">{libperf_version}</refmiscinfo>
79+<refmiscinfo class="manual">libperf Manual</refmiscinfo>
80+</refmeta>
81+<refnamediv>
82+ <refname>{manname1}</refname>
83+ <refname>{manname2}</refname>
84+ <refname>{manname3}</refname>
85+ <refname>{manname4}</refname>
86+ <refname>{manname5}</refname>
87+ <refname>{manname6}</refname>
88+ <refname>{manname7}</refname>
89+ <refname>{manname8}</refname>
90+ <refname>{manname9}</refname>
91+ <refname>{manname10}</refname>
92+ <refname>{manname11}</refname>
93+ <refname>{manname12}</refname>
94+ <refname>{manname13}</refname>
95+ <refname>{manname14}</refname>
96+ <refname>{manname15}</refname>
97+ <refname>{manname16}</refname>
98+ <refname>{manname17}</refname>
99+ <refname>{manname18}</refname>
100+ <refname>{manname19}</refname>
101+ <refname>{manname20}</refname>
102+ <refname>{manname21}</refname>
103+ <refname>{manname22}</refname>
104+ <refname>{manname23}</refname>
105+ <refname>{manname24}</refname>
106+ <refname>{manname25}</refname>
107+ <refname>{manname26}</refname>
108+ <refname>{manname27}</refname>
109+ <refname>{manname28}</refname>
110+ <refname>{manname29}</refname>
111+ <refname>{manname30}</refname>
112+ <refpurpose>{manpurpose}</refpurpose>
113+</refnamediv>
114+endif::backend-docbook[]
115+endif::doctype-manpage[]
116+
117+ifdef::backend-xhtml11[]
118+[linktep-inlinemacro]
119+<a href="{target}.html">{target}{0?({0})}</a>
120+endif::backend-xhtml11[]
tools/lib/perf/Documentation/examples/sampling.c+119−0
@@ -0,0 +1,119 @@
1+#include <linux/perf_event.h>
2+#include <perf/evlist.h>
3+#include <perf/evsel.h>
4+#include <perf/cpumap.h>
5+#include <perf/threadmap.h>
6+#include <perf/mmap.h>
7+#include <perf/core.h>
8+#include <perf/event.h>
9+#include <stdio.h>
10+#include <unistd.h>
11+
12+static int libperf_print(enum libperf_print_level level,
13+ const char *fmt, va_list ap)
14+{
15+ return vfprintf(stderr, fmt, ap);
16+}
17+
18+union u64_swap {
19+ __u64 val64;
20+ __u32 val32[2];
21+};
22+
23+int main(int argc, char **argv)
24+{
25+ struct perf_evlist *evlist;
26+ struct perf_evsel *evsel;
27+ struct perf_mmap *map;
28+ struct perf_cpu_map *cpus;
29+ struct perf_event_attr attr = {
30+ .type = PERF_TYPE_HARDWARE,
31+ .config = PERF_COUNT_HW_CPU_CYCLES,
32+ .disabled = 1,
33+ .freq = 1,
34+ .sample_freq = 10,
35+ .sample_type = PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_CPU|PERF_SAMPLE_PERIOD,
36+ };
37+ int err = -1;
38+ union perf_event *event;
39+
40+ libperf_init(libperf_print);
41+
42+ cpus = perf_cpu_map__new(NULL);
43+ if (!cpus) {
44+ fprintf(stderr, "failed to create cpus\n");
45+ return -1;
46+ }
47+
48+ evlist = perf_evlist__new();
49+ if (!evlist) {
50+ fprintf(stderr, "failed to create evlist\n");
51+ goto out_cpus;
52+ }
53+
54+ evsel = perf_evsel__new(&attr);
55+ if (!evsel) {
56+ fprintf(stderr, "failed to create cycles\n");
57+ goto out_cpus;
58+ }
59+
60+ perf_evlist__add(evlist, evsel);
61+
62+ perf_evlist__set_maps(evlist, cpus, NULL);
63+
64+ err = perf_evlist__open(evlist);
65+ if (err) {
66+ fprintf(stderr, "failed to open evlist\n");
67+ goto out_evlist;
68+ }
69+
70+ err = perf_evlist__mmap(evlist, 4);
71+ if (err) {
72+ fprintf(stderr, "failed to mmap evlist\n");
73+ goto out_evlist;
74+ }
75+
76+ perf_evlist__enable(evlist);
77+ sleep(3);
78+ perf_evlist__disable(evlist);
79+
80+ perf_evlist__for_each_mmap(evlist, map, false) {
81+ if (perf_mmap__read_init(map) < 0)
82+ continue;
83+
84+ while ((event = perf_mmap__read_event(map)) != NULL) {
85+ int cpu, pid, tid;
86+ __u64 ip, period, *array;
87+ union u64_swap u;
88+
89+ array = event->sample.array;
90+
91+ ip = *array;
92+ array++;
93+
94+ u.val64 = *array;
95+ pid = u.val32[0];
96+ tid = u.val32[1];
97+ array++;
98+
99+ u.val64 = *array;
100+ cpu = u.val32[0];
101+ array++;
102+
103+ period = *array;
104+
105+ fprintf(stdout, "cpu %3d, pid %6d, tid %6d, ip %20llx, period %20llu\n",
106+ cpu, pid, tid, ip, period);
107+
108+ perf_mmap__consume(map);
109+ }
110+
111+ perf_mmap__read_done(map);
112+ }
113+
114+out_evlist:
115+ perf_evlist__delete(evlist);
116+out_cpus:
117+ perf_cpu_map__put(cpus);
118+ return err;
119+}
tools/lib/perf/Documentation/libperf-counting.txt+211−0
@@ -0,0 +1,211 @@
1+libperf-counting(7)
2+===================
3+
4+NAME
5+----
6+libperf-counting - counting interface
7+
8+DESCRIPTION
9+-----------
10+The counting interface provides API to meassure and get count for specific perf events.
11+
12+The following test tries to explain count on `counting.c` example.
13+
14+It is by no means complete guide to counting, but shows libperf basic API for counting.
15+
16+The `counting.c` comes with libbperf package and can be compiled and run like:
17+
18+[source,bash]
19+--
20+$ gcc -o counting counting.c -lperf
21+$ sudo ./counting
22+count 176792, enabled 176944, run 176944
23+count 176242, enabled 176242, run 176242
24+--
25+
26+It requires root access, because of the `PERF_COUNT_SW_CPU_CLOCK` event,
27+which is available only for root.
28+
29+The `counting.c` example monitors two events on the current process and displays their count, in a nutshel it:
30+
31+* creates events
32+* adds them to the event list
33+* opens and enables events through the event list
34+* does some workload
35+* disables events
36+* reads and displays event counts
37+* destroys the event list
38+
39+The first thing you need to do before using libperf is to call init function:
40+
41+[source,c]
42+--
43+ 8 static int libperf_print(enum libperf_print_level level,
44+ 9 const char *fmt, va_list ap)
45+ 10 {
46+ 11 return vfprintf(stderr, fmt, ap);
47+ 12 }
48+
49+ 14 int main(int argc, char **argv)
50+ 15 {
51+ ...
52+ 35 libperf_init(libperf_print);
53+--
54+
55+It will setup the library and sets function for debug output from library.
56+
57+The `libperf_print` callback will receive any message with its debug level,
58+defined as:
59+
60+[source,c]
61+--
62+enum libperf_print_level {
63+ LIBPERF_ERR,
64+ LIBPERF_WARN,
65+ LIBPERF_INFO,
66+ LIBPERF_DEBUG,
67+ LIBPERF_DEBUG2,
68+ LIBPERF_DEBUG3,
69+};
70+--
71+
72+Once the setup is complete we start by defining specific events using the `struct perf_event_attr`.
73+
74+We create software events for cpu and task:
75+
76+[source,c]
77+--
78+ 20 struct perf_event_attr attr1 = {
79+ 21 .type = PERF_TYPE_SOFTWARE,
80+ 22 .config = PERF_COUNT_SW_CPU_CLOCK,
81+ 23 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING,
82+ 24 .disabled = 1,
83+ 25 };
84+ 26 struct perf_event_attr attr2 = {
85+ 27 .type = PERF_TYPE_SOFTWARE,
86+ 28 .config = PERF_COUNT_SW_TASK_CLOCK,
87+ 29 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING,
88+ 30 .disabled = 1,
89+ 31 };
90+--
91+
92+The `read_format` setup tells perf to include timing details together with each count.
93+
94+Next step is to prepare threads map.
95+
96+In this case we will monitor current process, so we create threads map with single pid (0):
97+
98+[source,c]
99+--
100+ 37 threads = perf_thread_map__new_dummy();
101+ 38 if (!threads) {
102+ 39 fprintf(stderr, "failed to create threads\n");
103+ 40 return -1;
104+ 41 }
105+ 42
106+ 43 perf_thread_map__set_pid(threads, 0, 0);
107+--
108+
109+Now we create libperf's event list, which will serve as holder for the events we want:
110+
111+[source,c]
112+--
113+ 45 evlist = perf_evlist__new();
114+ 46 if (!evlist) {
115+ 47 fprintf(stderr, "failed to create evlist\n");
116+ 48 goto out_threads;
117+ 49 }
118+--
119+
120+We create libperf's events for the attributes we defined earlier and add them to the list:
121+
122+[source,c]
123+--
124+ 51 evsel = perf_evsel__new(&attr1);
125+ 52 if (!evsel) {
126+ 53 fprintf(stderr, "failed to create evsel1\n");
127+ 54 goto out_evlist;
128+ 55 }
129+ 56
130+ 57 perf_evlist__add(evlist, evsel);
131+ 58
132+ 59 evsel = perf_evsel__new(&attr2);
133+ 60 if (!evsel) {
134+ 61 fprintf(stderr, "failed to create evsel2\n");
135+ 62 goto out_evlist;
136+ 63 }
137+ 64
138+ 65 perf_evlist__add(evlist, evsel);
139+--
140+
141+Configure event list with the thread map and open events:
142+
143+[source,c]
144+--
145+ 67 perf_evlist__set_maps(evlist, NULL, threads);
146+ 68
147+ 69 err = perf_evlist__open(evlist);
148+ 70 if (err) {
149+ 71 fprintf(stderr, "failed to open evsel\n");
150+ 72 goto out_evlist;
151+ 73 }
152+--
153+
154+Both events are created as disabled (note the `disabled = 1` assignment above),
155+so we need to enable the whole list explicitely (both events).
156+
157+From this moment events are counting and we can do our workload.
158+
159+When we are done we disable the events list.
160+
161+[source,c]
162+--
163+ 75 perf_evlist__enable(evlist);
164+ 76
165+ 77 while (count--);
166+ 78
167+ 79 perf_evlist__disable(evlist);
168+--
169+
170+Now we need to get the counts from events, following code iterates throught the events list and read counts:
171+
172+[source,c]
173+--
174+ 81 perf_evlist__for_each_evsel(evlist, evsel) {
175+ 82 perf_evsel__read(evsel, 0, 0, &counts);
176+ 83 fprintf(stdout, "count %llu, enabled %llu, run %llu\n",
177+ 84 counts.val, counts.ena, counts.run);
178+ 85 }
179+--
180+
181+And finaly cleanup.
182+
183+We close the whole events list (both events) and remove it together with the threads map:
184+
185+[source,c]
186+--
187+ 87 perf_evlist__close(evlist);
188+ 88
189+ 89 out_evlist:
190+ 90 perf_evlist__delete(evlist);
191+ 91 out_threads:
192+ 92 perf_thread_map__put(threads);
193+ 93 return err;
194+ 94 }
195+--
196+
197+REPORTING BUGS
198+--------------
199+Report bugs to <linux-perf-users@vger.kernel.org>.
200+
201+LICENSE
202+-------
203+libperf is Free Software licensed under the GNU LGPL 2.1
204+
205+RESOURCES
206+---------
207+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
208+
209+SEE ALSO
210+--------
211+libperf(3), libperf-sampling(7)
tools/lib/perf/Documentation/libperf-sampling.txt+243−0
@@ -0,0 +1,243 @@
1+libperf-sampling(7)
2+===================
3+
4+NAME
5+----
6+libperf-sampling - sampling interface
7+
8+
9+DESCRIPTION
10+-----------
11+The sampling interface provides API to meassure and get count for specific perf events.
12+
13+The following test tries to explain count on `sampling.c` example.
14+
15+It is by no means complete guide to sampling, but shows libperf basic API for sampling.
16+
17+The `sampling.c` comes with libbperf package and can be compiled and run like:
18+
19+[source,bash]
20+--
21+$ gcc -o sampling sampling.c -lperf
22+$ sudo ./sampling
23+cpu 0, pid 0, tid 0, ip ffffffffad06c4e6, period 1
24+cpu 0, pid 4465, tid 4469, ip ffffffffad118748, period 18322959
25+cpu 0, pid 0, tid 0, ip ffffffffad115722, period 33544846
26+cpu 0, pid 4465, tid 4470, ip 7f84fe0cdad6, period 23687474
27+cpu 0, pid 0, tid 0, ip ffffffffad9e0349, period 34255790
28+cpu 0, pid 4465, tid 4469, ip ffffffffad136581, period 38664069
29+cpu 0, pid 0, tid 0, ip ffffffffad9e55e2, period 21922384
30+cpu 0, pid 4465, tid 4470, ip 7f84fe0ebebf, period 17655175
31+...
32+--
33+
34+It requires root access, because it uses hardware cycles event.
35+
36+The `sampling.c` example profiles/samples all CPUs with hardware cycles, in a nutshel it:
37+
38+- creates events
39+- adds them to the event list
40+- opens and enables events through the event list
41+- sleeps for 3 seconds
42+- disables events
43+- reads and displays recorded samples
44+- destroys the event list
45+
46+The first thing you need to do before using libperf is to call init function:
47+
48+[source,c]
49+--
50+ 12 static int libperf_print(enum libperf_print_level level,
51+ 13 const char *fmt, va_list ap)
52+ 14 {
53+ 15 return vfprintf(stderr, fmt, ap);
54+ 16 }
55+
56+ 23 int main(int argc, char **argv)
57+ 24 {
58+ ...
59+ 40 libperf_init(libperf_print);
60+--
61+
62+It will setup the library and sets function for debug output from library.
63+
64+The `libperf_print` callback will receive any message with its debug level,
65+defined as:
66+
67+[source,c]
68+--
69+enum libperf_print_level {
70+ LIBPERF_ERR,
71+ LIBPERF_WARN,
72+ LIBPERF_INFO,
73+ LIBPERF_DEBUG,
74+ LIBPERF_DEBUG2,
75+ LIBPERF_DEBUG3,
76+};
77+--
78+
79+Once the setup is complete we start by defining cycles event using the `struct perf_event_attr`:
80+
81+[source,c]
82+--
83+ 29 struct perf_event_attr attr = {
84+ 30 .type = PERF_TYPE_HARDWARE,
85+ 31 .config = PERF_COUNT_HW_CPU_CYCLES,
86+ 32 .disabled = 1,
87+ 33 .freq = 1,
88+ 34 .sample_freq = 10,
89+ 35 .sample_type = PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_CPU|PERF_SAMPLE_PERIOD,
90+ 36 };
91+--
92+
93+Next step is to prepare cpus map.
94+
95+In this case we will monitor all the available CPUs:
96+
97+[source,c]
98+--
99+ 42 cpus = perf_cpu_map__new(NULL);
100+ 43 if (!cpus) {
101+ 44 fprintf(stderr, "failed to create cpus\n");
102+ 45 return -1;
103+ 46 }
104+--
105+
106+Now we create libperf's event list, which will serve as holder for the cycles event:
107+
108+[source,c]
109+--
110+ 48 evlist = perf_evlist__new();
111+ 49 if (!evlist) {
112+ 50 fprintf(stderr, "failed to create evlist\n");
113+ 51 goto out_cpus;
114+ 52 }
115+--
116+
117+We create libperf's event for the cycles attribute we defined earlier and add it to the list:
118+
119+[source,c]
120+--
121+ 54 evsel = perf_evsel__new(&attr);
122+ 55 if (!evsel) {
123+ 56 fprintf(stderr, "failed to create cycles\n");
124+ 57 goto out_cpus;
125+ 58 }
126+ 59
127+ 60 perf_evlist__add(evlist, evsel);
128+--
129+
130+Configure event list with the cpus map and open event:
131+
132+[source,c]
133+--
134+ 62 perf_evlist__set_maps(evlist, cpus, NULL);
135+ 63
136+ 64 err = perf_evlist__open(evlist);
137+ 65 if (err) {
138+ 66 fprintf(stderr, "failed to open evlist\n");
139+ 67 goto out_evlist;
140+ 68 }
141+--
142+
143+Once the events list is open, we can create memory maps AKA perf ring buffers:
144+
145+[source,c]
146+--
147+ 70 err = perf_evlist__mmap(evlist, 4);
148+ 71 if (err) {
149+ 72 fprintf(stderr, "failed to mmap evlist\n");
150+ 73 goto out_evlist;
151+ 74 }
152+--
153+
154+The event is created as disabled (note the `disabled = 1` assignment above),
155+so we need to enable the events list explicitely.
156+
157+From this moment the cycles event is sampling.
158+
159+We will sleep for 3 seconds while the ring buffers get data from all CPUs, then we disable the events list.
160+
161+[source,c]
162+--
163+ 76 perf_evlist__enable(evlist);
164+ 77 sleep(3);
165+ 78 perf_evlist__disable(evlist);
166+--
167+
168+Following code walks through the ring buffers and reads stored events/samples:
169+
170+[source,c]
171+--
172+ 80 perf_evlist__for_each_mmap(evlist, map, false) {
173+ 81 if (perf_mmap__read_init(map) < 0)
174+ 82 continue;
175+ 83
176+ 84 while ((event = perf_mmap__read_event(map)) != NULL) {
177+
178+ /* process event */
179+
180+108 perf_mmap__consume(map);
181+109 }
182+110 perf_mmap__read_done(map);
183+111 }
184+
185+--
186+
187+Each sample needs to get parsed:
188+
189+[source,c]
190+--
191+ 85 int cpu, pid, tid;
192+ 86 __u64 ip, period, *array;
193+ 87 union u64_swap u;
194+ 88
195+ 89 array = event->sample.array;
196+ 90
197+ 91 ip = *array;
198+ 92 array++;
199+ 93
200+ 94 u.val64 = *array;
201+ 95 pid = u.val32[0];
202+ 96 tid = u.val32[1];
203+ 97 array++;
204+ 98
205+ 99 u.val64 = *array;
206+100 cpu = u.val32[0];
207+101 array++;
208+102
209+103 period = *array;
210+104
211+105 fprintf(stdout, "cpu %3d, pid %6d, tid %6d, ip %20llx, period %20llu\n",
212+106 cpu, pid, tid, ip, period);
213+--
214+
215+And finaly cleanup.
216+
217+We close the whole events list (both events) and remove it together with the threads map:
218+
219+[source,c]
220+--
221+113 out_evlist:
222+114 perf_evlist__delete(evlist);
223+115 out_cpus:
224+116 perf_cpu_map__put(cpus);
225+117 return err;
226+118 }
227+--
228+
229+REPORTING BUGS
230+--------------
231+Report bugs to <linux-perf-users@vger.kernel.org>.
232+
233+LICENSE
234+-------
235+libperf is Free Software licensed under the GNU LGPL 2.1
236+
237+RESOURCES
238+---------
239+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
240+
241+SEE ALSO
242+--------
243+libperf(3), libperf-counting(7)
tools/lib/perf/Documentation/libperf.txt+246−0
@@ -0,0 +1,246 @@
1+libperf(3)
2+==========
3+
4+NAME
5+----
6+libperf - Linux kernel perf event library
7+
8+
9+SYNOPSIS
10+--------
11+*Generic API:*
12+
13+[source,c]
14+--
15+ #include <perf/core.h>
16+
17+ enum libperf_print_level {
18+ LIBPERF_ERR,
19+ LIBPERF_WARN,
20+ LIBPERF_INFO,
21+ LIBPERF_DEBUG,
22+ LIBPERF_DEBUG2,
23+ LIBPERF_DEBUG3,
24+ };
25+
26+ typedef int (*libperf_print_fn_t)(enum libperf_print_level level,
27+ const char *, va_list ap);
28+
29+ void libperf_init(libperf_print_fn_t fn);
30+--
31+
32+*API to handle cpu maps:*
33+
34+[source,c]
35+--
36+ #include <perf/cpumap.h>
37+
38+ struct perf_cpu_map;
39+
40+ struct perf_cpu_map *perf_cpu_map__dummy_new(void);
41+ struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list);
42+ struct perf_cpu_map *perf_cpu_map__read(FILE *file);
43+ struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map);
44+ struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig,
45+ struct perf_cpu_map *other);
46+ void perf_cpu_map__put(struct perf_cpu_map *map);
47+ int perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx);
48+ int perf_cpu_map__nr(const struct perf_cpu_map *cpus);
49+ bool perf_cpu_map__empty(const struct perf_cpu_map *map);
50+ int perf_cpu_map__max(struct perf_cpu_map *map);
51+
52+ #define perf_cpu_map__for_each_cpu(cpu, idx, cpus)
53+--
54+
55+*API to handle thread maps:*
56+
57+[source,c]
58+--
59+ #include <perf/threadmap.h>
60+
61+ struct perf_thread_map;
62+
63+ struct perf_thread_map *perf_thread_map__new_dummy(void);
64+
65+ void perf_thread_map__set_pid(struct perf_thread_map *map, int thread, pid_t pid);
66+ char *perf_thread_map__comm(struct perf_thread_map *map, int thread);
67+ int perf_thread_map__nr(struct perf_thread_map *threads);
68+ pid_t perf_thread_map__pid(struct perf_thread_map *map, int thread);
69+
70+ struct perf_thread_map *perf_thread_map__get(struct perf_thread_map *map);
71+ void perf_thread_map__put(struct perf_thread_map *map);
72+--
73+
74+*API to handle event lists:*
75+
76+[source,c]
77+--
78+ #include <perf/evlist.h>
79+
80+ struct perf_evlist;
81+
82+ void perf_evlist__add(struct perf_evlist *evlist,
83+ struct perf_evsel *evsel);
84+ void perf_evlist__remove(struct perf_evlist *evlist,
85+ struct perf_evsel *evsel);
86+ struct perf_evlist *perf_evlist__new(void);
87+ void perf_evlist__delete(struct perf_evlist *evlist);
88+ struct perf_evsel* perf_evlist__next(struct perf_evlist *evlist,
89+ struct perf_evsel *evsel);
90+ int perf_evlist__open(struct perf_evlist *evlist);
91+ void perf_evlist__close(struct perf_evlist *evlist);
92+ void perf_evlist__enable(struct perf_evlist *evlist);
93+ void perf_evlist__disable(struct perf_evlist *evlist);
94+
95+ #define perf_evlist__for_each_evsel(evlist, pos)
96+
97+ void perf_evlist__set_maps(struct perf_evlist *evlist,
98+ struct perf_cpu_map *cpus,
99+ struct perf_thread_map *threads);
100+ int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
101+ int perf_evlist__filter_pollfd(struct perf_evlist *evlist,
102+ short revents_and_mask);
103+
104+ int perf_evlist__mmap(struct perf_evlist *evlist, int pages);
105+ void perf_evlist__munmap(struct perf_evlist *evlist);
106+
107+ struct perf_mmap *perf_evlist__next_mmap(struct perf_evlist *evlist,
108+ struct perf_mmap *map,
109+ bool overwrite);
110+
111+ #define perf_evlist__for_each_mmap(evlist, pos, overwrite)
112+--
113+
114+*API to handle events:*
115+
116+[source,c]
117+--
118+ #include <perf/evsel.h>*
119+
120+ struct perf_evsel;
121+
122+ struct perf_counts_values {
123+ union {
124+ struct {
125+ uint64_t val;
126+ uint64_t ena;
127+ uint64_t run;
128+ };
129+ uint64_t values[3];
130+ };
131+ };
132+
133+ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr);
134+ void perf_evsel__delete(struct perf_evsel *evsel);
135+ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
136+ struct perf_thread_map *threads);
137+ void perf_evsel__close(struct perf_evsel *evsel);
138+ void perf_evsel__close_cpu(struct perf_evsel *evsel, int cpu);
139+ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
140+ struct perf_counts_values *count);
141+ int perf_evsel__enable(struct perf_evsel *evsel);
142+ int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu);
143+ int perf_evsel__disable(struct perf_evsel *evsel);
144+ int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu);
145+ struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel);
146+ struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel);
147+ struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel);
148+--
149+
150+*API to handle maps (perf ring buffers):*
151+
152+[source,c]
153+--
154+ #include <perf/mmap.h>
155+
156+ struct perf_mmap;
157+
158+ void perf_mmap__consume(struct perf_mmap *map);
159+ int perf_mmap__read_init(struct perf_mmap *map);
160+ void perf_mmap__read_done(struct perf_mmap *map);
161+ union perf_event *perf_mmap__read_event(struct perf_mmap *map);
162+--
163+
164+*Structures to access perf API events:*
165+
166+[source,c]
167+--
168+ #include <perf/event.h>
169+
170+ struct perf_record_mmap;
171+ struct perf_record_mmap2;
172+ struct perf_record_comm;
173+ struct perf_record_namespaces;
174+ struct perf_record_fork;
175+ struct perf_record_lost;
176+ struct perf_record_lost_samples;
177+ struct perf_record_read;
178+ struct perf_record_throttle;
179+ struct perf_record_ksymbol;
180+ struct perf_record_bpf_event;
181+ struct perf_record_sample;
182+ struct perf_record_switch;
183+ struct perf_record_header_attr;
184+ struct perf_record_record_cpu_map;
185+ struct perf_record_cpu_map_data;
186+ struct perf_record_cpu_map;
187+ struct perf_record_event_update_cpus;
188+ struct perf_record_event_update_scale;
189+ struct perf_record_event_update;
190+ struct perf_trace_event_type;
191+ struct perf_record_header_event_type;
192+ struct perf_record_header_tracing_data;
193+ struct perf_record_header_build_id;
194+ struct perf_record_id_index;
195+ struct perf_record_auxtrace_info;
196+ struct perf_record_auxtrace;
197+ struct perf_record_auxtrace_error;
198+ struct perf_record_aux;
199+ struct perf_record_itrace_start;
200+ struct perf_record_thread_map_entry;
201+ struct perf_record_thread_map;
202+ struct perf_record_stat_config_entry;
203+ struct perf_record_stat_config;
204+ struct perf_record_stat;
205+ struct perf_record_stat_round;
206+ struct perf_record_time_conv;
207+ struct perf_record_header_feature;
208+ struct perf_record_compressed;
209+--
210+
211+DESCRIPTION
212+-----------
213+The libperf library provides an API to access the linux kernel perf
214+events subsystem.
215+
216+Following objects are key to the libperf interface:
217+
218+[horizontal]
219+
220+struct perf_cpu_map:: Provides a cpu list abstraction.
221+
222+struct perf_thread_map:: Provides a thread list abstraction.
223+
224+struct perf_evsel:: Provides an abstraction for single a perf event.
225+
226+struct perf_evlist:: Gathers several struct perf_evsel object and performs functions on all of them.
227+
228+struct perf_mmap:: Provides an abstraction for accessing perf ring buffer.
229+
230+The exported API functions bind these objects together.
231+
232+REPORTING BUGS
233+--------------
234+Report bugs to <linux-perf-users@vger.kernel.org>.
235+
236+LICENSE
237+-------
238+libperf is Free Software licensed under the GNU LGPL 2.1
239+
240+RESOURCES
241+---------
242+https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
243+
244+SEE ALSO
245+--------
246+libperf-sampling(7), libperf-counting(7)
tools/lib/perf/Documentation/manpage-1.72.xsl+14−0
@@ -0,0 +1,14 @@
1+<!-- manpage-1.72.xsl:
2+ special settings for manpages rendered from asciidoc+docbook
3+ handles peculiarities in docbook-xsl 1.72.0 -->
4+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
5+ version="1.0">
6+
7+<xsl:import href="manpage-base.xsl"/>
8+
9+<!-- these are the special values for the roff control characters
10+ needed for docbook-xsl 1.72.0 -->
11+<xsl:param name="git.docbook.backslash">&#x2593;</xsl:param>
12+<xsl:param name="git.docbook.dot" >&#x2302;</xsl:param>
13+
14+</xsl:stylesheet>
tools/lib/perf/Documentation/manpage-base.xsl+35−0
@@ -0,0 +1,35 @@
1+<!-- manpage-base.xsl:
2+ special formatting for manpages rendered from asciidoc+docbook -->
3+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4+ version="1.0">
5+
6+<!-- these params silence some output from xmlto -->
7+<xsl:param name="man.output.quietly" select="1"/>
8+<xsl:param name="refentry.meta.get.quietly" select="1"/>
9+
10+<!-- convert asciidoc callouts to man page format;
11+ git.docbook.backslash and git.docbook.dot params
12+ must be supplied by another XSL file or other means -->
13+<xsl:template match="co">
14+ <xsl:value-of select="concat(
15+ $git.docbook.backslash,'fB(',
16+ substring-after(@id,'-'),')',
17+ $git.docbook.backslash,'fR')"/>
18+</xsl:template>
19+<xsl:template match="calloutlist">
20+ <xsl:value-of select="$git.docbook.dot"/>
21+ <xsl:text>sp&#10;</xsl:text>
22+ <xsl:apply-templates/>
23+ <xsl:text>&#10;</xsl:text>
24+</xsl:template>
25+<xsl:template match="callout">
26+ <xsl:value-of select="concat(
27+ $git.docbook.backslash,'fB',
28+ substring-after(@arearefs,'-'),
29+ '. ',$git.docbook.backslash,'fR')"/>
30+ <xsl:apply-templates/>
31+ <xsl:value-of select="$git.docbook.dot"/>
32+ <xsl:text>br&#10;</xsl:text>
33+</xsl:template>
34+
35+</xsl:stylesheet>
tools/lib/perf/Documentation/manpage-bold-literal.xsl+17−0
@@ -0,0 +1,17 @@
1+<!-- manpage-bold-literal.xsl:
2+ special formatting for manpages rendered from asciidoc+docbook -->
3+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4+ version="1.0">
5+
6+<!-- render literal text as bold (instead of plain or monospace);
7+ this makes literal text easier to distinguish in manpages
8+ viewed on a tty -->
9+<xsl:template match="literal">
10+ <xsl:value-of select="$git.docbook.backslash"/>
11+ <xsl:text>fB</xsl:text>
12+ <xsl:apply-templates/>
13+ <xsl:value-of select="$git.docbook.backslash"/>
14+ <xsl:text>fR</xsl:text>
15+</xsl:template>
16+
17+</xsl:stylesheet>
tools/lib/perf/Documentation/manpage-normal.xsl+13−0
@@ -0,0 +1,13 @@
1+<!-- manpage-normal.xsl:
2+ special settings for manpages rendered from asciidoc+docbook
3+ handles anything we want to keep away from docbook-xsl 1.72.0 -->
4+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
5+ version="1.0">
6+
7+<xsl:import href="manpage-base.xsl"/>
8+
9+<!-- these are the normal values for the roff control characters -->
10+<xsl:param name="git.docbook.backslash">\</xsl:param>
11+<xsl:param name="git.docbook.dot" >.</xsl:param>
12+
13+</xsl:stylesheet>
tools/lib/perf/Documentation/manpage-suppress-sp.xsl+21−0
@@ -0,0 +1,21 @@
1+<!-- manpage-suppress-sp.xsl:
2+ special settings for manpages rendered from asciidoc+docbook
3+ handles erroneous, inline .sp in manpage output of some
4+ versions of docbook-xsl -->
5+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
6+ version="1.0">
7+
8+<!-- attempt to work around spurious .sp at the tail of the line
9+ that some versions of docbook stylesheets seem to add -->
10+<xsl:template match="simpara">
11+ <xsl:variable name="content">
12+ <xsl:apply-templates/>
13+ </xsl:variable>
14+ <xsl:value-of select="normalize-space($content)"/>
15+ <xsl:if test="not(ancestor::authorblurb) and
16+ not(ancestor::personblurb)">
17+ <xsl:text>&#10;&#10;</xsl:text>
18+ </xsl:if>
19+</xsl:template>
20+
21+</xsl:stylesheet>
tools/lib/perf/Makefilerenamed from tools/perf/lib/Makefile+5−2
@@ -60,7 +60,7 @@ else · 59 unmodified lines
6060 endif
6161
6262 INCLUDES = \
63−-I$(srctree)/tools/perf/lib/include \
63+-I$(srctree)/tools/lib/perf/include \
6464 -I$(srctree)/tools/lib/ \
6565 -I$(srctree)/tools/include \
6666 -I$(srctree)/tools/arch/$(SRCARCH)/include/ \
@@ -181,7 +181,10 @@ install_pkgconfig: $(LIBPERF_PC) · 114 unmodified lines
181181 $(call QUIET_INSTALL, $(LIBPERF_PC)) \
182182 $(call do_install,$(LIBPERF_PC),$(libdir_SQ)/pkgconfig,644)
183183
184−install: install_lib install_headers install_pkgconfig
184+install_doc:
185+ $(Q)$(MAKE) -C Documentation install-man install-html install-examples
186+
187+install: install_lib install_headers install_pkgconfig install_doc
185188
186189 FORCE:
187190
tools/lib/perf/core.crenamed from tools/perf/lib/core.c+0−0

File renamed without changes.

tools/lib/perf/cpumap.crenamed from tools/perf/lib/cpumap.c+0−0

File renamed without changes.

tools/lib/perf/evlist.crenamed from tools/perf/lib/evlist.c+3−0
@@ -164,6 +164,9 @@ void perf_evlist__set_maps(struct perf_evlist *evlist, · 163 unmodified lines
164164 evlist->threads = perf_thread_map__get(threads);
165165 }
166166
167+ if (!evlist->all_cpus && cpus)
168+ evlist->all_cpus = perf_cpu_map__get(cpus);
169+
167170 perf_evlist__propagate_maps(evlist);
168171 }
169172
tools/lib/perf/evsel.crenamed from tools/perf/lib/evsel.c+0−0

File renamed without changes.

tools/lib/perf/include/internal/cpumap.hrenamed from tools/perf/lib/include/internal/cpumap.h+0−0

File renamed without changes.

tools/lib/perf/include/internal/evlist.hrenamed from tools/perf/lib/include/internal/evlist.h+0−0

File renamed without changes.

tools/lib/perf/include/internal/evsel.hrenamed from tools/perf/lib/include/internal/evsel.h+0−0

File renamed without changes.

tools/lib/perf/include/internal/lib.hrenamed from tools/perf/lib/include/internal/lib.h+0−0

File renamed without changes.

tools/lib/perf/include/internal/mmap.hrenamed from tools/perf/lib/include/internal/mmap.h+0−0

File renamed without changes.

tools/lib/perf/include/internal/tests.hrenamed from tools/perf/lib/include/internal/tests.h+0−0

File renamed without changes.

tools/lib/perf/include/internal/threadmap.hrenamed from tools/perf/lib/include/internal/threadmap.h+0−0

File renamed without changes.

tools/lib/perf/include/internal/xyarray.hrenamed from tools/perf/lib/include/internal/xyarray.h+0−0

File renamed without changes.

tools/lib/perf/include/perf/core.hrenamed from tools/perf/lib/include/perf/core.h+0−0

File renamed without changes.

tools/lib/perf/include/perf/cpumap.hrenamed from tools/perf/lib/include/perf/cpumap.h+0−0

File renamed without changes.

tools/lib/perf/include/perf/event.hrenamed from tools/perf/lib/include/perf/event.h+0−0

File renamed without changes.

tools/lib/perf/include/perf/evlist.hrenamed from tools/perf/lib/include/perf/evlist.h+0−0

File renamed without changes.

tools/lib/perf/include/perf/evsel.hrenamed from tools/perf/lib/include/perf/evsel.h+0−0

File renamed without changes.

tools/lib/perf/include/perf/mmap.hrenamed from tools/perf/lib/include/perf/mmap.h+0−0

File renamed without changes.

tools/lib/perf/include/perf/threadmap.hrenamed from tools/perf/lib/include/perf/threadmap.h+0−0

File renamed without changes.

tools/lib/perf/internal.hrenamed from tools/perf/lib/internal.h+0−0

File renamed without changes.

tools/lib/perf/lib.crenamed from tools/perf/lib/lib.c+0−0

File renamed without changes.

tools/lib/perf/libperf.maprenamed from tools/perf/lib/libperf.map+0−0

File renamed without changes.

tools/lib/perf/libperf.pc.templaterenamed from tools/perf/lib/libperf.pc.template+0−0

File renamed without changes.

tools/lib/perf/mmap.crenamed from tools/perf/lib/mmap.c+0−0

File renamed without changes.

tools/lib/perf/tests/Makefilerenamed from tools/perf/lib/tests/Makefile+1−1
@@ -16,7 +16,7 @@ all: · 15 unmodified lines
1616
1717 include $(srctree)/tools/scripts/Makefile.include
1818
19−INCLUDE = -I$(srctree)/tools/perf/lib/include -I$(srctree)/tools/include -I$(srctree)/tools/lib
19+INCLUDE = -I$(srctree)/tools/lib/perf/include -I$(srctree)/tools/include -I$(srctree)/tools/lib
2020
2121 $(TESTS_A): FORCE
2222 $(QUIET_LINK)$(CC) $(INCLUDE) $(CFLAGS) -o $@ $(subst -a,.c,$@) ../libperf.a $(LIBAPI)
tools/lib/perf/tests/test-cpumap.crenamed from tools/perf/lib/tests/test-cpumap.c+0−0

File renamed without changes.

tools/lib/perf/tests/test-evlist.crenamed from tools/perf/lib/tests/test-evlist.c+0−0

File renamed without changes.

tools/lib/perf/tests/test-evsel.crenamed from tools/perf/lib/tests/test-evsel.c+0−0

File renamed without changes.

tools/lib/perf/tests/test-threadmap.crenamed from tools/perf/lib/tests/test-threadmap.c+0−0

File renamed without changes.

tools/lib/perf/threadmap.crenamed from tools/perf/lib/threadmap.c+0−0

File renamed without changes.

tools/lib/perf/xyarray.crenamed from tools/perf/lib/xyarray.c+0−0

File renamed without changes.

tools/lib/string.c+7−0
@@ -96,6 +96,10 @@ int strtobool(const char *s, bool *res) · 95 unmodified lines
9696 * If libc has strlcpy() then that version will override this
9797 * implementation:
9898 */
99+#ifdef __clang__
100+#pragma clang diagnostic push
101+#pragma clang diagnostic ignored "-Wignored-attributes"
102+#endif
99103 size_t __weak strlcpy(char *dest, const char *src, size_t size)
100104 {
101105 size_t ret = strlen(src);
@@ -107,6 +111,9 @@ size_t __weak strlcpy(char *dest, const char *src, size_t size) · 5 unmodified lines
107111 }
108112 return ret;
109113 }
114+#ifdef __clang__
115+#pragma clang diagnostic pop
116+#endif
110117
111118 /**
112119 * skip_spaces - Removes leading whitespace from @str.
tools/perf/Documentation/perf-annotate.txt+6−0
@@ -112,6 +112,12 @@ OPTIONS · 111 unmodified lines
112112 --objdump=<path>::
113113 Path to objdump binary.
114114
115+--prefix=PREFIX::
116+--prefix-strip=N::
117+ Remove first N entries from source file path names in executables
118+ and add PREFIX. This allows to display source code compiled on systems
119+ with different file system layout.
120+
115121 --skip-missing::
116122 Skip symbols that cannot be annotated.
117123
tools/perf/Documentation/perf-report.txt+6−0
@@ -367,6 +367,12 @@ OPTIONS · 366 unmodified lines
367367 --objdump=<path>::
368368 Path to objdump binary.
369369
370+--prefix=PREFIX::
371+--prefix-strip=N::
372+ Remove first N entries from source file path names in executables
373+ and add PREFIX. This allows to display source code compiled on systems
374+ with different file system layout.
375+
370376 --group::
371377 Show event group information together. It forces group output also
372378 if there are no groups defined in data file.
tools/perf/Documentation/perf-sched.txt+4−0
@@ -110,6 +110,10 @@ OPTIONS for 'perf sched timehist' · 109 unmodified lines
110110 --max-stack::
111111 Maximum number of functions to display in backtrace, default 5.
112112
113+-C=::
114+--cpu=::
115+ Only show events for the given CPU(s) (comma separated list).
116+
113117 -p=::
114118 --pid=::
115119 Only show events for given process ID (comma separated list).
tools/perf/Documentation/perf-top.txt+6−0
@@ -158,6 +158,12 @@ Default is to monitor all CPUS. · 157 unmodified lines
158158 -M::
159159 --disassembler-style=:: Set disassembler style for objdump.
160160
161+--prefix=PREFIX::
162+--prefix-strip=N::
163+ Remove first N entries from source file path names in executables
164+ and add PREFIX. This allows to display source code compiled on systems
165+ with different file system layout.
166+
161167 --source::
162168 Interleave source code with assembly code. Enabled by default,
163169 disable with --no-source.
tools/perf/MANIFEST+1−0
@@ -7,6 +7,7 @@ tools/lib/traceevent · 6 unmodified lines
77 tools/lib/api
88 tools/lib/bpf
99 tools/lib/subcmd
10+tools/lib/perf
1011 tools/lib/argv_split.c
1112 tools/lib/ctype.c
1213 tools/lib/hweight.c
tools/perf/Makefile.config+1−1
@@ -286,7 +286,7 @@ ifeq ($(DEBUG),0) · 285 unmodified lines
286286 endif
287287 endif
288288
289−INC_FLAGS += -I$(src-perf)/lib/include
289+INC_FLAGS += -I$(srctree)/tools/lib/perf/include
290290 INC_FLAGS += -I$(src-perf)/util/include
291291 INC_FLAGS += -I$(src-perf)/arch/$(SRCARCH)/include
292292 INC_FLAGS += -I$(srctree)/tools/include/
tools/perf/Makefile.perf+1−1
@@ -230,7 +230,7 @@ LIB_DIR = $(srctree)/tools/lib/api/ · 229 unmodified lines
230230 TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
231231 BPF_DIR = $(srctree)/tools/lib/bpf/
232232 SUBCMD_DIR = $(srctree)/tools/lib/subcmd/
233−LIBPERF_DIR = $(srctree)/tools/perf/lib/
233+LIBPERF_DIR = $(srctree)/tools/lib/perf/
234234
235235 # Set FEATURE_TESTS to 'all' so all possible feature checkers are executed.
236236 # Without this setting the output feature dump file misses some features, for
tools/perf/builtin-annotate.c+7−0
@@ -535,6 +535,10 @@ int cmd_annotate(int argc, const char **argv) · 534 unmodified lines
535535 "Display raw encoding of assembly instructions (default)"),
536536 OPT_STRING('M', "disassembler-style", &annotate.opts.disassembler_style, "disassembler style",
537537 "Specify disassembler style (e.g. -M intel for intel syntax)"),
538+ OPT_STRING(0, "prefix", &annotate.opts.prefix, "prefix",
539+ "Add prefix to source file path names in programs (with --prefix-strip)"),
540+ OPT_STRING(0, "prefix-strip", &annotate.opts.prefix_strip, "N",
541+ "Strip first N entries of source file path name in programs (with --prefix)"),
538542 OPT_STRING(0, "objdump", &annotate.opts.objdump_path, "path",
539543 "objdump binary to use for disassembly and annotations"),
540544 OPT_BOOLEAN(0, "group", &symbol_conf.event_group,
@@ -574,6 +578,9 @@ int cmd_annotate(int argc, const char **argv) · 33 unmodified lines
574578 annotate.sym_hist_filter = argv[0];
575579 }
576580
581+ if (annotate_check_args(&annotate.opts) < 0)
582+ return -EINVAL;
583+
577584 if (symbol_conf.show_nr_samples && annotate.use_gtk) {
578585 pr_err("--show-nr-samples is not available in --gtk mode at this time\n");
579586 return ret;
tools/perf/builtin-c2c.c+8−6
@@ -595,8 +595,8 @@ tot_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused, · 594 unmodified lines
595595 {
596596 struct c2c_hist_entry *c2c_left;
597597 struct c2c_hist_entry *c2c_right;
598− unsigned int tot_hitm_left;
599− unsigned int tot_hitm_right;
598+ uint64_t tot_hitm_left;
599+ uint64_t tot_hitm_right;
600600
601601 c2c_left = container_of(left, struct c2c_hist_entry, he);
602602 c2c_right = container_of(right, struct c2c_hist_entry, he);
@@ -629,7 +629,8 @@ __f ## _cmp(struct perf_hpp_fmt *fmt __maybe_unused, \ · 26 unmodified lines
629629 \
630630 c2c_left = container_of(left, struct c2c_hist_entry, he); \
631631 c2c_right = container_of(right, struct c2c_hist_entry, he); \
632− return c2c_left->stats.__f - c2c_right->stats.__f; \
632+ return (uint64_t) c2c_left->stats.__f - \
633+ (uint64_t) c2c_right->stats.__f; \
633634 }
634635
635636 #define STAT_FN(__f) \
@@ -682,7 +683,8 @@ ld_llcmiss_cmp(struct perf_hpp_fmt *fmt __maybe_unused, · 46 unmodified lines
682683 c2c_left = container_of(left, struct c2c_hist_entry, he);
683684 c2c_right = container_of(right, struct c2c_hist_entry, he);
684685
685− return llc_miss(&c2c_left->stats) - llc_miss(&c2c_right->stats);
686+ return (uint64_t) llc_miss(&c2c_left->stats) -
687+ (uint64_t) llc_miss(&c2c_right->stats);
686688 }
687689
688690 static uint64_t total_records(struct c2c_stats *stats)
@@ -2384,7 +2386,7 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he) · 1695 unmodified lines
23842386 c2c_browser__update_nr_entries(browser);
23852387
23862388 while (1) {
2387− key = hist_browser__run(browser, "? - help", true);
2389+ key = hist_browser__run(browser, "? - help", true, 0);
23882390
23892391 switch (key) {
23902392 case 's':
@@ -2453,7 +2455,7 @@ static int perf_c2c__hists_browse(struct hists *hists) · 62 unmodified lines
24532455 c2c_browser__update_nr_entries(browser);
24542456
24552457 while (1) {
2456− key = hist_browser__run(browser, "? - help", true);
2458+ key = hist_browser__run(browser, "? - help", true, 0);
24572459
24582460 switch (key) {
24592461 case 'q':
tools/perf/builtin-record.c+22−6
@@ -62,6 +62,7 @@ · 61 unmodified lines
6262 #include <linux/string.h>
6363 #include <linux/time64.h>
6464 #include <linux/zalloc.h>
65+#include <linux/bitmap.h>
6566
6667 struct switch_output {
6768 bool enabled;
@@ -93,7 +94,7 @@ struct record { · 25 unmodified lines
9394 bool timestamp_boundary;
9495 struct switch_output switch_output;
9596 unsigned long long samples;
96− cpu_set_t affinity_mask;
97+ struct mmap_cpu_mask affinity_mask;
9798 unsigned long output_max_size; /* = 0: unlimited */
9899 };
99100
@@ -961,10 +962,15 @@ static struct perf_event_header finished_round_event = { · 861 unmodified lines
961962 static void record__adjust_affinity(struct record *rec, struct mmap *map)
962963 {
963964 if (rec->opts.affinity != PERF_AFFINITY_SYS &&
964− !CPU_EQUAL(&rec->affinity_mask, &map->affinity_mask)) {
965− CPU_ZERO(&rec->affinity_mask);
966− CPU_OR(&rec->affinity_mask, &rec->affinity_mask, &map->affinity_mask);
967− sched_setaffinity(0, sizeof(rec->affinity_mask), &rec->affinity_mask);
965+ !bitmap_equal(rec->affinity_mask.bits, map->affinity_mask.bits,
966+ rec->affinity_mask.nbits)) {
967+ bitmap_zero(rec->affinity_mask.bits, rec->affinity_mask.nbits);
968+ bitmap_or(rec->affinity_mask.bits, rec->affinity_mask.bits,
969+ map->affinity_mask.bits, rec->affinity_mask.nbits);
970+ sched_setaffinity(0, MMAP_CPU_MASK_BYTES(&rec->affinity_mask),
971+ (cpu_set_t *)rec->affinity_mask.bits);
972+ if (verbose == 2)
973+ mmap_cpu_mask__scnprintf(&rec->affinity_mask, "thread");
968974 }
969975 }
970976
@@ -2433,7 +2439,6 @@ int cmd_record(int argc, const char **argv) · 1462 unmodified lines
24332439 # undef REASON
24342440 #endif
24352441
2436− CPU_ZERO(&rec->affinity_mask);
24372442 rec->opts.affinity = PERF_AFFINITY_SYS;
24382443
24392444 rec->evlist = evlist__new();
@@ -2499,6 +2504,16 @@ int cmd_record(int argc, const char **argv) · 59 unmodified lines
24992504
25002505 symbol__init(NULL);
25012506
2507+ if (rec->opts.affinity != PERF_AFFINITY_SYS) {
2508+ rec->affinity_mask.nbits = cpu__max_cpu();
2509+ rec->affinity_mask.bits = bitmap_alloc(rec->affinity_mask.nbits);
2510+ if (!rec->affinity_mask.bits) {
2511+ pr_err("Failed to allocate thread mask for %zd cpus\n", rec->affinity_mask.nbits);
2512+ return -ENOMEM;
2513+ }
2514+ pr_debug2("thread mask[%zd]: empty\n", rec->affinity_mask.nbits);
2515+ }
2516+
25022517 err = record__auxtrace_init(rec);
25032518 if (err)
25042519 goto out;
@@ -2613,6 +2628,7 @@ int cmd_record(int argc, const char **argv) · 108 unmodified lines
26132628
26142629 err = __cmd_record(&record, argc, argv);
26152630 out:
2631+ bitmap_free(rec->affinity_mask.bits);
26162632 evlist__delete(rec->evlist);
26172633 symbol__exit();
26182634 auxtrace_record__free(rec->itr);
tools/perf/builtin-report.c+12−4
@@ -412,10 +412,10 @@ static int report__setup_sample_type(struct report *rep) · 411 unmodified lines
412412 PERF_SAMPLE_BRANCH_ANY))
413413 rep->nonany_branch_mode = true;
414414
415−#ifndef HAVE_LIBUNWIND_SUPPORT
415+#if !defined(HAVE_LIBUNWIND_SUPPORT) && !defined(HAVE_DWARF_SUPPORT)
416416 if (dwarf_callchain_users) {
417− ui__warning("Please install libunwind development packages "
418− "during the perf build.\n");
417+ ui__warning("Please install libunwind or libdw "
418+ "development packages during the perf build.\n");
419419 }
420420 #endif
421421
@@ -1164,7 +1164,8 @@ int cmd_report(int argc, const char **argv) · 742 unmodified lines
11641164 report_callchain_help, &report_parse_callchain_opt,
11651165 callchain_default_opt),
11661166 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
1167− "Accumulate callchains of children and show total overhead as well"),
1167+ "Accumulate callchains of children and show total overhead as well. "
1168+ "Enabled by default, use --no-children to disable."),
11681169 OPT_INTEGER(0, "max-stack", &report.max_stack,
11691170 "Set the maximum stack depth when parsing the callchain, "
11701171 "anything beyond the specified depth will be ignored. "
@@ -1207,6 +1208,10 @@ int cmd_report(int argc, const char **argv) · 36 unmodified lines
12071208 "Display raw encoding of assembly instructions (default)"),
12081209 OPT_STRING('M', "disassembler-style", &report.annotation_opts.disassembler_style, "disassembler style",
12091210 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1211+ OPT_STRING(0, "prefix", &report.annotation_opts.prefix, "prefix",
1212+ "Add prefix to source file path names in programs (with --prefix-strip)"),
1213+ OPT_STRING(0, "prefix-strip", &report.annotation_opts.prefix_strip, "N",
1214+ "Strip first N entries of source file path name in programs (with --prefix)"),
12101215 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
12111216 "Show a column with the sum of periods"),
12121217 OPT_BOOLEAN_SET(0, "group", &symbol_conf.event_group, &report.group_set,
@@ -1286,6 +1291,9 @@ int cmd_report(int argc, const char **argv) · 73 unmodified lines
12861291 report.symbol_filter_str = argv[0];
12871292 }
12881293
1294+ if (annotate_check_args(&report.annotation_opts) < 0)
1295+ return -EINVAL;
1296+
12891297 if (report.mmaps_mode)
12901298 report.tasks_mode = true;
12911299
tools/perf/builtin-sched.c+13−0
@@ -51,6 +51,9 @@ · 50 unmodified lines
5151 #define SYM_LEN 129
5252 #define MAX_PID 1024000
5353
54+static const char *cpu_list;
55+static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
56+
5457 struct sched_atom;
5558
5659 struct task_desc {
@@ -2008,6 +2011,9 @@ static void timehist_print_sample(struct perf_sched *sched, · 1951 unmodified lines
20082011 char nstr[30];
20092012 u64 wait_time;
20102013
2014+ if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
2015+ return;
2016+
20112017 timestamp__scnprintf_usec(t, tstr, sizeof(tstr));
20122018 printf("%15s [%04d] ", tstr, sample->cpu);
20132019
@@ -2994,6 +3000,12 @@ static int perf_sched__timehist(struct perf_sched *sched) · 980 unmodified lines
29943000 if (IS_ERR(session))
29953001 return PTR_ERR(session);
29963002
3003+ if (cpu_list) {
3004+ err = perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap);
3005+ if (err < 0)
3006+ goto out;
3007+ }
3008+
29973009 evlist = session->evlist;
29983010
29993011 symbol__init(&session->header.env);
@@ -3429,6 +3441,7 @@ int cmd_sched(int argc, const char **argv) · 429 unmodified lines
34293441 "analyze events only for given process id(s)"),
34303442 OPT_STRING('t', "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
34313443 "analyze events only for given thread id(s)"),
3444+ OPT_STRING('C', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
34323445 OPT_PARENT(sched_options)
34333446 };
34343447
tools/perf/builtin-top.c+7−0
@@ -1512,6 +1512,10 @@ int cmd_top(int argc, const char **argv) · 1511 unmodified lines
15121512 "objdump binary to use for disassembly and annotations"),
15131513 OPT_STRING('M', "disassembler-style", &top.annotation_opts.disassembler_style, "disassembler style",
15141514 "Specify disassembler style (e.g. -M intel for intel syntax)"),
1515+ OPT_STRING(0, "prefix", &top.annotation_opts.prefix, "prefix",
1516+ "Add prefix to source file path names in programs (with --prefix-strip)"),
1517+ OPT_STRING(0, "prefix-strip", &top.annotation_opts.prefix_strip, "N",
1518+ "Strip first N entries of source file path name in programs (with --prefix)"),
15151519 OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"),
15161520 OPT_CALLBACK(0, "percent-limit", &top, "percent",
15171521 "Don't show entries under that percent", parse_percent_limit),
@@ -1582,6 +1586,9 @@ int cmd_top(int argc, const char **argv) · 64 unmodified lines
15821586 if (argc)
15831587 usage_with_options(top_usage, options);
15841588
1589+ if (annotate_check_args(&top.annotation_opts) < 0)
1590+ goto out_delete_evlist;
1591+
15851592 if (!top.evlist->core.nr_entries &&
15861593 perf_evlist__add_default(top.evlist) < 0) {
15871594 pr_err("Not enough memory for event selector list\n");
tools/perf/lib/Documentation/Makefile+0−7
@@ -1,7 +0,0 @@
1−all:
2− rst2man man/libperf.rst > man/libperf.7
3− rst2pdf tutorial/tutorial.rst
4−
5−clean:
6− rm -f man/libperf.7
7− rm -f tutorial/tutorial.pdf
tools/perf/lib/Documentation/man/libperf.rst+0−100
@@ -1,100 +0,0 @@
1−.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2−
3−libperf
4−
5−The libperf library provides an API to access the linux kernel perf
6−events subsystem. It provides the following high level objects:
7−
8− - struct perf_cpu_map
9− - struct perf_thread_map
10− - struct perf_evlist
11− - struct perf_evsel
12−
13−reference
14−=========
15−Function reference by header files:
16−
17−perf/core.h
18−-----------
19−.. code-block:: c
20−
21− typedef int (\*libperf_print_fn_t)(enum libperf_print_level level,
22− const char \*, va_list ap);
23−
24− void libperf_set_print(libperf_print_fn_t fn);
25−
26−perf/cpumap.h
27−-------------
28−.. code-block:: c
29−
30− struct perf_cpu_map \*perf_cpu_map__dummy_new(void);
31− struct perf_cpu_map \*perf_cpu_map__new(const char \*cpu_list);
32− struct perf_cpu_map \*perf_cpu_map__read(FILE \*file);
33− struct perf_cpu_map \*perf_cpu_map__get(struct perf_cpu_map \*map);
34− void perf_cpu_map__put(struct perf_cpu_map \*map);
35− int perf_cpu_map__cpu(const struct perf_cpu_map \*cpus, int idx);
36− int perf_cpu_map__nr(const struct perf_cpu_map \*cpus);
37− perf_cpu_map__for_each_cpu(cpu, idx, cpus)
38−
39−perf/threadmap.h
40−----------------
41−.. code-block:: c
42−
43− struct perf_thread_map \*perf_thread_map__new_dummy(void);
44− void perf_thread_map__set_pid(struct perf_thread_map \*map, int thread, pid_t pid);
45− char \*perf_thread_map__comm(struct perf_thread_map \*map, int thread);
46− struct perf_thread_map \*perf_thread_map__get(struct perf_thread_map \*map);
47− void perf_thread_map__put(struct perf_thread_map \*map);
48−
49−perf/evlist.h
50−-------------
51−.. code-block::
52−
53− void perf_evlist__init(struct perf_evlist \*evlist);
54− void perf_evlist__add(struct perf_evlist \*evlist,
55− struct perf_evsel \*evsel);
56− void perf_evlist__remove(struct perf_evlist \*evlist,
57− struct perf_evsel \*evsel);
58− struct perf_evlist \*perf_evlist__new(void);
59− void perf_evlist__delete(struct perf_evlist \*evlist);
60− struct perf_evsel\* perf_evlist__next(struct perf_evlist \*evlist,
61− struct perf_evsel \*evsel);
62− int perf_evlist__open(struct perf_evlist \*evlist);
63− void perf_evlist__close(struct perf_evlist \*evlist);
64− void perf_evlist__enable(struct perf_evlist \*evlist);
65− void perf_evlist__disable(struct perf_evlist \*evlist);
66− perf_evlist__for_each_evsel(evlist, pos)
67− void perf_evlist__set_maps(struct perf_evlist \*evlist,
68− struct perf_cpu_map \*cpus,
69− struct perf_thread_map \*threads);
70−
71−perf/evsel.h
72−------------
73−.. code-block:: c
74−
75− struct perf_counts_values {
76− union {
77− struct {
78− uint64_t val;
79− uint64_t ena;
80− uint64_t run;
81− };
82− uint64_t values[3];
83− };
84− };
85−
86− void perf_evsel__init(struct perf_evsel \*evsel,
87− struct perf_event_attr \*attr);
88− struct perf_evsel \*perf_evsel__new(struct perf_event_attr \*attr);
89− void perf_evsel__delete(struct perf_evsel \*evsel);
90− int perf_evsel__open(struct perf_evsel \*evsel, struct perf_cpu_map \*cpus,
91− struct perf_thread_map \*threads);
92− void perf_evsel__close(struct perf_evsel \*evsel);
93− int perf_evsel__read(struct perf_evsel \*evsel, int cpu, int thread,
94− struct perf_counts_values \*count);
95− int perf_evsel__enable(struct perf_evsel \*evsel);
96− int perf_evsel__disable(struct perf_evsel \*evsel);
97− int perf_evsel__apply_filter(struct perf_evsel \*evsel, const char \*filter);
98− struct perf_cpu_map \*perf_evsel__cpus(struct perf_evsel \*evsel);
99− struct perf_thread_map \*perf_evsel__threads(struct perf_evsel \*evsel);
100− struct perf_event_attr \*perf_evsel__attr(struct perf_evsel \*evsel);
tools/perf/lib/Documentation/tutorial/tutorial.rst+0−123
@@ -1,123 +0,0 @@
1−.. SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2−
3−libperf tutorial
4−================
5−
6−Compile and install libperf from kernel sources
7−===============================================
8−.. code-block:: bash
9−
10− git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
11− cd linux/tools/perf/lib
12− make
13− sudo make install prefix=/usr
14−
15−Libperf object
16−==============
17−The libperf library provides several high level objects:
18−
19−struct perf_cpu_map
20− Provides a cpu list abstraction.
21−
22−struct perf_thread_map
23− Provides a thread list abstraction.
24−
25−struct perf_evsel
26− Provides an abstraction for single a perf event.
27−
28−struct perf_evlist
29− Gathers several struct perf_evsel object and performs functions on all of them.
30−
31−The exported API binds these objects together,
32−for full reference see the libperf.7 man page.
33−
34−Examples
35−========
36−Examples aim to explain libperf functionality on simple use cases.
37−They are based in on a checked out linux kernel git tree:
38−
39−.. code-block:: bash
40−
41− $ cd tools/perf/lib/Documentation/tutorial/
42− $ ls -d ex-*
43− ex-1-compile ex-2-evsel-stat ex-3-evlist-stat
44−
45−ex-1-compile example
46−====================
47−This example shows the basic usage of *struct perf_cpu_map*,
48−how to create it and display its cpus:
49−
50−.. code-block:: bash
51−
52− $ cd ex-1-compile/
53− $ make
54− gcc -o test test.c -lperf
55− $ ./test
56− 0 1 2 3 4 5 6 7
57−
58−
59−The full code listing is here:
60−
61−.. code-block:: c
62−
63− 1 #include <perf/cpumap.h>
64− 2
65− 3 int main(int argc, char **Argv)
66− 4 {
67− 5 struct perf_cpu_map *cpus;
68− 6 int cpu, tmp;
69− 7
70− 8 cpus = perf_cpu_map__new(NULL);
71− 9
72− 10 perf_cpu_map__for_each_cpu(cpu, tmp, cpus)
73− 11 fprintf(stdout, "%d ", cpu);
74− 12
75− 13 fprintf(stdout, "\n");
76− 14
77− 15 perf_cpu_map__put(cpus);
78− 16 return 0;
79− 17 }
80−
81−
82−First you need to include the proper header to have *struct perf_cpumap*
83−declaration and functions:
84−
85−.. code-block:: c
86−
87− 1 #include <perf/cpumap.h>
88−
89−
90−The *struct perf_cpumap* object is created by *perf_cpu_map__new* call.
91−The *NULL* argument asks it to populate the object with the current online CPUs list:
92−
93−.. code-block:: c
94−
95− 8 cpus = perf_cpu_map__new(NULL);
96−
97−This is paired with a *perf_cpu_map__put*, that drops its reference at the end, possibly deleting it.
98−
99−.. code-block:: c
100−
101− 15 perf_cpu_map__put(cpus);
102−
103−The iteration through the *struct perf_cpumap* CPUs is done using the *perf_cpu_map__for_each_cpu*
104−macro which requires 3 arguments:
105−
106−- cpu - the cpu numer
107−- tmp - iteration helper variable
108−- cpus - the *struct perf_cpumap* object
109−
110−.. code-block:: c
111−
112− 10 perf_cpu_map__for_each_cpu(cpu, tmp, cpus)
113− 11 fprintf(stdout, "%d ", cpu);
114−
115−ex-2-evsel-stat example
116−=======================
117−
118−TBD
119−
120−ex-3-evlist-stat example
121−========================
122−
123−TBD
tools/perf/tests/bp_signal.c+5−5
@@ -263,20 +263,20 @@ int test__bp_signal(struct test *test __maybe_unused, int subtest __maybe_unused · 262 unmodified lines
263263 if (count1 == 11)
264264 pr_debug("failed: RF EFLAG recursion issue detected\n");
265265 else
266− pr_debug("failed: wrong count for bp1%lld\n", count1);
266+ pr_debug("failed: wrong count for bp1: %lld, expected 1\n", count1);
267267 }
268268
269269 if (overflows != 3)
270− pr_debug("failed: wrong overflow hit\n");
270+ pr_debug("failed: wrong overflow (%d) hit, expected 3\n", overflows);
271271
272272 if (overflows_2 != 3)
273− pr_debug("failed: wrong overflow_2 hit\n");
273+ pr_debug("failed: wrong overflow_2 (%d) hit, expected 3\n", overflows_2);
274274
275275 if (count2 != 3)
276− pr_debug("failed: wrong count for bp2\n");
276+ pr_debug("failed: wrong count for bp2 (%lld), expected 3\n", count2);
277277
278278 if (count3 != 2)
279− pr_debug("failed: wrong count for bp3\n");
279+ pr_debug("failed: wrong count for bp3 (%lld), expected 2\n", count3);
280280
281281 return count1 == 1 && overflows == 3 && count2 == 3 && overflows_2 == 3 && count3 == 2 ?
282282 TEST_OK : TEST_FAIL;
tools/perf/trace/beauty/sockaddr.c+1−1
@@ -72,5 +72,5 @@ size_t syscall_arg__scnprintf_sockaddr(char *bf, size_t size, struct syscall_arg · 71 unmodified lines
7272 if (arg->augmented.args)
7373 return syscall_arg__scnprintf_augmented_sockaddr(arg, bf, size);
7474
75− return scnprintf(bf, size, "%#x", arg->val);
75+ return scnprintf(bf, size, "%#lx", arg->val);
7676 }
tools/perf/ui/browsers/hists.c+191−86
@@ -18,7 +18,9 @@ · 17 unmodified lines
1818 #include "../../util/evlist.h"
1919 #include "../../util/header.h"
2020 #include "../../util/hist.h"
21+#include "../../util/machine.h"
2122 #include "../../util/map.h"
23+#include "../../util/maps.h"
2224 #include "../../util/symbol.h"
2325 #include "../../util/map_symbol.h"
2426 #include "../../util/branch.h"
@@ -391,6 +393,57 @@ static void hist_entry__init_have_children(struct hist_entry *he) · 366 unmodified lines
391393 he->init_have_children = true;
392394 }
393395
396+static bool hist_browser__selection_has_children(struct hist_browser *browser)
397+{
398+ struct hist_entry *he = browser->he_selection;
399+ struct map_symbol *ms = browser->selection;
400+
401+ if (!he || !ms)
402+ return false;
403+
404+ if (ms == &he->ms)
405+ return he->has_children;
406+
407+ return container_of(ms, struct callchain_list, ms)->has_children;
408+}
409+
410+static bool hist_browser__he_selection_unfolded(struct hist_browser *browser)
411+{
412+ return browser->he_selection ? browser->he_selection->unfolded : false;
413+}
414+
415+static bool hist_browser__selection_unfolded(struct hist_browser *browser)
416+{
417+ struct hist_entry *he = browser->he_selection;
418+ struct map_symbol *ms = browser->selection;
419+
420+ if (!he || !ms)
421+ return false;
422+
423+ if (ms == &he->ms)
424+ return he->unfolded;
425+
426+ return container_of(ms, struct callchain_list, ms)->unfolded;
427+}
428+
429+static char *hist_browser__selection_sym_name(struct hist_browser *browser, char *bf, size_t size)
430+{
431+ struct hist_entry *he = browser->he_selection;
432+ struct map_symbol *ms = browser->selection;
433+ struct callchain_list *callchain_entry;
434+
435+ if (!he || !ms)
436+ return NULL;
437+
438+ if (ms == &he->ms) {
439+ hist_entry__sym_snprintf(he, bf, size, 0);
440+ return bf + 4; // skip the level, e.g. '[k] '
441+ }
442+
443+ callchain_entry = container_of(ms, struct callchain_list, ms);
444+ return callchain_list__sym_name(callchain_entry, bf, size, browser->show_dso);
445+}
446+
394447 static bool hist_browser__toggle_fold(struct hist_browser *browser)
395448 {
396449 struct hist_entry *he = browser->he_selection;
@@ -624,10 +677,81 @@ static int hist_browser__title(struct hist_browser *browser, char *bf, size_t si · 227 unmodified lines
624677 return browser->title ? browser->title(browser, bf, size) : 0;
625678 }
626679
680+static int hist_browser__handle_hotkey(struct hist_browser *browser, bool warn_lost_event, char *title, int key)
681+{
682+ switch (key) {
683+ case K_TIMER: {
684+ struct hist_browser_timer *hbt = browser->hbt;
685+ u64 nr_entries;
686+
687+ WARN_ON_ONCE(!hbt);
688+
689+ if (hbt)
690+ hbt->timer(hbt->arg);
691+
692+ if (hist_browser__has_filter(browser) || symbol_conf.report_hierarchy)
693+ hist_browser__update_nr_entries(browser);
694+
695+ nr_entries = hist_browser__nr_entries(browser);
696+ ui_browser__update_nr_entries(&browser->b, nr_entries);
697+
698+ if (warn_lost_event &&
699+ (browser->hists->stats.nr_lost_warned !=
700+ browser->hists->stats.nr_events[PERF_RECORD_LOST])) {
701+ browser->hists->stats.nr_lost_warned =
702+ browser->hists->stats.nr_events[PERF_RECORD_LOST];
703+ ui_browser__warn_lost_events(&browser->b);
704+ }
705+
706+ hist_browser__title(browser, title, sizeof(title));
707+ ui_browser__show_title(&browser->b, title);
708+ break;
709+ }
710+ case 'D': { /* Debug */
711+ struct hist_entry *h = rb_entry(browser->b.top, struct hist_entry, rb_node);
712+ static int seq;
713+
714+ ui_helpline__pop();
715+ ui_helpline__fpush("%d: nr_ent=(%d,%d), etl: %d, rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d",
716+ seq++, browser->b.nr_entries, browser->hists->nr_entries,
717+ browser->b.extra_title_lines, browser->b.rows,
718+ browser->b.index, browser->b.top_idx, h->row_offset, h->nr_rows);
719+ }
720+ break;
721+ case 'C':
722+ /* Collapse the whole world. */
723+ hist_browser__set_folding(browser, false);
724+ break;
725+ case 'c':
726+ /* Collapse the selected entry. */
727+ hist_browser__set_folding_selected(browser, false);
728+ break;
729+ case 'E':
730+ /* Expand the whole world. */
731+ hist_browser__set_folding(browser, true);
732+ break;
733+ case 'e':
734+ /* Expand the selected entry. */
735+ hist_browser__set_folding_selected(browser, !hist_browser__he_selection_unfolded(browser));
736+ break;
737+ case 'H':
738+ browser->show_headers = !browser->show_headers;
739+ hist_browser__update_rows(browser);
740+ break;
741+ case '+':
742+ if (hist_browser__toggle_fold(browser))
743+ break;
744+ /* fall thru */
745+ default:
746+ return -1;
747+ }
748+
749+ return 0;
750+}
751+
627752 int hist_browser__run(struct hist_browser *browser, const char *help,
628− bool warn_lost_event)
753+ bool warn_lost_event, int key)
629754 {
630− int key;
631755 char title[160];
632756 struct hist_browser_timer *hbt = browser->hbt;
633757 int delay_secs = hbt ? hbt->refresh : 0;
@@ -640,79 +764,14 @@ int hist_browser__run(struct hist_browser *browser, const char *help, · 6 unmodified lines
640764 if (ui_browser__show(&browser->b, title, "%s", help) < 0)
641765 return -1;
642766
767+ if (key && hist_browser__handle_hotkey(browser, warn_lost_event, title, key))
768+ goto out;
769+
643770 while (1) {
644771 key = ui_browser__run(&browser->b, delay_secs);
645772
646− switch (key) {
647− case K_TIMER: {
648− u64 nr_entries;
649−
650− WARN_ON_ONCE(!hbt);
651−
652− if (hbt)
653− hbt->timer(hbt->arg);
654−
655− if (hist_browser__has_filter(browser) ||
656− symbol_conf.report_hierarchy)
657− hist_browser__update_nr_entries(browser);
658−
659− nr_entries = hist_browser__nr_entries(browser);
660− ui_browser__update_nr_entries(&browser->b, nr_entries);
661−
662− if (warn_lost_event &&
663− (browser->hists->stats.nr_lost_warned !=
664− browser->hists->stats.nr_events[PERF_RECORD_LOST])) {
665− browser->hists->stats.nr_lost_warned =
666− browser->hists->stats.nr_events[PERF_RECORD_LOST];
667− ui_browser__warn_lost_events(&browser->b);
668− }
669−
670− hist_browser__title(browser, title, sizeof(title));
671− ui_browser__show_title(&browser->b, title);
672− continue;
673− }
674− case 'D': { /* Debug */
675− static int seq;
676− struct hist_entry *h = rb_entry(browser->b.top,
677− struct hist_entry, rb_node);
678− ui_helpline__pop();
679− ui_helpline__fpush("%d: nr_ent=(%d,%d), etl: %d, rows=%d, idx=%d, fve: idx=%d, row_off=%d, nrows=%d",
680− seq++, browser->b.nr_entries,
681− browser->hists->nr_entries,
682− browser->b.extra_title_lines,
683− browser->b.rows,
684− browser->b.index,
685− browser->b.top_idx,
686− h->row_offset, h->nr_rows);
687− }
688− break;
689− case 'C':
690− /* Collapse the whole world. */
691− hist_browser__set_folding(browser, false);
692− break;
693− case 'c':
694− /* Collapse the selected entry. */
695− hist_browser__set_folding_selected(browser, false);
773+ if (hist_browser__handle_hotkey(browser, warn_lost_event, title, key))
696774 break;
697− case 'E':
698− /* Expand the whole world. */
699− hist_browser__set_folding(browser, true);
700− break;
701− case 'e':
702− /* Expand the selected entry. */
703− hist_browser__set_folding_selected(browser, true);
704− break;
705− case 'H':
706− browser->show_headers = !browser->show_headers;
707− hist_browser__update_rows(browser);
708− break;
709− case K_ENTER:
710− if (hist_browser__toggle_fold(browser))
711− break;
712− /* fall thru */
713− default:
714− goto out;
715− }
716775 }
717776 out:
718777 ui_browser__hide(&browser->b);
@@ -2339,7 +2398,7 @@ close_file_and_continue: · 1620 unmodified lines
23392398 closedir(pwd_dir);
23402399
23412400 if (nr_options) {
2342− choice = ui__popup_menu(nr_options, options);
2401+ choice = ui__popup_menu(nr_options, options, NULL);
23432402 if (choice < nr_options && choice >= 0) {
23442403 tmp = strdup(abs_path[choice]);
23452404 if (tmp) {
@@ -2411,7 +2470,8 @@ add_annotate_opt(struct hist_browser *browser __maybe_unused, · 65 unmodified lines
24112470 struct popup_action *act, char **optstr,
24122471 struct map_symbol *ms)
24132472 {
2414− if (ms->sym == NULL || ms->map->dso->annotate_warned)
2473+ if (ms->sym == NULL || ms->map->dso->annotate_warned ||
2474+ symbol__annotation(ms->sym)->src == NULL)
24152475 return 0;
24162476
24172477 if (asprintf(optstr, "Annotate %s", ms->sym->name) < 0)
@@ -2484,11 +2544,8 @@ add_thread_opt(struct hist_browser *browser, struct popup_action *act, · 66 unmodified lines
24842544 return 1;
24852545 }
24862546
2487−static int
2488−do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
2547+static int hists_browser__zoom_map(struct hist_browser *browser, struct map *map)
24892548 {
2490− struct map *map = act->ms.map;
2491−
24922549 if (!hists__has(browser->hists, dso) || map == NULL)
24932550 return 0;
24942551
@@ -2510,6 +2567,12 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act) · 15 unmodified lines
25102567 return 0;
25112568 }
25122569
2570+static int
2571+do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
2572+{
2573+ return hists_browser__zoom_map(browser, act->ms.map);
2574+}
2575+
25132576 static int
25142577 add_dso_opt(struct hist_browser *browser, struct popup_action *act,
25152578 char **optstr, struct map *map)
@@ -2517,7 +2580,7 @@ add_dso_opt(struct hist_browser *browser, struct popup_action *act, · 1 unmodified line
25172580 if (!hists__has(browser->hists, dso) || map == NULL)
25182581 return 0;
25192582
2520− if (asprintf(optstr, "Zoom %s %s DSO",
2583+ if (asprintf(optstr, "Zoom %s %s DSO (use the 'k' hotkey to zoom directly into the kernel)",
25212584 browser->hists->dso_filter ? "out of" : "into",
25222585 __map__is_kernel(map) ? "the Kernel" : map->dso->short_name) < 0)
25232586 return 0;
@@ -2527,6 +2590,28 @@ add_dso_opt(struct hist_browser *browser, struct popup_action *act, · 3 unmodified lines
25272590 return 1;
25282591 }
25292592
2593+static int do_toggle_callchain(struct hist_browser *browser, struct popup_action *act __maybe_unused)
2594+{
2595+ hist_browser__toggle_fold(browser);
2596+ return 0;
2597+}
2598+
2599+static int add_callchain_toggle_opt(struct hist_browser *browser, struct popup_action *act, char **optstr)
2600+{
2601+ char sym_name[512];
2602+
2603+ if (!hist_browser__selection_has_children(browser))
2604+ return 0;
2605+
2606+ if (asprintf(optstr, "%s [%s] callchain (one level, same as '+' hotkey, use 'e'/'c' for the whole main level entry)",
2607+ hist_browser__selection_unfolded(browser) ? "Collapse" : "Expand",
2608+ hist_browser__selection_sym_name(browser, sym_name, sizeof(sym_name))) < 0)
2609+ return 0;
2610+
2611+ act->fn = do_toggle_callchain;
2612+ return 1;
2613+}
2614+
25302615 static int
25312616 do_browse_map(struct hist_browser *browser __maybe_unused,
25322617 struct popup_action *act)
@@ -2858,12 +2943,15 @@ static int perf_evsel__hists_browse(struct evsel *evsel, int nr_events, · 325 unmodified lines
28582943 "For symbolic views (--sort has sym):\n\n" \
28592944 "ENTER Zoom into DSO/Threads & Annotate current symbol\n" \
28602945 "ESC Zoom out\n" \
2946+ "+ Expand/Collapse one callchain level\n" \
28612947 "a Annotate current symbol\n" \
28622948 "C Collapse all callchains\n" \
28632949 "d Zoom into current DSO\n" \
2950+ "e Expand/Collapse main entry callchains\n" \
28642951 "E Expand all callchains\n" \
28652952 "F Toggle percentage of filtered entries\n" \
28662953 "H Display column headers\n" \
2954+ "k Zoom into the kernel map\n" \
28672955 "L Change percent limit\n" \
28682956 "m Display context menu\n" \
28692957 "S Zoom into current Processor Socket\n" \
@@ -2914,13 +3002,13 @@ static int perf_evsel__hists_browse(struct evsel *evsel, int nr_events, · 44 unmodified lines
29143002 while (1) {
29153003 struct thread *thread = NULL;
29163004 struct map *map = NULL;
2917− int choice = 0;
3005+ int choice;
29183006 int socked_id = -1;
29193007
2920− nr_options = 0;
2921−
2922− key = hist_browser__run(browser, helpline,
2923− warn_lost_event);
3008+ key = 0; // reset key
3009+do_hotkey: // key came straight from options ui__popup_menu()
3010+ choice = nr_options = 0;
3011+ key = hist_browser__run(browser, helpline, warn_lost_event, key);
29243012
29253013 if (browser->he_selection != NULL) {
29263014 thread = hist_browser__selected_thread(browser);
@@ -2950,6 +3038,14 @@ static int perf_evsel__hists_browse(struct evsel *evsel, int nr_events, · 23 unmodified lines
29503038 browser->selection->map->dso->annotate_warned)
29513039 continue;
29523040
3041+ if (symbol__annotation(browser->selection->sym)->src == NULL) {
3042+ ui_browser__warning(&browser->b, delay_secs * 2,
3043+ "No samples for the \"%s\" symbol.\n\n"
3044+ "Probably appeared just in a callchain",
3045+ browser->selection->sym->name);
3046+ continue;
3047+ }
3048+
29533049 actions->ms.map = browser->selection->map;
29543050 actions->ms.sym = browser->selection->sym;
29553051 do_annotate(browser, actions);
@@ -2961,6 +3057,10 @@ static int perf_evsel__hists_browse(struct evsel *evsel, int nr_events, · 5 unmodified lines
29613057 actions->ms.map = map;
29623058 do_zoom_dso(browser, actions);
29633059 continue;
3060+ case 'k':
3061+ if (browser->selection != NULL)
3062+ hists_browser__zoom_map(browser, browser->selection->maps->machine->vmlinux_map);
3063+ continue;
29643064 case 'V':
29653065 verbose = (verbose + 1) % 4;
29663066 browser->show_dso = verbose > 0;
@@ -3062,6 +3162,7 @@ static int perf_evsel__hists_browse(struct evsel *evsel, int nr_events, · 95 unmodified lines
30623162
30633163 continue;
30643164 }
3165+ actions->ms.map = map;
30653166 top = pstack__peek(browser->pstack);
30663167 if (top == &browser->hists->dso_filter) {
30673168 /*
@@ -3135,6 +3236,7 @@ skip_annotation: · 67 unmodified lines
31353236 &options[nr_options], thread);
31363237 nr_options += add_dso_opt(browser, &actions[nr_options],
31373238 &options[nr_options], map);
3239+ nr_options += add_callchain_toggle_opt(browser, &actions[nr_options], &options[nr_options]);
31383240 nr_options += add_map_opt(browser, &actions[nr_options],
31393241 &options[nr_options],
31403242 browser->selection ?
@@ -3193,10 +3295,13 @@ skip_scripting: · 52 unmodified lines
31933295 do {
31943296 struct popup_action *act;
31953297
3196− choice = ui__popup_menu(nr_options, options);
3197− if (choice == -1 || choice >= nr_options)
3298+ choice = ui__popup_menu(nr_options, options, &key);
3299+ if (choice == -1)
31983300 break;
31993301
3302+ if (choice == nr_options)
3303+ goto do_hotkey;
3304+
32003305 act = &actions[choice];
32013306 key = act->fn(browser, act);
32023307 } while (key == 1);
@@ -3492,7 +3597,7 @@ int block_hists_tui_browse(struct block_hist *bh, struct evsel *evsel, · 289 unmodified lines
34923597 memset(&action, 0, sizeof(action));
34933598
34943599 while (1) {
3495− key = hist_browser__run(browser, "? - help", true);
3600+ key = hist_browser__run(browser, "? - help", true, 0);
34963601
34973602 switch (key) {
34983603 case 'q':
tools/perf/ui/browsers/hists.h+1−1
@@ -34,7 +34,7 @@ struct hist_browser { · 33 unmodified lines
3434 struct hist_browser *hist_browser__new(struct hists *hists);
3535 void hist_browser__delete(struct hist_browser *browser);
3636 int hist_browser__run(struct hist_browser *browser, const char *help,
37− bool warn_lost_event);
37+ bool warn_lost_event, int key);
3838 void hist_browser__init(struct hist_browser *browser,
3939 struct hists *hists);
4040 #endif /* _PERF_UI_BROWSER_HISTS_H_ */
tools/perf/ui/browsers/res_sample.c+1−1
@@ -56,7 +56,7 @@ int res_sample_browse(struct res_sample *res_samples, int num_res, · 55 unmodified lines
5656 return -1;
5757 }
5858 }
59− choice = ui__popup_menu(num_res, names);
59+ choice = ui__popup_menu(num_res, names, NULL);
6060 for (i = 0; i < num_res; i++)
6161 zfree(&names[i]);
6262 free(names);
tools/perf/ui/browsers/scripts.c+1−1
@@ -126,7 +126,7 @@ static int list_scripts(char *script_name, bool *custom, · 125 unmodified lines
126126 SCRIPT_FULLPATH_LEN);
127127 if (num < 0)
128128 num = 0;
129− choice = ui__popup_menu(num + max_std, (char * const *)names);
129+ choice = ui__popup_menu(num + max_std, (char * const *)names, NULL);
130130 if (choice < 0) {
131131 ret = -1;
132132 goto out;
tools/perf/ui/gtk/Build+6−1
@@ -1,4 +1,4 @@
1−CFLAGS_gtk += -fPIC $(GTK_CFLAGS)
1+CFLAGS_gtk += -fPIC $(GTK_CFLAGS) -Wno-deprecated-declarations
22
33 gtk-y += browser.o
44 gtk-y += hists.o
@@ -7,3 +7,8 @@ gtk-y += util.o · 2 unmodified lines
77 gtk-y += helpline.o
88 gtk-y += progress.o
99 gtk-y += annotate.o
10+gtk-y += zalloc.o
11+
12+$(OUTPUT)ui/gtk/zalloc.o: ../lib/zalloc.c FORCE
13+ $(call rule_mkdir)
14+ $(call if_changed_dep,cc_o_c)
tools/perf/ui/tui/util.c+8−4
@@ -23,7 +23,7 @@ static void ui_browser__argv_write(struct ui_browser *browser, · 22 unmodified lines
2323 ui_browser__write_nstring(browser, *arg, browser->width);
2424 }
2525
26−static int popup_menu__run(struct ui_browser *menu)
26+static int popup_menu__run(struct ui_browser *menu, int *keyp)
2727 {
2828 int key;
2929
@@ -45,6 +45,11 @@ static int popup_menu__run(struct ui_browser *menu) · 15 unmodified lines
4545 key = -1;
4646 break;
4747 default:
48+ if (keyp) {
49+ *keyp = key;
50+ key = menu->nr_entries;
51+ break;
52+ }
4853 continue;
4954 }
5055
@@ -55,7 +60,7 @@ static int popup_menu__run(struct ui_browser *menu) · 4 unmodified lines
5560 return key;
5661 }
5762
58−int ui__popup_menu(int argc, char * const argv[])
63+int ui__popup_menu(int argc, char * const argv[], int *keyp)
5964 {
6065 struct ui_browser menu = {
6166 .entries = (void *)argv,
@@ -64,8 +69,7 @@ int ui__popup_menu(int argc, char * const argv[]) · 2 unmodified lines
6469 .write = ui_browser__argv_write,
6570 .nr_entries = argc,
6671 };
67−
68− return popup_menu__run(&menu);
72+ return popup_menu__run(&menu, keyp);
6973 }
7074
7175 int ui_browser__input_window(const char *title, const char *text, char *input,
tools/perf/ui/util.h+1−1
@@ -5,7 +5,7 @@ · 4 unmodified lines
55 #include <stdarg.h>
66
77 int ui__getch(int delay_secs);
8−int ui__popup_menu(int argc, char * const argv[]);
8+int ui__popup_menu(int argc, char * const argv[], int *keyp);
99 int ui__help_window(const char *text);
1010 int ui__dialog_yesno(const char *msg);
1111 void __ui__info_window(const char *title, const char *text, const char *exit_msg);
tools/perf/util/annotate.c+17−2
@@ -1966,14 +1966,20 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) · 1965 unmodified lines
19661966 err = asprintf(&command,
19671967 "%s %s%s --start-address=0x%016" PRIx64
19681968 " --stop-address=0x%016" PRIx64
1969− " -l -d %s %s -C \"$1\"",
1969+ " -l -d %s %s %s %c%s%c %s%s -C \"$1\"",
19701970 opts->objdump_path ?: "objdump",
19711971 opts->disassembler_style ? "-M " : "",
19721972 opts->disassembler_style ?: "",
19731973 map__rip_2objdump(map, sym->start),
19741974 map__rip_2objdump(map, sym->end),
19751975 opts->show_asm_raw ? "" : "--no-show-raw-insn",
1976− opts->annotate_src ? "-S" : "");
1976+ opts->annotate_src ? "-S" : "",
1977+ opts->prefix ? "--prefix " : "",
1978+ opts->prefix ? '"' : ' ',
1979+ opts->prefix ?: "",
1980+ opts->prefix ? '"' : ' ',
1981+ opts->prefix_strip ? "--prefix-strip=" : "",
1982+ opts->prefix_strip ?: "");
19771983
19781984 if (err < 0) {
19791985 pr_err("Failure allocating memory for the command to run\n");
@@ -3204,3 +3210,12 @@ out: · 1224 unmodified lines
32043210 free(str1);
32053211 return err;
32063212 }
3213+
3214+int annotate_check_args(struct annotation_options *args)
3215+{
3216+ if (args->prefix_strip && !args->prefix) {
3217+ pr_err("--prefix-strip requires --prefix\n");
3218+ return -1;
3219+ }
3220+ return 0;
3221+}
tools/perf/util/annotate.h+5−0
@@ -94,6 +94,8 @@ struct annotation_options { · 93 unmodified lines
9494 int context;
9595 const char *objdump_path;
9696 const char *disassembler_style;
97+ const char *prefix;
98+ const char *prefix_strip;
9799 unsigned int percent_type;
98100 };
99101
@@ -415,4 +417,7 @@ void annotation_config__init(void); · 315 unmodified lines
415417
416418 int annotate_parse_percent_type(const struct option *opt, const char *_str,
417419 int unset);
420+
421+int annotate_check_args(struct annotation_options *args);
422+
418423 #endif /* __PERF_ANNOTATE_H */
tools/perf/util/c++/clang.cpp+4−0
@@ -71,7 +71,11 @@ getModuleFromSource(llvm::opt::ArgStringList CFlags, · 70 unmodified lines
7171 CompilerInstance Clang;
7272 Clang.createDiagnostics();
7373
74+#if CLANG_VERSION_MAJOR < 9
7475 Clang.setVirtualFileSystem(&*VFS);
76+#else
77+ Clang.createFileManager(&*VFS);
78+#endif
7579
7680 #if CLANG_VERSION_MAJOR < 4
7781 IntrusiveRefCntPtr<CompilerInvocation> CI =
tools/perf/util/expr.y+2−1
@@ -12,7 +12,8 @@ · 11 unmodified lines
1212 #define MAXIDLEN 256
1313 %}
1414
15−%pure-parser
15+%define api.pure full
16+
1617 %parse-param { double *final_val }
1718 %parse-param { struct parse_ctx *ctx }
1819 %parse-param { const char **pp }
tools/perf/util/header.c+1−1
@@ -2922,7 +2922,7 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full) · 2921 unmodified lines
29222922 if (ret == -1)
29232923 return -1;
29242924
2925− stctime = st.st_ctime;
2925+ stctime = st.st_mtime;
29262926 fprintf(fp, "# captured on : %s", ctime(&stctime));
29272927
29282928 fprintf(fp, "# header version : %u\n", header->version);
tools/perf/util/mmap.c+34−6
@@ -23,6 +23,18 @@ · 22 unmodified lines
2323 #include "mmap.h"
2424 #include "../perf.h"
2525 #include <internal/lib.h> /* page_size */
26+#include <linux/bitmap.h>
27+
28+#define MASK_SIZE 1023
29+void mmap_cpu_mask__scnprintf(struct mmap_cpu_mask *mask, const char *tag)
30+{
31+ char buf[MASK_SIZE + 1];
32+ size_t len;
33+
34+ len = bitmap_scnprintf(mask->bits, mask->nbits, buf, MASK_SIZE);
35+ buf[len] = '\0';
36+ pr_debug("%p: %s mask[%zd]: %s\n", mask, tag, mask->nbits, buf);
37+}
2638
2739 size_t mmap__mmap_len(struct mmap *map)
2840 {
@@ -207,6 +219,8 @@ static void perf_mmap__aio_munmap(struct mmap *map __maybe_unused) · 178 unmodified lines
207219
208220 void mmap__munmap(struct mmap *map)
209221 {
222+ bitmap_free(map->affinity_mask.bits);
223+
210224 perf_mmap__aio_munmap(map);
211225 if (map->data != NULL) {
212226 munmap(map->data, mmap__mmap_len(map));
@@ -215,7 +229,7 @@ void mmap__munmap(struct mmap *map) · 2 unmodified lines
215229 auxtrace_mmap__munmap(&map->auxtrace_mmap);
216230 }
217231
218−static void build_node_mask(int node, cpu_set_t *mask)
232+static void build_node_mask(int node, struct mmap_cpu_mask *mask)
219233 {
220234 int c, cpu, nr_cpus;
221235 const struct perf_cpu_map *cpu_map = NULL;
@@ -228,17 +242,23 @@ static void build_node_mask(int node, cpu_set_t *mask) · 6 unmodified lines
228242 for (c = 0; c < nr_cpus; c++) {
229243 cpu = cpu_map->map[c]; /* map c index to online cpu index */
230244 if (cpu__get_node(cpu) == node)
231− CPU_SET(cpu, mask);
245+ set_bit(cpu, mask->bits);
232246 }
233247 }
234248
235−static void perf_mmap__setup_affinity_mask(struct mmap *map, struct mmap_params *mp)
249+static int perf_mmap__setup_affinity_mask(struct mmap *map, struct mmap_params *mp)
236250 {
237− CPU_ZERO(&map->affinity_mask);
251+ map->affinity_mask.nbits = cpu__max_cpu();
252+ map->affinity_mask.bits = bitmap_alloc(map->affinity_mask.nbits);
253+ if (!map->affinity_mask.bits)
254+ return -1;
255+
238256 if (mp->affinity == PERF_AFFINITY_NODE && cpu__max_node() > 1)
239257 build_node_mask(cpu__get_node(map->core.cpu), &map->affinity_mask);
240258 else if (mp->affinity == PERF_AFFINITY_CPU)
241− CPU_SET(map->core.cpu, &map->affinity_mask);
259+ set_bit(map->core.cpu, map->affinity_mask.bits);
260+
261+ return 0;
242262 }
243263
244264 int mmap__mmap(struct mmap *map, struct mmap_params *mp, int fd, int cpu)
@@ -249,7 +269,15 @@ int mmap__mmap(struct mmap *map, struct mmap_params *mp, int fd, int cpu) · 4 unmodified lines
249269 return -1;
250270 }
251271
252− perf_mmap__setup_affinity_mask(map, mp);
272+ if (mp->affinity != PERF_AFFINITY_SYS &&
273+ perf_mmap__setup_affinity_mask(map, mp)) {
274+ pr_debug2("failed to alloc mmap affinity mask, error %d\n",
275+ errno);
276+ return -1;
277+ }
278+
279+ if (verbose == 2)
280+ mmap_cpu_mask__scnprintf(&map->affinity_mask, "mmap");
253281
254282 map->core.flush = mp->flush;
255283
tools/perf/util/mmap.h+12−1
@@ -15,6 +15,15 @@ · 14 unmodified lines
1515 #include "event.h"
1616
1717 struct aiocb;
18+
19+struct mmap_cpu_mask {
20+ unsigned long *bits;
21+ size_t nbits;
22+};
23+
24+#define MMAP_CPU_MASK_BYTES(m) \
25+ (BITS_TO_LONGS(((struct mmap_cpu_mask *)m)->nbits) * sizeof(unsigned long))
26+
1827 /**
1928 * struct mmap - perf's ring buffer mmap details
2029 *
@@ -31,7 +40,7 @@ struct mmap { · 10 unmodified lines
3140 int nr_cblocks;
3241 } aio;
3342 #endif
34− cpu_set_t affinity_mask;
43+ struct mmap_cpu_mask affinity_mask;
3544 void *data;
3645 int comp_level;
3746 };
@@ -52,4 +61,6 @@ int perf_mmap__push(struct mmap *md, void *to, · 14 unmodified lines
5261
5362 size_t mmap__mmap_len(struct mmap *map);
5463
64+void mmap_cpu_mask__scnprintf(struct mmap_cpu_mask *mask, const char *tag);
65+
5566 #endif /*__PERF_MMAP_H */
tools/perf/util/parse-events.y+1−1
@@ -1,4 +1,4 @@
1−%pure-parser
1+%define api.pure full
22 %parse-param {void *_parse_state}
33 %parse-param {void *scanner}
44 %lex-param {void* scanner}
tools/perf/util/sort.c+1−2
@@ -324,8 +324,7 @@ static int _hist_entry__sym_snprintf(struct map_symbol *ms, · 323 unmodified lines
324324 return ret;
325325 }
326326
327−static int hist_entry__sym_snprintf(struct hist_entry *he, char *bf,
328− size_t size, unsigned int width)
327+int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width)
329328 {
330329 return _hist_entry__sym_snprintf(&he->ms, he->ip,
331330 he->level, bf, size, width);
tools/perf/util/sort.h+2−0
@@ -164,6 +164,8 @@ static __pure inline bool hist_entry__has_callchains(struct hist_entry *he) · 163 unmodified lines
164164 return he->callchain_size != 0;
165165 }
166166
167+int hist_entry__sym_snprintf(struct hist_entry *he, char *bf, size_t size, unsigned int width);
168+
167169 static inline bool hist_entry__has_pairs(struct hist_entry *he)
168170 {
169171 return !list_empty(&he->pairs.node);