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 | |||
