diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-24 13:02:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-24 13:02:14 -0400 |
commit | 3fa2fe2ce09c5a16be69c5319eb3347271a99735 (patch) | |
tree | 7067760e7006dec7ac6fe18fe3d09851293b63ea | |
parent | d88f48e12821ab4b2244124d50ac094568f48db5 (diff) | |
parent | 05f5ece76a88a2cd4859bc93f90379733dd8b4a3 (diff) |
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar:
"This tree contains various perf fixes on the kernel side, plus three
hw/event-enablement late additions:
- Intel Memory Bandwidth Monitoring events and handling
- the AMD Accumulated Power Mechanism reporting facility
- more IOMMU events
... and a final round of perf tooling updates/fixes"
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (44 commits)
perf llvm: Use strerror_r instead of the thread unsafe strerror one
perf llvm: Use realpath to canonicalize paths
perf tools: Unexport some methods unused outside strbuf.c
perf probe: No need to use formatting strbuf method
perf help: Use asprintf instead of adhoc equivalents
perf tools: Remove unused perf_pathdup, xstrdup functions
perf tools: Do not include stringify.h from the kernel sources
tools include: Copy linux/stringify.h from the kernel
tools lib traceevent: Remove redundant CPU output
perf tools: Remove needless 'extern' from function prototypes
perf tools: Simplify die() mechanism
perf tools: Remove unused DIE_IF macro
perf script: Remove lots of unused arguments
perf thread: Rename perf_event__preprocess_sample_addr to thread__resolve
perf machine: Rename perf_event__preprocess_sample to machine__resolve
perf tools: Add cpumode to struct perf_sample
perf tests: Forward the perf_sample in the dwarf unwind test
perf tools: Remove misplaced __maybe_unused
perf list: Fix documentation of :ppp
perf bench numa: Fix assertion for nodes bitfield
...
95 files changed, 1336 insertions, 634 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 54478b7635de..2dc18605831f 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -1210,6 +1210,15 @@ config MICROCODE_OLD_INTERFACE | |||
1210 | def_bool y | 1210 | def_bool y |
1211 | depends on MICROCODE | 1211 | depends on MICROCODE |
1212 | 1212 | ||
1213 | config PERF_EVENTS_AMD_POWER | ||
1214 | depends on PERF_EVENTS && CPU_SUP_AMD | ||
1215 | tristate "AMD Processor Power Reporting Mechanism" | ||
1216 | ---help--- | ||
1217 | Provide power reporting mechanism support for AMD processors. | ||
1218 | Currently, it leverages X86_FEATURE_ACC_POWER | ||
1219 | (CPUID Fn8000_0007_EDX[12]) interface to calculate the | ||
1220 | average power consumption on Family 15h processors. | ||
1221 | |||
1213 | config X86_MSR | 1222 | config X86_MSR |
1214 | tristate "/dev/cpu/*/msr - Model-specific register support" | 1223 | tristate "/dev/cpu/*/msr - Model-specific register support" |
1215 | ---help--- | 1224 | ---help--- |
diff --git a/arch/x86/events/Makefile b/arch/x86/events/Makefile index fdfea1511cc0..f59618a39990 100644 --- a/arch/x86/events/Makefile +++ b/arch/x86/events/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | obj-y += core.o | 1 | obj-y += core.o |
2 | 2 | ||
3 | obj-$(CONFIG_CPU_SUP_AMD) += amd/core.o amd/uncore.o | 3 | obj-$(CONFIG_CPU_SUP_AMD) += amd/core.o amd/uncore.o |
4 | obj-$(CONFIG_PERF_EVENTS_AMD_POWER) += amd/power.o | ||
4 | obj-$(CONFIG_X86_LOCAL_APIC) += amd/ibs.o msr.o | 5 | obj-$(CONFIG_X86_LOCAL_APIC) += amd/ibs.o msr.o |
5 | ifdef CONFIG_AMD_IOMMU | 6 | ifdef CONFIG_AMD_IOMMU |
6 | obj-$(CONFIG_CPU_SUP_AMD) += amd/iommu.o | 7 | obj-$(CONFIG_CPU_SUP_AMD) += amd/iommu.o |
diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c index 51087c29b2c2..3ea25c3917c0 100644 --- a/arch/x86/events/amd/ibs.c +++ b/arch/x86/events/amd/ibs.c | |||
@@ -376,7 +376,13 @@ static void perf_ibs_start(struct perf_event *event, int flags) | |||
376 | hwc->state = 0; | 376 | hwc->state = 0; |
377 | 377 | ||
378 | perf_ibs_set_period(perf_ibs, hwc, &period); | 378 | perf_ibs_set_period(perf_ibs, hwc, &period); |
379 | /* | ||
380 | * Set STARTED before enabling the hardware, such that | ||
381 | * a subsequent NMI must observe it. Then clear STOPPING | ||
382 | * such that we don't consume NMIs by accident. | ||
383 | */ | ||
379 | set_bit(IBS_STARTED, pcpu->state); | 384 | set_bit(IBS_STARTED, pcpu->state); |
385 | clear_bit(IBS_STOPPING, pcpu->state); | ||
380 | perf_ibs_enable_event(perf_ibs, hwc, period >> 4); | 386 | perf_ibs_enable_event(perf_ibs, hwc, period >> 4); |
381 | 387 | ||
382 | perf_event_update_userpage(event); | 388 | perf_event_update_userpage(event); |
@@ -390,7 +396,7 @@ static void perf_ibs_stop(struct perf_event *event, int flags) | |||
390 | u64 config; | 396 | u64 config; |
391 | int stopping; | 397 | int stopping; |
392 | 398 | ||
393 | stopping = test_and_clear_bit(IBS_STARTED, pcpu->state); | 399 | stopping = test_bit(IBS_STARTED, pcpu->state); |
394 | 400 | ||
395 | if (!stopping && (hwc->state & PERF_HES_UPTODATE)) | 401 | if (!stopping && (hwc->state & PERF_HES_UPTODATE)) |
396 | return; | 402 | return; |
@@ -398,8 +404,24 @@ static void perf_ibs_stop(struct perf_event *event, int flags) | |||
398 | rdmsrl(hwc->config_base, config); | 404 | rdmsrl(hwc->config_base, config); |
399 | 405 | ||
400 | if (stopping) { | 406 | if (stopping) { |
407 | /* | ||
408 | * Set STOPPING before disabling the hardware, such that it | ||
409 | * must be visible to NMIs the moment we clear the EN bit, | ||
410 | * at which point we can generate an !VALID sample which | ||
411 | * we need to consume. | ||
412 | */ | ||
401 | set_bit(IBS_STOPPING, pcpu->state); | 413 | set_bit(IBS_STOPPING, pcpu->state); |
402 | perf_ibs_disable_event(perf_ibs, hwc, config); | 414 | perf_ibs_disable_event(perf_ibs, hwc, config); |
415 | /* | ||
416 | * Clear STARTED after disabling the hardware; if it were | ||
417 | * cleared before an NMI hitting after the clear but before | ||
418 | * clearing the EN bit might think it a spurious NMI and not | ||
419 | * handle it. | ||
420 | * | ||
421 | * Clearing it after, however, creates the problem of the NMI | ||
422 | * handler seeing STARTED but not having a valid sample. | ||
423 | */ | ||
424 | clear_bit(IBS_STARTED, pcpu->state); | ||
403 | WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); | 425 | WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); |
404 | hwc->state |= PERF_HES_STOPPED; | 426 | hwc->state |= PERF_HES_STOPPED; |
405 | } | 427 | } |
@@ -527,20 +549,24 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs) | |||
527 | u64 *buf, *config, period; | 549 | u64 *buf, *config, period; |
528 | 550 | ||
529 | if (!test_bit(IBS_STARTED, pcpu->state)) { | 551 | if (!test_bit(IBS_STARTED, pcpu->state)) { |
552 | fail: | ||
530 | /* | 553 | /* |
531 | * Catch spurious interrupts after stopping IBS: After | 554 | * Catch spurious interrupts after stopping IBS: After |
532 | * disabling IBS there could be still incoming NMIs | 555 | * disabling IBS there could be still incoming NMIs |
533 | * with samples that even have the valid bit cleared. | 556 | * with samples that even have the valid bit cleared. |
534 | * Mark all this NMIs as handled. | 557 | * Mark all this NMIs as handled. |
535 | */ | 558 | */ |
536 | return test_and_clear_bit(IBS_STOPPING, pcpu->state) ? 1 : 0; | 559 | if (test_and_clear_bit(IBS_STOPPING, pcpu->state)) |
560 | return 1; | ||
561 | |||
562 | return 0; | ||
537 | } | 563 | } |
538 | 564 | ||
539 | msr = hwc->config_base; | 565 | msr = hwc->config_base; |
540 | buf = ibs_data.regs; | 566 | buf = ibs_data.regs; |
541 | rdmsrl(msr, *buf); | 567 | rdmsrl(msr, *buf); |
542 | if (!(*buf++ & perf_ibs->valid_mask)) | 568 | if (!(*buf++ & perf_ibs->valid_mask)) |
543 | return 0; | 569 | goto fail; |
544 | 570 | ||
545 | config = &ibs_data.regs[0]; | 571 | config = &ibs_data.regs[0]; |
546 | perf_ibs_event_update(perf_ibs, event, config); | 572 | perf_ibs_event_update(perf_ibs, event, config); |
@@ -599,7 +625,7 @@ static int perf_ibs_handle_irq(struct perf_ibs *perf_ibs, struct pt_regs *iregs) | |||
599 | throttle = perf_event_overflow(event, &data, ®s); | 625 | throttle = perf_event_overflow(event, &data, ®s); |
600 | out: | 626 | out: |
601 | if (throttle) | 627 | if (throttle) |
602 | perf_ibs_disable_event(perf_ibs, hwc, *config); | 628 | perf_ibs_stop(event, 0); |
603 | else | 629 | else |
604 | perf_ibs_enable_event(perf_ibs, hwc, period >> 4); | 630 | perf_ibs_enable_event(perf_ibs, hwc, period >> 4); |
605 | 631 | ||
@@ -611,6 +637,7 @@ out: | |||
611 | static int | 637 | static int |
612 | perf_ibs_nmi_handler(unsigned int cmd, struct pt_regs *regs) | 638 | perf_ibs_nmi_handler(unsigned int cmd, struct pt_regs *regs) |
613 | { | 639 | { |
640 | u64 stamp = sched_clock(); | ||
614 | int handled = 0; | 641 | int handled = 0; |
615 | 642 | ||
616 | handled += perf_ibs_handle_irq(&perf_ibs_fetch, regs); | 643 | handled += perf_ibs_handle_irq(&perf_ibs_fetch, regs); |
@@ -619,6 +646,8 @@ perf_ibs_nmi_handler(unsigned int cmd, struct pt_regs *regs) | |||
619 | if (handled) | 646 | if (handled) |
620 | inc_irq_stat(apic_perf_irqs); | 647 | inc_irq_stat(apic_perf_irqs); |
621 | 648 | ||
649 | perf_sample_event_took(sched_clock() - stamp); | ||
650 | |||
622 | return handled; | 651 | return handled; |
623 | } | 652 | } |
624 | NOKPROBE_SYMBOL(perf_ibs_nmi_handler); | 653 | NOKPROBE_SYMBOL(perf_ibs_nmi_handler); |
diff --git a/arch/x86/events/amd/iommu.c b/arch/x86/events/amd/iommu.c index 635e5eba0caf..40625ca7a190 100644 --- a/arch/x86/events/amd/iommu.c +++ b/arch/x86/events/amd/iommu.c | |||
@@ -118,6 +118,11 @@ static struct amd_iommu_event_desc amd_iommu_v2_event_descs[] = { | |||
118 | AMD_IOMMU_EVENT_DESC(cmd_processed, "csource=0x11"), | 118 | AMD_IOMMU_EVENT_DESC(cmd_processed, "csource=0x11"), |
119 | AMD_IOMMU_EVENT_DESC(cmd_processed_inv, "csource=0x12"), | 119 | AMD_IOMMU_EVENT_DESC(cmd_processed_inv, "csource=0x12"), |
120 | AMD_IOMMU_EVENT_DESC(tlb_inv, "csource=0x13"), | 120 | AMD_IOMMU_EVENT_DESC(tlb_inv, "csource=0x13"), |
121 | AMD_IOMMU_EVENT_DESC(ign_rd_wr_mmio_1ff8h, "csource=0x14"), | ||
122 | AMD_IOMMU_EVENT_DESC(vapic_int_non_guest, "csource=0x15"), | ||
123 | AMD_IOMMU_EVENT_DESC(vapic_int_guest, "csource=0x16"), | ||
124 | AMD_IOMMU_EVENT_DESC(smi_recv, "csource=0x17"), | ||
125 | AMD_IOMMU_EVENT_DESC(smi_blk, "csource=0x18"), | ||
121 | { /* end: all zeroes */ }, | 126 | { /* end: all zeroes */ }, |
122 | }; | 127 | }; |
123 | 128 | ||
diff --git a/arch/x86/events/amd/power.c b/arch/x86/events/amd/power.c new file mode 100644 index 000000000000..55a3529dbf12 --- /dev/null +++ b/arch/x86/events/amd/power.c | |||
@@ -0,0 +1,353 @@ | |||
1 | /* | ||
2 | * Performance events - AMD Processor Power Reporting Mechanism | ||
3 | * | ||
4 | * Copyright (C) 2016 Advanced Micro Devices, Inc. | ||
5 | * | ||
6 | * Author: Huang Rui <ray.huang@amd.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/perf_event.h> | ||
16 | #include <asm/cpu_device_id.h> | ||
17 | #include "../perf_event.h" | ||
18 | |||
19 | #define MSR_F15H_CU_PWR_ACCUMULATOR 0xc001007a | ||
20 | #define MSR_F15H_CU_MAX_PWR_ACCUMULATOR 0xc001007b | ||
21 | #define MSR_F15H_PTSC 0xc0010280 | ||
22 | |||
23 | /* Event code: LSB 8 bits, passed in attr->config any other bit is reserved. */ | ||
24 | #define AMD_POWER_EVENT_MASK 0xFFULL | ||
25 | |||
26 | /* | ||
27 | * Accumulated power status counters. | ||
28 | */ | ||
29 | #define AMD_POWER_EVENTSEL_PKG 1 | ||
30 | |||
31 | /* | ||
32 | * The ratio of compute unit power accumulator sample period to the | ||
33 | * PTSC period. | ||
34 | */ | ||
35 | static unsigned int cpu_pwr_sample_ratio; | ||
36 | |||
37 | /* Maximum accumulated power of a compute unit. */ | ||
38 | static u64 max_cu_acc_power; | ||
39 | |||
40 | static struct pmu pmu_class; | ||
41 | |||
42 | /* | ||
43 | * Accumulated power represents the sum of each compute unit's (CU) power | ||
44 | * consumption. On any core of each CU we read the total accumulated power from | ||
45 | * MSR_F15H_CU_PWR_ACCUMULATOR. cpu_mask represents CPU bit map of all cores | ||
46 | * which are picked to measure the power for the CUs they belong to. | ||
47 | */ | ||
48 | static cpumask_t cpu_mask; | ||
49 | |||
50 | static void event_update(struct perf_event *event) | ||
51 | { | ||
52 | struct hw_perf_event *hwc = &event->hw; | ||
53 | u64 prev_pwr_acc, new_pwr_acc, prev_ptsc, new_ptsc; | ||
54 | u64 delta, tdelta; | ||
55 | |||
56 | prev_pwr_acc = hwc->pwr_acc; | ||
57 | prev_ptsc = hwc->ptsc; | ||
58 | rdmsrl(MSR_F15H_CU_PWR_ACCUMULATOR, new_pwr_acc); | ||
59 | rdmsrl(MSR_F15H_PTSC, new_ptsc); | ||
60 | |||
61 | /* | ||
62 | * Calculate the CU power consumption over a time period, the unit of | ||
63 | * final value (delta) is micro-Watts. Then add it to the event count. | ||
64 | */ | ||
65 | if (new_pwr_acc < prev_pwr_acc) { | ||
66 | delta = max_cu_acc_power + new_pwr_acc; | ||
67 | delta -= prev_pwr_acc; | ||
68 | } else | ||
69 | delta = new_pwr_acc - prev_pwr_acc; | ||
70 | |||
71 | delta *= cpu_pwr_sample_ratio * 1000; | ||
72 | tdelta = new_ptsc - prev_ptsc; | ||
73 | |||
74 | do_div(delta, tdelta); | ||
75 | local64_add(delta, &event->count); | ||
76 | } | ||
77 | |||
78 | static void __pmu_event_start(struct perf_event *event) | ||
79 | { | ||
80 | if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED))) | ||
81 | return; | ||
82 | |||
83 | event->hw.state = 0; | ||
84 | |||
85 | rdmsrl(MSR_F15H_PTSC, event->hw.ptsc); | ||
86 | rdmsrl(MSR_F15H_CU_PWR_ACCUMULATOR, event->hw.pwr_acc); | ||
87 | } | ||
88 | |||
89 | static void pmu_event_start(struct perf_event *event, int mode) | ||
90 | { | ||
91 | __pmu_event_start(event); | ||
92 | } | ||
93 | |||
94 | static void pmu_event_stop(struct perf_event *event, int mode) | ||
95 | { | ||
96 | struct hw_perf_event *hwc = &event->hw; | ||
97 | |||
98 | /* Mark event as deactivated and stopped. */ | ||
99 | if (!(hwc->state & PERF_HES_STOPPED)) | ||
100 | hwc->state |= PERF_HES_STOPPED; | ||
101 | |||
102 | /* Check if software counter update is necessary. */ | ||
103 | if ((mode & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) { | ||
104 | /* | ||
105 | * Drain the remaining delta count out of an event | ||
106 | * that we are disabling: | ||
107 | */ | ||
108 | event_update(event); | ||
109 | hwc->state |= PERF_HES_UPTODATE; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | static int pmu_event_add(struct perf_event *event, int mode) | ||
114 | { | ||
115 | struct hw_perf_event *hwc = &event->hw; | ||
116 | |||
117 | hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED; | ||
118 | |||
119 | if (mode & PERF_EF_START) | ||
120 | __pmu_event_start(event); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static void pmu_event_del(struct perf_event *event, int flags) | ||
126 | { | ||
127 | pmu_event_stop(event, PERF_EF_UPDATE); | ||
128 | } | ||
129 | |||
130 | static int pmu_event_init(struct perf_event *event) | ||
131 | { | ||
132 | u64 cfg = event->attr.config & AMD_POWER_EVENT_MASK; | ||
133 | |||
134 | /* Only look at AMD power events. */ | ||
135 | if (event->attr.type != pmu_class.type) | ||
136 | return -ENOENT; | ||
137 | |||
138 | /* Unsupported modes and filters. */ | ||
139 | if (event->attr.exclude_user || | ||
140 | event->attr.exclude_kernel || | ||
141 | event->attr.exclude_hv || | ||
142 | event->attr.exclude_idle || | ||
143 | event->attr.exclude_host || | ||
144 | event->attr.exclude_guest || | ||
145 | /* no sampling */ | ||
146 | event->attr.sample_period) | ||
147 | return -EINVAL; | ||
148 | |||
149 | if (cfg != AMD_POWER_EVENTSEL_PKG) | ||
150 | return -EINVAL; | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static void pmu_event_read(struct perf_event *event) | ||
156 | { | ||
157 | event_update(event); | ||
158 | } | ||
159 | |||
160 | static ssize_t | ||
161 | get_attr_cpumask(struct device *dev, struct device_attribute *attr, char *buf) | ||
162 | { | ||
163 | return cpumap_print_to_pagebuf(true, buf, &cpu_mask); | ||
164 | } | ||
165 | |||
166 | static DEVICE_ATTR(cpumask, S_IRUGO, get_attr_cpumask, NULL); | ||
167 | |||
168 | static struct attribute *pmu_attrs[] = { | ||
169 | &dev_attr_cpumask.attr, | ||
170 | NULL, | ||
171 | }; | ||
172 | |||
173 | static struct attribute_group pmu_attr_group = { | ||
174 | .attrs = pmu_attrs, | ||
175 | }; | ||
176 | |||
177 | /* | ||
178 | * Currently it only supports to report the power of each | ||
179 | * processor/package. | ||
180 | */ | ||
181 | EVENT_ATTR_STR(power-pkg, power_pkg, "event=0x01"); | ||
182 | |||
183 | EVENT_ATTR_STR(power-pkg.unit, power_pkg_unit, "mWatts"); | ||
184 | |||
185 | /* Convert the count from micro-Watts to milli-Watts. */ | ||
186 | EVENT_ATTR_STR(power-pkg.scale, power_pkg_scale, "1.000000e-3"); | ||
187 | |||
188 | static struct attribute *events_attr[] = { | ||
189 | EVENT_PTR(power_pkg), | ||
190 | EVENT_PTR(power_pkg_unit), | ||
191 | EVENT_PTR(power_pkg_scale), | ||
192 | NULL, | ||
193 | }; | ||
194 | |||
195 | static struct attribute_group pmu_events_group = { | ||
196 | .name = "events", | ||
197 | .attrs = events_attr, | ||
198 | }; | ||
199 | |||
200 | PMU_FORMAT_ATTR(event, "config:0-7"); | ||
201 | |||
202 | static struct attribute *formats_attr[] = { | ||
203 | &format_attr_event.attr, | ||
204 | NULL, | ||
205 | }; | ||
206 | |||
207 | static struct attribute_group pmu_format_group = { | ||
208 | .name = "format", | ||
209 | .attrs = formats_attr, | ||
210 | }; | ||
211 | |||
212 | static const struct attribute_group *attr_groups[] = { | ||
213 | &pmu_attr_group, | ||
214 | &pmu_format_group, | ||
215 | &pmu_events_group, | ||
216 | NULL, | ||
217 | }; | ||
218 | |||
219 | static struct pmu pmu_class = { | ||
220 | .attr_groups = attr_groups, | ||
221 | /* system-wide only */ | ||
222 | .task_ctx_nr = perf_invalid_context, | ||
223 | .event_init = pmu_event_init, | ||
224 | .add = pmu_event_add, | ||
225 | .del = pmu_event_del, | ||
226 | .start = pmu_event_start, | ||
227 | .stop = pmu_event_stop, | ||
228 | .read = pmu_event_read, | ||
229 | }; | ||
230 | |||
231 | static void power_cpu_exit(int cpu) | ||
232 | { | ||
233 | int target; | ||
234 | |||
235 | if (!cpumask_test_and_clear_cpu(cpu, &cpu_mask)) | ||
236 | return; | ||
237 | |||
238 | /* | ||
239 | * Find a new CPU on the same compute unit, if was set in cpumask | ||
240 | * and still some CPUs on compute unit. Then migrate event and | ||
241 | * context to new CPU. | ||
242 | */ | ||
243 | target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu); | ||
244 | if (target < nr_cpumask_bits) { | ||
245 | cpumask_set_cpu(target, &cpu_mask); | ||
246 | perf_pmu_migrate_context(&pmu_class, cpu, target); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | static void power_cpu_init(int cpu) | ||
251 | { | ||
252 | int target; | ||
253 | |||
254 | /* | ||
255 | * 1) If any CPU is set at cpu_mask in the same compute unit, do | ||
256 | * nothing. | ||
257 | * 2) If no CPU is set at cpu_mask in the same compute unit, | ||
258 | * set current STARTING CPU. | ||
259 | * | ||
260 | * Note: if there is a CPU aside of the new one already in the | ||
261 | * sibling mask, then it is also in cpu_mask. | ||
262 | */ | ||
263 | target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu); | ||
264 | if (target >= nr_cpumask_bits) | ||
265 | cpumask_set_cpu(cpu, &cpu_mask); | ||
266 | } | ||
267 | |||
268 | static int | ||
269 | power_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) | ||
270 | { | ||
271 | unsigned int cpu = (long)hcpu; | ||
272 | |||
273 | switch (action & ~CPU_TASKS_FROZEN) { | ||
274 | case CPU_DOWN_FAILED: | ||
275 | case CPU_STARTING: | ||
276 | power_cpu_init(cpu); | ||
277 | break; | ||
278 | case CPU_DOWN_PREPARE: | ||
279 | power_cpu_exit(cpu); | ||
280 | break; | ||
281 | default: | ||
282 | break; | ||
283 | } | ||
284 | |||
285 | return NOTIFY_OK; | ||
286 | } | ||
287 | |||
288 | static struct notifier_block power_cpu_notifier_nb = { | ||
289 | .notifier_call = power_cpu_notifier, | ||
290 | .priority = CPU_PRI_PERF, | ||
291 | }; | ||
292 | |||
293 | static const struct x86_cpu_id cpu_match[] = { | ||
294 | { .vendor = X86_VENDOR_AMD, .family = 0x15 }, | ||
295 | {}, | ||
296 | }; | ||
297 | |||
298 | static int __init amd_power_pmu_init(void) | ||
299 | { | ||
300 | int cpu, target, ret; | ||
301 | |||
302 | if (!x86_match_cpu(cpu_match)) | ||
303 | return 0; | ||
304 | |||
305 | if (!boot_cpu_has(X86_FEATURE_ACC_POWER)) | ||
306 | return -ENODEV; | ||
307 | |||
308 | cpu_pwr_sample_ratio = cpuid_ecx(0x80000007); | ||
309 | |||
310 | if (rdmsrl_safe(MSR_F15H_CU_MAX_PWR_ACCUMULATOR, &max_cu_acc_power)) { | ||
311 | pr_err("Failed to read max compute unit power accumulator MSR\n"); | ||
312 | return -ENODEV; | ||
313 | } | ||
314 | |||
315 | cpu_notifier_register_begin(); | ||
316 | |||
317 | /* Choose one online core of each compute unit. */ | ||
318 | for_each_online_cpu(cpu) { | ||
319 | target = cpumask_first(topology_sibling_cpumask(cpu)); | ||
320 | if (!cpumask_test_cpu(target, &cpu_mask)) | ||
321 | cpumask_set_cpu(target, &cpu_mask); | ||
322 | } | ||
323 | |||
324 | ret = perf_pmu_register(&pmu_class, "power", -1); | ||
325 | if (WARN_ON(ret)) { | ||
326 | pr_warn("AMD Power PMU registration failed\n"); | ||
327 | goto out; | ||
328 | } | ||
329 | |||
330 | __register_cpu_notifier(&power_cpu_notifier_nb); | ||
331 | |||
332 | pr_info("AMD Power PMU detected\n"); | ||
333 | |||
334 | out: | ||
335 | cpu_notifier_register_done(); | ||
336 | |||
337 | return ret; | ||
338 | } | ||
339 | module_init(amd_power_pmu_init); | ||
340 | |||
341 | static void __exit amd_power_pmu_exit(void) | ||
342 | { | ||
343 | cpu_notifier_register_begin(); | ||
344 | __unregister_cpu_notifier(&power_cpu_notifier_nb); | ||
345 | cpu_notifier_register_done(); | ||
346 | |||
347 | perf_pmu_unregister(&pmu_class); | ||
348 | } | ||
349 | module_exit(amd_power_pmu_exit); | ||
350 | |||
351 | MODULE_AUTHOR("Huang Rui <ray.huang@amd.com>"); | ||
352 | MODULE_DESCRIPTION("AMD Processor Power Reporting Mechanism"); | ||
353 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 9b6ad08aa51a..041e442a3e28 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c | |||
@@ -1602,8 +1602,7 @@ __init struct attribute **merge_attr(struct attribute **a, struct attribute **b) | |||
1602 | return new; | 1602 | return new; |
1603 | } | 1603 | } |
1604 | 1604 | ||
1605 | ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, | 1605 | ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, char *page) |
1606 | char *page) | ||
1607 | { | 1606 | { |
1608 | struct perf_pmu_events_attr *pmu_attr = \ | 1607 | struct perf_pmu_events_attr *pmu_attr = \ |
1609 | container_of(attr, struct perf_pmu_events_attr, attr); | 1608 | container_of(attr, struct perf_pmu_events_attr, attr); |
@@ -1615,6 +1614,7 @@ ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, | |||
1615 | 1614 | ||
1616 | return x86_pmu.events_sysfs_show(page, config); | 1615 | return x86_pmu.events_sysfs_show(page, config); |
1617 | } | 1616 | } |
1617 | EXPORT_SYMBOL_GPL(events_sysfs_show); | ||
1618 | 1618 | ||
1619 | EVENT_ATTR(cpu-cycles, CPU_CYCLES ); | 1619 | EVENT_ATTR(cpu-cycles, CPU_CYCLES ); |
1620 | EVENT_ATTR(instructions, INSTRUCTIONS ); | 1620 | EVENT_ATTR(instructions, INSTRUCTIONS ); |
diff --git a/arch/x86/events/intel/cqm.c b/arch/x86/events/intel/cqm.c index 93cb412a5579..7b5fd811ef45 100644 --- a/arch/x86/events/intel/cqm.c +++ b/arch/x86/events/intel/cqm.c | |||
@@ -13,8 +13,16 @@ | |||
13 | #define MSR_IA32_QM_CTR 0x0c8e | 13 | #define MSR_IA32_QM_CTR 0x0c8e |
14 | #define MSR_IA32_QM_EVTSEL 0x0c8d | 14 | #define MSR_IA32_QM_EVTSEL 0x0c8d |
15 | 15 | ||
16 | #define MBM_CNTR_WIDTH 24 | ||
17 | /* | ||
18 | * Guaranteed time in ms as per SDM where MBM counters will not overflow. | ||
19 | */ | ||
20 | #define MBM_CTR_OVERFLOW_TIME 1000 | ||
21 | |||
16 | static u32 cqm_max_rmid = -1; | 22 | static u32 cqm_max_rmid = -1; |
17 | static unsigned int cqm_l3_scale; /* supposedly cacheline size */ | 23 | static unsigned int cqm_l3_scale; /* supposedly cacheline size */ |
24 | static bool cqm_enabled, mbm_enabled; | ||
25 | unsigned int mbm_socket_max; | ||
18 | 26 | ||
19 | /** | 27 | /** |
20 | * struct intel_pqr_state - State cache for the PQR MSR | 28 | * struct intel_pqr_state - State cache for the PQR MSR |
@@ -42,8 +50,37 @@ struct intel_pqr_state { | |||
42 | * interrupts disabled, which is sufficient for the protection. | 50 | * interrupts disabled, which is sufficient for the protection. |
43 | */ | 51 | */ |
44 | static DEFINE_PER_CPU(struct intel_pqr_state, pqr_state); | 52 | static DEFINE_PER_CPU(struct intel_pqr_state, pqr_state); |
53 | static struct hrtimer *mbm_timers; | ||
54 | /** | ||
55 | * struct sample - mbm event's (local or total) data | ||
56 | * @total_bytes #bytes since we began monitoring | ||
57 | * @prev_msr previous value of MSR | ||
58 | */ | ||
59 | struct sample { | ||
60 | u64 total_bytes; | ||
61 | u64 prev_msr; | ||
62 | }; | ||
45 | 63 | ||
46 | /* | 64 | /* |
65 | * samples profiled for total memory bandwidth type events | ||
66 | */ | ||
67 | static struct sample *mbm_total; | ||
68 | /* | ||
69 | * samples profiled for local memory bandwidth type events | ||
70 | */ | ||
71 | static struct sample *mbm_local; | ||
72 | |||
73 | #define pkg_id topology_physical_package_id(smp_processor_id()) | ||
74 | /* | ||
75 | * rmid_2_index returns the index for the rmid in mbm_local/mbm_total array. | ||
76 | * mbm_total[] and mbm_local[] are linearly indexed by socket# * max number of | ||
77 | * rmids per socket, an example is given below | ||
78 | * RMID1 of Socket0: vrmid = 1 | ||
79 | * RMID1 of Socket1: vrmid = 1 * (cqm_max_rmid + 1) + 1 | ||
80 | * RMID1 of Socket2: vrmid = 2 * (cqm_max_rmid + 1) + 1 | ||
81 | */ | ||
82 | #define rmid_2_index(rmid) ((pkg_id * (cqm_max_rmid + 1)) + rmid) | ||
83 | /* | ||
47 | * Protects cache_cgroups and cqm_rmid_free_lru and cqm_rmid_limbo_lru. | 84 | * Protects cache_cgroups and cqm_rmid_free_lru and cqm_rmid_limbo_lru. |
48 | * Also protects event->hw.cqm_rmid | 85 | * Also protects event->hw.cqm_rmid |
49 | * | 86 | * |
@@ -65,9 +102,13 @@ static cpumask_t cqm_cpumask; | |||
65 | #define RMID_VAL_ERROR (1ULL << 63) | 102 | #define RMID_VAL_ERROR (1ULL << 63) |
66 | #define RMID_VAL_UNAVAIL (1ULL << 62) | 103 | #define RMID_VAL_UNAVAIL (1ULL << 62) |
67 | 104 | ||
68 | #define QOS_L3_OCCUP_EVENT_ID (1 << 0) | 105 | /* |
69 | 106 | * Event IDs are used to program IA32_QM_EVTSEL before reading event | |
70 | #define QOS_EVENT_MASK QOS_L3_OCCUP_EVENT_ID | 107 | * counter from IA32_QM_CTR |
108 | */ | ||
109 | #define QOS_L3_OCCUP_EVENT_ID 0x01 | ||
110 | #define QOS_MBM_TOTAL_EVENT_ID 0x02 | ||
111 | #define QOS_MBM_LOCAL_EVENT_ID 0x03 | ||
71 | 112 | ||
72 | /* | 113 | /* |
73 | * This is central to the rotation algorithm in __intel_cqm_rmid_rotate(). | 114 | * This is central to the rotation algorithm in __intel_cqm_rmid_rotate(). |
@@ -211,6 +252,21 @@ static void __put_rmid(u32 rmid) | |||
211 | list_add_tail(&entry->list, &cqm_rmid_limbo_lru); | 252 | list_add_tail(&entry->list, &cqm_rmid_limbo_lru); |
212 | } | 253 | } |
213 | 254 | ||
255 | static void cqm_cleanup(void) | ||
256 | { | ||
257 | int i; | ||
258 | |||
259 | if (!cqm_rmid_ptrs) | ||
260 | return; | ||
261 | |||
262 | for (i = 0; i < cqm_max_rmid; i++) | ||
263 | kfree(cqm_rmid_ptrs[i]); | ||
264 | |||
265 | kfree(cqm_rmid_ptrs); | ||
266 | cqm_rmid_ptrs = NULL; | ||
267 | cqm_enabled = false; | ||
268 | } | ||
269 | |||
214 | static int intel_cqm_setup_rmid_cache(void) | 270 | static int intel_cqm_setup_rmid_cache(void) |
215 | { | 271 | { |
216 | struct cqm_rmid_entry *entry; | 272 | struct cqm_rmid_entry *entry; |
@@ -218,7 +274,7 @@ static int intel_cqm_setup_rmid_cache(void) | |||
218 | int r = 0; | 274 | int r = 0; |
219 | 275 | ||
220 | nr_rmids = cqm_max_rmid + 1; | 276 | nr_rmids = cqm_max_rmid + 1; |
221 | cqm_rmid_ptrs = kmalloc(sizeof(struct cqm_rmid_entry *) * | 277 | cqm_rmid_ptrs = kzalloc(sizeof(struct cqm_rmid_entry *) * |
222 | nr_rmids, GFP_KERNEL); | 278 | nr_rmids, GFP_KERNEL); |
223 | if (!cqm_rmid_ptrs) | 279 | if (!cqm_rmid_ptrs) |
224 | return -ENOMEM; | 280 | return -ENOMEM; |
@@ -249,11 +305,9 @@ static int intel_cqm_setup_rmid_cache(void) | |||
249 | mutex_unlock(&cache_mutex); | 305 | mutex_unlock(&cache_mutex); |
250 | 306 | ||
251 | return 0; | 307 | return 0; |
252 | fail: | ||
253 | while (r--) | ||
254 | kfree(cqm_rmid_ptrs[r]); | ||
255 | 308 | ||
256 | kfree(cqm_rmid_ptrs); | 309 | fail: |
310 | cqm_cleanup(); | ||
257 | return -ENOMEM; | 311 | return -ENOMEM; |
258 | } | 312 | } |
259 | 313 | ||
@@ -281,9 +335,13 @@ static bool __match_event(struct perf_event *a, struct perf_event *b) | |||
281 | 335 | ||
282 | /* | 336 | /* |
283 | * Events that target same task are placed into the same cache group. | 337 | * Events that target same task are placed into the same cache group. |
338 | * Mark it as a multi event group, so that we update ->count | ||
339 | * for every event rather than just the group leader later. | ||
284 | */ | 340 | */ |
285 | if (a->hw.target == b->hw.target) | 341 | if (a->hw.target == b->hw.target) { |
342 | b->hw.is_group_event = true; | ||
286 | return true; | 343 | return true; |
344 | } | ||
287 | 345 | ||
288 | /* | 346 | /* |
289 | * Are we an inherited event? | 347 | * Are we an inherited event? |
@@ -392,10 +450,26 @@ static bool __conflict_event(struct perf_event *a, struct perf_event *b) | |||
392 | 450 | ||
393 | struct rmid_read { | 451 | struct rmid_read { |
394 | u32 rmid; | 452 | u32 rmid; |
453 | u32 evt_type; | ||
395 | atomic64_t value; | 454 | atomic64_t value; |
396 | }; | 455 | }; |
397 | 456 | ||
398 | static void __intel_cqm_event_count(void *info); | 457 | static void __intel_cqm_event_count(void *info); |
458 | static void init_mbm_sample(u32 rmid, u32 evt_type); | ||
459 | static void __intel_mbm_event_count(void *info); | ||
460 | |||
461 | static bool is_mbm_event(int e) | ||
462 | { | ||
463 | return (e >= QOS_MBM_TOTAL_EVENT_ID && e <= QOS_MBM_LOCAL_EVENT_ID); | ||
464 | } | ||
465 | |||
466 | static void cqm_mask_call(struct rmid_read *rr) | ||
467 | { | ||
468 | if (is_mbm_event(rr->evt_type)) | ||
469 | on_each_cpu_mask(&cqm_cpumask, __intel_mbm_event_count, rr, 1); | ||
470 | else | ||
471 | on_each_cpu_mask(&cqm_cpumask, __intel_cqm_event_count, rr, 1); | ||
472 | } | ||
399 | 473 | ||
400 | /* | 474 | /* |
401 | * Exchange the RMID of a group of events. | 475 | * Exchange the RMID of a group of events. |
@@ -413,12 +487,12 @@ static u32 intel_cqm_xchg_rmid(struct perf_event *group, u32 rmid) | |||
413 | */ | 487 | */ |
414 | if (__rmid_valid(old_rmid) && !__rmid_valid(rmid)) { | 488 | if (__rmid_valid(old_rmid) && !__rmid_valid(rmid)) { |
415 | struct rmid_read rr = { | 489 | struct rmid_read rr = { |
416 | .value = ATOMIC64_INIT(0), | ||
417 | .rmid = old_rmid, | 490 | .rmid = old_rmid, |
491 | .evt_type = group->attr.config, | ||
492 | .value = ATOMIC64_INIT(0), | ||
418 | }; | 493 | }; |
419 | 494 | ||
420 | on_each_cpu_mask(&cqm_cpumask, __intel_cqm_event_count, | 495 | cqm_mask_call(&rr); |
421 | &rr, 1); | ||
422 | local64_set(&group->count, atomic64_read(&rr.value)); | 496 | local64_set(&group->count, atomic64_read(&rr.value)); |
423 | } | 497 | } |
424 | 498 | ||
@@ -430,6 +504,22 @@ static u32 intel_cqm_xchg_rmid(struct perf_event *group, u32 rmid) | |||
430 | 504 | ||
431 | raw_spin_unlock_irq(&cache_lock); | 505 | raw_spin_unlock_irq(&cache_lock); |
432 | 506 | ||
507 | /* | ||
508 | * If the allocation is for mbm, init the mbm stats. | ||
509 | * Need to check if each event in the group is mbm event | ||
510 | * because there could be multiple type of events in the same group. | ||
511 | */ | ||
512 | if (__rmid_valid(rmid)) { | ||
513 | event = group; | ||
514 | if (is_mbm_event(event->attr.config)) | ||
515 | init_mbm_sample(rmid, event->attr.config); | ||
516 | |||
517 | list_for_each_entry(event, head, hw.cqm_group_entry) { | ||
518 | if (is_mbm_event(event->attr.config)) | ||
519 | init_mbm_sample(rmid, event->attr.config); | ||
520 | } | ||
521 | } | ||
522 | |||
433 | return old_rmid; | 523 | return old_rmid; |
434 | } | 524 | } |
435 | 525 | ||
@@ -837,6 +927,72 @@ static void intel_cqm_rmid_rotate(struct work_struct *work) | |||
837 | schedule_delayed_work(&intel_cqm_rmid_work, delay); | 927 | schedule_delayed_work(&intel_cqm_rmid_work, delay); |
838 | } | 928 | } |
839 | 929 | ||
930 | static u64 update_sample(unsigned int rmid, u32 evt_type, int first) | ||
931 | { | ||
932 | struct sample *mbm_current; | ||
933 | u32 vrmid = rmid_2_index(rmid); | ||
934 | u64 val, bytes, shift; | ||
935 | u32 eventid; | ||
936 | |||
937 | if (evt_type == QOS_MBM_LOCAL_EVENT_ID) { | ||
938 | mbm_current = &mbm_local[vrmid]; | ||
939 | eventid = QOS_MBM_LOCAL_EVENT_ID; | ||
940 | } else { | ||
941 | mbm_current = &mbm_total[vrmid]; | ||
942 | eventid = QOS_MBM_TOTAL_EVENT_ID; | ||
943 | } | ||
944 | |||
945 | wrmsr(MSR_IA32_QM_EVTSEL, eventid, rmid); | ||
946 | rdmsrl(MSR_IA32_QM_CTR, val); | ||
947 | if (val & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) | ||
948 | return mbm_current->total_bytes; | ||
949 | |||
950 | if (first) { | ||
951 | mbm_current->prev_msr = val; | ||
952 | mbm_current->total_bytes = 0; | ||
953 | return mbm_current->total_bytes; | ||
954 | } | ||
955 | |||
956 | /* | ||
957 | * The h/w guarantees that counters will not overflow | ||
958 | * so long as we poll them at least once per second. | ||
959 | */ | ||
960 | shift = 64 - MBM_CNTR_WIDTH; | ||
961 | bytes = (val << shift) - (mbm_current->prev_msr << shift); | ||
962 | bytes >>= shift; | ||
963 | |||
964 | bytes *= cqm_l3_scale; | ||
965 | |||
966 | mbm_current->total_bytes += bytes; | ||
967 | mbm_current->prev_msr = val; | ||
968 | |||
969 | return mbm_current->total_bytes; | ||
970 | } | ||
971 | |||
972 | static u64 rmid_read_mbm(unsigned int rmid, u32 evt_type) | ||
973 | { | ||
974 | return update_sample(rmid, evt_type, 0); | ||
975 | } | ||
976 | |||
977 | static void __intel_mbm_event_init(void *info) | ||
978 | { | ||
979 | struct rmid_read *rr = info; | ||
980 | |||
981 | update_sample(rr->rmid, rr->evt_type, 1); | ||
982 | } | ||
983 | |||
984 | static void init_mbm_sample(u32 rmid, u32 evt_type) | ||
985 | { | ||
986 | struct rmid_read rr = { | ||
987 | .rmid = rmid, | ||
988 | .evt_type = evt_type, | ||
989 | .value = ATOMIC64_INIT(0), | ||
990 | }; | ||
991 | |||
992 | /* on each socket, init sample */ | ||
993 | on_each_cpu_mask(&cqm_cpumask, __intel_mbm_event_init, &rr, 1); | ||
994 | } | ||
995 | |||
840 | /* | 996 | /* |
841 | * Find a group and setup RMID. | 997 | * Find a group and setup RMID. |
842 | * | 998 | * |
@@ -849,6 +1005,7 @@ static void intel_cqm_setup_event(struct perf_event *event, | |||
849 | bool conflict = false; | 1005 | bool conflict = false; |
850 | u32 rmid; | 1006 | u32 rmid; |
851 | 1007 | ||
1008 | event->hw.is_group_event = false; | ||
852 | list_for_each_entry(iter, &cache_groups, hw.cqm_groups_entry) { | 1009 | list_for_each_entry(iter, &cache_groups, hw.cqm_groups_entry) { |
853 | rmid = iter->hw.cqm_rmid; | 1010 | rmid = iter->hw.cqm_rmid; |
854 | 1011 | ||
@@ -856,6 +1013,8 @@ static void intel_cqm_setup_event(struct perf_event *event, | |||
856 | /* All tasks in a group share an RMID */ | 1013 | /* All tasks in a group share an RMID */ |
857 | event->hw.cqm_rmid = rmid; | 1014 | event->hw.cqm_rmid = rmid; |
858 | *group = iter; | 1015 | *group = iter; |
1016 | if (is_mbm_event(event->attr.config) && __rmid_valid(rmid)) | ||
1017 | init_mbm_sample(rmid, event->attr.config); | ||
859 | return; | 1018 | return; |
860 | } | 1019 | } |
861 | 1020 | ||
@@ -872,6 +1031,9 @@ static void intel_cqm_setup_event(struct perf_event *event, | |||
872 | else | 1031 | else |
873 | rmid = __get_rmid(); | 1032 | rmid = __get_rmid(); |
874 | 1033 | ||
1034 | if (is_mbm_event(event->attr.config) && __rmid_valid(rmid)) | ||
1035 | init_mbm_sample(rmid, event->attr.config); | ||
1036 | |||
875 | event->hw.cqm_rmid = rmid; | 1037 | event->hw.cqm_rmid = rmid; |
876 | } | 1038 | } |
877 | 1039 | ||
@@ -893,7 +1055,10 @@ static void intel_cqm_event_read(struct perf_event *event) | |||
893 | if (!__rmid_valid(rmid)) | 1055 | if (!__rmid_valid(rmid)) |
894 | goto out; | 1056 | goto out; |
895 | 1057 | ||
896 | val = __rmid_read(rmid); | 1058 | if (is_mbm_event(event->attr.config)) |
1059 | val = rmid_read_mbm(rmid, event->attr.config); | ||
1060 | else | ||
1061 | val = __rmid_read(rmid); | ||
897 | 1062 | ||
898 | /* | 1063 | /* |
899 | * Ignore this reading on error states and do not update the value. | 1064 | * Ignore this reading on error states and do not update the value. |
@@ -924,10 +1089,100 @@ static inline bool cqm_group_leader(struct perf_event *event) | |||
924 | return !list_empty(&event->hw.cqm_groups_entry); | 1089 | return !list_empty(&event->hw.cqm_groups_entry); |
925 | } | 1090 | } |
926 | 1091 | ||
1092 | static void __intel_mbm_event_count(void *info) | ||
1093 | { | ||
1094 | struct rmid_read *rr = info; | ||
1095 | u64 val; | ||
1096 | |||
1097 | val = rmid_read_mbm(rr->rmid, rr->evt_type); | ||
1098 | if (val & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) | ||
1099 | return; | ||
1100 | atomic64_add(val, &rr->value); | ||
1101 | } | ||
1102 | |||
1103 | static enum hrtimer_restart mbm_hrtimer_handle(struct hrtimer *hrtimer) | ||
1104 | { | ||
1105 | struct perf_event *iter, *iter1; | ||
1106 | int ret = HRTIMER_RESTART; | ||
1107 | struct list_head *head; | ||
1108 | unsigned long flags; | ||
1109 | u32 grp_rmid; | ||
1110 | |||
1111 | /* | ||
1112 | * Need to cache_lock as the timer Event Select MSR reads | ||
1113 | * can race with the mbm/cqm count() and mbm_init() reads. | ||
1114 | */ | ||
1115 | raw_spin_lock_irqsave(&cache_lock, flags); | ||
1116 | |||
1117 | if (list_empty(&cache_groups)) { | ||
1118 | ret = HRTIMER_NORESTART; | ||
1119 | goto out; | ||
1120 | } | ||
1121 | |||
1122 | list_for_each_entry(iter, &cache_groups, hw.cqm_groups_entry) { | ||
1123 | grp_rmid = iter->hw.cqm_rmid; | ||
1124 | if (!__rmid_valid(grp_rmid)) | ||
1125 | continue; | ||
1126 | if (is_mbm_event(iter->attr.config)) | ||
1127 | update_sample(grp_rmid, iter->attr.config, 0); | ||
1128 | |||
1129 | head = &iter->hw.cqm_group_entry; | ||
1130 | if (list_empty(head)) | ||
1131 | continue; | ||
1132 | list_for_each_entry(iter1, head, hw.cqm_group_entry) { | ||
1133 | if (!iter1->hw.is_group_event) | ||
1134 | break; | ||
1135 | if (is_mbm_event(iter1->attr.config)) | ||
1136 | update_sample(iter1->hw.cqm_rmid, | ||
1137 | iter1->attr.config, 0); | ||
1138 | } | ||
1139 | } | ||
1140 | |||
1141 | hrtimer_forward_now(hrtimer, ms_to_ktime(MBM_CTR_OVERFLOW_TIME)); | ||
1142 | out: | ||
1143 | raw_spin_unlock_irqrestore(&cache_lock, flags); | ||
1144 | |||
1145 | return ret; | ||
1146 | } | ||
1147 | |||
1148 | static void __mbm_start_timer(void *info) | ||
1149 | { | ||
1150 | hrtimer_start(&mbm_timers[pkg_id], ms_to_ktime(MBM_CTR_OVERFLOW_TIME), | ||
1151 | HRTIMER_MODE_REL_PINNED); | ||
1152 | } | ||
1153 | |||
1154 | static void __mbm_stop_timer(void *info) | ||
1155 | { | ||
1156 | hrtimer_cancel(&mbm_timers[pkg_id]); | ||
1157 | } | ||
1158 | |||
1159 | static void mbm_start_timers(void) | ||
1160 | { | ||
1161 | on_each_cpu_mask(&cqm_cpumask, __mbm_start_timer, NULL, 1); | ||
1162 | } | ||
1163 | |||
1164 | static void mbm_stop_timers(void) | ||
1165 | { | ||
1166 | on_each_cpu_mask(&cqm_cpumask, __mbm_stop_timer, NULL, 1); | ||
1167 | } | ||
1168 | |||
1169 | static void mbm_hrtimer_init(void) | ||
1170 | { | ||
1171 | struct hrtimer *hr; | ||
1172 | int i; | ||
1173 | |||
1174 | for (i = 0; i < mbm_socket_max; i++) { | ||
1175 | hr = &mbm_timers[i]; | ||
1176 | hrtimer_init(hr, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
1177 | hr->function = mbm_hrtimer_handle; | ||
1178 | } | ||
1179 | } | ||
1180 | |||
927 | static u64 intel_cqm_event_count(struct perf_event *event) | 1181 | static u64 intel_cqm_event_count(struct perf_event *event) |
928 | { | 1182 | { |
929 | unsigned long flags; | 1183 | unsigned long flags; |
930 | struct rmid_read rr = { | 1184 | struct rmid_read rr = { |
1185 | .evt_type = event->attr.config, | ||
931 | .value = ATOMIC64_INIT(0), | 1186 | .value = ATOMIC64_INIT(0), |
932 | }; | 1187 | }; |
933 | 1188 | ||
@@ -940,7 +1195,9 @@ static u64 intel_cqm_event_count(struct perf_event *event) | |||
940 | return __perf_event_count(event); | 1195 | return __perf_event_count(event); |
941 | 1196 | ||
942 | /* | 1197 | /* |
943 | * Only the group leader gets to report values. This stops us | 1198 | * Only the group leader gets to report values except in case of |
1199 | * multiple events in the same group, we still need to read the | ||
1200 | * other events.This stops us | ||
944 | * reporting duplicate values to userspace, and gives us a clear | 1201 | * reporting duplicate values to userspace, and gives us a clear |
945 | * rule for which task gets to report the values. | 1202 | * rule for which task gets to report the values. |
946 | * | 1203 | * |
@@ -948,7 +1205,7 @@ static u64 intel_cqm_event_count(struct perf_event *event) | |||
948 | * specific packages - we forfeit that ability when we create | 1205 | * specific packages - we forfeit that ability when we create |
949 | * task events. | 1206 | * task events. |
950 | */ | 1207 | */ |
951 | if (!cqm_group_leader(event)) | 1208 | if (!cqm_group_leader(event) && !event->hw.is_group_event) |
952 | return 0; | 1209 | return 0; |
953 | 1210 | ||
954 | /* | 1211 | /* |
@@ -975,7 +1232,7 @@ static u64 intel_cqm_event_count(struct perf_event *event) | |||
975 | if (!__rmid_valid(rr.rmid)) | 1232 | if (!__rmid_valid(rr.rmid)) |
976 | goto out; | 1233 | goto out; |
977 | 1234 | ||
978 | on_each_cpu_mask(&cqm_cpumask, __intel_cqm_event_count, &rr, 1); | 1235 | cqm_mask_call(&rr); |
979 | 1236 | ||
980 | raw_spin_lock_irqsave(&cache_lock, flags); | 1237 | raw_spin_lock_irqsave(&cache_lock, flags); |
981 | if (event->hw.cqm_rmid == rr.rmid) | 1238 | if (event->hw.cqm_rmid == rr.rmid) |
@@ -1046,8 +1303,14 @@ static int intel_cqm_event_add(struct perf_event *event, int mode) | |||
1046 | static void intel_cqm_event_destroy(struct perf_event *event) | 1303 | static void intel_cqm_event_destroy(struct perf_event *event) |
1047 | { | 1304 | { |
1048 | struct perf_event *group_other = NULL; | 1305 | struct perf_event *group_other = NULL; |
1306 | unsigned long flags; | ||
1049 | 1307 | ||
1050 | mutex_lock(&cache_mutex); | 1308 | mutex_lock(&cache_mutex); |
1309 | /* | ||
1310 | * Hold the cache_lock as mbm timer handlers could be | ||
1311 | * scanning the list of events. | ||
1312 | */ | ||
1313 | raw_spin_lock_irqsave(&cache_lock, flags); | ||
1051 | 1314 | ||
1052 | /* | 1315 | /* |
1053 | * If there's another event in this group... | 1316 | * If there's another event in this group... |
@@ -1079,6 +1342,14 @@ static void intel_cqm_event_destroy(struct perf_event *event) | |||
1079 | } | 1342 | } |
1080 | } | 1343 | } |
1081 | 1344 | ||
1345 | raw_spin_unlock_irqrestore(&cache_lock, flags); | ||
1346 | |||
1347 | /* | ||
1348 | * Stop the mbm overflow timers when the last event is destroyed. | ||
1349 | */ | ||
1350 | if (mbm_enabled && list_empty(&cache_groups)) | ||
1351 | mbm_stop_timers(); | ||
1352 | |||
1082 | mutex_unlock(&cache_mutex); | 1353 | mutex_unlock(&cache_mutex); |
1083 | } | 1354 | } |
1084 | 1355 | ||
@@ -1086,11 +1357,13 @@ static int intel_cqm_event_init(struct perf_event *event) | |||
1086 | { | 1357 | { |
1087 | struct perf_event *group = NULL; | 1358 | struct perf_event *group = NULL; |
1088 | bool rotate = false; | 1359 | bool rotate = false; |
1360 | unsigned long flags; | ||
1089 | 1361 | ||
1090 | if (event->attr.type != intel_cqm_pmu.type) | 1362 | if (event->attr.type != intel_cqm_pmu.type) |
1091 | return -ENOENT; | 1363 | return -ENOENT; |
1092 | 1364 | ||
1093 | if (event->attr.config & ~QOS_EVENT_MASK) | 1365 | if ((event->attr.config < QOS_L3_OCCUP_EVENT_ID) || |
1366 | (event->attr.config > QOS_MBM_LOCAL_EVENT_ID)) | ||
1094 | return -EINVAL; | 1367 | return -EINVAL; |
1095 | 1368 | ||
1096 | /* unsupported modes and filters */ | 1369 | /* unsupported modes and filters */ |
@@ -1110,9 +1383,21 @@ static int intel_cqm_event_init(struct perf_event *event) | |||
1110 | 1383 | ||
1111 | mutex_lock(&cache_mutex); | 1384 | mutex_lock(&cache_mutex); |
1112 | 1385 | ||
1386 | /* | ||
1387 | * Start the mbm overflow timers when the first event is created. | ||
1388 | */ | ||
1389 | if (mbm_enabled && list_empty(&cache_groups)) | ||
1390 | mbm_start_timers(); | ||
1391 | |||
1113 | /* Will also set rmid */ | 1392 | /* Will also set rmid */ |
1114 | intel_cqm_setup_event(event, &group); | 1393 | intel_cqm_setup_event(event, &group); |
1115 | 1394 | ||
1395 | /* | ||
1396 | * Hold the cache_lock as mbm timer handlers be | ||
1397 | * scanning the list of events. | ||
1398 | */ | ||
1399 | raw_spin_lock_irqsave(&cache_lock, flags); | ||
1400 | |||
1116 | if (group) { | 1401 | if (group) { |
1117 | list_add_tail(&event->hw.cqm_group_entry, | 1402 | list_add_tail(&event->hw.cqm_group_entry, |
1118 | &group->hw.cqm_group_entry); | 1403 | &group->hw.cqm_group_entry); |
@@ -1131,6 +1416,7 @@ static int intel_cqm_event_init(struct perf_event *event) | |||
1131 | rotate = true; | 1416 | rotate = true; |
1132 | } | 1417 | } |
1133 | 1418 | ||
1419 | raw_spin_unlock_irqrestore(&cache_lock, flags); | ||
1134 | mutex_unlock(&cache_mutex); | 1420 | mutex_unlock(&cache_mutex); |
1135 | 1421 | ||
1136 | if (rotate) | 1422 | if (rotate) |
@@ -1145,6 +1431,16 @@ EVENT_ATTR_STR(llc_occupancy.unit, intel_cqm_llc_unit, "Bytes"); | |||
1145 | EVENT_ATTR_STR(llc_occupancy.scale, intel_cqm_llc_scale, NULL); | 1431 | EVENT_ATTR_STR(llc_occupancy.scale, intel_cqm_llc_scale, NULL); |
1146 | EVENT_ATTR_STR(llc_occupancy.snapshot, intel_cqm_llc_snapshot, "1"); | 1432 | EVENT_ATTR_STR(llc_occupancy.snapshot, intel_cqm_llc_snapshot, "1"); |
1147 | 1433 | ||
1434 | EVENT_ATTR_STR(total_bytes, intel_cqm_total_bytes, "event=0x02"); | ||
1435 | EVENT_ATTR_STR(total_bytes.per-pkg, intel_cqm_total_bytes_pkg, "1"); | ||
1436 | EVENT_ATTR_STR(total_bytes.unit, intel_cqm_total_bytes_unit, "MB"); | ||
1437 | EVENT_ATTR_STR(total_bytes.scale, intel_cqm_total_bytes_scale, "1e-6"); | ||
1438 | |||
1439 | EVENT_ATTR_STR(local_bytes, intel_cqm_local_bytes, "event=0x03"); | ||
1440 | EVENT_ATTR_STR(local_bytes.per-pkg, intel_cqm_local_bytes_pkg, "1"); | ||
1441 | EVENT_ATTR_STR(local_bytes.unit, intel_cqm_local_bytes_unit, "MB"); | ||
1442 | EVENT_ATTR_STR(local_bytes.scale, intel_cqm_local_bytes_scale, "1e-6"); | ||
1443 | |||
1148 | static struct attribute *intel_cqm_events_attr[] = { | 1444 | static struct attribute *intel_cqm_events_attr[] = { |
1149 | EVENT_PTR(intel_cqm_llc), | 1445 | EVENT_PTR(intel_cqm_llc), |
1150 | EVENT_PTR(intel_cqm_llc_pkg), | 1446 | EVENT_PTR(intel_cqm_llc_pkg), |
@@ -1154,9 +1450,38 @@ static struct attribute *intel_cqm_events_attr[] = { | |||
1154 | NULL, | 1450 | NULL, |
1155 | }; | 1451 | }; |
1156 | 1452 | ||
1453 | static struct attribute *intel_mbm_events_attr[] = { | ||
1454 | EVENT_PTR(intel_cqm_total_bytes), | ||
1455 | EVENT_PTR(intel_cqm_local_bytes), | ||
1456 | EVENT_PTR(intel_cqm_total_bytes_pkg), | ||
1457 | EVENT_PTR(intel_cqm_local_bytes_pkg), | ||
1458 | EVENT_PTR(intel_cqm_total_bytes_unit), | ||
1459 | EVENT_PTR(intel_cqm_local_bytes_unit), | ||
1460 | EVENT_PTR(intel_cqm_total_bytes_scale), | ||
1461 | EVENT_PTR(intel_cqm_local_bytes_scale), | ||
1462 | NULL, | ||
1463 | }; | ||
1464 | |||
1465 | static struct attribute *intel_cmt_mbm_events_attr[] = { | ||
1466 | EVENT_PTR(intel_cqm_llc), | ||
1467 | EVENT_PTR(intel_cqm_total_bytes), | ||
1468 | EVENT_PTR(intel_cqm_local_bytes), | ||
1469 | EVENT_PTR(intel_cqm_llc_pkg), | ||
1470 | EVENT_PTR(intel_cqm_total_bytes_pkg), | ||
1471 | EVENT_PTR(intel_cqm_local_bytes_pkg), | ||
1472 | EVENT_PTR(intel_cqm_llc_unit), | ||
1473 | EVENT_PTR(intel_cqm_total_bytes_unit), | ||
1474 | EVENT_PTR(intel_cqm_local_bytes_unit), | ||
1475 | EVENT_PTR(intel_cqm_llc_scale), | ||
1476 | EVENT_PTR(intel_cqm_total_bytes_scale), | ||
1477 | EVENT_PTR(intel_cqm_local_bytes_scale), | ||
1478 | EVENT_PTR(intel_cqm_llc_snapshot), | ||
1479 | NULL, | ||
1480 | }; | ||
1481 | |||
1157 | static struct attribute_group intel_cqm_events_group = { | 1482 | static struct attribute_group intel_cqm_events_group = { |
1158 | .name = "events", | 1483 | .name = "events", |
1159 | .attrs = intel_cqm_events_attr, | 1484 | .attrs = NULL, |
1160 | }; | 1485 | }; |
1161 | 1486 | ||
1162 | PMU_FORMAT_ATTR(event, "config:0-7"); | 1487 | PMU_FORMAT_ATTR(event, "config:0-7"); |
@@ -1303,12 +1628,70 @@ static const struct x86_cpu_id intel_cqm_match[] = { | |||
1303 | {} | 1628 | {} |
1304 | }; | 1629 | }; |
1305 | 1630 | ||
1631 | static void mbm_cleanup(void) | ||
1632 | { | ||
1633 | if (!mbm_enabled) | ||
1634 | return; | ||
1635 | |||
1636 | kfree(mbm_local); | ||
1637 | kfree(mbm_total); | ||
1638 | mbm_enabled = false; | ||
1639 | } | ||
1640 | |||
1641 | static const struct x86_cpu_id intel_mbm_local_match[] = { | ||
1642 | { .vendor = X86_VENDOR_INTEL, .feature = X86_FEATURE_CQM_MBM_LOCAL }, | ||
1643 | {} | ||
1644 | }; | ||
1645 | |||
1646 | static const struct x86_cpu_id intel_mbm_total_match[] = { | ||
1647 | { .vendor = X86_VENDOR_INTEL, .feature = X86_FEATURE_CQM_MBM_TOTAL }, | ||
1648 | {} | ||
1649 | }; | ||
1650 | |||
1651 | static int intel_mbm_init(void) | ||
1652 | { | ||
1653 | int ret = 0, array_size, maxid = cqm_max_rmid + 1; | ||
1654 | |||
1655 | mbm_socket_max = topology_max_packages(); | ||
1656 | array_size = sizeof(struct sample) * maxid * mbm_socket_max; | ||
1657 | mbm_local = kmalloc(array_size, GFP_KERNEL); | ||
1658 | if (!mbm_local) | ||
1659 | return -ENOMEM; | ||
1660 | |||
1661 | mbm_total = kmalloc(array_size, GFP_KERNEL); | ||
1662 | if (!mbm_total) { | ||
1663 | ret = -ENOMEM; | ||
1664 | goto out; | ||
1665 | } | ||
1666 | |||
1667 | array_size = sizeof(struct hrtimer) * mbm_socket_max; | ||
1668 | mbm_timers = kmalloc(array_size, GFP_KERNEL); | ||
1669 | if (!mbm_timers) { | ||
1670 | ret = -ENOMEM; | ||
1671 | goto out; | ||
1672 | } | ||
1673 | mbm_hrtimer_init(); | ||
1674 | |||
1675 | out: | ||
1676 | if (ret) | ||
1677 | mbm_cleanup(); | ||
1678 | |||
1679 | return ret; | ||
1680 | } | ||
1681 | |||
1306 | static int __init intel_cqm_init(void) | 1682 | static int __init intel_cqm_init(void) |
1307 | { | 1683 | { |
1308 | char *str, scale[20]; | 1684 | char *str = NULL, scale[20]; |
1309 | int i, cpu, ret; | 1685 | int i, cpu, ret; |
1310 | 1686 | ||
1311 | if (!x86_match_cpu(intel_cqm_match)) | 1687 | if (x86_match_cpu(intel_cqm_match)) |
1688 | cqm_enabled = true; | ||
1689 | |||
1690 | if (x86_match_cpu(intel_mbm_local_match) && | ||
1691 | x86_match_cpu(intel_mbm_total_match)) | ||
1692 | mbm_enabled = true; | ||
1693 | |||
1694 | if (!cqm_enabled && !mbm_enabled) | ||
1312 | return -ENODEV; | 1695 | return -ENODEV; |
1313 | 1696 | ||
1314 | cqm_l3_scale = boot_cpu_data.x86_cache_occ_scale; | 1697 | cqm_l3_scale = boot_cpu_data.x86_cache_occ_scale; |
@@ -1365,16 +1748,41 @@ static int __init intel_cqm_init(void) | |||
1365 | cqm_pick_event_reader(i); | 1748 | cqm_pick_event_reader(i); |
1366 | } | 1749 | } |
1367 | 1750 | ||
1368 | __perf_cpu_notifier(intel_cqm_cpu_notifier); | 1751 | if (mbm_enabled) |
1752 | ret = intel_mbm_init(); | ||
1753 | if (ret && !cqm_enabled) | ||
1754 | goto out; | ||
1755 | |||
1756 | if (cqm_enabled && mbm_enabled) | ||
1757 | intel_cqm_events_group.attrs = intel_cmt_mbm_events_attr; | ||
1758 | else if (!cqm_enabled && mbm_enabled) | ||
1759 | intel_cqm_events_group.attrs = intel_mbm_events_attr; | ||
1760 | else if (cqm_enabled && !mbm_enabled) | ||
1761 | intel_cqm_events_group.attrs = intel_cqm_events_attr; | ||
1369 | 1762 | ||
1370 | ret = perf_pmu_register(&intel_cqm_pmu, "intel_cqm", -1); | 1763 | ret = perf_pmu_register(&intel_cqm_pmu, "intel_cqm", -1); |
1371 | if (ret) | 1764 | if (ret) { |
1372 | pr_err("Intel CQM perf registration failed: %d\n", ret); | 1765 | pr_err("Intel CQM perf registration failed: %d\n", ret); |
1373 | else | 1766 | goto out; |
1767 | } | ||
1768 | |||
1769 | if (cqm_enabled) | ||
1374 | pr_info("Intel CQM monitoring enabled\n"); | 1770 | pr_info("Intel CQM monitoring enabled\n"); |
1771 | if (mbm_enabled) | ||
1772 | pr_info("Intel MBM enabled\n"); | ||
1375 | 1773 | ||
1774 | /* | ||
1775 | * Register the hot cpu notifier once we are sure cqm | ||
1776 | * is enabled to avoid notifier leak. | ||
1777 | */ | ||
1778 | __perf_cpu_notifier(intel_cqm_cpu_notifier); | ||
1376 | out: | 1779 | out: |
1377 | cpu_notifier_register_done(); | 1780 | cpu_notifier_register_done(); |
1781 | if (ret) { | ||
1782 | kfree(str); | ||
1783 | cqm_cleanup(); | ||
1784 | mbm_cleanup(); | ||
1785 | } | ||
1378 | 1786 | ||
1379 | return ret; | 1787 | return ret; |
1380 | } | 1788 | } |
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index ce7211a07c0b..8584b90d8e0b 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c | |||
@@ -570,11 +570,12 @@ int intel_pmu_drain_bts_buffer(void) | |||
570 | * We will overwrite the from and to address before we output | 570 | * We will overwrite the from and to address before we output |
571 | * the sample. | 571 | * the sample. |
572 | */ | 572 | */ |
573 | rcu_read_lock(); | ||
573 | perf_prepare_sample(&header, &data, event, ®s); | 574 | perf_prepare_sample(&header, &data, event, ®s); |
574 | 575 | ||
575 | if (perf_output_begin(&handle, event, header.size * | 576 | if (perf_output_begin(&handle, event, header.size * |
576 | (top - base - skip))) | 577 | (top - base - skip))) |
577 | return 1; | 578 | goto unlock; |
578 | 579 | ||
579 | for (at = base; at < top; at++) { | 580 | for (at = base; at < top; at++) { |
580 | /* Filter out any records that contain kernel addresses. */ | 581 | /* Filter out any records that contain kernel addresses. */ |
@@ -593,6 +594,8 @@ int intel_pmu_drain_bts_buffer(void) | |||
593 | /* There's new data available. */ | 594 | /* There's new data available. */ |
594 | event->hw.interrupts++; | 595 | event->hw.interrupts++; |
595 | event->pending_kill = POLL_IN; | 596 | event->pending_kill = POLL_IN; |
597 | unlock: | ||
598 | rcu_read_unlock(); | ||
596 | return 1; | 599 | return 1; |
597 | } | 600 | } |
598 | 601 | ||
diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c index b834a3f55a01..70c93f9b03ac 100644 --- a/arch/x86/events/intel/rapl.c +++ b/arch/x86/events/intel/rapl.c | |||
@@ -711,6 +711,7 @@ static int __init rapl_pmu_init(void) | |||
711 | rapl_pmu_events_group.attrs = rapl_events_cln_attr; | 711 | rapl_pmu_events_group.attrs = rapl_events_cln_attr; |
712 | break; | 712 | break; |
713 | case 63: /* Haswell-Server */ | 713 | case 63: /* Haswell-Server */ |
714 | case 79: /* Broadwell-Server */ | ||
714 | apply_quirk = true; | 715 | apply_quirk = true; |
715 | rapl_cntr_mask = RAPL_IDX_SRV; | 716 | rapl_cntr_mask = RAPL_IDX_SRV; |
716 | rapl_pmu_events_group.attrs = rapl_events_srv_attr; | 717 | rapl_pmu_events_group.attrs = rapl_events_srv_attr; |
@@ -718,6 +719,7 @@ static int __init rapl_pmu_init(void) | |||
718 | case 60: /* Haswell */ | 719 | case 60: /* Haswell */ |
719 | case 69: /* Haswell-Celeron */ | 720 | case 69: /* Haswell-Celeron */ |
720 | case 61: /* Broadwell */ | 721 | case 61: /* Broadwell */ |
722 | case 71: /* Broadwell-H */ | ||
721 | rapl_cntr_mask = RAPL_IDX_HSW; | 723 | rapl_cntr_mask = RAPL_IDX_HSW; |
722 | rapl_pmu_events_group.attrs = rapl_events_hsw_attr; | 724 | rapl_pmu_events_group.attrs = rapl_events_hsw_attr; |
723 | break; | 725 | break; |
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c index 93f6bd9bf761..ab2bcaaebe38 100644 --- a/arch/x86/events/intel/uncore_snbep.c +++ b/arch/x86/events/intel/uncore_snbep.c | |||
@@ -46,7 +46,6 @@ | |||
46 | (SNBEP_PMON_CTL_EV_SEL_MASK | \ | 46 | (SNBEP_PMON_CTL_EV_SEL_MASK | \ |
47 | SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \ | 47 | SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \ |
48 | SNBEP_PMON_CTL_EDGE_DET | \ | 48 | SNBEP_PMON_CTL_EDGE_DET | \ |
49 | SNBEP_PMON_CTL_EV_SEL_EXT | \ | ||
50 | SNBEP_PMON_CTL_INVERT | \ | 49 | SNBEP_PMON_CTL_INVERT | \ |
51 | SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \ | 50 | SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \ |
52 | SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \ | 51 | SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \ |
@@ -148,7 +147,6 @@ | |||
148 | /* IVBEP PCU */ | 147 | /* IVBEP PCU */ |
149 | #define IVBEP_PCU_MSR_PMON_RAW_EVENT_MASK \ | 148 | #define IVBEP_PCU_MSR_PMON_RAW_EVENT_MASK \ |
150 | (SNBEP_PMON_CTL_EV_SEL_MASK | \ | 149 | (SNBEP_PMON_CTL_EV_SEL_MASK | \ |
151 | SNBEP_PMON_CTL_EV_SEL_EXT | \ | ||
152 | SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \ | 150 | SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \ |
153 | SNBEP_PMON_CTL_EDGE_DET | \ | 151 | SNBEP_PMON_CTL_EDGE_DET | \ |
154 | SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \ | 152 | SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \ |
@@ -258,7 +256,6 @@ | |||
258 | SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \ | 256 | SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \ |
259 | SNBEP_PMON_CTL_EDGE_DET | \ | 257 | SNBEP_PMON_CTL_EDGE_DET | \ |
260 | SNBEP_CBO_PMON_CTL_TID_EN | \ | 258 | SNBEP_CBO_PMON_CTL_TID_EN | \ |
261 | SNBEP_PMON_CTL_EV_SEL_EXT | \ | ||
262 | SNBEP_PMON_CTL_INVERT | \ | 259 | SNBEP_PMON_CTL_INVERT | \ |
263 | KNL_PCU_MSR_PMON_CTL_TRESH_MASK | \ | 260 | KNL_PCU_MSR_PMON_CTL_TRESH_MASK | \ |
264 | SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \ | 261 | SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \ |
@@ -472,7 +469,7 @@ static struct attribute *snbep_uncore_cbox_formats_attr[] = { | |||
472 | }; | 469 | }; |
473 | 470 | ||
474 | static struct attribute *snbep_uncore_pcu_formats_attr[] = { | 471 | static struct attribute *snbep_uncore_pcu_formats_attr[] = { |
475 | &format_attr_event_ext.attr, | 472 | &format_attr_event.attr, |
476 | &format_attr_occ_sel.attr, | 473 | &format_attr_occ_sel.attr, |
477 | &format_attr_edge.attr, | 474 | &format_attr_edge.attr, |
478 | &format_attr_inv.attr, | 475 | &format_attr_inv.attr, |
@@ -1313,7 +1310,7 @@ static struct attribute *ivbep_uncore_cbox_formats_attr[] = { | |||
1313 | }; | 1310 | }; |
1314 | 1311 | ||
1315 | static struct attribute *ivbep_uncore_pcu_formats_attr[] = { | 1312 | static struct attribute *ivbep_uncore_pcu_formats_attr[] = { |
1316 | &format_attr_event_ext.attr, | 1313 | &format_attr_event.attr, |
1317 | &format_attr_occ_sel.attr, | 1314 | &format_attr_occ_sel.attr, |
1318 | &format_attr_edge.attr, | 1315 | &format_attr_edge.attr, |
1319 | &format_attr_thresh5.attr, | 1316 | &format_attr_thresh5.attr, |
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 3d1a84383162..8f9afefd2dc5 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h | |||
@@ -94,7 +94,7 @@ | |||
94 | #define X86_FEATURE_REP_GOOD ( 3*32+16) /* rep microcode works well */ | 94 | #define X86_FEATURE_REP_GOOD ( 3*32+16) /* rep microcode works well */ |
95 | #define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" Mfence synchronizes RDTSC */ | 95 | #define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" Mfence synchronizes RDTSC */ |
96 | #define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" Lfence synchronizes RDTSC */ | 96 | #define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" Lfence synchronizes RDTSC */ |
97 | /* free, was #define X86_FEATURE_11AP ( 3*32+19) * "" Bad local APIC aka 11AP */ | 97 | #define X86_FEATURE_ACC_POWER ( 3*32+19) /* AMD Accumulated Power Mechanism */ |
98 | #define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */ | 98 | #define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */ |
99 | #define X86_FEATURE_ALWAYS ( 3*32+21) /* "" Always-present feature */ | 99 | #define X86_FEATURE_ALWAYS ( 3*32+21) /* "" Always-present feature */ |
100 | #define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */ | 100 | #define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */ |
@@ -245,6 +245,8 @@ | |||
245 | 245 | ||
246 | /* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:1 (edx), word 12 */ | 246 | /* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:1 (edx), word 12 */ |
247 | #define X86_FEATURE_CQM_OCCUP_LLC (12*32+ 0) /* LLC occupancy monitoring if 1 */ | 247 | #define X86_FEATURE_CQM_OCCUP_LLC (12*32+ 0) /* LLC occupancy monitoring if 1 */ |
248 | #define X86_FEATURE_CQM_MBM_TOTAL (12*32+ 1) /* LLC Total MBM monitoring */ | ||
249 | #define X86_FEATURE_CQM_MBM_LOCAL (12*32+ 2) /* LLC Local MBM monitoring */ | ||
248 | 250 | ||
249 | /* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */ | 251 | /* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */ |
250 | #define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */ | 252 | #define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */ |
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index e51021c9207a..6e47e3a916f1 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
@@ -309,7 +309,6 @@ static void amd_get_topology(struct cpuinfo_x86 *c) | |||
309 | u32 eax, ebx, ecx, edx; | 309 | u32 eax, ebx, ecx, edx; |
310 | 310 | ||
311 | cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); | 311 | cpuid(0x8000001e, &eax, &ebx, &ecx, &edx); |
312 | nodes_per_socket = ((ecx >> 8) & 7) + 1; | ||
313 | node_id = ecx & 7; | 312 | node_id = ecx & 7; |
314 | 313 | ||
315 | /* get compute unit information */ | 314 | /* get compute unit information */ |
@@ -320,7 +319,6 @@ static void amd_get_topology(struct cpuinfo_x86 *c) | |||
320 | u64 value; | 319 | u64 value; |
321 | 320 | ||
322 | rdmsrl(MSR_FAM10H_NODE_ID, value); | 321 | rdmsrl(MSR_FAM10H_NODE_ID, value); |
323 | nodes_per_socket = ((value >> 3) & 7) + 1; | ||
324 | node_id = value & 7; | 322 | node_id = value & 7; |
325 | } else | 323 | } else |
326 | return; | 324 | return; |
@@ -522,6 +520,18 @@ static void bsp_init_amd(struct cpuinfo_x86 *c) | |||
522 | 520 | ||
523 | if (cpu_has(c, X86_FEATURE_MWAITX)) | 521 | if (cpu_has(c, X86_FEATURE_MWAITX)) |
524 | use_mwaitx_delay(); | 522 | use_mwaitx_delay(); |
523 | |||
524 | if (boot_cpu_has(X86_FEATURE_TOPOEXT)) { | ||
525 | u32 ecx; | ||
526 | |||
527 | ecx = cpuid_ecx(0x8000001e); | ||
528 | nodes_per_socket = ((ecx >> 8) & 7) + 1; | ||
529 | } else if (boot_cpu_has(X86_FEATURE_NODEID_MSR)) { | ||
530 | u64 value; | ||
531 | |||
532 | rdmsrl(MSR_FAM10H_NODE_ID, value); | ||
533 | nodes_per_socket = ((value >> 3) & 7) + 1; | ||
534 | } | ||
525 | } | 535 | } |
526 | 536 | ||
527 | static void early_init_amd(struct cpuinfo_x86 *c) | 537 | static void early_init_amd(struct cpuinfo_x86 *c) |
@@ -539,6 +549,10 @@ static void early_init_amd(struct cpuinfo_x86 *c) | |||
539 | set_sched_clock_stable(); | 549 | set_sched_clock_stable(); |
540 | } | 550 | } |
541 | 551 | ||
552 | /* Bit 12 of 8000_0007 edx is accumulated power mechanism. */ | ||
553 | if (c->x86_power & BIT(12)) | ||
554 | set_cpu_cap(c, X86_FEATURE_ACC_POWER); | ||
555 | |||
542 | #ifdef CONFIG_X86_64 | 556 | #ifdef CONFIG_X86_64 |
543 | set_cpu_cap(c, X86_FEATURE_SYSCALL32); | 557 | set_cpu_cap(c, X86_FEATURE_SYSCALL32); |
544 | #else | 558 | #else |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 9988caf42161..8394b3d1f94f 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -692,7 +692,9 @@ void get_cpu_cap(struct cpuinfo_x86 *c) | |||
692 | cpuid_count(0x0000000F, 1, &eax, &ebx, &ecx, &edx); | 692 | cpuid_count(0x0000000F, 1, &eax, &ebx, &ecx, &edx); |
693 | c->x86_capability[CPUID_F_1_EDX] = edx; | 693 | c->x86_capability[CPUID_F_1_EDX] = edx; |
694 | 694 | ||
695 | if (cpu_has(c, X86_FEATURE_CQM_OCCUP_LLC)) { | 695 | if ((cpu_has(c, X86_FEATURE_CQM_OCCUP_LLC)) || |
696 | ((cpu_has(c, X86_FEATURE_CQM_MBM_TOTAL)) || | ||
697 | (cpu_has(c, X86_FEATURE_CQM_MBM_LOCAL)))) { | ||
696 | c->x86_cache_max_rmid = ecx; | 698 | c->x86_cache_max_rmid = ecx; |
697 | c->x86_cache_occ_scale = ebx; | 699 | c->x86_cache_occ_scale = ebx; |
698 | } | 700 | } |
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 78fda2a69ab8..f291275ffd71 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
@@ -121,6 +121,7 @@ struct hw_perf_event { | |||
121 | struct { /* intel_cqm */ | 121 | struct { /* intel_cqm */ |
122 | int cqm_state; | 122 | int cqm_state; |
123 | u32 cqm_rmid; | 123 | u32 cqm_rmid; |
124 | int is_group_event; | ||
124 | struct list_head cqm_events_entry; | 125 | struct list_head cqm_events_entry; |
125 | struct list_head cqm_groups_entry; | 126 | struct list_head cqm_groups_entry; |
126 | struct list_head cqm_group_entry; | 127 | struct list_head cqm_group_entry; |
@@ -128,6 +129,10 @@ struct hw_perf_event { | |||
128 | struct { /* itrace */ | 129 | struct { /* itrace */ |
129 | int itrace_started; | 130 | int itrace_started; |
130 | }; | 131 | }; |
132 | struct { /* amd_power */ | ||
133 | u64 pwr_acc; | ||
134 | u64 ptsc; | ||
135 | }; | ||
131 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | 136 | #ifdef CONFIG_HAVE_HW_BREAKPOINT |
132 | struct { /* breakpoint */ | 137 | struct { /* breakpoint */ |
133 | /* | 138 | /* |
diff --git a/kernel/events/core.c b/kernel/events/core.c index 712570dddacd..de24fbce5277 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -376,8 +376,11 @@ static void update_perf_cpu_limits(void) | |||
376 | u64 tmp = perf_sample_period_ns; | 376 | u64 tmp = perf_sample_period_ns; |
377 | 377 | ||
378 | tmp *= sysctl_perf_cpu_time_max_percent; | 378 | tmp *= sysctl_perf_cpu_time_max_percent; |
379 | do_div(tmp, 100); | 379 | tmp = div_u64(tmp, 100); |
380 | ACCESS_ONCE(perf_sample_allowed_ns) = tmp; | 380 | if (!tmp) |
381 | tmp = 1; | ||
382 | |||
383 | WRITE_ONCE(perf_sample_allowed_ns, tmp); | ||
381 | } | 384 | } |
382 | 385 | ||
383 | static int perf_rotate_context(struct perf_cpu_context *cpuctx); | 386 | static int perf_rotate_context(struct perf_cpu_context *cpuctx); |
@@ -409,7 +412,13 @@ int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write, | |||
409 | if (ret || !write) | 412 | if (ret || !write) |
410 | return ret; | 413 | return ret; |
411 | 414 | ||
412 | update_perf_cpu_limits(); | 415 | if (sysctl_perf_cpu_time_max_percent == 100) { |
416 | printk(KERN_WARNING | ||
417 | "perf: Dynamic interrupt throttling disabled, can hang your system!\n"); | ||
418 | WRITE_ONCE(perf_sample_allowed_ns, 0); | ||
419 | } else { | ||
420 | update_perf_cpu_limits(); | ||
421 | } | ||
413 | 422 | ||
414 | return 0; | 423 | return 0; |
415 | } | 424 | } |
@@ -423,62 +432,68 @@ int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write, | |||
423 | #define NR_ACCUMULATED_SAMPLES 128 | 432 | #define NR_ACCUMULATED_SAMPLES 128 |
424 | static DEFINE_PER_CPU(u64, running_sample_length); | 433 | static DEFINE_PER_CPU(u64, running_sample_length); |
425 | 434 | ||
435 | static u64 __report_avg; | ||
436 | static u64 __report_allowed; | ||
437 | |||
426 | static void perf_duration_warn(struct irq_work *w) | 438 | static void perf_duration_warn(struct irq_work *w) |
427 | { | 439 | { |
428 | u64 allowed_ns = ACCESS_ONCE(perf_sample_allowed_ns); | ||
429 | u64 avg_local_sample_len; | ||
430 | u64 local_samples_len; | ||
431 | |||
432 | local_samples_len = __this_cpu_read(running_sample_length); | ||
433 | avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES; | ||
434 | |||
435 | printk_ratelimited(KERN_WARNING | 440 | printk_ratelimited(KERN_WARNING |
436 | "perf interrupt took too long (%lld > %lld), lowering " | 441 | "perf: interrupt took too long (%lld > %lld), lowering " |
437 | "kernel.perf_event_max_sample_rate to %d\n", | 442 | "kernel.perf_event_max_sample_rate to %d\n", |
438 | avg_local_sample_len, allowed_ns >> 1, | 443 | __report_avg, __report_allowed, |
439 | sysctl_perf_event_sample_rate); | 444 | sysctl_perf_event_sample_rate); |
440 | } | 445 | } |
441 | 446 | ||
442 | static DEFINE_IRQ_WORK(perf_duration_work, perf_duration_warn); | 447 | static DEFINE_IRQ_WORK(perf_duration_work, perf_duration_warn); |
443 | 448 | ||
444 | void perf_sample_event_took(u64 sample_len_ns) | 449 | void perf_sample_event_took(u64 sample_len_ns) |
445 | { | 450 | { |
446 | u64 allowed_ns = ACCESS_ONCE(perf_sample_allowed_ns); | 451 | u64 max_len = READ_ONCE(perf_sample_allowed_ns); |
447 | u64 avg_local_sample_len; | 452 | u64 running_len; |
448 | u64 local_samples_len; | 453 | u64 avg_len; |
454 | u32 max; | ||
449 | 455 | ||
450 | if (allowed_ns == 0) | 456 | if (max_len == 0) |
451 | return; | 457 | return; |
452 | 458 | ||
453 | /* decay the counter by 1 average sample */ | 459 | /* Decay the counter by 1 average sample. */ |
454 | local_samples_len = __this_cpu_read(running_sample_length); | 460 | running_len = __this_cpu_read(running_sample_length); |
455 | local_samples_len -= local_samples_len/NR_ACCUMULATED_SAMPLES; | 461 | running_len -= running_len/NR_ACCUMULATED_SAMPLES; |
456 | local_samples_len += sample_len_ns; | 462 | running_len += sample_len_ns; |
457 | __this_cpu_write(running_sample_length, local_samples_len); | 463 | __this_cpu_write(running_sample_length, running_len); |
458 | 464 | ||
459 | /* | 465 | /* |
460 | * note: this will be biased artifically low until we have | 466 | * Note: this will be biased artifically low until we have |
461 | * seen NR_ACCUMULATED_SAMPLES. Doing it this way keeps us | 467 | * seen NR_ACCUMULATED_SAMPLES. Doing it this way keeps us |
462 | * from having to maintain a count. | 468 | * from having to maintain a count. |
463 | */ | 469 | */ |
464 | avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES; | 470 | avg_len = running_len/NR_ACCUMULATED_SAMPLES; |
465 | 471 | if (avg_len <= max_len) | |
466 | if (avg_local_sample_len <= allowed_ns) | ||
467 | return; | 472 | return; |
468 | 473 | ||
469 | if (max_samples_per_tick <= 1) | 474 | __report_avg = avg_len; |
470 | return; | 475 | __report_allowed = max_len; |
471 | 476 | ||
472 | max_samples_per_tick = DIV_ROUND_UP(max_samples_per_tick, 2); | 477 | /* |
473 | sysctl_perf_event_sample_rate = max_samples_per_tick * HZ; | 478 | * Compute a throttle threshold 25% below the current duration. |
474 | perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate; | 479 | */ |
480 | avg_len += avg_len / 4; | ||
481 | max = (TICK_NSEC / 100) * sysctl_perf_cpu_time_max_percent; | ||
482 | if (avg_len < max) | ||
483 | max /= (u32)avg_len; | ||
484 | else | ||
485 | max = 1; | ||
475 | 486 | ||
476 | update_perf_cpu_limits(); | 487 | WRITE_ONCE(perf_sample_allowed_ns, avg_len); |
488 | WRITE_ONCE(max_samples_per_tick, max); | ||
489 | |||
490 | sysctl_perf_event_sample_rate = max * HZ; | ||
491 | perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate; | ||
477 | 492 | ||
478 | if (!irq_work_queue(&perf_duration_work)) { | 493 | if (!irq_work_queue(&perf_duration_work)) { |
479 | early_printk("perf interrupt took too long (%lld > %lld), lowering " | 494 | early_printk("perf: interrupt took too long (%lld > %lld), lowering " |
480 | "kernel.perf_event_max_sample_rate to %d\n", | 495 | "kernel.perf_event_max_sample_rate to %d\n", |
481 | avg_local_sample_len, allowed_ns >> 1, | 496 | __report_avg, __report_allowed, |
482 | sysctl_perf_event_sample_rate); | 497 | sysctl_perf_event_sample_rate); |
483 | } | 498 | } |
484 | } | 499 | } |
@@ -4210,6 +4225,14 @@ static void __perf_event_period(struct perf_event *event, | |||
4210 | active = (event->state == PERF_EVENT_STATE_ACTIVE); | 4225 | active = (event->state == PERF_EVENT_STATE_ACTIVE); |
4211 | if (active) { | 4226 | if (active) { |
4212 | perf_pmu_disable(ctx->pmu); | 4227 | perf_pmu_disable(ctx->pmu); |
4228 | /* | ||
4229 | * We could be throttled; unthrottle now to avoid the tick | ||
4230 | * trying to unthrottle while we already re-started the event. | ||
4231 | */ | ||
4232 | if (event->hw.interrupts == MAX_INTERRUPTS) { | ||
4233 | event->hw.interrupts = 0; | ||
4234 | perf_log_throttle(event, 1); | ||
4235 | } | ||
4213 | event->pmu->stop(event, PERF_EF_UPDATE); | 4236 | event->pmu->stop(event, PERF_EF_UPDATE); |
4214 | } | 4237 | } |
4215 | 4238 | ||
@@ -9426,10 +9449,29 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) | |||
9426 | switch (action & ~CPU_TASKS_FROZEN) { | 9449 | switch (action & ~CPU_TASKS_FROZEN) { |
9427 | 9450 | ||
9428 | case CPU_UP_PREPARE: | 9451 | case CPU_UP_PREPARE: |
9452 | /* | ||
9453 | * This must be done before the CPU comes alive, because the | ||
9454 | * moment we can run tasks we can encounter (software) events. | ||
9455 | * | ||
9456 | * Specifically, someone can have inherited events on kthreadd | ||
9457 | * or a pre-existing worker thread that gets re-bound. | ||
9458 | */ | ||
9429 | perf_event_init_cpu(cpu); | 9459 | perf_event_init_cpu(cpu); |
9430 | break; | 9460 | break; |
9431 | 9461 | ||
9432 | case CPU_DOWN_PREPARE: | 9462 | case CPU_DOWN_PREPARE: |
9463 | /* | ||
9464 | * This must be done before the CPU dies because after that an | ||
9465 | * active event might want to IPI the CPU and that'll not work | ||
9466 | * so great for dead CPUs. | ||
9467 | * | ||
9468 | * XXX smp_call_function_single() return -ENXIO without a warn | ||
9469 | * so we could possibly deal with this. | ||
9470 | * | ||
9471 | * This is safe against new events arriving because | ||
9472 | * sys_perf_event_open() serializes against hotplug using | ||
9473 | * get_online_cpus(). | ||
9474 | */ | ||
9433 | perf_event_exit_cpu(cpu); | 9475 | perf_event_exit_cpu(cpu); |
9434 | break; | 9476 | break; |
9435 | default: | 9477 | default: |
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 1faad2cfdb9e..c61f0cbd308b 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c | |||
@@ -746,8 +746,10 @@ struct ring_buffer *rb_alloc(int nr_pages, long watermark, int cpu, int flags) | |||
746 | 746 | ||
747 | rb->user_page = all_buf; | 747 | rb->user_page = all_buf; |
748 | rb->data_pages[0] = all_buf + PAGE_SIZE; | 748 | rb->data_pages[0] = all_buf + PAGE_SIZE; |
749 | rb->page_order = ilog2(nr_pages); | 749 | if (nr_pages) { |
750 | rb->nr_pages = !!nr_pages; | 750 | rb->nr_pages = 1; |
751 | rb->page_order = ilog2(nr_pages); | ||
752 | } | ||
751 | 753 | ||
752 | ring_buffer_init(rb, watermark, flags); | 754 | ring_buffer_init(rb, watermark, flags); |
753 | 755 | ||
diff --git a/tools/include/linux/stringify.h b/tools/include/linux/stringify.h new file mode 100644 index 000000000000..841cec8ed525 --- /dev/null +++ b/tools/include/linux/stringify.h | |||
@@ -0,0 +1,12 @@ | |||
1 | #ifndef __LINUX_STRINGIFY_H | ||
2 | #define __LINUX_STRINGIFY_H | ||
3 | |||
4 | /* Indirect stringification. Doing two levels allows the parameter to be a | ||
5 | * macro itself. For example, compile with -DFOO=bar, __stringify(FOO) | ||
6 | * converts to "bar". | ||
7 | */ | ||
8 | |||
9 | #define __stringify_1(x...) #x | ||
10 | #define __stringify(x...) __stringify_1(x) | ||
11 | |||
12 | #endif /* !__LINUX_STRINGIFY_H */ | ||
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile index bbc82c614bee..316f308a63ea 100644 --- a/tools/lib/api/Makefile +++ b/tools/lib/api/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | include ../../scripts/Makefile.include | 1 | include ../../scripts/Makefile.include |
2 | include ../../perf/config/utilities.mak # QUIET_CLEAN | 2 | include ../../scripts/utilities.mak # QUIET_CLEAN |
3 | 3 | ||
4 | ifeq ($(srctree),) | 4 | ifeq ($(srctree),) |
5 | srctree := $(patsubst %/,%,$(dir $(shell pwd))) | 5 | srctree := $(patsubst %/,%,$(dir $(shell pwd))) |
diff --git a/tools/lib/subcmd/Makefile b/tools/lib/subcmd/Makefile index 1faecb82ad42..a8103700c172 100644 --- a/tools/lib/subcmd/Makefile +++ b/tools/lib/subcmd/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | include ../../scripts/Makefile.include | 1 | include ../../scripts/Makefile.include |
2 | include ../../perf/config/utilities.mak # QUIET_CLEAN | 2 | include ../../scripts/utilities.mak # QUIET_CLEAN |
3 | 3 | ||
4 | ifeq ($(srctree),) | 4 | ifeq ($(srctree),) |
5 | srctree := $(patsubst %/,%,$(dir $(shell pwd))) | 5 | srctree := $(patsubst %/,%,$(dir $(shell pwd))) |
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 190cc886ab91..a8b6357d1ffe 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
@@ -5427,10 +5427,8 @@ void pevent_print_event_time(struct pevent *pevent, struct trace_seq *s, | |||
5427 | } | 5427 | } |
5428 | 5428 | ||
5429 | if (pevent->latency_format) { | 5429 | if (pevent->latency_format) { |
5430 | trace_seq_printf(s, " %3d", record->cpu); | ||
5431 | pevent_data_lat_fmt(pevent, s, record); | 5430 | pevent_data_lat_fmt(pevent, s, record); |
5432 | } else | 5431 | } |
5433 | trace_seq_printf(s, " [%03d]", record->cpu); | ||
5434 | 5432 | ||
5435 | if (use_usec_format) { | 5433 | if (use_usec_format) { |
5436 | if (pevent->flags & PEVENT_NSEC_OUTPUT) { | 5434 | if (pevent->flags & PEVENT_NSEC_OUTPUT) { |
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile index 3ba1c0b09908..098cfb9ca8f0 100644 --- a/tools/perf/Documentation/Makefile +++ b/tools/perf/Documentation/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | include ../../scripts/Makefile.include | 1 | include ../../scripts/Makefile.include |
2 | include ../config/utilities.mak | 2 | include ../../scripts/utilities.mak |
3 | 3 | ||
4 | MAN1_TXT= \ | 4 | MAN1_TXT= \ |
5 | $(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \ | 5 | $(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \ |
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt index 79483f40e991..ec723d0a5bb3 100644 --- a/tools/perf/Documentation/perf-list.txt +++ b/tools/perf/Documentation/perf-list.txt | |||
@@ -40,10 +40,12 @@ address should be. The 'p' modifier can be specified multiple times: | |||
40 | 0 - SAMPLE_IP can have arbitrary skid | 40 | 0 - SAMPLE_IP can have arbitrary skid |
41 | 1 - SAMPLE_IP must have constant skid | 41 | 1 - SAMPLE_IP must have constant skid |
42 | 2 - SAMPLE_IP requested to have 0 skid | 42 | 2 - SAMPLE_IP requested to have 0 skid |
43 | 3 - SAMPLE_IP must have 0 skid | 43 | 3 - SAMPLE_IP must have 0 skid, or uses randomization to avoid |
44 | sample shadowing effects. | ||
44 | 45 | ||
45 | For Intel systems precise event sampling is implemented with PEBS | 46 | For Intel systems precise event sampling is implemented with PEBS |
46 | which supports up to precise-level 2. | 47 | which supports up to precise-level 2, and precise level 3 for |
48 | some special cases | ||
47 | 49 | ||
48 | On AMD systems it is implemented using IBS (up to precise-level 2). | 50 | On AMD systems it is implemented using IBS (up to precise-level 2). |
49 | The precise modifier works with event types 0x76 (cpu-cycles, CPU | 51 | The precise modifier works with event types 0x76 (cpu-cycles, CPU |
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 4a4fad4182f5..000ea210389d 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -3,7 +3,7 @@ include ../scripts/Makefile.include | |||
3 | # The default target of this Makefile is... | 3 | # The default target of this Makefile is... |
4 | all: | 4 | all: |
5 | 5 | ||
6 | include config/utilities.mak | 6 | include ../scripts/utilities.mak |
7 | 7 | ||
8 | # Define V to have a more verbose compile. | 8 | # Define V to have a more verbose compile. |
9 | # | 9 | # |
diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c index 6c1b8a75db09..6138bdef6e63 100644 --- a/tools/perf/arch/powerpc/util/header.c +++ b/tools/perf/arch/powerpc/util/header.c | |||
@@ -3,9 +3,7 @@ | |||
3 | #include <stdio.h> | 3 | #include <stdio.h> |
4 | #include <stdlib.h> | 4 | #include <stdlib.h> |
5 | #include <string.h> | 5 | #include <string.h> |
6 | 6 | #include <linux/stringify.h> | |
7 | #include "../../util/header.h" | ||
8 | #include "../../util/util.h" | ||
9 | 7 | ||
10 | #define mfspr(rn) ({unsigned long rval; \ | 8 | #define mfspr(rn) ({unsigned long rval; \ |
11 | asm volatile("mfspr %0," __stringify(rn) \ | 9 | asm volatile("mfspr %0," __stringify(rn) \ |
diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h index a50df86f2b9b..579a592990dd 100644 --- a/tools/perf/bench/bench.h +++ b/tools/perf/bench/bench.h | |||
@@ -25,19 +25,17 @@ | |||
25 | # endif | 25 | # endif |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | extern int bench_numa(int argc, const char **argv, const char *prefix); | 28 | int bench_numa(int argc, const char **argv, const char *prefix); |
29 | extern int bench_sched_messaging(int argc, const char **argv, const char *prefix); | 29 | int bench_sched_messaging(int argc, const char **argv, const char *prefix); |
30 | extern int bench_sched_pipe(int argc, const char **argv, const char *prefix); | 30 | int bench_sched_pipe(int argc, const char **argv, const char *prefix); |
31 | extern int bench_mem_memcpy(int argc, const char **argv, | 31 | int bench_mem_memcpy(int argc, const char **argv, const char *prefix); |
32 | const char *prefix __maybe_unused); | 32 | int bench_mem_memset(int argc, const char **argv, const char *prefix); |
33 | extern int bench_mem_memset(int argc, const char **argv, const char *prefix); | 33 | int bench_futex_hash(int argc, const char **argv, const char *prefix); |
34 | extern int bench_futex_hash(int argc, const char **argv, const char *prefix); | 34 | int bench_futex_wake(int argc, const char **argv, const char *prefix); |
35 | extern int bench_futex_wake(int argc, const char **argv, const char *prefix); | 35 | int bench_futex_wake_parallel(int argc, const char **argv, const char *prefix); |
36 | extern int bench_futex_wake_parallel(int argc, const char **argv, | 36 | int bench_futex_requeue(int argc, const char **argv, const char *prefix); |
37 | const char *prefix); | ||
38 | extern int bench_futex_requeue(int argc, const char **argv, const char *prefix); | ||
39 | /* pi futexes */ | 37 | /* pi futexes */ |
40 | extern int bench_futex_lock_pi(int argc, const char **argv, const char *prefix); | 38 | int bench_futex_lock_pi(int argc, const char **argv, const char *prefix); |
41 | 39 | ||
42 | #define BENCH_FORMAT_DEFAULT_STR "default" | 40 | #define BENCH_FORMAT_DEFAULT_STR "default" |
43 | #define BENCH_FORMAT_DEFAULT 0 | 41 | #define BENCH_FORMAT_DEFAULT 0 |
diff --git a/tools/perf/bench/mem-memcpy-arch.h b/tools/perf/bench/mem-memcpy-arch.h index 57b4ed871459..5aad2a9408b0 100644 --- a/tools/perf/bench/mem-memcpy-arch.h +++ b/tools/perf/bench/mem-memcpy-arch.h | |||
@@ -2,7 +2,7 @@ | |||
2 | #ifdef HAVE_ARCH_X86_64_SUPPORT | 2 | #ifdef HAVE_ARCH_X86_64_SUPPORT |
3 | 3 | ||
4 | #define MEMCPY_FN(fn, name, desc) \ | 4 | #define MEMCPY_FN(fn, name, desc) \ |
5 | extern void *fn(void *, const void *, size_t); | 5 | void *fn(void *, const void *, size_t); |
6 | 6 | ||
7 | #include "mem-memcpy-x86-64-asm-def.h" | 7 | #include "mem-memcpy-x86-64-asm-def.h" |
8 | 8 | ||
diff --git a/tools/perf/bench/mem-memset-arch.h b/tools/perf/bench/mem-memset-arch.h index 633800cb0dcb..0d15786d9ae3 100644 --- a/tools/perf/bench/mem-memset-arch.h +++ b/tools/perf/bench/mem-memset-arch.h | |||
@@ -2,7 +2,7 @@ | |||
2 | #ifdef HAVE_ARCH_X86_64_SUPPORT | 2 | #ifdef HAVE_ARCH_X86_64_SUPPORT |
3 | 3 | ||
4 | #define MEMSET_FN(fn, name, desc) \ | 4 | #define MEMSET_FN(fn, name, desc) \ |
5 | extern void *fn(void *, int, size_t); | 5 | void *fn(void *, int, size_t); |
6 | 6 | ||
7 | #include "mem-memset-x86-64-asm-def.h" | 7 | #include "mem-memset-x86-64-asm-def.h" |
8 | 8 | ||
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c index 5049d6357a46..7500d959d7eb 100644 --- a/tools/perf/bench/numa.c +++ b/tools/perf/bench/numa.c | |||
@@ -293,7 +293,7 @@ static void bind_to_memnode(int node) | |||
293 | if (node == -1) | 293 | if (node == -1) |
294 | return; | 294 | return; |
295 | 295 | ||
296 | BUG_ON(g->p.nr_nodes > (int)sizeof(nodemask)); | 296 | BUG_ON(g->p.nr_nodes > (int)sizeof(nodemask)*8); |
297 | nodemask = 1L << node; | 297 | nodemask = 1L << node; |
298 | 298 | ||
299 | ret = set_mempolicy(MPOL_BIND, &nodemask, sizeof(nodemask)*8); | 299 | ret = set_mempolicy(MPOL_BIND, &nodemask, sizeof(nodemask)*8); |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index cfe366375c4b..814158393656 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -94,7 +94,7 @@ static int process_sample_event(struct perf_tool *tool, | |||
94 | struct addr_location al; | 94 | struct addr_location al; |
95 | int ret = 0; | 95 | int ret = 0; |
96 | 96 | ||
97 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { | 97 | if (machine__resolve(machine, &al, sample) < 0) { |
98 | pr_warning("problem processing %d event, skipping it.\n", | 98 | pr_warning("problem processing %d event, skipping it.\n", |
99 | event->header.type); | 99 | event->header.type); |
100 | return -1; | 100 | return -1; |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 4d72359fd15a..8053a8ceefda 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -330,7 +330,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, | |||
330 | struct hists *hists = evsel__hists(evsel); | 330 | struct hists *hists = evsel__hists(evsel); |
331 | int ret = -1; | 331 | int ret = -1; |
332 | 332 | ||
333 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { | 333 | if (machine__resolve(machine, &al, sample) < 0) { |
334 | pr_warning("problem processing %d event, skipping it.\n", | 334 | pr_warning("problem processing %d event, skipping it.\n", |
335 | event->header.type); | 335 | event->header.type); |
336 | return -1; | 336 | return -1; |
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 49d55e21b1b0..bc1de9b8fd67 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c | |||
@@ -106,12 +106,14 @@ static void exec_woman_emacs(const char *path, const char *page) | |||
106 | 106 | ||
107 | if (!check_emacsclient_version()) { | 107 | if (!check_emacsclient_version()) { |
108 | /* This works only with emacsclient version >= 22. */ | 108 | /* This works only with emacsclient version >= 22. */ |
109 | struct strbuf man_page = STRBUF_INIT; | 109 | char *man_page; |
110 | 110 | ||
111 | if (!path) | 111 | if (!path) |
112 | path = "emacsclient"; | 112 | path = "emacsclient"; |
113 | strbuf_addf(&man_page, "(woman \"%s\")", page); | 113 | if (asprintf(&man_page, "(woman \"%s\")", page) > 0) { |
114 | execlp(path, "emacsclient", "-e", man_page.buf, NULL); | 114 | execlp(path, "emacsclient", "-e", man_page, NULL); |
115 | free(man_page); | ||
116 | } | ||
115 | warning("failed to exec '%s': %s", path, | 117 | warning("failed to exec '%s': %s", path, |
116 | strerror_r(errno, sbuf, sizeof(sbuf))); | 118 | strerror_r(errno, sbuf, sizeof(sbuf))); |
117 | } | 119 | } |
@@ -122,7 +124,7 @@ static void exec_man_konqueror(const char *path, const char *page) | |||
122 | const char *display = getenv("DISPLAY"); | 124 | const char *display = getenv("DISPLAY"); |
123 | 125 | ||
124 | if (display && *display) { | 126 | if (display && *display) { |
125 | struct strbuf man_page = STRBUF_INIT; | 127 | char *man_page; |
126 | const char *filename = "kfmclient"; | 128 | const char *filename = "kfmclient"; |
127 | char sbuf[STRERR_BUFSIZE]; | 129 | char sbuf[STRERR_BUFSIZE]; |
128 | 130 | ||
@@ -141,8 +143,10 @@ static void exec_man_konqueror(const char *path, const char *page) | |||
141 | filename = file; | 143 | filename = file; |
142 | } else | 144 | } else |
143 | path = "kfmclient"; | 145 | path = "kfmclient"; |
144 | strbuf_addf(&man_page, "man:%s(1)", page); | 146 | if (asprintf(&man_page, "man:%s(1)", page) > 0) { |
145 | execlp(path, filename, "newTab", man_page.buf, NULL); | 147 | execlp(path, filename, "newTab", man_page, NULL); |
148 | free(man_page); | ||
149 | } | ||
146 | warning("failed to exec '%s': %s", path, | 150 | warning("failed to exec '%s': %s", path, |
147 | strerror_r(errno, sbuf, sizeof(sbuf))); | 151 | strerror_r(errno, sbuf, sizeof(sbuf))); |
148 | } | 152 | } |
@@ -161,11 +165,13 @@ static void exec_man_man(const char *path, const char *page) | |||
161 | 165 | ||
162 | static void exec_man_cmd(const char *cmd, const char *page) | 166 | static void exec_man_cmd(const char *cmd, const char *page) |
163 | { | 167 | { |
164 | struct strbuf shell_cmd = STRBUF_INIT; | ||
165 | char sbuf[STRERR_BUFSIZE]; | 168 | char sbuf[STRERR_BUFSIZE]; |
169 | char *shell_cmd; | ||
166 | 170 | ||
167 | strbuf_addf(&shell_cmd, "%s %s", cmd, page); | 171 | if (asprintf(&shell_cmd, "%s %s", cmd, page) > 0) { |
168 | execl("/bin/sh", "sh", "-c", shell_cmd.buf, NULL); | 172 | execl("/bin/sh", "sh", "-c", shell_cmd, NULL); |
173 | free(shell_cmd); | ||
174 | } | ||
169 | warning("failed to exec '%s': %s", cmd, | 175 | warning("failed to exec '%s': %s", cmd, |
170 | strerror_r(errno, sbuf, sizeof(sbuf))); | 176 | strerror_r(errno, sbuf, sizeof(sbuf))); |
171 | } | 177 | } |
@@ -299,43 +305,33 @@ static int is_perf_command(const char *s) | |||
299 | is_in_cmdlist(&other_cmds, s); | 305 | is_in_cmdlist(&other_cmds, s); |
300 | } | 306 | } |
301 | 307 | ||
302 | static const char *prepend(const char *prefix, const char *cmd) | ||
303 | { | ||
304 | size_t pre_len = strlen(prefix); | ||
305 | size_t cmd_len = strlen(cmd); | ||
306 | char *p = malloc(pre_len + cmd_len + 1); | ||
307 | memcpy(p, prefix, pre_len); | ||
308 | strcpy(p + pre_len, cmd); | ||
309 | return p; | ||
310 | } | ||
311 | |||
312 | static const char *cmd_to_page(const char *perf_cmd) | 308 | static const char *cmd_to_page(const char *perf_cmd) |
313 | { | 309 | { |
310 | char *s; | ||
311 | |||
314 | if (!perf_cmd) | 312 | if (!perf_cmd) |
315 | return "perf"; | 313 | return "perf"; |
316 | else if (!prefixcmp(perf_cmd, "perf")) | 314 | else if (!prefixcmp(perf_cmd, "perf")) |
317 | return perf_cmd; | 315 | return perf_cmd; |
318 | else | 316 | |
319 | return prepend("perf-", perf_cmd); | 317 | return asprintf(&s, "perf-%s", perf_cmd) < 0 ? NULL : s; |
320 | } | 318 | } |
321 | 319 | ||
322 | static void setup_man_path(void) | 320 | static void setup_man_path(void) |
323 | { | 321 | { |
324 | struct strbuf new_path = STRBUF_INIT; | 322 | char *new_path; |
325 | const char *old_path = getenv("MANPATH"); | 323 | const char *old_path = getenv("MANPATH"); |
326 | 324 | ||
327 | /* We should always put ':' after our path. If there is no | 325 | /* We should always put ':' after our path. If there is no |
328 | * old_path, the ':' at the end will let 'man' to try | 326 | * old_path, the ':' at the end will let 'man' to try |
329 | * system-wide paths after ours to find the manual page. If | 327 | * system-wide paths after ours to find the manual page. If |
330 | * there is old_path, we need ':' as delimiter. */ | 328 | * there is old_path, we need ':' as delimiter. */ |
331 | strbuf_addstr(&new_path, system_path(PERF_MAN_PATH)); | 329 | if (asprintf(&new_path, "%s:%s", system_path(PERF_MAN_PATH), old_path ?: "") > 0) { |
332 | strbuf_addch(&new_path, ':'); | 330 | setenv("MANPATH", new_path, 1); |
333 | if (old_path) | 331 | free(new_path); |
334 | strbuf_addstr(&new_path, old_path); | 332 | } else { |
335 | 333 | error("Unable to setup man path"); | |
336 | setenv("MANPATH", new_path.buf, 1); | 334 | } |
337 | |||
338 | strbuf_release(&new_path); | ||
339 | } | 335 | } |
340 | 336 | ||
341 | static void exec_viewer(const char *name, const char *page) | 337 | static void exec_viewer(const char *name, const char *page) |
@@ -380,7 +376,7 @@ static int show_info_page(const char *perf_cmd) | |||
380 | return -1; | 376 | return -1; |
381 | } | 377 | } |
382 | 378 | ||
383 | static int get_html_page_path(struct strbuf *page_path, const char *page) | 379 | static int get_html_page_path(char **page_path, const char *page) |
384 | { | 380 | { |
385 | struct stat st; | 381 | struct stat st; |
386 | const char *html_path = system_path(PERF_HTML_PATH); | 382 | const char *html_path = system_path(PERF_HTML_PATH); |
@@ -392,10 +388,7 @@ static int get_html_page_path(struct strbuf *page_path, const char *page) | |||
392 | return -1; | 388 | return -1; |
393 | } | 389 | } |
394 | 390 | ||
395 | strbuf_init(page_path, 0); | 391 | return asprintf(page_path, "%s/%s.html", html_path, page); |
396 | strbuf_addf(page_path, "%s/%s.html", html_path, page); | ||
397 | |||
398 | return 0; | ||
399 | } | 392 | } |
400 | 393 | ||
401 | /* | 394 | /* |
@@ -413,12 +406,12 @@ static void open_html(const char *path) | |||
413 | static int show_html_page(const char *perf_cmd) | 406 | static int show_html_page(const char *perf_cmd) |
414 | { | 407 | { |
415 | const char *page = cmd_to_page(perf_cmd); | 408 | const char *page = cmd_to_page(perf_cmd); |
416 | struct strbuf page_path; /* it leaks but we exec bellow */ | 409 | char *page_path; /* it leaks but we exec bellow */ |
417 | 410 | ||
418 | if (get_html_page_path(&page_path, page) != 0) | 411 | if (get_html_page_path(&page_path, page) < 0) |
419 | return -1; | 412 | return -1; |
420 | 413 | ||
421 | open_html(page_path.buf); | 414 | open_html(page_path); |
422 | 415 | ||
423 | return 0; | 416 | return 0; |
424 | } | 417 | } |
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 7fa68663ed72..d1a2d104f2bc 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -131,8 +131,7 @@ static int copy_bytes(struct perf_inject *inject, int fd, off_t size) | |||
131 | 131 | ||
132 | static s64 perf_event__repipe_auxtrace(struct perf_tool *tool, | 132 | static s64 perf_event__repipe_auxtrace(struct perf_tool *tool, |
133 | union perf_event *event, | 133 | union perf_event *event, |
134 | struct perf_session *session | 134 | struct perf_session *session) |
135 | __maybe_unused) | ||
136 | { | 135 | { |
137 | struct perf_inject *inject = container_of(tool, struct perf_inject, | 136 | struct perf_inject *inject = container_of(tool, struct perf_inject, |
138 | tool); | 137 | tool); |
@@ -417,9 +416,6 @@ static int perf_event__inject_buildid(struct perf_tool *tool, | |||
417 | { | 416 | { |
418 | struct addr_location al; | 417 | struct addr_location al; |
419 | struct thread *thread; | 418 | struct thread *thread; |
420 | u8 cpumode; | ||
421 | |||
422 | cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
423 | 419 | ||
424 | thread = machine__findnew_thread(machine, sample->pid, sample->tid); | 420 | thread = machine__findnew_thread(machine, sample->pid, sample->tid); |
425 | if (thread == NULL) { | 421 | if (thread == NULL) { |
@@ -428,7 +424,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool, | |||
428 | goto repipe; | 424 | goto repipe; |
429 | } | 425 | } |
430 | 426 | ||
431 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, &al); | 427 | thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, &al); |
432 | 428 | ||
433 | if (al.map != NULL) { | 429 | if (al.map != NULL) { |
434 | if (!al.map->dso->hit) { | 430 | if (!al.map->dso->hit) { |
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 88aeac9aa1da..85db3be4b3cb 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c | |||
@@ -131,7 +131,7 @@ dump_raw_samples(struct perf_tool *tool, | |||
131 | struct addr_location al; | 131 | struct addr_location al; |
132 | const char *fmt; | 132 | const char *fmt; |
133 | 133 | ||
134 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { | 134 | if (machine__resolve(machine, &al, sample) < 0) { |
135 | fprintf(stderr, "problem processing %d event, skipping it.\n", | 135 | fprintf(stderr, "problem processing %d event, skipping it.\n", |
136 | event->header.type); | 136 | event->header.type); |
137 | return -1; | 137 | return -1; |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 7eea49f9ed46..160ea23b45aa 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -41,6 +41,7 @@ | |||
41 | 41 | ||
42 | #include <dlfcn.h> | 42 | #include <dlfcn.h> |
43 | #include <linux/bitmap.h> | 43 | #include <linux/bitmap.h> |
44 | #include <linux/stringify.h> | ||
44 | 45 | ||
45 | struct report { | 46 | struct report { |
46 | struct perf_tool tool; | 47 | struct perf_tool tool; |
@@ -154,7 +155,7 @@ static int process_sample_event(struct perf_tool *tool, | |||
154 | }; | 155 | }; |
155 | int ret = 0; | 156 | int ret = 0; |
156 | 157 | ||
157 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { | 158 | if (machine__resolve(machine, &al, sample) < 0) { |
158 | pr_debug("problem processing %d event, skipping it.\n", | 159 | pr_debug("problem processing %d event, skipping it.\n", |
159 | event->header.type); | 160 | event->header.type); |
160 | return -1; | 161 | return -1; |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 57f9a7e7f7d3..3770c3dffe5e 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -405,9 +405,7 @@ out: | |||
405 | return 0; | 405 | return 0; |
406 | } | 406 | } |
407 | 407 | ||
408 | static void print_sample_iregs(union perf_event *event __maybe_unused, | 408 | static void print_sample_iregs(struct perf_sample *sample, |
409 | struct perf_sample *sample, | ||
410 | struct thread *thread __maybe_unused, | ||
411 | struct perf_event_attr *attr) | 409 | struct perf_event_attr *attr) |
412 | { | 410 | { |
413 | struct regs_dump *regs = &sample->intr_regs; | 411 | struct regs_dump *regs = &sample->intr_regs; |
@@ -476,10 +474,7 @@ mispred_str(struct branch_entry *br) | |||
476 | return br->flags.predicted ? 'P' : 'M'; | 474 | return br->flags.predicted ? 'P' : 'M'; |
477 | } | 475 | } |
478 | 476 | ||
479 | static void print_sample_brstack(union perf_event *event __maybe_unused, | 477 | static void print_sample_brstack(struct perf_sample *sample) |
480 | struct perf_sample *sample, | ||
481 | struct thread *thread __maybe_unused, | ||
482 | struct perf_event_attr *attr __maybe_unused) | ||
483 | { | 478 | { |
484 | struct branch_stack *br = sample->branch_stack; | 479 | struct branch_stack *br = sample->branch_stack; |
485 | u64 i; | 480 | u64 i; |
@@ -498,14 +493,11 @@ static void print_sample_brstack(union perf_event *event __maybe_unused, | |||
498 | } | 493 | } |
499 | } | 494 | } |
500 | 495 | ||
501 | static void print_sample_brstacksym(union perf_event *event __maybe_unused, | 496 | static void print_sample_brstacksym(struct perf_sample *sample, |
502 | struct perf_sample *sample, | 497 | struct thread *thread) |
503 | struct thread *thread __maybe_unused, | ||
504 | struct perf_event_attr *attr __maybe_unused) | ||
505 | { | 498 | { |
506 | struct branch_stack *br = sample->branch_stack; | 499 | struct branch_stack *br = sample->branch_stack; |
507 | struct addr_location alf, alt; | 500 | struct addr_location alf, alt; |
508 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
509 | u64 i, from, to; | 501 | u64 i, from, to; |
510 | 502 | ||
511 | if (!(br && br->nr)) | 503 | if (!(br && br->nr)) |
@@ -518,11 +510,11 @@ static void print_sample_brstacksym(union perf_event *event __maybe_unused, | |||
518 | from = br->entries[i].from; | 510 | from = br->entries[i].from; |
519 | to = br->entries[i].to; | 511 | to = br->entries[i].to; |
520 | 512 | ||
521 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, from, &alf); | 513 | thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf); |
522 | if (alf.map) | 514 | if (alf.map) |
523 | alf.sym = map__find_symbol(alf.map, alf.addr, NULL); | 515 | alf.sym = map__find_symbol(alf.map, alf.addr, NULL); |
524 | 516 | ||
525 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, to, &alt); | 517 | thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt); |
526 | if (alt.map) | 518 | if (alt.map) |
527 | alt.sym = map__find_symbol(alt.map, alt.addr, NULL); | 519 | alt.sym = map__find_symbol(alt.map, alt.addr, NULL); |
528 | 520 | ||
@@ -538,8 +530,7 @@ static void print_sample_brstacksym(union perf_event *event __maybe_unused, | |||
538 | } | 530 | } |
539 | 531 | ||
540 | 532 | ||
541 | static void print_sample_addr(union perf_event *event, | 533 | static void print_sample_addr(struct perf_sample *sample, |
542 | struct perf_sample *sample, | ||
543 | struct thread *thread, | 534 | struct thread *thread, |
544 | struct perf_event_attr *attr) | 535 | struct perf_event_attr *attr) |
545 | { | 536 | { |
@@ -550,7 +541,7 @@ static void print_sample_addr(union perf_event *event, | |||
550 | if (!sample_addr_correlates_sym(attr)) | 541 | if (!sample_addr_correlates_sym(attr)) |
551 | return; | 542 | return; |
552 | 543 | ||
553 | perf_event__preprocess_sample_addr(event, sample, thread, &al); | 544 | thread__resolve(thread, &al, sample); |
554 | 545 | ||
555 | if (PRINT_FIELD(SYM)) { | 546 | if (PRINT_FIELD(SYM)) { |
556 | printf(" "); | 547 | printf(" "); |
@@ -567,8 +558,7 @@ static void print_sample_addr(union perf_event *event, | |||
567 | } | 558 | } |
568 | } | 559 | } |
569 | 560 | ||
570 | static void print_sample_bts(union perf_event *event, | 561 | static void print_sample_bts(struct perf_sample *sample, |
571 | struct perf_sample *sample, | ||
572 | struct perf_evsel *evsel, | 562 | struct perf_evsel *evsel, |
573 | struct thread *thread, | 563 | struct thread *thread, |
574 | struct addr_location *al) | 564 | struct addr_location *al) |
@@ -598,7 +588,7 @@ static void print_sample_bts(union perf_event *event, | |||
598 | ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && | 588 | ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && |
599 | !output[attr->type].user_set)) { | 589 | !output[attr->type].user_set)) { |
600 | printf(" => "); | 590 | printf(" => "); |
601 | print_sample_addr(event, sample, thread, attr); | 591 | print_sample_addr(sample, thread, attr); |
602 | } | 592 | } |
603 | 593 | ||
604 | if (print_srcline_last) | 594 | if (print_srcline_last) |
@@ -747,7 +737,7 @@ static size_t data_src__printf(u64 data_src) | |||
747 | return printf("%-*s", maxlen, out); | 737 | return printf("%-*s", maxlen, out); |
748 | } | 738 | } |
749 | 739 | ||
750 | static void process_event(struct perf_script *script, union perf_event *event, | 740 | static void process_event(struct perf_script *script, |
751 | struct perf_sample *sample, struct perf_evsel *evsel, | 741 | struct perf_sample *sample, struct perf_evsel *evsel, |
752 | struct addr_location *al) | 742 | struct addr_location *al) |
753 | { | 743 | { |
@@ -776,7 +766,7 @@ static void process_event(struct perf_script *script, union perf_event *event, | |||
776 | print_sample_flags(sample->flags); | 766 | print_sample_flags(sample->flags); |
777 | 767 | ||
778 | if (is_bts_event(attr)) { | 768 | if (is_bts_event(attr)) { |
779 | print_sample_bts(event, sample, evsel, thread, al); | 769 | print_sample_bts(sample, evsel, thread, al); |
780 | return; | 770 | return; |
781 | } | 771 | } |
782 | 772 | ||
@@ -784,7 +774,7 @@ static void process_event(struct perf_script *script, union perf_event *event, | |||
784 | event_format__print(evsel->tp_format, sample->cpu, | 774 | event_format__print(evsel->tp_format, sample->cpu, |
785 | sample->raw_data, sample->raw_size); | 775 | sample->raw_data, sample->raw_size); |
786 | if (PRINT_FIELD(ADDR)) | 776 | if (PRINT_FIELD(ADDR)) |
787 | print_sample_addr(event, sample, thread, attr); | 777 | print_sample_addr(sample, thread, attr); |
788 | 778 | ||
789 | if (PRINT_FIELD(DATA_SRC)) | 779 | if (PRINT_FIELD(DATA_SRC)) |
790 | data_src__printf(sample->data_src); | 780 | data_src__printf(sample->data_src); |
@@ -804,12 +794,12 @@ static void process_event(struct perf_script *script, union perf_event *event, | |||
804 | } | 794 | } |
805 | 795 | ||
806 | if (PRINT_FIELD(IREGS)) | 796 | if (PRINT_FIELD(IREGS)) |
807 | print_sample_iregs(event, sample, thread, attr); | 797 | print_sample_iregs(sample, attr); |
808 | 798 | ||
809 | if (PRINT_FIELD(BRSTACK)) | 799 | if (PRINT_FIELD(BRSTACK)) |
810 | print_sample_brstack(event, sample, thread, attr); | 800 | print_sample_brstack(sample); |
811 | else if (PRINT_FIELD(BRSTACKSYM)) | 801 | else if (PRINT_FIELD(BRSTACKSYM)) |
812 | print_sample_brstacksym(event, sample, thread, attr); | 802 | print_sample_brstacksym(sample, thread); |
813 | 803 | ||
814 | if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT)) | 804 | if (perf_evsel__is_bpf_output(evsel) && PRINT_FIELD(BPF_OUTPUT)) |
815 | print_sample_bpf_output(sample); | 805 | print_sample_bpf_output(sample); |
@@ -905,7 +895,7 @@ static int process_sample_event(struct perf_tool *tool, | |||
905 | return 0; | 895 | return 0; |
906 | } | 896 | } |
907 | 897 | ||
908 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { | 898 | if (machine__resolve(machine, &al, sample) < 0) { |
909 | pr_err("problem processing %d event, skipping it.\n", | 899 | pr_err("problem processing %d event, skipping it.\n", |
910 | event->header.type); | 900 | event->header.type); |
911 | return -1; | 901 | return -1; |
@@ -920,7 +910,7 @@ static int process_sample_event(struct perf_tool *tool, | |||
920 | if (scripting_ops) | 910 | if (scripting_ops) |
921 | scripting_ops->process_event(event, sample, evsel, &al); | 911 | scripting_ops->process_event(event, sample, evsel, &al); |
922 | else | 912 | else |
923 | process_event(scr, event, sample, evsel, &al); | 913 | process_event(scr, sample, evsel, &al); |
924 | 914 | ||
925 | out_put: | 915 | out_put: |
926 | addr_location__put(&al); | 916 | addr_location__put(&al); |
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index bd7a7757176f..40cc9bb3506c 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -489,7 +489,7 @@ static const char *cat_backtrace(union perf_event *event, | |||
489 | if (!chain) | 489 | if (!chain) |
490 | goto exit; | 490 | goto exit; |
491 | 491 | ||
492 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) { | 492 | if (machine__resolve(machine, &al, sample) < 0) { |
493 | fprintf(stderr, "problem processing %d event, skipping it.\n", | 493 | fprintf(stderr, "problem processing %d event, skipping it.\n", |
494 | event->header.type); | 494 | event->header.type); |
495 | goto exit; | 495 | goto exit; |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 94af190f6843..833214979c4f 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -67,6 +67,7 @@ | |||
67 | #include <sys/utsname.h> | 67 | #include <sys/utsname.h> |
68 | #include <sys/mman.h> | 68 | #include <sys/mman.h> |
69 | 69 | ||
70 | #include <linux/stringify.h> | ||
70 | #include <linux/types.h> | 71 | #include <linux/types.h> |
71 | 72 | ||
72 | static volatile int done; | 73 | static volatile int done; |
@@ -728,7 +729,7 @@ static void perf_event__process_sample(struct perf_tool *tool, | |||
728 | if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) | 729 | if (event->header.misc & PERF_RECORD_MISC_EXACT_IP) |
729 | top->exact_samples++; | 730 | top->exact_samples++; |
730 | 731 | ||
731 | if (perf_event__preprocess_sample(event, machine, &al, sample) < 0) | 732 | if (machine__resolve(machine, &al, sample) < 0) |
732 | return; | 733 | return; |
733 | 734 | ||
734 | if (!top->kptr_restrict_warned && | 735 | if (!top->kptr_restrict_warned && |
@@ -809,7 +810,6 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) | |||
809 | struct perf_session *session = top->session; | 810 | struct perf_session *session = top->session; |
810 | union perf_event *event; | 811 | union perf_event *event; |
811 | struct machine *machine; | 812 | struct machine *machine; |
812 | u8 origin; | ||
813 | int ret; | 813 | int ret; |
814 | 814 | ||
815 | while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) { | 815 | while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) { |
@@ -822,12 +822,10 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) | |||
822 | evsel = perf_evlist__id2evsel(session->evlist, sample.id); | 822 | evsel = perf_evlist__id2evsel(session->evlist, sample.id); |
823 | assert(evsel != NULL); | 823 | assert(evsel != NULL); |
824 | 824 | ||
825 | origin = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
826 | |||
827 | if (event->header.type == PERF_RECORD_SAMPLE) | 825 | if (event->header.type == PERF_RECORD_SAMPLE) |
828 | ++top->samples; | 826 | ++top->samples; |
829 | 827 | ||
830 | switch (origin) { | 828 | switch (sample.cpumode) { |
831 | case PERF_RECORD_MISC_USER: | 829 | case PERF_RECORD_MISC_USER: |
832 | ++top->us_samples; | 830 | ++top->us_samples; |
833 | if (top->hide_user_symbols) | 831 | if (top->hide_user_symbols) |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 8dc98c598b1a..93ac724fb635 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -2256,11 +2256,10 @@ static void print_location(FILE *f, struct perf_sample *sample, | |||
2256 | 2256 | ||
2257 | static int trace__pgfault(struct trace *trace, | 2257 | static int trace__pgfault(struct trace *trace, |
2258 | struct perf_evsel *evsel, | 2258 | struct perf_evsel *evsel, |
2259 | union perf_event *event, | 2259 | union perf_event *event __maybe_unused, |
2260 | struct perf_sample *sample) | 2260 | struct perf_sample *sample) |
2261 | { | 2261 | { |
2262 | struct thread *thread; | 2262 | struct thread *thread; |
2263 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
2264 | struct addr_location al; | 2263 | struct addr_location al; |
2265 | char map_type = 'd'; | 2264 | char map_type = 'd'; |
2266 | struct thread_trace *ttrace; | 2265 | struct thread_trace *ttrace; |
@@ -2279,7 +2278,7 @@ static int trace__pgfault(struct trace *trace, | |||
2279 | if (trace->summary_only) | 2278 | if (trace->summary_only) |
2280 | goto out; | 2279 | goto out; |
2281 | 2280 | ||
2282 | thread__find_addr_location(thread, cpumode, MAP__FUNCTION, | 2281 | thread__find_addr_location(thread, sample->cpumode, MAP__FUNCTION, |
2283 | sample->ip, &al); | 2282 | sample->ip, &al); |
2284 | 2283 | ||
2285 | trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output); | 2284 | trace__fprintf_entry_head(trace, thread, 0, sample->time, trace->output); |
@@ -2292,11 +2291,11 @@ static int trace__pgfault(struct trace *trace, | |||
2292 | 2291 | ||
2293 | fprintf(trace->output, "] => "); | 2292 | fprintf(trace->output, "] => "); |
2294 | 2293 | ||
2295 | thread__find_addr_location(thread, cpumode, MAP__VARIABLE, | 2294 | thread__find_addr_location(thread, sample->cpumode, MAP__VARIABLE, |
2296 | sample->addr, &al); | 2295 | sample->addr, &al); |
2297 | 2296 | ||
2298 | if (!al.map) { | 2297 | if (!al.map) { |
2299 | thread__find_addr_location(thread, cpumode, | 2298 | thread__find_addr_location(thread, sample->cpumode, |
2300 | MAP__FUNCTION, sample->addr, &al); | 2299 | MAP__FUNCTION, sample->addr, &al); |
2301 | 2300 | ||
2302 | if (al.map) | 2301 | if (al.map) |
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h index 3f871b54e261..41c24010ab43 100644 --- a/tools/perf/builtin.h +++ b/tools/perf/builtin.h | |||
@@ -7,38 +7,38 @@ | |||
7 | extern const char perf_usage_string[]; | 7 | extern const char perf_usage_string[]; |
8 | extern const char perf_more_info_string[]; | 8 | extern const char perf_more_info_string[]; |
9 | 9 | ||
10 | extern void list_common_cmds_help(void); | 10 | void list_common_cmds_help(void); |
11 | extern const char *help_unknown_cmd(const char *cmd); | 11 | const char *help_unknown_cmd(const char *cmd); |
12 | extern void prune_packed_objects(int); | 12 | void prune_packed_objects(int); |
13 | extern int read_line_with_nul(char *buf, int size, FILE *file); | 13 | int read_line_with_nul(char *buf, int size, FILE *file); |
14 | extern int check_pager_config(const char *cmd); | 14 | int check_pager_config(const char *cmd); |
15 | 15 | ||
16 | extern int cmd_annotate(int argc, const char **argv, const char *prefix); | 16 | int cmd_annotate(int argc, const char **argv, const char *prefix); |
17 | extern int cmd_bench(int argc, const char **argv, const char *prefix); | 17 | int cmd_bench(int argc, const char **argv, const char *prefix); |
18 | extern int cmd_buildid_cache(int argc, const char **argv, const char *prefix); | 18 | int cmd_buildid_cache(int argc, const char **argv, const char *prefix); |
19 | extern int cmd_buildid_list(int argc, const char **argv, const char *prefix); | 19 | int cmd_buildid_list(int argc, const char **argv, const char *prefix); |
20 | extern int cmd_config(int argc, const char **argv, const char *prefix); | 20 | int cmd_config(int argc, const char **argv, const char *prefix); |
21 | extern int cmd_diff(int argc, const char **argv, const char *prefix); | 21 | int cmd_diff(int argc, const char **argv, const char *prefix); |
22 | extern int cmd_evlist(int argc, const char **argv, const char *prefix); | 22 | int cmd_evlist(int argc, const char **argv, const char *prefix); |
23 | extern int cmd_help(int argc, const char **argv, const char *prefix); | 23 | int cmd_help(int argc, const char **argv, const char *prefix); |
24 | extern int cmd_sched(int argc, const char **argv, const char *prefix); | 24 | int cmd_sched(int argc, const char **argv, const char *prefix); |
25 | extern int cmd_list(int argc, const char **argv, const char *prefix); | 25 | int cmd_list(int argc, const char **argv, const char *prefix); |
26 | extern int cmd_record(int argc, const char **argv, const char *prefix); | 26 | int cmd_record(int argc, const char **argv, const char *prefix); |
27 | extern int cmd_report(int argc, const char **argv, const char *prefix); | 27 | int cmd_report(int argc, const char **argv, const char *prefix); |
28 | extern int cmd_stat(int argc, const char **argv, const char *prefix); | 28 | int cmd_stat(int argc, const char **argv, const char *prefix); |
29 | extern int cmd_timechart(int argc, const char **argv, const char *prefix); | 29 | int cmd_timechart(int argc, const char **argv, const char *prefix); |
30 | extern int cmd_top(int argc, const char **argv, const char *prefix); | 30 | int cmd_top(int argc, const char **argv, const char *prefix); |
31 | extern int cmd_script(int argc, const char **argv, const char *prefix); | 31 | int cmd_script(int argc, const char **argv, const char *prefix); |
32 | extern int cmd_version(int argc, const char **argv, const char *prefix); | 32 | int cmd_version(int argc, const char **argv, const char *prefix); |
33 | extern int cmd_probe(int argc, const char **argv, const char *prefix); | 33 | int cmd_probe(int argc, const char **argv, const char *prefix); |
34 | extern int cmd_kmem(int argc, const char **argv, const char *prefix); | 34 | int cmd_kmem(int argc, const char **argv, const char *prefix); |
35 | extern int cmd_lock(int argc, const char **argv, const char *prefix); | 35 | int cmd_lock(int argc, const char **argv, const char *prefix); |
36 | extern int cmd_kvm(int argc, const char **argv, const char *prefix); | 36 | int cmd_kvm(int argc, const char **argv, const char *prefix); |
37 | extern int cmd_test(int argc, const char **argv, const char *prefix); | 37 | int cmd_test(int argc, const char **argv, const char *prefix); |
38 | extern int cmd_trace(int argc, const char **argv, const char *prefix); | 38 | int cmd_trace(int argc, const char **argv, const char *prefix); |
39 | extern int cmd_inject(int argc, const char **argv, const char *prefix); | 39 | int cmd_inject(int argc, const char **argv, const char *prefix); |
40 | extern int cmd_mem(int argc, const char **argv, const char *prefix); | 40 | int cmd_mem(int argc, const char **argv, const char *prefix); |
41 | extern int cmd_data(int argc, const char **argv, const char *prefix); | 41 | int cmd_data(int argc, const char **argv, const char *prefix); |
42 | 42 | ||
43 | extern int find_scripts(char **scripts_array, char **scripts_path_array); | 43 | int find_scripts(char **scripts_array, char **scripts_path_array); |
44 | #endif | 44 | #endif |
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index eca6a912e8c2..f7d7f5a1cad5 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile | |||
@@ -109,7 +109,7 @@ ifdef PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET | |||
109 | CFLAGS += -DHAVE_ARCH_REGS_QUERY_REGISTER_OFFSET | 109 | CFLAGS += -DHAVE_ARCH_REGS_QUERY_REGISTER_OFFSET |
110 | endif | 110 | endif |
111 | 111 | ||
112 | include $(src-perf)/config/utilities.mak | 112 | include $(srctree)/tools/scripts/utilities.mak |
113 | 113 | ||
114 | ifeq ($(call get-executable,$(FLEX)),) | 114 | ifeq ($(call get-executable,$(FLEX)),) |
115 | dummy := $(error Error: $(FLEX) is missing on this system, please install it) | 115 | dummy := $(error Error: $(FLEX) is missing on this system, please install it) |
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index afc9ad0a0515..abd3f0ec0c0b 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c | |||
@@ -293,7 +293,6 @@ static int process_sample_event(struct machine *machine, | |||
293 | { | 293 | { |
294 | struct perf_sample sample; | 294 | struct perf_sample sample; |
295 | struct thread *thread; | 295 | struct thread *thread; |
296 | u8 cpumode; | ||
297 | int ret; | 296 | int ret; |
298 | 297 | ||
299 | if (perf_evlist__parse_sample(evlist, event, &sample)) { | 298 | if (perf_evlist__parse_sample(evlist, event, &sample)) { |
@@ -307,9 +306,7 @@ static int process_sample_event(struct machine *machine, | |||
307 | return -1; | 306 | return -1; |
308 | } | 307 | } |
309 | 308 | ||
310 | cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 309 | ret = read_object_code(sample.ip, READLEN, sample.cpumode, thread, state); |
311 | |||
312 | ret = read_object_code(sample.ip, READLEN, cpumode, thread, state); | ||
313 | thread__put(thread); | 310 | thread__put(thread); |
314 | return ret; | 311 | return ret; |
315 | } | 312 | } |
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c index 1c5c0221cea2..8f6eb853aaf7 100644 --- a/tools/perf/tests/dwarf-unwind.c +++ b/tools/perf/tests/dwarf-unwind.c | |||
@@ -20,10 +20,10 @@ | |||
20 | 20 | ||
21 | static int mmap_handler(struct perf_tool *tool __maybe_unused, | 21 | static int mmap_handler(struct perf_tool *tool __maybe_unused, |
22 | union perf_event *event, | 22 | union perf_event *event, |
23 | struct perf_sample *sample __maybe_unused, | 23 | struct perf_sample *sample, |
24 | struct machine *machine) | 24 | struct machine *machine) |
25 | { | 25 | { |
26 | return machine__process_mmap2_event(machine, event, NULL); | 26 | return machine__process_mmap2_event(machine, event, sample); |
27 | } | 27 | } |
28 | 28 | ||
29 | static int init_live_machine(struct machine *machine) | 29 | static int init_live_machine(struct machine *machine) |
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c index 071a8b5f5232..f55f4bd47932 100644 --- a/tools/perf/tests/hists_common.c +++ b/tools/perf/tests/hists_common.c | |||
@@ -100,9 +100,11 @@ struct machine *setup_fake_machine(struct machines *machines) | |||
100 | } | 100 | } |
101 | 101 | ||
102 | for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) { | 102 | for (i = 0; i < ARRAY_SIZE(fake_mmap_info); i++) { |
103 | struct perf_sample sample = { | ||
104 | .cpumode = PERF_RECORD_MISC_USER, | ||
105 | }; | ||
103 | union perf_event fake_mmap_event = { | 106 | union perf_event fake_mmap_event = { |
104 | .mmap = { | 107 | .mmap = { |
105 | .header = { .misc = PERF_RECORD_MISC_USER, }, | ||
106 | .pid = fake_mmap_info[i].pid, | 108 | .pid = fake_mmap_info[i].pid, |
107 | .tid = fake_mmap_info[i].pid, | 109 | .tid = fake_mmap_info[i].pid, |
108 | .start = fake_mmap_info[i].start, | 110 | .start = fake_mmap_info[i].start, |
@@ -114,7 +116,7 @@ struct machine *setup_fake_machine(struct machines *machines) | |||
114 | strcpy(fake_mmap_event.mmap.filename, | 116 | strcpy(fake_mmap_event.mmap.filename, |
115 | fake_mmap_info[i].filename); | 117 | fake_mmap_info[i].filename); |
116 | 118 | ||
117 | machine__process_mmap_event(machine, &fake_mmap_event, NULL); | 119 | machine__process_mmap_event(machine, &fake_mmap_event, &sample); |
118 | } | 120 | } |
119 | 121 | ||
120 | for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) { | 122 | for (i = 0; i < ARRAY_SIZE(fake_symbols); i++) { |
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c index ecf136c385d5..ed5aa9eaeb6c 100644 --- a/tools/perf/tests/hists_cumulate.c +++ b/tools/perf/tests/hists_cumulate.c | |||
@@ -81,11 +81,6 @@ static int add_hist_entries(struct hists *hists, struct machine *machine) | |||
81 | size_t i; | 81 | size_t i; |
82 | 82 | ||
83 | for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { | 83 | for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { |
84 | const union perf_event event = { | ||
85 | .header = { | ||
86 | .misc = PERF_RECORD_MISC_USER, | ||
87 | }, | ||
88 | }; | ||
89 | struct hist_entry_iter iter = { | 84 | struct hist_entry_iter iter = { |
90 | .evsel = evsel, | 85 | .evsel = evsel, |
91 | .sample = &sample, | 86 | .sample = &sample, |
@@ -97,13 +92,13 @@ static int add_hist_entries(struct hists *hists, struct machine *machine) | |||
97 | else | 92 | else |
98 | iter.ops = &hist_iter_normal; | 93 | iter.ops = &hist_iter_normal; |
99 | 94 | ||
95 | sample.cpumode = PERF_RECORD_MISC_USER; | ||
100 | sample.pid = fake_samples[i].pid; | 96 | sample.pid = fake_samples[i].pid; |
101 | sample.tid = fake_samples[i].pid; | 97 | sample.tid = fake_samples[i].pid; |
102 | sample.ip = fake_samples[i].ip; | 98 | sample.ip = fake_samples[i].ip; |
103 | sample.callchain = (struct ip_callchain *)fake_callchains[i]; | 99 | sample.callchain = (struct ip_callchain *)fake_callchains[i]; |
104 | 100 | ||
105 | if (perf_event__preprocess_sample(&event, machine, &al, | 101 | if (machine__resolve(machine, &al, &sample) < 0) |
106 | &sample) < 0) | ||
107 | goto out; | 102 | goto out; |
108 | 103 | ||
109 | if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH, | 104 | if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH, |
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index 34b945a55d4d..b825d24f8186 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c | |||
@@ -58,11 +58,6 @@ static int add_hist_entries(struct perf_evlist *evlist, | |||
58 | */ | 58 | */ |
59 | evlist__for_each(evlist, evsel) { | 59 | evlist__for_each(evlist, evsel) { |
60 | for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { | 60 | for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { |
61 | const union perf_event event = { | ||
62 | .header = { | ||
63 | .misc = PERF_RECORD_MISC_USER, | ||
64 | }, | ||
65 | }; | ||
66 | struct hist_entry_iter iter = { | 61 | struct hist_entry_iter iter = { |
67 | .evsel = evsel, | 62 | .evsel = evsel, |
68 | .sample = &sample, | 63 | .sample = &sample, |
@@ -76,12 +71,12 @@ static int add_hist_entries(struct perf_evlist *evlist, | |||
76 | hists->dso_filter = NULL; | 71 | hists->dso_filter = NULL; |
77 | hists->symbol_filter_str = NULL; | 72 | hists->symbol_filter_str = NULL; |
78 | 73 | ||
74 | sample.cpumode = PERF_RECORD_MISC_USER; | ||
79 | sample.pid = fake_samples[i].pid; | 75 | sample.pid = fake_samples[i].pid; |
80 | sample.tid = fake_samples[i].pid; | 76 | sample.tid = fake_samples[i].pid; |
81 | sample.ip = fake_samples[i].ip; | 77 | sample.ip = fake_samples[i].ip; |
82 | 78 | ||
83 | if (perf_event__preprocess_sample(&event, machine, &al, | 79 | if (machine__resolve(machine, &al, &sample) < 0) |
84 | &sample) < 0) | ||
85 | goto out; | 80 | goto out; |
86 | 81 | ||
87 | al.socket = fake_samples[i].socket; | 82 | al.socket = fake_samples[i].socket; |
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index 64b257d8d557..358324e47805 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c | |||
@@ -76,17 +76,12 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) | |||
76 | struct hists *hists = evsel__hists(evsel); | 76 | struct hists *hists = evsel__hists(evsel); |
77 | 77 | ||
78 | for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { | 78 | for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { |
79 | const union perf_event event = { | 79 | sample.cpumode = PERF_RECORD_MISC_USER; |
80 | .header = { | ||
81 | .misc = PERF_RECORD_MISC_USER, | ||
82 | }, | ||
83 | }; | ||
84 | |||
85 | sample.pid = fake_common_samples[k].pid; | 80 | sample.pid = fake_common_samples[k].pid; |
86 | sample.tid = fake_common_samples[k].pid; | 81 | sample.tid = fake_common_samples[k].pid; |
87 | sample.ip = fake_common_samples[k].ip; | 82 | sample.ip = fake_common_samples[k].ip; |
88 | if (perf_event__preprocess_sample(&event, machine, &al, | 83 | |
89 | &sample) < 0) | 84 | if (machine__resolve(machine, &al, &sample) < 0) |
90 | goto out; | 85 | goto out; |
91 | 86 | ||
92 | he = __hists__add_entry(hists, &al, NULL, | 87 | he = __hists__add_entry(hists, &al, NULL, |
@@ -102,17 +97,10 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) | |||
102 | } | 97 | } |
103 | 98 | ||
104 | for (k = 0; k < ARRAY_SIZE(fake_samples[i]); k++) { | 99 | for (k = 0; k < ARRAY_SIZE(fake_samples[i]); k++) { |
105 | const union perf_event event = { | ||
106 | .header = { | ||
107 | .misc = PERF_RECORD_MISC_USER, | ||
108 | }, | ||
109 | }; | ||
110 | |||
111 | sample.pid = fake_samples[i][k].pid; | 100 | sample.pid = fake_samples[i][k].pid; |
112 | sample.tid = fake_samples[i][k].pid; | 101 | sample.tid = fake_samples[i][k].pid; |
113 | sample.ip = fake_samples[i][k].ip; | 102 | sample.ip = fake_samples[i][k].ip; |
114 | if (perf_event__preprocess_sample(&event, machine, &al, | 103 | if (machine__resolve(machine, &al, &sample) < 0) |
115 | &sample) < 0) | ||
116 | goto out; | 104 | goto out; |
117 | 105 | ||
118 | he = __hists__add_entry(hists, &al, NULL, | 106 | he = __hists__add_entry(hists, &al, NULL, |
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c index 23cce67c7e48..d3556fbe8c5c 100644 --- a/tools/perf/tests/hists_output.c +++ b/tools/perf/tests/hists_output.c | |||
@@ -51,11 +51,6 @@ static int add_hist_entries(struct hists *hists, struct machine *machine) | |||
51 | size_t i; | 51 | size_t i; |
52 | 52 | ||
53 | for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { | 53 | for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { |
54 | const union perf_event event = { | ||
55 | .header = { | ||
56 | .misc = PERF_RECORD_MISC_USER, | ||
57 | }, | ||
58 | }; | ||
59 | struct hist_entry_iter iter = { | 54 | struct hist_entry_iter iter = { |
60 | .evsel = evsel, | 55 | .evsel = evsel, |
61 | .sample = &sample, | 56 | .sample = &sample, |
@@ -63,13 +58,13 @@ static int add_hist_entries(struct hists *hists, struct machine *machine) | |||
63 | .hide_unresolved = false, | 58 | .hide_unresolved = false, |
64 | }; | 59 | }; |
65 | 60 | ||
61 | sample.cpumode = PERF_RECORD_MISC_USER; | ||
66 | sample.cpu = fake_samples[i].cpu; | 62 | sample.cpu = fake_samples[i].cpu; |
67 | sample.pid = fake_samples[i].pid; | 63 | sample.pid = fake_samples[i].pid; |
68 | sample.tid = fake_samples[i].pid; | 64 | sample.tid = fake_samples[i].pid; |
69 | sample.ip = fake_samples[i].ip; | 65 | sample.ip = fake_samples[i].ip; |
70 | 66 | ||
71 | if (perf_event__preprocess_sample(&event, machine, &al, | 67 | if (machine__resolve(machine, &al, &sample) < 0) |
72 | &sample) < 0) | ||
73 | goto out; | 68 | goto out; |
74 | 69 | ||
75 | if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH, | 70 | if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH, |
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c index bd9bf7e343b1..2aa45b606fa4 100644 --- a/tools/perf/ui/gtk/hists.c +++ b/tools/perf/ui/gtk/hists.c | |||
@@ -55,7 +55,7 @@ static u64 he_get_acc_##_field(struct hist_entry *he) \ | |||
55 | return he->stat_acc->_field; \ | 55 | return he->stat_acc->_field; \ |
56 | } \ | 56 | } \ |
57 | \ | 57 | \ |
58 | static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt __maybe_unused, \ | 58 | static int perf_gtk__hpp_color_##_type(struct perf_hpp_fmt *fmt, \ |
59 | struct perf_hpp *hpp, \ | 59 | struct perf_hpp *hpp, \ |
60 | struct hist_entry *he) \ | 60 | struct hist_entry *he) \ |
61 | { \ | 61 | { \ |
diff --git a/tools/perf/util/Build b/tools/perf/util/Build index eea25e2424e9..da48fd843438 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build | |||
@@ -1,4 +1,3 @@ | |||
1 | libperf-y += abspath.o | ||
2 | libperf-y += alias.o | 1 | libperf-y += alias.o |
3 | libperf-y += annotate.o | 2 | libperf-y += annotate.o |
4 | libperf-y += build-id.o | 3 | libperf-y += build-id.o |
diff --git a/tools/perf/util/abspath.c b/tools/perf/util/abspath.c deleted file mode 100644 index 0e76affe9c36..000000000000 --- a/tools/perf/util/abspath.c +++ /dev/null | |||
@@ -1,37 +0,0 @@ | |||
1 | #include "cache.h" | ||
2 | |||
3 | static const char *get_pwd_cwd(void) | ||
4 | { | ||
5 | static char cwd[PATH_MAX + 1]; | ||
6 | char *pwd; | ||
7 | struct stat cwd_stat, pwd_stat; | ||
8 | if (getcwd(cwd, PATH_MAX) == NULL) | ||
9 | return NULL; | ||
10 | pwd = getenv("PWD"); | ||
11 | if (pwd && strcmp(pwd, cwd)) { | ||
12 | stat(cwd, &cwd_stat); | ||
13 | if (!stat(pwd, &pwd_stat) && | ||
14 | pwd_stat.st_dev == cwd_stat.st_dev && | ||
15 | pwd_stat.st_ino == cwd_stat.st_ino) { | ||
16 | strlcpy(cwd, pwd, PATH_MAX); | ||
17 | } | ||
18 | } | ||
19 | return cwd; | ||
20 | } | ||
21 | |||
22 | const char *make_nonrelative_path(const char *path) | ||
23 | { | ||
24 | static char buf[PATH_MAX + 1]; | ||
25 | |||
26 | if (is_absolute_path(path)) { | ||
27 | if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) | ||
28 | die("Too long path: %.*s", 60, path); | ||
29 | } else { | ||
30 | const char *cwd = get_pwd_cwd(); | ||
31 | if (!cwd) | ||
32 | die("Cannot determine the current working directory"); | ||
33 | if (snprintf(buf, PATH_MAX, "%s/%s", cwd, path) >= PATH_MAX) | ||
34 | die("Too long path: %.*s", 60, path); | ||
35 | } | ||
36 | return buf; | ||
37 | } | ||
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index cea323d9ee7e..9241f8c2b7e1 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h | |||
@@ -158,7 +158,7 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); | |||
158 | 158 | ||
159 | int hist_entry__annotate(struct hist_entry *he, size_t privsize); | 159 | int hist_entry__annotate(struct hist_entry *he, size_t privsize); |
160 | 160 | ||
161 | int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym); | 161 | int symbol__annotate_init(struct map *map, struct symbol *sym); |
162 | int symbol__annotate_printf(struct symbol *sym, struct map *map, | 162 | int symbol__annotate_printf(struct symbol *sym, struct map *map, |
163 | struct perf_evsel *evsel, bool full_paths, | 163 | struct perf_evsel *evsel, bool full_paths, |
164 | int min_pcnt, int max_lines, int context); | 164 | int min_pcnt, int max_lines, int context); |
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h index e5a8e2d4f2af..57ff31ecb8e4 100644 --- a/tools/perf/util/auxtrace.h +++ b/tools/perf/util/auxtrace.h | |||
@@ -517,7 +517,7 @@ static inline void auxtrace__free(struct perf_session *session) | |||
517 | 517 | ||
518 | static inline struct auxtrace_record * | 518 | static inline struct auxtrace_record * |
519 | auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, | 519 | auxtrace_record__init(struct perf_evlist *evlist __maybe_unused, |
520 | int *err __maybe_unused) | 520 | int *err) |
521 | { | 521 | { |
522 | *err = 0; | 522 | *err = 0; |
523 | return NULL; | 523 | return NULL; |
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index f1479eeef7da..0573c2ec861d 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -28,7 +28,6 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, | |||
28 | struct machine *machine) | 28 | struct machine *machine) |
29 | { | 29 | { |
30 | struct addr_location al; | 30 | struct addr_location al; |
31 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
32 | struct thread *thread = machine__findnew_thread(machine, sample->pid, | 31 | struct thread *thread = machine__findnew_thread(machine, sample->pid, |
33 | sample->tid); | 32 | sample->tid); |
34 | 33 | ||
@@ -38,7 +37,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused, | |||
38 | return -1; | 37 | return -1; |
39 | } | 38 | } |
40 | 39 | ||
41 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, &al); | 40 | thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, &al); |
42 | 41 | ||
43 | if (al.map != NULL) | 42 | if (al.map != NULL) |
44 | al.map->dso->hit = 1; | 43 | al.map->dso->hit = 1; |
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h index 3ca453f0c51f..1f5a93c2c9a2 100644 --- a/tools/perf/util/cache.h +++ b/tools/perf/util/cache.h | |||
@@ -26,14 +26,14 @@ | |||
26 | extern const char *config_exclusive_filename; | 26 | extern const char *config_exclusive_filename; |
27 | 27 | ||
28 | typedef int (*config_fn_t)(const char *, const char *, void *); | 28 | typedef int (*config_fn_t)(const char *, const char *, void *); |
29 | extern int perf_default_config(const char *, const char *, void *); | 29 | int perf_default_config(const char *, const char *, void *); |
30 | extern int perf_config(config_fn_t fn, void *); | 30 | int perf_config(config_fn_t fn, void *); |
31 | extern int perf_config_int(const char *, const char *); | 31 | int perf_config_int(const char *, const char *); |
32 | extern u64 perf_config_u64(const char *, const char *); | 32 | u64 perf_config_u64(const char *, const char *); |
33 | extern int perf_config_bool(const char *, const char *); | 33 | int perf_config_bool(const char *, const char *); |
34 | extern int config_error_nonbool(const char *); | 34 | int config_error_nonbool(const char *); |
35 | extern const char *perf_config_dirname(const char *, const char *); | 35 | const char *perf_config_dirname(const char *, const char *); |
36 | extern const char *perf_etc_perfconfig(void); | 36 | const char *perf_etc_perfconfig(void); |
37 | 37 | ||
38 | char *alias_lookup(const char *alias); | 38 | char *alias_lookup(const char *alias); |
39 | int split_cmdline(char *cmdline, const char ***argv); | 39 | int split_cmdline(char *cmdline, const char ***argv); |
@@ -64,13 +64,9 @@ static inline int is_absolute_path(const char *path) | |||
64 | return path[0] == '/'; | 64 | return path[0] == '/'; |
65 | } | 65 | } |
66 | 66 | ||
67 | const char *make_nonrelative_path(const char *path); | ||
68 | char *strip_path_suffix(const char *path, const char *suffix); | 67 | char *strip_path_suffix(const char *path, const char *suffix); |
69 | 68 | ||
70 | extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); | 69 | char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); |
71 | extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); | 70 | char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); |
72 | |||
73 | extern char *perf_pathdup(const char *fmt, ...) | ||
74 | __attribute__((format (printf, 1, 2))); | ||
75 | 71 | ||
76 | #endif /* __PERF_CACHE_H */ | 72 | #endif /* __PERF_CACHE_H */ |
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 18dd22269764..d2a9e694810c 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -220,7 +220,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * | |||
220 | bool hide_unresolved); | 220 | bool hide_unresolved); |
221 | 221 | ||
222 | extern const char record_callchain_help[]; | 222 | extern const char record_callchain_help[]; |
223 | extern int parse_callchain_record(const char *arg, struct callchain_param *param); | 223 | int parse_callchain_record(const char *arg, struct callchain_param *param); |
224 | int parse_callchain_record_opt(const char *arg, struct callchain_param *param); | 224 | int parse_callchain_record_opt(const char *arg, struct callchain_param *param); |
225 | int parse_callchain_report_opt(const char *arg); | 225 | int parse_callchain_report_opt(const char *arg); |
226 | int parse_callchain_top_opt(const char *arg); | 226 | int parse_callchain_top_opt(const char *arg); |
@@ -236,7 +236,7 @@ static inline void callchain_cursor_snapshot(struct callchain_cursor *dest, | |||
236 | } | 236 | } |
237 | 237 | ||
238 | #ifdef HAVE_SKIP_CALLCHAIN_IDX | 238 | #ifdef HAVE_SKIP_CALLCHAIN_IDX |
239 | extern int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain); | 239 | int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain); |
240 | #else | 240 | #else |
241 | static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused, | 241 | static inline int arch_skip_callchain_idx(struct thread *thread __maybe_unused, |
242 | struct ip_callchain *chain __maybe_unused) | 242 | struct ip_callchain *chain __maybe_unused) |
diff --git a/tools/perf/util/cgroup.h b/tools/perf/util/cgroup.h index b4b8cb42fe5e..31f8dcdbd7ef 100644 --- a/tools/perf/util/cgroup.h +++ b/tools/perf/util/cgroup.h | |||
@@ -13,7 +13,7 @@ struct cgroup_sel { | |||
13 | 13 | ||
14 | 14 | ||
15 | extern int nr_cgroups; /* number of explicit cgroups defined */ | 15 | extern int nr_cgroups; /* number of explicit cgroups defined */ |
16 | extern void close_cgroup(struct cgroup_sel *cgrp); | 16 | void close_cgroup(struct cgroup_sel *cgrp); |
17 | extern int parse_cgroups(const struct option *opt, const char *str, int unset); | 17 | int parse_cgroups(const struct option *opt, const char *str, int unset); |
18 | 18 | ||
19 | #endif /* __CGROUP_H__ */ | 19 | #endif /* __CGROUP_H__ */ |
diff --git a/tools/perf/util/cloexec.h b/tools/perf/util/cloexec.h index 3bee6773ddb0..d0d465953d36 100644 --- a/tools/perf/util/cloexec.h +++ b/tools/perf/util/cloexec.h | |||
@@ -5,7 +5,7 @@ unsigned long perf_event_open_cloexec_flag(void); | |||
5 | 5 | ||
6 | #ifdef __GLIBC_PREREQ | 6 | #ifdef __GLIBC_PREREQ |
7 | #if !__GLIBC_PREREQ(2, 6) && !defined(__UCLIBC__) | 7 | #if !__GLIBC_PREREQ(2, 6) && !defined(__UCLIBC__) |
8 | extern int sched_getcpu(void) __THROW; | 8 | int sched_getcpu(void) __THROW; |
9 | #endif | 9 | #endif |
10 | #endif | 10 | #endif |
11 | 11 | ||
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 811af89ce0bb..bbf69d248ec5 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c | |||
@@ -632,7 +632,7 @@ static bool is_flush_needed(struct ctf_stream *cs) | |||
632 | } | 632 | } |
633 | 633 | ||
634 | static int process_sample_event(struct perf_tool *tool, | 634 | static int process_sample_event(struct perf_tool *tool, |
635 | union perf_event *_event __maybe_unused, | 635 | union perf_event *_event, |
636 | struct perf_sample *sample, | 636 | struct perf_sample *sample, |
637 | struct perf_evsel *evsel, | 637 | struct perf_evsel *evsel, |
638 | struct machine *machine __maybe_unused) | 638 | struct machine *machine __maybe_unused) |
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c index 1c9689e4cc17..049438d51b9a 100644 --- a/tools/perf/util/db-export.c +++ b/tools/perf/util/db-export.c | |||
@@ -333,7 +333,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event, | |||
333 | sample_addr_correlates_sym(&evsel->attr)) { | 333 | sample_addr_correlates_sym(&evsel->attr)) { |
334 | struct addr_location addr_al; | 334 | struct addr_location addr_al; |
335 | 335 | ||
336 | perf_event__preprocess_sample_addr(event, sample, thread, &addr_al); | 336 | thread__resolve(thread, &addr_al, sample); |
337 | err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id, | 337 | err = db_ids_from_al(dbe, &addr_al, &es.addr_dso_db_id, |
338 | &es.addr_sym_db_id, &es.addr_offset); | 338 | &es.addr_sym_db_id, &es.addr_offset); |
339 | if (err) | 339 | if (err) |
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 45ec4d0a50ed..0953280629cf 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h | |||
@@ -162,6 +162,7 @@ struct dso { | |||
162 | u8 loaded; | 162 | u8 loaded; |
163 | u8 rel; | 163 | u8 rel; |
164 | u8 build_id[BUILD_ID_SIZE]; | 164 | u8 build_id[BUILD_ID_SIZE]; |
165 | u64 text_offset; | ||
165 | const char *short_name; | 166 | const char *short_name; |
166 | const char *long_name; | 167 | const char *long_name; |
167 | u16 long_name_len; | 168 | u16 long_name_len; |
@@ -301,7 +302,7 @@ int __kmod_path__parse(struct kmod_path *m, const char *path, | |||
301 | * TODO | 302 | * TODO |
302 | */ | 303 | */ |
303 | int dso__data_get_fd(struct dso *dso, struct machine *machine); | 304 | int dso__data_get_fd(struct dso *dso, struct machine *machine); |
304 | void dso__data_put_fd(struct dso *dso __maybe_unused); | 305 | void dso__data_put_fd(struct dso *dso); |
305 | void dso__data_close(struct dso *dso); | 306 | void dso__data_close(struct dso *dso); |
306 | 307 | ||
307 | off_t dso__data_size(struct dso *dso, struct machine *machine); | 308 | off_t dso__data_size(struct dso *dso, struct machine *machine); |
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c index a509aa8433a1..577e600c8eb1 100644 --- a/tools/perf/util/dwarf-aux.c +++ b/tools/perf/util/dwarf-aux.c | |||
@@ -915,7 +915,7 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf) | |||
915 | tmp = "*"; | 915 | tmp = "*"; |
916 | else if (tag == DW_TAG_subroutine_type) { | 916 | else if (tag == DW_TAG_subroutine_type) { |
917 | /* Function pointer */ | 917 | /* Function pointer */ |
918 | strbuf_addf(buf, "(function_type)"); | 918 | strbuf_add(buf, "(function_type)", 15); |
919 | return 0; | 919 | return 0; |
920 | } else { | 920 | } else { |
921 | if (!dwarf_diename(&type)) | 921 | if (!dwarf_diename(&type)) |
@@ -932,7 +932,7 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf) | |||
932 | } | 932 | } |
933 | ret = die_get_typename(&type, buf); | 933 | ret = die_get_typename(&type, buf); |
934 | if (ret == 0) | 934 | if (ret == 0) |
935 | strbuf_addf(buf, "%s", tmp); | 935 | strbuf_addstr(buf, tmp); |
936 | 936 | ||
937 | return ret; | 937 | return ret; |
938 | } | 938 | } |
@@ -951,7 +951,7 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf) | |||
951 | ret = die_get_typename(vr_die, buf); | 951 | ret = die_get_typename(vr_die, buf); |
952 | if (ret < 0) { | 952 | if (ret < 0) { |
953 | pr_debug("Failed to get type, make it unknown.\n"); | 953 | pr_debug("Failed to get type, make it unknown.\n"); |
954 | strbuf_addf(buf, "(unknown_type)"); | 954 | strbuf_add(buf, " (unknown_type)", 14); |
955 | } | 955 | } |
956 | 956 | ||
957 | strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); | 957 | strbuf_addf(buf, "\t%s", dwarf_diename(vr_die)); |
@@ -1013,7 +1013,7 @@ static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die, | |||
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | if (!first) | 1015 | if (!first) |
1016 | strbuf_addf(buf, "]>"); | 1016 | strbuf_add(buf, "]>", 2); |
1017 | 1017 | ||
1018 | out: | 1018 | out: |
1019 | free(scopes); | 1019 | free(scopes); |
@@ -1076,7 +1076,7 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf) | |||
1076 | } | 1076 | } |
1077 | 1077 | ||
1078 | if (!first) | 1078 | if (!first) |
1079 | strbuf_addf(buf, "]>"); | 1079 | strbuf_add(buf, "]>", 2); |
1080 | 1080 | ||
1081 | return ret; | 1081 | return ret; |
1082 | } | 1082 | } |
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h index c42ec366f2a7..dc0ce1adb075 100644 --- a/tools/perf/util/dwarf-aux.h +++ b/tools/perf/util/dwarf-aux.h | |||
@@ -25,48 +25,48 @@ | |||
25 | #include <elfutils/version.h> | 25 | #include <elfutils/version.h> |
26 | 26 | ||
27 | /* Find the realpath of the target file */ | 27 | /* Find the realpath of the target file */ |
28 | extern const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname); | 28 | const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname); |
29 | 29 | ||
30 | /* Get DW_AT_comp_dir (should be NULL with older gcc) */ | 30 | /* Get DW_AT_comp_dir (should be NULL with older gcc) */ |
31 | extern const char *cu_get_comp_dir(Dwarf_Die *cu_die); | 31 | const char *cu_get_comp_dir(Dwarf_Die *cu_die); |
32 | 32 | ||
33 | /* Get a line number and file name for given address */ | 33 | /* Get a line number and file name for given address */ |
34 | extern int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr, | 34 | int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr, |
35 | const char **fname, int *lineno); | 35 | const char **fname, int *lineno); |
36 | 36 | ||
37 | /* Walk on funcitons at given address */ | 37 | /* Walk on funcitons at given address */ |
38 | extern int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr, | 38 | int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr, |
39 | int (*callback)(Dwarf_Die *, void *), void *data); | 39 | int (*callback)(Dwarf_Die *, void *), void *data); |
40 | 40 | ||
41 | /* Ensure that this DIE is a subprogram and definition (not declaration) */ | 41 | /* Ensure that this DIE is a subprogram and definition (not declaration) */ |
42 | extern bool die_is_func_def(Dwarf_Die *dw_die); | 42 | bool die_is_func_def(Dwarf_Die *dw_die); |
43 | 43 | ||
44 | /* Ensure that this DIE is an instance of a subprogram */ | 44 | /* Ensure that this DIE is an instance of a subprogram */ |
45 | extern bool die_is_func_instance(Dwarf_Die *dw_die); | 45 | bool die_is_func_instance(Dwarf_Die *dw_die); |
46 | 46 | ||
47 | /* Compare diename and tname */ | 47 | /* Compare diename and tname */ |
48 | extern bool die_compare_name(Dwarf_Die *dw_die, const char *tname); | 48 | bool die_compare_name(Dwarf_Die *dw_die, const char *tname); |
49 | 49 | ||
50 | /* Matching diename with glob pattern */ | 50 | /* Matching diename with glob pattern */ |
51 | extern bool die_match_name(Dwarf_Die *dw_die, const char *glob); | 51 | bool die_match_name(Dwarf_Die *dw_die, const char *glob); |
52 | 52 | ||
53 | /* Get callsite line number of inline-function instance */ | 53 | /* Get callsite line number of inline-function instance */ |
54 | extern int die_get_call_lineno(Dwarf_Die *in_die); | 54 | int die_get_call_lineno(Dwarf_Die *in_die); |
55 | 55 | ||
56 | /* Get callsite file name of inlined function instance */ | 56 | /* Get callsite file name of inlined function instance */ |
57 | extern const char *die_get_call_file(Dwarf_Die *in_die); | 57 | const char *die_get_call_file(Dwarf_Die *in_die); |
58 | 58 | ||
59 | /* Get type die */ | 59 | /* Get type die */ |
60 | extern Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem); | 60 | Dwarf_Die *die_get_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem); |
61 | 61 | ||
62 | /* Get a type die, but skip qualifiers and typedef */ | 62 | /* Get a type die, but skip qualifiers and typedef */ |
63 | extern Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem); | 63 | Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem); |
64 | 64 | ||
65 | /* Check whether the DIE is signed or not */ | 65 | /* Check whether the DIE is signed or not */ |
66 | extern bool die_is_signed_type(Dwarf_Die *tp_die); | 66 | bool die_is_signed_type(Dwarf_Die *tp_die); |
67 | 67 | ||
68 | /* Get data_member_location offset */ | 68 | /* Get data_member_location offset */ |
69 | extern int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs); | 69 | int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs); |
70 | 70 | ||
71 | /* Return values for die_find_child() callbacks */ | 71 | /* Return values for die_find_child() callbacks */ |
72 | enum { | 72 | enum { |
@@ -77,29 +77,29 @@ enum { | |||
77 | }; | 77 | }; |
78 | 78 | ||
79 | /* Search child DIEs */ | 79 | /* Search child DIEs */ |
80 | extern Dwarf_Die *die_find_child(Dwarf_Die *rt_die, | 80 | Dwarf_Die *die_find_child(Dwarf_Die *rt_die, |
81 | int (*callback)(Dwarf_Die *, void *), | 81 | int (*callback)(Dwarf_Die *, void *), |
82 | void *data, Dwarf_Die *die_mem); | 82 | void *data, Dwarf_Die *die_mem); |
83 | 83 | ||
84 | /* Search a non-inlined function including given address */ | 84 | /* Search a non-inlined function including given address */ |
85 | extern Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, | 85 | Dwarf_Die *die_find_realfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, |
86 | Dwarf_Die *die_mem); | 86 | Dwarf_Die *die_mem); |
87 | 87 | ||
88 | /* Search a non-inlined function with tail call at given address */ | 88 | /* Search a non-inlined function with tail call at given address */ |
89 | Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, | 89 | Dwarf_Die *die_find_tailfunc(Dwarf_Die *cu_die, Dwarf_Addr addr, |
90 | Dwarf_Die *die_mem); | 90 | Dwarf_Die *die_mem); |
91 | 91 | ||
92 | /* Search the top inlined function including given address */ | 92 | /* Search the top inlined function including given address */ |
93 | extern Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, | 93 | Dwarf_Die *die_find_top_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, |
94 | Dwarf_Die *die_mem); | 94 | Dwarf_Die *die_mem); |
95 | 95 | ||
96 | /* Search the deepest inlined function including given address */ | 96 | /* Search the deepest inlined function including given address */ |
97 | extern Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, | 97 | Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, |
98 | Dwarf_Die *die_mem); | 98 | Dwarf_Die *die_mem); |
99 | 99 | ||
100 | /* Walk on the instances of given DIE */ | 100 | /* Walk on the instances of given DIE */ |
101 | extern int die_walk_instances(Dwarf_Die *in_die, | 101 | int die_walk_instances(Dwarf_Die *in_die, |
102 | int (*callback)(Dwarf_Die *, void *), void *data); | 102 | int (*callback)(Dwarf_Die *, void *), void *data); |
103 | 103 | ||
104 | /* Walker on lines (Note: line number will not be sorted) */ | 104 | /* Walker on lines (Note: line number will not be sorted) */ |
105 | typedef int (* line_walk_callback_t) (const char *fname, int lineno, | 105 | typedef int (* line_walk_callback_t) (const char *fname, int lineno, |
@@ -109,22 +109,20 @@ typedef int (* line_walk_callback_t) (const char *fname, int lineno, | |||
109 | * Walk on lines inside given DIE. If the DIE is a subprogram, walk only on | 109 | * Walk on lines inside given DIE. If the DIE is a subprogram, walk only on |
110 | * the lines inside the subprogram, otherwise the DIE must be a CU DIE. | 110 | * the lines inside the subprogram, otherwise the DIE must be a CU DIE. |
111 | */ | 111 | */ |
112 | extern int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, | 112 | int die_walk_lines(Dwarf_Die *rt_die, line_walk_callback_t callback, void *data); |
113 | void *data); | ||
114 | 113 | ||
115 | /* Find a variable called 'name' at given address */ | 114 | /* Find a variable called 'name' at given address */ |
116 | extern Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name, | 115 | Dwarf_Die *die_find_variable_at(Dwarf_Die *sp_die, const char *name, |
117 | Dwarf_Addr addr, Dwarf_Die *die_mem); | 116 | Dwarf_Addr addr, Dwarf_Die *die_mem); |
118 | 117 | ||
119 | /* Find a member called 'name' */ | 118 | /* Find a member called 'name' */ |
120 | extern Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name, | 119 | Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name, |
121 | Dwarf_Die *die_mem); | 120 | Dwarf_Die *die_mem); |
122 | 121 | ||
123 | /* Get the name of given variable DIE */ | 122 | /* Get the name of given variable DIE */ |
124 | extern int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf); | 123 | int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf); |
125 | 124 | ||
126 | /* Get the name and type of given variable DIE, stored as "type\tname" */ | 125 | /* Get the name and type of given variable DIE, stored as "type\tname" */ |
127 | extern int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf); | 126 | int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf); |
128 | extern int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, | 127 | int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf); |
129 | struct strbuf *buf); | ||
130 | #endif | 128 | #endif |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 7bad5c3fa7b7..52cf479bc593 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -1295,12 +1295,9 @@ void thread__find_addr_location(struct thread *thread, | |||
1295 | * Callers need to drop the reference to al->thread, obtained in | 1295 | * Callers need to drop the reference to al->thread, obtained in |
1296 | * machine__findnew_thread() | 1296 | * machine__findnew_thread() |
1297 | */ | 1297 | */ |
1298 | int perf_event__preprocess_sample(const union perf_event *event, | 1298 | int machine__resolve(struct machine *machine, struct addr_location *al, |
1299 | struct machine *machine, | 1299 | struct perf_sample *sample) |
1300 | struct addr_location *al, | ||
1301 | struct perf_sample *sample) | ||
1302 | { | 1300 | { |
1303 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
1304 | struct thread *thread = machine__findnew_thread(machine, sample->pid, | 1301 | struct thread *thread = machine__findnew_thread(machine, sample->pid, |
1305 | sample->tid); | 1302 | sample->tid); |
1306 | 1303 | ||
@@ -1315,11 +1312,11 @@ int perf_event__preprocess_sample(const union perf_event *event, | |||
1315 | * events, but for older perf.data files there was no such thing, so do | 1312 | * events, but for older perf.data files there was no such thing, so do |
1316 | * it now. | 1313 | * it now. |
1317 | */ | 1314 | */ |
1318 | if (cpumode == PERF_RECORD_MISC_KERNEL && | 1315 | if (sample->cpumode == PERF_RECORD_MISC_KERNEL && |
1319 | machine__kernel_map(machine) == NULL) | 1316 | machine__kernel_map(machine) == NULL) |
1320 | machine__create_kernel_maps(machine); | 1317 | machine__create_kernel_maps(machine); |
1321 | 1318 | ||
1322 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->ip, al); | 1319 | thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->ip, al); |
1323 | dump_printf(" ...... dso: %s\n", | 1320 | dump_printf(" ...... dso: %s\n", |
1324 | al->map ? al->map->dso->long_name : | 1321 | al->map ? al->map->dso->long_name : |
1325 | al->level == 'H' ? "[hypervisor]" : "<not found>"); | 1322 | al->level == 'H' ? "[hypervisor]" : "<not found>"); |
@@ -1395,16 +1392,12 @@ bool sample_addr_correlates_sym(struct perf_event_attr *attr) | |||
1395 | return false; | 1392 | return false; |
1396 | } | 1393 | } |
1397 | 1394 | ||
1398 | void perf_event__preprocess_sample_addr(union perf_event *event, | 1395 | void thread__resolve(struct thread *thread, struct addr_location *al, |
1399 | struct perf_sample *sample, | 1396 | struct perf_sample *sample) |
1400 | struct thread *thread, | ||
1401 | struct addr_location *al) | ||
1402 | { | 1397 | { |
1403 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 1398 | thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, sample->addr, al); |
1404 | |||
1405 | thread__find_addr_map(thread, cpumode, MAP__FUNCTION, sample->addr, al); | ||
1406 | if (!al->map) | 1399 | if (!al->map) |
1407 | thread__find_addr_map(thread, cpumode, MAP__VARIABLE, | 1400 | thread__find_addr_map(thread, sample->cpumode, MAP__VARIABLE, |
1408 | sample->addr, al); | 1401 | sample->addr, al); |
1409 | 1402 | ||
1410 | al->cpu = sample->cpu; | 1403 | al->cpu = sample->cpu; |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index b7ffb7ee9971..6bb1c928350d 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -192,6 +192,7 @@ struct perf_sample { | |||
192 | u64 data_src; | 192 | u64 data_src; |
193 | u32 flags; | 193 | u32 flags; |
194 | u16 insn_len; | 194 | u16 insn_len; |
195 | u8 cpumode; | ||
195 | void *raw_data; | 196 | void *raw_data; |
196 | struct ip_callchain *callchain; | 197 | struct ip_callchain *callchain; |
197 | struct branch_stack *branch_stack; | 198 | struct branch_stack *branch_stack; |
@@ -597,10 +598,8 @@ int perf_event__process(struct perf_tool *tool, | |||
597 | 598 | ||
598 | struct addr_location; | 599 | struct addr_location; |
599 | 600 | ||
600 | int perf_event__preprocess_sample(const union perf_event *event, | 601 | int machine__resolve(struct machine *machine, struct addr_location *al, |
601 | struct machine *machine, | 602 | struct perf_sample *sample); |
602 | struct addr_location *al, | ||
603 | struct perf_sample *sample); | ||
604 | 603 | ||
605 | void addr_location__put(struct addr_location *al); | 604 | void addr_location__put(struct addr_location *al); |
606 | 605 | ||
@@ -608,10 +607,8 @@ struct thread; | |||
608 | 607 | ||
609 | bool is_bts_event(struct perf_event_attr *attr); | 608 | bool is_bts_event(struct perf_event_attr *attr); |
610 | bool sample_addr_correlates_sym(struct perf_event_attr *attr); | 609 | bool sample_addr_correlates_sym(struct perf_event_attr *attr); |
611 | void perf_event__preprocess_sample_addr(union perf_event *event, | 610 | void thread__resolve(struct thread *thread, struct addr_location *al, |
612 | struct perf_sample *sample, | 611 | struct perf_sample *sample); |
613 | struct thread *thread, | ||
614 | struct addr_location *al); | ||
615 | 612 | ||
616 | const char *perf_event__name(unsigned int id); | 613 | const char *perf_event__name(unsigned int id); |
617 | 614 | ||
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 0902fe418754..738ce226002b 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -1643,6 +1643,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, | |||
1643 | data->stream_id = data->id = data->time = -1ULL; | 1643 | data->stream_id = data->id = data->time = -1ULL; |
1644 | data->period = evsel->attr.sample_period; | 1644 | data->period = evsel->attr.sample_period; |
1645 | data->weight = 0; | 1645 | data->weight = 0; |
1646 | data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
1646 | 1647 | ||
1647 | if (event->header.type != PERF_RECORD_SAMPLE) { | 1648 | if (event->header.type != PERF_RECORD_SAMPLE) { |
1648 | if (!evsel->attr.sample_id_all) | 1649 | if (!evsel->attr.sample_id_all) |
diff --git a/tools/perf/util/genelf.h b/tools/perf/util/genelf.h index 45bf9c6d3257..cd67e64a0494 100644 --- a/tools/perf/util/genelf.h +++ b/tools/perf/util/genelf.h | |||
@@ -2,12 +2,10 @@ | |||
2 | #define __GENELF_H__ | 2 | #define __GENELF_H__ |
3 | 3 | ||
4 | /* genelf.c */ | 4 | /* genelf.c */ |
5 | extern int jit_write_elf(int fd, uint64_t code_addr, const char *sym, | 5 | int jit_write_elf(int fd, uint64_t code_addr, const char *sym, |
6 | const void *code, int csize, | 6 | const void *code, int csize, void *debug, int nr_debug_entries); |
7 | void *debug, int nr_debug_entries); | ||
8 | /* genelf_debug.c */ | 7 | /* genelf_debug.c */ |
9 | extern int jit_add_debug_info(Elf *e, uint64_t code_addr, | 8 | int jit_add_debug_info(Elf *e, uint64_t code_addr, void *debug, int nr_debug_entries); |
10 | void *debug, int nr_debug_entries); | ||
11 | 9 | ||
12 | #if defined(__arm__) | 10 | #if defined(__arm__) |
13 | #define GEN_ELF_ARCH EM_ARM | 11 | #define GEN_ELF_ARCH EM_ARM |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 73e38e472ecd..90680ec9f8b8 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -1872,11 +1872,6 @@ static int process_cpu_topology(struct perf_file_section *section, | |||
1872 | if (ph->needs_swap) | 1872 | if (ph->needs_swap) |
1873 | nr = bswap_32(nr); | 1873 | nr = bswap_32(nr); |
1874 | 1874 | ||
1875 | if (nr > (u32)cpu_nr) { | ||
1876 | pr_debug("core_id number is too big." | ||
1877 | "You may need to upgrade the perf tool.\n"); | ||
1878 | goto free_cpu; | ||
1879 | } | ||
1880 | ph->env.cpu[i].core_id = nr; | 1875 | ph->env.cpu[i].core_id = nr; |
1881 | 1876 | ||
1882 | ret = readn(fd, &nr, sizeof(nr)); | 1877 | ret = readn(fd, &nr, sizeof(nr)); |
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 3d87ca823c0a..d306ca118449 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h | |||
@@ -121,7 +121,7 @@ int perf_event__synthesize_event_update_cpus(struct perf_tool *tool, | |||
121 | perf_event__handler_t process); | 121 | perf_event__handler_t process); |
122 | int perf_event__process_attr(struct perf_tool *tool, union perf_event *event, | 122 | int perf_event__process_attr(struct perf_tool *tool, union perf_event *event, |
123 | struct perf_evlist **pevlist); | 123 | struct perf_evlist **pevlist); |
124 | int perf_event__process_event_update(struct perf_tool *tool __maybe_unused, | 124 | int perf_event__process_event_update(struct perf_tool *tool, |
125 | union perf_event *event, | 125 | union perf_event *event, |
126 | struct perf_evlist **pevlist); | 126 | struct perf_evlist **pevlist); |
127 | size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp); | 127 | size_t perf_event__fprintf_event_update(union perf_event *event, FILE *fp); |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 290b3cbf6877..31c4641fe5ff 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -670,7 +670,7 @@ iter_prepare_branch_entry(struct hist_entry_iter *iter, struct addr_location *al | |||
670 | } | 670 | } |
671 | 671 | ||
672 | static int | 672 | static int |
673 | iter_add_single_branch_entry(struct hist_entry_iter *iter __maybe_unused, | 673 | iter_add_single_branch_entry(struct hist_entry_iter *iter, |
674 | struct addr_location *al __maybe_unused) | 674 | struct addr_location *al __maybe_unused) |
675 | { | 675 | { |
676 | /* to avoid calling callback function */ | 676 | /* to avoid calling callback function */ |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index ead18c82294f..bec0cd660fbd 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -433,8 +433,7 @@ void hist__account_cycles(struct branch_stack *bs, struct addr_location *al, | |||
433 | struct perf_sample *sample, bool nonany_branch_mode); | 433 | struct perf_sample *sample, bool nonany_branch_mode); |
434 | 434 | ||
435 | struct option; | 435 | struct option; |
436 | int parse_filter_percentage(const struct option *opt __maybe_unused, | 436 | int parse_filter_percentage(const struct option *opt, const char *arg, int unset); |
437 | const char *arg, int unset __maybe_unused); | ||
438 | int perf_hist_config(const char *var, const char *value); | 437 | int perf_hist_config(const char *var, const char *value); |
439 | 438 | ||
440 | void perf_hpp_list__init(struct perf_hpp_list *list); | 439 | void perf_hpp_list__init(struct perf_hpp_list *list); |
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c index eb0e7f8bf515..6bc3ecd2e7ca 100644 --- a/tools/perf/util/intel-bts.c +++ b/tools/perf/util/intel-bts.c | |||
@@ -678,7 +678,7 @@ static int intel_bts_process_auxtrace_event(struct perf_session *session, | |||
678 | return 0; | 678 | return 0; |
679 | } | 679 | } |
680 | 680 | ||
681 | static int intel_bts_flush(struct perf_session *session __maybe_unused, | 681 | static int intel_bts_flush(struct perf_session *session, |
682 | struct perf_tool *tool __maybe_unused) | 682 | struct perf_tool *tool __maybe_unused) |
683 | { | 683 | { |
684 | struct intel_bts *bts = container_of(session->auxtrace, struct intel_bts, | 684 | struct intel_bts *bts = container_of(session->auxtrace, struct intel_bts, |
diff --git a/tools/perf/util/jit.h b/tools/perf/util/jit.h index a1e99da0715a..3f42ee4d2a0b 100644 --- a/tools/perf/util/jit.h +++ b/tools/perf/util/jit.h | |||
@@ -3,13 +3,9 @@ | |||
3 | 3 | ||
4 | #include <data.h> | 4 | #include <data.h> |
5 | 5 | ||
6 | extern int jit_process(struct perf_session *session, | 6 | int jit_process(struct perf_session *session, struct perf_data_file *output, |
7 | struct perf_data_file *output, | 7 | struct machine *machine, char *filename, pid_t pid, u64 *nbytes); |
8 | struct machine *machine, | 8 | |
9 | char *filename, | 9 | int jit_inject_record(const char *filename); |
10 | pid_t pid, | ||
11 | u64 *nbytes); | ||
12 | |||
13 | extern int jit_inject_record(const char *filename); | ||
14 | 10 | ||
15 | #endif /* __JIT_H__ */ | 11 | #endif /* __JIT_H__ */ |
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c index 00724d496d38..33071d6159bc 100644 --- a/tools/perf/util/llvm-utils.c +++ b/tools/perf/util/llvm-utils.c | |||
@@ -3,11 +3,11 @@ | |||
3 | * Copyright (C) 2015, Huawei Inc. | 3 | * Copyright (C) 2015, Huawei Inc. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <limits.h> | ||
6 | #include <stdio.h> | 7 | #include <stdio.h> |
7 | #include "util.h" | 8 | #include <stdlib.h> |
8 | #include "debug.h" | 9 | #include "debug.h" |
9 | #include "llvm-utils.h" | 10 | #include "llvm-utils.h" |
10 | #include "cache.h" | ||
11 | 11 | ||
12 | #define CLANG_BPF_CMD_DEFAULT_TEMPLATE \ | 12 | #define CLANG_BPF_CMD_DEFAULT_TEMPLATE \ |
13 | "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\ | 13 | "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\ |
@@ -98,11 +98,12 @@ read_from_pipe(const char *cmd, void **p_buf, size_t *p_read_sz) | |||
98 | void *buf = NULL; | 98 | void *buf = NULL; |
99 | FILE *file = NULL; | 99 | FILE *file = NULL; |
100 | size_t read_sz = 0, buf_sz = 0; | 100 | size_t read_sz = 0, buf_sz = 0; |
101 | char serr[STRERR_BUFSIZE]; | ||
101 | 102 | ||
102 | file = popen(cmd, "r"); | 103 | file = popen(cmd, "r"); |
103 | if (!file) { | 104 | if (!file) { |
104 | pr_err("ERROR: unable to popen cmd: %s\n", | 105 | pr_err("ERROR: unable to popen cmd: %s\n", |
105 | strerror(errno)); | 106 | strerror_r(errno, serr, sizeof(serr))); |
106 | return -EINVAL; | 107 | return -EINVAL; |
107 | } | 108 | } |
108 | 109 | ||
@@ -136,7 +137,7 @@ read_from_pipe(const char *cmd, void **p_buf, size_t *p_read_sz) | |||
136 | 137 | ||
137 | if (ferror(file)) { | 138 | if (ferror(file)) { |
138 | pr_err("ERROR: error occurred when reading from pipe: %s\n", | 139 | pr_err("ERROR: error occurred when reading from pipe: %s\n", |
139 | strerror(errno)); | 140 | strerror_r(errno, serr, sizeof(serr))); |
140 | err = -EIO; | 141 | err = -EIO; |
141 | goto errout; | 142 | goto errout; |
142 | } | 143 | } |
@@ -334,10 +335,18 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, | |||
334 | unsigned int kernel_version; | 335 | unsigned int kernel_version; |
335 | char linux_version_code_str[64]; | 336 | char linux_version_code_str[64]; |
336 | const char *clang_opt = llvm_param.clang_opt; | 337 | const char *clang_opt = llvm_param.clang_opt; |
337 | char clang_path[PATH_MAX], nr_cpus_avail_str[64]; | 338 | char clang_path[PATH_MAX], abspath[PATH_MAX], nr_cpus_avail_str[64]; |
339 | char serr[STRERR_BUFSIZE]; | ||
338 | char *kbuild_dir = NULL, *kbuild_include_opts = NULL; | 340 | char *kbuild_dir = NULL, *kbuild_include_opts = NULL; |
339 | const char *template = llvm_param.clang_bpf_cmd_template; | 341 | const char *template = llvm_param.clang_bpf_cmd_template; |
340 | 342 | ||
343 | if (path[0] != '-' && realpath(path, abspath) == NULL) { | ||
344 | err = errno; | ||
345 | pr_err("ERROR: problems with path %s: %s\n", | ||
346 | path, strerror_r(err, serr, sizeof(serr))); | ||
347 | return -err; | ||
348 | } | ||
349 | |||
341 | if (!template) | 350 | if (!template) |
342 | template = CLANG_BPF_CMD_DEFAULT_TEMPLATE; | 351 | template = CLANG_BPF_CMD_DEFAULT_TEMPLATE; |
343 | 352 | ||
@@ -362,7 +371,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, | |||
362 | if (nr_cpus_avail <= 0) { | 371 | if (nr_cpus_avail <= 0) { |
363 | pr_err( | 372 | pr_err( |
364 | "WARNING:\tunable to get available CPUs in this system: %s\n" | 373 | "WARNING:\tunable to get available CPUs in this system: %s\n" |
365 | " \tUse 128 instead.\n", strerror(errno)); | 374 | " \tUse 128 instead.\n", strerror_r(errno, serr, sizeof(serr))); |
366 | nr_cpus_avail = 128; | 375 | nr_cpus_avail = 128; |
367 | } | 376 | } |
368 | snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d", | 377 | snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d", |
@@ -387,8 +396,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, | |||
387 | * stdin to be source file (testing). | 396 | * stdin to be source file (testing). |
388 | */ | 397 | */ |
389 | force_set_env("CLANG_SOURCE", | 398 | force_set_env("CLANG_SOURCE", |
390 | (path[0] == '-') ? path : | 399 | (path[0] == '-') ? path : abspath); |
391 | make_nonrelative_path(path)); | ||
392 | 400 | ||
393 | pr_debug("llvm compiling command template: %s\n", template); | 401 | pr_debug("llvm compiling command template: %s\n", template); |
394 | err = read_from_pipe(template, &obj_buf, &obj_buf_sz); | 402 | err = read_from_pipe(template, &obj_buf, &obj_buf_sz); |
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h index 5b3cf1c229e2..23b9a743fe72 100644 --- a/tools/perf/util/llvm-utils.h +++ b/tools/perf/util/llvm-utils.h | |||
@@ -39,11 +39,10 @@ struct llvm_param { | |||
39 | }; | 39 | }; |
40 | 40 | ||
41 | extern struct llvm_param llvm_param; | 41 | extern struct llvm_param llvm_param; |
42 | extern int perf_llvm_config(const char *var, const char *value); | 42 | int perf_llvm_config(const char *var, const char *value); |
43 | 43 | ||
44 | extern int llvm__compile_bpf(const char *path, void **p_obj_buf, | 44 | int llvm__compile_bpf(const char *path, void **p_obj_buf, size_t *p_obj_buf_sz); |
45 | size_t *p_obj_buf_sz); | ||
46 | 45 | ||
47 | /* This function is for test__llvm() use only */ | 46 | /* This function is for test__llvm() use only */ |
48 | extern int llvm__search_clang(void); | 47 | int llvm__search_clang(void); |
49 | #endif | 48 | #endif |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index ad79297c76c8..80b9b6a87990 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -1301,9 +1301,8 @@ out_problem: | |||
1301 | 1301 | ||
1302 | int machine__process_mmap2_event(struct machine *machine, | 1302 | int machine__process_mmap2_event(struct machine *machine, |
1303 | union perf_event *event, | 1303 | union perf_event *event, |
1304 | struct perf_sample *sample __maybe_unused) | 1304 | struct perf_sample *sample) |
1305 | { | 1305 | { |
1306 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
1307 | struct thread *thread; | 1306 | struct thread *thread; |
1308 | struct map *map; | 1307 | struct map *map; |
1309 | enum map_type type; | 1308 | enum map_type type; |
@@ -1312,8 +1311,8 @@ int machine__process_mmap2_event(struct machine *machine, | |||
1312 | if (dump_trace) | 1311 | if (dump_trace) |
1313 | perf_event__fprintf_mmap2(event, stdout); | 1312 | perf_event__fprintf_mmap2(event, stdout); |
1314 | 1313 | ||
1315 | if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || | 1314 | if (sample->cpumode == PERF_RECORD_MISC_GUEST_KERNEL || |
1316 | cpumode == PERF_RECORD_MISC_KERNEL) { | 1315 | sample->cpumode == PERF_RECORD_MISC_KERNEL) { |
1317 | ret = machine__process_kernel_mmap_event(machine, event); | 1316 | ret = machine__process_kernel_mmap_event(machine, event); |
1318 | if (ret < 0) | 1317 | if (ret < 0) |
1319 | goto out_problem; | 1318 | goto out_problem; |
@@ -1355,9 +1354,8 @@ out_problem: | |||
1355 | } | 1354 | } |
1356 | 1355 | ||
1357 | int machine__process_mmap_event(struct machine *machine, union perf_event *event, | 1356 | int machine__process_mmap_event(struct machine *machine, union perf_event *event, |
1358 | struct perf_sample *sample __maybe_unused) | 1357 | struct perf_sample *sample) |
1359 | { | 1358 | { |
1360 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
1361 | struct thread *thread; | 1359 | struct thread *thread; |
1362 | struct map *map; | 1360 | struct map *map; |
1363 | enum map_type type; | 1361 | enum map_type type; |
@@ -1366,8 +1364,8 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event | |||
1366 | if (dump_trace) | 1364 | if (dump_trace) |
1367 | perf_event__fprintf_mmap(event, stdout); | 1365 | perf_event__fprintf_mmap(event, stdout); |
1368 | 1366 | ||
1369 | if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || | 1367 | if (sample->cpumode == PERF_RECORD_MISC_GUEST_KERNEL || |
1370 | cpumode == PERF_RECORD_MISC_KERNEL) { | 1368 | sample->cpumode == PERF_RECORD_MISC_KERNEL) { |
1371 | ret = machine__process_kernel_mmap_event(machine, event); | 1369 | ret = machine__process_kernel_mmap_event(machine, event); |
1372 | if (ret < 0) | 1370 | if (ret < 0) |
1373 | goto out_problem; | 1371 | goto out_problem; |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 1a3e45baf97f..8499db281158 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
@@ -94,7 +94,7 @@ int machine__process_aux_event(struct machine *machine, | |||
94 | union perf_event *event); | 94 | union perf_event *event); |
95 | int machine__process_itrace_start_event(struct machine *machine, | 95 | int machine__process_itrace_start_event(struct machine *machine, |
96 | union perf_event *event); | 96 | union perf_event *event); |
97 | int machine__process_switch_event(struct machine *machine __maybe_unused, | 97 | int machine__process_switch_event(struct machine *machine, |
98 | union perf_event *event); | 98 | union perf_event *event); |
99 | int machine__process_mmap_event(struct machine *machine, union perf_event *event, | 99 | int machine__process_mmap_event(struct machine *machine, union perf_event *event, |
100 | struct perf_sample *sample); | 100 | struct perf_sample *sample); |
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 67e493088e81..d740c3ca9a1d 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
@@ -22,19 +22,18 @@ struct tracepoint_path { | |||
22 | struct tracepoint_path *next; | 22 | struct tracepoint_path *next; |
23 | }; | 23 | }; |
24 | 24 | ||
25 | extern struct tracepoint_path *tracepoint_id_to_path(u64 config); | 25 | struct tracepoint_path *tracepoint_id_to_path(u64 config); |
26 | extern struct tracepoint_path *tracepoint_name_to_path(const char *name); | 26 | struct tracepoint_path *tracepoint_name_to_path(const char *name); |
27 | extern bool have_tracepoints(struct list_head *evlist); | 27 | bool have_tracepoints(struct list_head *evlist); |
28 | 28 | ||
29 | const char *event_type(int type); | 29 | const char *event_type(int type); |
30 | 30 | ||
31 | extern int parse_events_option(const struct option *opt, const char *str, | 31 | int parse_events_option(const struct option *opt, const char *str, int unset); |
32 | int unset); | 32 | int parse_events(struct perf_evlist *evlist, const char *str, |
33 | extern int parse_events(struct perf_evlist *evlist, const char *str, | 33 | struct parse_events_error *error); |
34 | struct parse_events_error *error); | 34 | int parse_events_terms(struct list_head *terms, const char *str); |
35 | extern int parse_events_terms(struct list_head *terms, const char *str); | 35 | int parse_filter(const struct option *opt, const char *str, int unset); |
36 | extern int parse_filter(const struct option *opt, const char *str, int unset); | 36 | int exclude_perf(const struct option *opt, const char *arg, int unset); |
37 | extern int exclude_perf(const struct option *opt, const char *arg, int unset); | ||
38 | 37 | ||
39 | #define EVENTS_HELP_MAX (128*1024) | 38 | #define EVENTS_HELP_MAX (128*1024) |
40 | 39 | ||
@@ -183,7 +182,7 @@ void print_symbol_events(const char *event_glob, unsigned type, | |||
183 | void print_tracepoint_events(const char *subsys_glob, const char *event_glob, | 182 | void print_tracepoint_events(const char *subsys_glob, const char *event_glob, |
184 | bool name_only); | 183 | bool name_only); |
185 | int print_hwcache_events(const char *event_glob, bool name_only); | 184 | int print_hwcache_events(const char *event_glob, bool name_only); |
186 | extern int is_valid_tracepoint(const char *event_string); | 185 | int is_valid_tracepoint(const char *event_string); |
187 | 186 | ||
188 | int valid_event_mount(const char *eventfs); | 187 | int valid_event_mount(const char *eventfs); |
189 | char *parse_events_formats_error_string(char *additional_terms); | 188 | char *parse_events_formats_error_string(char *additional_terms); |
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c index 3654d964e49d..3bf6bf82ff2d 100644 --- a/tools/perf/util/path.c +++ b/tools/perf/util/path.c | |||
@@ -41,36 +41,6 @@ static char *cleanup_path(char *path) | |||
41 | return path; | 41 | return path; |
42 | } | 42 | } |
43 | 43 | ||
44 | static char *perf_vsnpath(char *buf, size_t n, const char *fmt, va_list args) | ||
45 | { | ||
46 | const char *perf_dir = get_perf_dir(); | ||
47 | size_t len; | ||
48 | |||
49 | len = strlen(perf_dir); | ||
50 | if (n < len + 1) | ||
51 | goto bad; | ||
52 | memcpy(buf, perf_dir, len); | ||
53 | if (len && !is_dir_sep(perf_dir[len-1])) | ||
54 | buf[len++] = '/'; | ||
55 | len += vsnprintf(buf + len, n - len, fmt, args); | ||
56 | if (len >= n) | ||
57 | goto bad; | ||
58 | return cleanup_path(buf); | ||
59 | bad: | ||
60 | strlcpy(buf, bad_path, n); | ||
61 | return buf; | ||
62 | } | ||
63 | |||
64 | char *perf_pathdup(const char *fmt, ...) | ||
65 | { | ||
66 | char path[PATH_MAX]; | ||
67 | va_list args; | ||
68 | va_start(args, fmt); | ||
69 | (void)perf_vsnpath(path, sizeof(path), fmt, args); | ||
70 | va_end(args); | ||
71 | return xstrdup(path); | ||
72 | } | ||
73 | |||
74 | char *mkpath(const char *fmt, ...) | 44 | char *mkpath(const char *fmt, ...) |
75 | { | 45 | { |
76 | va_list args; | 46 | va_list args; |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 93996ec4bbe3..8319fbb08636 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -2179,7 +2179,7 @@ static int perf_probe_event__sprintf(const char *group, const char *event, | |||
2179 | strbuf_addf(result, " in %s", module); | 2179 | strbuf_addf(result, " in %s", module); |
2180 | 2180 | ||
2181 | if (pev->nargs > 0) { | 2181 | if (pev->nargs > 0) { |
2182 | strbuf_addstr(result, " with"); | 2182 | strbuf_add(result, " with", 5); |
2183 | for (i = 0; i < pev->nargs; i++) { | 2183 | for (i = 0; i < pev->nargs; i++) { |
2184 | ret = synthesize_perf_probe_arg(&pev->args[i], | 2184 | ret = synthesize_perf_probe_arg(&pev->args[i], |
2185 | buf, 128); | 2185 | buf, 128); |
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index ba926c30f8cd..e54e7b011577 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
@@ -114,49 +114,44 @@ int init_probe_symbol_maps(bool user_only); | |||
114 | void exit_probe_symbol_maps(void); | 114 | void exit_probe_symbol_maps(void); |
115 | 115 | ||
116 | /* Command string to events */ | 116 | /* Command string to events */ |
117 | extern int parse_perf_probe_command(const char *cmd, | 117 | int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev); |
118 | struct perf_probe_event *pev); | 118 | int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev); |
119 | extern int parse_probe_trace_command(const char *cmd, | ||
120 | struct probe_trace_event *tev); | ||
121 | 119 | ||
122 | /* Events to command string */ | 120 | /* Events to command string */ |
123 | extern char *synthesize_perf_probe_command(struct perf_probe_event *pev); | 121 | char *synthesize_perf_probe_command(struct perf_probe_event *pev); |
124 | extern char *synthesize_probe_trace_command(struct probe_trace_event *tev); | 122 | char *synthesize_probe_trace_command(struct probe_trace_event *tev); |
125 | extern int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, | 123 | int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len); |
126 | size_t len); | ||
127 | 124 | ||
128 | /* Check the perf_probe_event needs debuginfo */ | 125 | /* Check the perf_probe_event needs debuginfo */ |
129 | extern bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); | 126 | bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); |
130 | 127 | ||
131 | /* Release event contents */ | 128 | /* Release event contents */ |
132 | extern void clear_perf_probe_event(struct perf_probe_event *pev); | 129 | void clear_perf_probe_event(struct perf_probe_event *pev); |
133 | extern void clear_probe_trace_event(struct probe_trace_event *tev); | 130 | void clear_probe_trace_event(struct probe_trace_event *tev); |
134 | 131 | ||
135 | /* Command string to line-range */ | 132 | /* Command string to line-range */ |
136 | extern int parse_line_range_desc(const char *cmd, struct line_range *lr); | 133 | int parse_line_range_desc(const char *cmd, struct line_range *lr); |
137 | 134 | ||
138 | /* Release line range members */ | 135 | /* Release line range members */ |
139 | extern void line_range__clear(struct line_range *lr); | 136 | void line_range__clear(struct line_range *lr); |
140 | 137 | ||
141 | /* Initialize line range */ | 138 | /* Initialize line range */ |
142 | extern int line_range__init(struct line_range *lr); | 139 | int line_range__init(struct line_range *lr); |
143 | 140 | ||
144 | extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs); | 141 | int add_perf_probe_events(struct perf_probe_event *pevs, int npevs); |
145 | extern int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs); | 142 | int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs); |
146 | extern int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs); | 143 | int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs); |
147 | extern void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs); | 144 | void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs); |
148 | extern int del_perf_probe_events(struct strfilter *filter); | 145 | int del_perf_probe_events(struct strfilter *filter); |
149 | 146 | ||
150 | extern int show_perf_probe_event(const char *group, const char *event, | 147 | int show_perf_probe_event(const char *group, const char *event, |
151 | struct perf_probe_event *pev, | 148 | struct perf_probe_event *pev, |
152 | const char *module, bool use_stdout); | 149 | const char *module, bool use_stdout); |
153 | extern int show_perf_probe_events(struct strfilter *filter); | 150 | int show_perf_probe_events(struct strfilter *filter); |
154 | extern int show_line_range(struct line_range *lr, const char *module, | 151 | int show_line_range(struct line_range *lr, const char *module, bool user); |
155 | bool user); | 152 | int show_available_vars(struct perf_probe_event *pevs, int npevs, |
156 | extern int show_available_vars(struct perf_probe_event *pevs, int npevs, | 153 | struct strfilter *filter); |
157 | struct strfilter *filter); | 154 | int show_available_funcs(const char *module, struct strfilter *filter, bool user); |
158 | extern int show_available_funcs(const char *module, struct strfilter *filter, | ||
159 | bool user); | ||
160 | bool arch__prefers_symtab(void); | 155 | bool arch__prefers_symtab(void); |
161 | void arch__fix_tev_from_maps(struct perf_probe_event *pev, | 156 | void arch__fix_tev_from_maps(struct perf_probe_event *pev, |
162 | struct probe_trace_event *tev, struct map *map); | 157 | struct probe_trace_event *tev, struct map *map); |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 4ce5c5e18f48..b3bd0fba0237 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -1314,18 +1314,18 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data) | |||
1314 | if (probe_conf.show_location_range) { | 1314 | if (probe_conf.show_location_range) { |
1315 | if (!externs) { | 1315 | if (!externs) { |
1316 | if (ret) | 1316 | if (ret) |
1317 | strbuf_addf(&buf, "[INV]\t"); | 1317 | strbuf_add(&buf, "[INV]\t", 6); |
1318 | else | 1318 | else |
1319 | strbuf_addf(&buf, "[VAL]\t"); | 1319 | strbuf_add(&buf, "[VAL]\t", 6); |
1320 | } else | 1320 | } else |
1321 | strbuf_addf(&buf, "[EXT]\t"); | 1321 | strbuf_add(&buf, "[EXT]\t", 6); |
1322 | } | 1322 | } |
1323 | 1323 | ||
1324 | ret2 = die_get_varname(die_mem, &buf); | 1324 | ret2 = die_get_varname(die_mem, &buf); |
1325 | 1325 | ||
1326 | if (!ret2 && probe_conf.show_location_range && | 1326 | if (!ret2 && probe_conf.show_location_range && |
1327 | !externs) { | 1327 | !externs) { |
1328 | strbuf_addf(&buf, "\t"); | 1328 | strbuf_addch(&buf, '\t'); |
1329 | ret2 = die_get_var_range(&af->pf.sp_die, | 1329 | ret2 = die_get_var_range(&af->pf.sp_die, |
1330 | die_mem, &buf); | 1330 | die_mem, &buf); |
1331 | } | 1331 | } |
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 0aec7704e395..51137fccb9c8 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h | |||
@@ -34,27 +34,25 @@ struct debuginfo { | |||
34 | }; | 34 | }; |
35 | 35 | ||
36 | /* This also tries to open distro debuginfo */ | 36 | /* This also tries to open distro debuginfo */ |
37 | extern struct debuginfo *debuginfo__new(const char *path); | 37 | struct debuginfo *debuginfo__new(const char *path); |
38 | extern void debuginfo__delete(struct debuginfo *dbg); | 38 | void debuginfo__delete(struct debuginfo *dbg); |
39 | 39 | ||
40 | /* Find probe_trace_events specified by perf_probe_event from debuginfo */ | 40 | /* Find probe_trace_events specified by perf_probe_event from debuginfo */ |
41 | extern int debuginfo__find_trace_events(struct debuginfo *dbg, | 41 | int debuginfo__find_trace_events(struct debuginfo *dbg, |
42 | struct perf_probe_event *pev, | 42 | struct perf_probe_event *pev, |
43 | struct probe_trace_event **tevs); | 43 | struct probe_trace_event **tevs); |
44 | 44 | ||
45 | /* Find a perf_probe_point from debuginfo */ | 45 | /* Find a perf_probe_point from debuginfo */ |
46 | extern int debuginfo__find_probe_point(struct debuginfo *dbg, | 46 | int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, |
47 | unsigned long addr, | 47 | struct perf_probe_point *ppt); |
48 | struct perf_probe_point *ppt); | ||
49 | 48 | ||
50 | /* Find a line range */ | 49 | /* Find a line range */ |
51 | extern int debuginfo__find_line_range(struct debuginfo *dbg, | 50 | int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr); |
52 | struct line_range *lr); | ||
53 | 51 | ||
54 | /* Find available variables */ | 52 | /* Find available variables */ |
55 | extern int debuginfo__find_available_vars_at(struct debuginfo *dbg, | 53 | int debuginfo__find_available_vars_at(struct debuginfo *dbg, |
56 | struct perf_probe_event *pev, | 54 | struct perf_probe_event *pev, |
57 | struct variable_list **vls); | 55 | struct variable_list **vls); |
58 | 56 | ||
59 | /* Find a src file from a DWARF tag path */ | 57 | /* Find a src file from a DWARF tag path */ |
60 | int get_real_path(const char *raw_path, const char *comp_dir, | 58 | int get_real_path(const char *raw_path, const char *comp_dir, |
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h index 172889ea234f..3340c9c4a6ca 100644 --- a/tools/perf/util/quote.h +++ b/tools/perf/util/quote.h | |||
@@ -24,6 +24,6 @@ | |||
24 | * sq_quote() in a real application. | 24 | * sq_quote() in a real application. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | extern void sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen); | 27 | void sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen); |
28 | 28 | ||
29 | #endif /* __PERF_QUOTE_H */ | 29 | #endif /* __PERF_QUOTE_H */ |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 60b3593d210d..4abd85c6346d 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -1107,12 +1107,11 @@ static struct machine *machines__find_for_cpumode(struct machines *machines, | |||
1107 | union perf_event *event, | 1107 | union perf_event *event, |
1108 | struct perf_sample *sample) | 1108 | struct perf_sample *sample) |
1109 | { | 1109 | { |
1110 | const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
1111 | struct machine *machine; | 1110 | struct machine *machine; |
1112 | 1111 | ||
1113 | if (perf_guest && | 1112 | if (perf_guest && |
1114 | ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) || | 1113 | ((sample->cpumode == PERF_RECORD_MISC_GUEST_KERNEL) || |
1115 | (cpumode == PERF_RECORD_MISC_GUEST_USER))) { | 1114 | (sample->cpumode == PERF_RECORD_MISC_GUEST_USER))) { |
1116 | u32 pid; | 1115 | u32 pid; |
1117 | 1116 | ||
1118 | if (event->header.type == PERF_RECORD_MMAP | 1117 | if (event->header.type == PERF_RECORD_MMAP |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 93fa136b0025..47966a1618c7 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -2225,7 +2225,7 @@ int hpp_dimension__add_output(unsigned col) | |||
2225 | } | 2225 | } |
2226 | 2226 | ||
2227 | static int sort_dimension__add(struct perf_hpp_list *list, const char *tok, | 2227 | static int sort_dimension__add(struct perf_hpp_list *list, const char *tok, |
2228 | struct perf_evlist *evlist __maybe_unused, | 2228 | struct perf_evlist *evlist, |
2229 | int level) | 2229 | int level) |
2230 | { | 2230 | { |
2231 | unsigned int i; | 2231 | unsigned int i; |
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c index b33ffb2af2cf..fdb71961143e 100644 --- a/tools/perf/util/stat-shadow.c +++ b/tools/perf/util/stat-shadow.c | |||
@@ -152,8 +152,7 @@ static const char *get_ratio_color(enum grc_type type, double ratio) | |||
152 | } | 152 | } |
153 | 153 | ||
154 | static void print_stalled_cycles_frontend(int cpu, | 154 | static void print_stalled_cycles_frontend(int cpu, |
155 | struct perf_evsel *evsel | 155 | struct perf_evsel *evsel, double avg, |
156 | __maybe_unused, double avg, | ||
157 | struct perf_stat_output_ctx *out) | 156 | struct perf_stat_output_ctx *out) |
158 | { | 157 | { |
159 | double total, ratio = 0.0; | 158 | double total, ratio = 0.0; |
@@ -175,8 +174,7 @@ static void print_stalled_cycles_frontend(int cpu, | |||
175 | } | 174 | } |
176 | 175 | ||
177 | static void print_stalled_cycles_backend(int cpu, | 176 | static void print_stalled_cycles_backend(int cpu, |
178 | struct perf_evsel *evsel | 177 | struct perf_evsel *evsel, double avg, |
179 | __maybe_unused, double avg, | ||
180 | struct perf_stat_output_ctx *out) | 178 | struct perf_stat_output_ctx *out) |
181 | { | 179 | { |
182 | double total, ratio = 0.0; | 180 | double total, ratio = 0.0; |
@@ -194,7 +192,7 @@ static void print_stalled_cycles_backend(int cpu, | |||
194 | } | 192 | } |
195 | 193 | ||
196 | static void print_branch_misses(int cpu, | 194 | static void print_branch_misses(int cpu, |
197 | struct perf_evsel *evsel __maybe_unused, | 195 | struct perf_evsel *evsel, |
198 | double avg, | 196 | double avg, |
199 | struct perf_stat_output_ctx *out) | 197 | struct perf_stat_output_ctx *out) |
200 | { | 198 | { |
@@ -213,7 +211,7 @@ static void print_branch_misses(int cpu, | |||
213 | } | 211 | } |
214 | 212 | ||
215 | static void print_l1_dcache_misses(int cpu, | 213 | static void print_l1_dcache_misses(int cpu, |
216 | struct perf_evsel *evsel __maybe_unused, | 214 | struct perf_evsel *evsel, |
217 | double avg, | 215 | double avg, |
218 | struct perf_stat_output_ctx *out) | 216 | struct perf_stat_output_ctx *out) |
219 | { | 217 | { |
@@ -232,7 +230,7 @@ static void print_l1_dcache_misses(int cpu, | |||
232 | } | 230 | } |
233 | 231 | ||
234 | static void print_l1_icache_misses(int cpu, | 232 | static void print_l1_icache_misses(int cpu, |
235 | struct perf_evsel *evsel __maybe_unused, | 233 | struct perf_evsel *evsel, |
236 | double avg, | 234 | double avg, |
237 | struct perf_stat_output_ctx *out) | 235 | struct perf_stat_output_ctx *out) |
238 | { | 236 | { |
@@ -250,7 +248,7 @@ static void print_l1_icache_misses(int cpu, | |||
250 | } | 248 | } |
251 | 249 | ||
252 | static void print_dtlb_cache_misses(int cpu, | 250 | static void print_dtlb_cache_misses(int cpu, |
253 | struct perf_evsel *evsel __maybe_unused, | 251 | struct perf_evsel *evsel, |
254 | double avg, | 252 | double avg, |
255 | struct perf_stat_output_ctx *out) | 253 | struct perf_stat_output_ctx *out) |
256 | { | 254 | { |
@@ -268,7 +266,7 @@ static void print_dtlb_cache_misses(int cpu, | |||
268 | } | 266 | } |
269 | 267 | ||
270 | static void print_itlb_cache_misses(int cpu, | 268 | static void print_itlb_cache_misses(int cpu, |
271 | struct perf_evsel *evsel __maybe_unused, | 269 | struct perf_evsel *evsel, |
272 | double avg, | 270 | double avg, |
273 | struct perf_stat_output_ctx *out) | 271 | struct perf_stat_output_ctx *out) |
274 | { | 272 | { |
@@ -286,7 +284,7 @@ static void print_itlb_cache_misses(int cpu, | |||
286 | } | 284 | } |
287 | 285 | ||
288 | static void print_ll_cache_misses(int cpu, | 286 | static void print_ll_cache_misses(int cpu, |
289 | struct perf_evsel *evsel __maybe_unused, | 287 | struct perf_evsel *evsel, |
290 | double avg, | 288 | double avg, |
291 | struct perf_stat_output_ctx *out) | 289 | struct perf_stat_output_ctx *out) |
292 | { | 290 | { |
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c index d3d279275432..8fb73295ec34 100644 --- a/tools/perf/util/strbuf.c +++ b/tools/perf/util/strbuf.c | |||
@@ -51,6 +51,13 @@ void strbuf_grow(struct strbuf *sb, size_t extra) | |||
51 | ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); | 51 | ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc); |
52 | } | 52 | } |
53 | 53 | ||
54 | void strbuf_addch(struct strbuf *sb, int c) | ||
55 | { | ||
56 | strbuf_grow(sb, 1); | ||
57 | sb->buf[sb->len++] = c; | ||
58 | sb->buf[sb->len] = '\0'; | ||
59 | } | ||
60 | |||
54 | void strbuf_add(struct strbuf *sb, const void *data, size_t len) | 61 | void strbuf_add(struct strbuf *sb, const void *data, size_t len) |
55 | { | 62 | { |
56 | strbuf_grow(sb, len); | 63 | strbuf_grow(sb, len); |
@@ -58,7 +65,7 @@ void strbuf_add(struct strbuf *sb, const void *data, size_t len) | |||
58 | strbuf_setlen(sb, sb->len + len); | 65 | strbuf_setlen(sb, sb->len + len); |
59 | } | 66 | } |
60 | 67 | ||
61 | void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) | 68 | static void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) |
62 | { | 69 | { |
63 | int len; | 70 | int len; |
64 | va_list ap_saved; | 71 | va_list ap_saved; |
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h index 7a32c838884d..ab9be0fbbd40 100644 --- a/tools/perf/util/strbuf.h +++ b/tools/perf/util/strbuf.h | |||
@@ -51,16 +51,16 @@ struct strbuf { | |||
51 | #define STRBUF_INIT { 0, 0, strbuf_slopbuf } | 51 | #define STRBUF_INIT { 0, 0, strbuf_slopbuf } |
52 | 52 | ||
53 | /*----- strbuf life cycle -----*/ | 53 | /*----- strbuf life cycle -----*/ |
54 | extern void strbuf_init(struct strbuf *buf, ssize_t hint); | 54 | void strbuf_init(struct strbuf *buf, ssize_t hint); |
55 | extern void strbuf_release(struct strbuf *); | 55 | void strbuf_release(struct strbuf *buf); |
56 | extern char *strbuf_detach(struct strbuf *, size_t *); | 56 | char *strbuf_detach(struct strbuf *buf, size_t *); |
57 | 57 | ||
58 | /*----- strbuf size related -----*/ | 58 | /*----- strbuf size related -----*/ |
59 | static inline ssize_t strbuf_avail(const struct strbuf *sb) { | 59 | static inline ssize_t strbuf_avail(const struct strbuf *sb) { |
60 | return sb->alloc ? sb->alloc - sb->len - 1 : 0; | 60 | return sb->alloc ? sb->alloc - sb->len - 1 : 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | extern void strbuf_grow(struct strbuf *, size_t); | 63 | void strbuf_grow(struct strbuf *buf, size_t); |
64 | 64 | ||
65 | static inline void strbuf_setlen(struct strbuf *sb, size_t len) { | 65 | static inline void strbuf_setlen(struct strbuf *sb, size_t len) { |
66 | if (!sb->alloc) | 66 | if (!sb->alloc) |
@@ -71,22 +71,17 @@ static inline void strbuf_setlen(struct strbuf *sb, size_t len) { | |||
71 | } | 71 | } |
72 | 72 | ||
73 | /*----- add data in your buffer -----*/ | 73 | /*----- add data in your buffer -----*/ |
74 | static inline void strbuf_addch(struct strbuf *sb, int c) { | 74 | void strbuf_addch(struct strbuf *sb, int c); |
75 | strbuf_grow(sb, 1); | ||
76 | sb->buf[sb->len++] = c; | ||
77 | sb->buf[sb->len] = '\0'; | ||
78 | } | ||
79 | 75 | ||
80 | extern void strbuf_add(struct strbuf *, const void *, size_t); | 76 | void strbuf_add(struct strbuf *buf, const void *, size_t); |
81 | static inline void strbuf_addstr(struct strbuf *sb, const char *s) { | 77 | static inline void strbuf_addstr(struct strbuf *sb, const char *s) { |
82 | strbuf_add(sb, s, strlen(s)); | 78 | strbuf_add(sb, s, strlen(s)); |
83 | } | 79 | } |
84 | 80 | ||
85 | __attribute__((format(printf,2,3))) | 81 | __attribute__((format(printf,2,3))) |
86 | extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...); | 82 | void strbuf_addf(struct strbuf *sb, const char *fmt, ...); |
87 | extern void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap); | ||
88 | 83 | ||
89 | /* XXX: if read fails, any partial read is undone */ | 84 | /* XXX: if read fails, any partial read is undone */ |
90 | extern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); | 85 | ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); |
91 | 86 | ||
92 | #endif /* __PERF_STRBUF_H */ | 87 | #endif /* __PERF_STRBUF_H */ |
diff --git a/tools/perf/util/svghelper.h b/tools/perf/util/svghelper.h index 9292a5291445..946fdf2db97c 100644 --- a/tools/perf/util/svghelper.h +++ b/tools/perf/util/svghelper.h | |||
@@ -3,32 +3,31 @@ | |||
3 | 3 | ||
4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
5 | 5 | ||
6 | extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end); | 6 | void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end); |
7 | extern void svg_ubox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges); | 7 | void svg_ubox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges); |
8 | extern void svg_lbox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges); | 8 | void svg_lbox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges); |
9 | extern void svg_fbox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges); | 9 | void svg_fbox(int Yslot, u64 start, u64 end, double height, const char *type, int fd, int err, int merges); |
10 | extern void svg_box(int Yslot, u64 start, u64 end, const char *type); | 10 | void svg_box(int Yslot, u64 start, u64 end, const char *type); |
11 | extern void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace); | 11 | void svg_blocked(int Yslot, int cpu, u64 start, u64 end, const char *backtrace); |
12 | extern void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace); | 12 | void svg_running(int Yslot, int cpu, u64 start, u64 end, const char *backtrace); |
13 | extern void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace); | 13 | void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace); |
14 | extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); | 14 | void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); |
15 | 15 | ||
16 | 16 | ||
17 | extern void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace); | 17 | void svg_process(int cpu, u64 start, u64 end, int pid, const char *name, const char *backtrace); |
18 | extern void svg_cstate(int cpu, u64 start, u64 end, int type); | 18 | void svg_cstate(int cpu, u64 start, u64 end, int type); |
19 | extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); | 19 | void svg_pstate(int cpu, u64 start, u64 end, u64 freq); |
20 | 20 | ||
21 | 21 | ||
22 | extern void svg_time_grid(double min_thickness); | 22 | void svg_time_grid(double min_thickness); |
23 | extern void svg_io_legenda(void); | 23 | void svg_io_legenda(void); |
24 | extern void svg_legenda(void); | 24 | void svg_legenda(void); |
25 | extern void svg_wakeline(u64 start, int row1, int row2, const char *backtrace); | 25 | void svg_wakeline(u64 start, int row1, int row2, const char *backtrace); |
26 | extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace); | 26 | void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2, const char *backtrace); |
27 | extern void svg_interrupt(u64 start, int row, const char *backtrace); | 27 | void svg_interrupt(u64 start, int row, const char *backtrace); |
28 | extern void svg_text(int Yslot, u64 start, const char *text); | 28 | void svg_text(int Yslot, u64 start, const char *text); |
29 | extern void svg_close(void); | 29 | void svg_close(void); |
30 | extern int svg_build_topology_map(char *sib_core, int sib_core_nr, | 30 | int svg_build_topology_map(char *sib_core, int sib_core_nr, char *sib_thr, int sib_thr_nr); |
31 | char *sib_thr, int sib_thr_nr); | ||
32 | 31 | ||
33 | extern int svg_page_width; | 32 | extern int svg_page_width; |
34 | extern u64 svg_highlight; | 33 | extern u64 svg_highlight; |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index b1dd68f358fc..bc229a74c6a9 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -793,6 +793,7 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
793 | uint32_t idx; | 793 | uint32_t idx; |
794 | GElf_Ehdr ehdr; | 794 | GElf_Ehdr ehdr; |
795 | GElf_Shdr shdr; | 795 | GElf_Shdr shdr; |
796 | GElf_Shdr tshdr; | ||
796 | Elf_Data *syms, *opddata = NULL; | 797 | Elf_Data *syms, *opddata = NULL; |
797 | GElf_Sym sym; | 798 | GElf_Sym sym; |
798 | Elf_Scn *sec, *sec_strndx; | 799 | Elf_Scn *sec, *sec_strndx; |
@@ -832,6 +833,9 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
832 | sec = syms_ss->symtab; | 833 | sec = syms_ss->symtab; |
833 | shdr = syms_ss->symshdr; | 834 | shdr = syms_ss->symshdr; |
834 | 835 | ||
836 | if (elf_section_by_name(elf, &ehdr, &tshdr, ".text", NULL)) | ||
837 | dso->text_offset = tshdr.sh_addr - tshdr.sh_offset; | ||
838 | |||
835 | if (runtime_ss->opdsec) | 839 | if (runtime_ss->opdsec) |
836 | opddata = elf_rawdata(runtime_ss->opdsec, NULL); | 840 | opddata = elf_rawdata(runtime_ss->opdsec, NULL); |
837 | 841 | ||
@@ -880,12 +884,8 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
880 | * Handle any relocation of vdso necessary because older kernels | 884 | * Handle any relocation of vdso necessary because older kernels |
881 | * attempted to prelink vdso to its virtual address. | 885 | * attempted to prelink vdso to its virtual address. |
882 | */ | 886 | */ |
883 | if (dso__is_vdso(dso)) { | 887 | if (dso__is_vdso(dso)) |
884 | GElf_Shdr tshdr; | 888 | map->reloc = map->start - dso->text_offset; |
885 | |||
886 | if (elf_section_by_name(elf, &ehdr, &tshdr, ".text", NULL)) | ||
887 | map->reloc = map->start - tshdr.sh_addr + tshdr.sh_offset; | ||
888 | } | ||
889 | 889 | ||
890 | dso->adjust_symbols = runtime_ss->adjust_symbols || ref_reloc(kmap); | 890 | dso->adjust_symbols = runtime_ss->adjust_symbols || ref_reloc(kmap); |
891 | /* | 891 | /* |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index a937053a0ae0..c8b7544d9267 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -34,8 +34,8 @@ | |||
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | #ifdef HAVE_LIBELF_SUPPORT | 36 | #ifdef HAVE_LIBELF_SUPPORT |
37 | extern Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, | 37 | Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep, |
38 | GElf_Shdr *shp, const char *name, size_t *idx); | 38 | GElf_Shdr *shp, const char *name, size_t *idx); |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | #ifndef DMGL_PARAMS | 41 | #ifndef DMGL_PARAMS |
diff --git a/tools/perf/util/usage.c b/tools/perf/util/usage.c index 6adfa18cdd4e..996046a66fe5 100644 --- a/tools/perf/util/usage.c +++ b/tools/perf/util/usage.c | |||
@@ -41,15 +41,9 @@ static void warn_builtin(const char *warn, va_list params) | |||
41 | /* If we are in a dlopen()ed .so write to a global variable would segfault | 41 | /* If we are in a dlopen()ed .so write to a global variable would segfault |
42 | * (ugh), so keep things static. */ | 42 | * (ugh), so keep things static. */ |
43 | static void (*usage_routine)(const char *err) NORETURN = usage_builtin; | 43 | static void (*usage_routine)(const char *err) NORETURN = usage_builtin; |
44 | static void (*die_routine)(const char *err, va_list params) NORETURN = die_builtin; | ||
45 | static void (*error_routine)(const char *err, va_list params) = error_builtin; | 44 | static void (*error_routine)(const char *err, va_list params) = error_builtin; |
46 | static void (*warn_routine)(const char *err, va_list params) = warn_builtin; | 45 | static void (*warn_routine)(const char *err, va_list params) = warn_builtin; |
47 | 46 | ||
48 | void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN) | ||
49 | { | ||
50 | die_routine = routine; | ||
51 | } | ||
52 | |||
53 | void set_warning_routine(void (*routine)(const char *err, va_list params)) | 47 | void set_warning_routine(void (*routine)(const char *err, va_list params)) |
54 | { | 48 | { |
55 | warn_routine = routine; | 49 | warn_routine = routine; |
@@ -65,7 +59,7 @@ void die(const char *err, ...) | |||
65 | va_list params; | 59 | va_list params; |
66 | 60 | ||
67 | va_start(params, err); | 61 | va_start(params, err); |
68 | die_routine(err, params); | 62 | die_builtin(err, params); |
69 | va_end(params); | 63 | va_end(params); |
70 | } | 64 | } |
71 | 65 | ||
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index d0d50cef8b2a..8298d607c738 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -133,25 +133,15 @@ extern char buildid_dir[]; | |||
133 | #define PERF_GTK_DSO "libperf-gtk.so" | 133 | #define PERF_GTK_DSO "libperf-gtk.so" |
134 | 134 | ||
135 | /* General helper functions */ | 135 | /* General helper functions */ |
136 | extern void usage(const char *err) NORETURN; | 136 | void usage(const char *err) NORETURN; |
137 | extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); | 137 | void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); |
138 | extern int error(const char *err, ...) __attribute__((format (printf, 1, 2))); | 138 | int error(const char *err, ...) __attribute__((format (printf, 1, 2))); |
139 | extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); | 139 | void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); |
140 | 140 | ||
141 | #include "../../../include/linux/stringify.h" | 141 | void set_warning_routine(void (*routine)(const char *err, va_list params)); |
142 | 142 | ||
143 | #define DIE_IF(cnd) \ | 143 | int prefixcmp(const char *str, const char *prefix); |
144 | do { if (cnd) \ | 144 | void set_buildid_dir(const char *dir); |
145 | die(" at (" __FILE__ ":" __stringify(__LINE__) "): " \ | ||
146 | __stringify(cnd) "\n"); \ | ||
147 | } while (0) | ||
148 | |||
149 | |||
150 | extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); | ||
151 | extern void set_warning_routine(void (*routine)(const char *err, va_list params)); | ||
152 | |||
153 | extern int prefixcmp(const char *str, const char *prefix); | ||
154 | extern void set_buildid_dir(const char *dir); | ||
155 | 145 | ||
156 | #ifdef __GLIBC_PREREQ | 146 | #ifdef __GLIBC_PREREQ |
157 | #if __GLIBC_PREREQ(2, 1) | 147 | #if __GLIBC_PREREQ(2, 1) |
@@ -172,8 +162,7 @@ static inline char *gitstrchrnul(const char *s, int c) | |||
172 | /* | 162 | /* |
173 | * Wrappers: | 163 | * Wrappers: |
174 | */ | 164 | */ |
175 | extern char *xstrdup(const char *str); | 165 | void *xrealloc(void *ptr, size_t size) __attribute__((weak)); |
176 | extern void *xrealloc(void *ptr, size_t size) __attribute__((weak)); | ||
177 | 166 | ||
178 | 167 | ||
179 | static inline void *zalloc(size_t size) | 168 | static inline void *zalloc(size_t size) |
diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c index 19f15b650703..5f1a07c4b87b 100644 --- a/tools/perf/util/wrapper.c +++ b/tools/perf/util/wrapper.c | |||
@@ -12,18 +12,6 @@ static inline void release_pack_memory(size_t size __maybe_unused, | |||
12 | { | 12 | { |
13 | } | 13 | } |
14 | 14 | ||
15 | char *xstrdup(const char *str) | ||
16 | { | ||
17 | char *ret = strdup(str); | ||
18 | if (!ret) { | ||
19 | release_pack_memory(strlen(str) + 1, -1); | ||
20 | ret = strdup(str); | ||
21 | if (!ret) | ||
22 | die("Out of memory, strdup failed"); | ||
23 | } | ||
24 | return ret; | ||
25 | } | ||
26 | |||
27 | void *xrealloc(void *ptr, size_t size) | 15 | void *xrealloc(void *ptr, size_t size) |
28 | { | 16 | { |
29 | void *ret = realloc(ptr, size); | 17 | void *ret = realloc(ptr, size); |
diff --git a/tools/perf/config/utilities.mak b/tools/scripts/utilities.mak index c16ce833079c..c16ce833079c 100644 --- a/tools/perf/config/utilities.mak +++ b/tools/scripts/utilities.mak | |||