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

* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (35 commits)
perf: Fix unexported generic perf_arch_fetch_caller_regs
perf record: Don't try to find buildids in a zero sized file
perf: export perf_trace_regs and perf_arch_fetch_caller_regs
perf, x86: Fix hw_perf_enable() event assignment
perf, ppc: Fix compile error due to new cpu notifiers
perf: Make the install relative to DESTDIR if specified
kprobes: Calculate the index correctly when freeing the out-of-line execution slot
perf tools: Fix sparse CPU numbering related bugs
perf_event: Fix oops triggered by cpu offline/online
perf: Drop the obsolete profile naming for trace events
perf: Take a hot regs snapshot for trace events
perf: Introduce new perf_fetch_caller_regs() for hot regs snapshot
perf/x86-64: Use frame pointer to walk on irq and process stacks
lockdep: Move lock events under lockdep recursion protection
perf report: Print the map table just after samples for which no map was found
perf report: Add multiple event support
perf session: Change perf_session post processing functions to take histogram tree
perf session: Add storage for seperating event types in report
perf session: Change add_hist_entry to take the tree root instead of session
perf record: Add ID and to recorded event data when recording multiple events
...

+741 -398
+20 -1
arch/powerpc/kernel/perf_event.c
··· 1287 1287 irq_exit(); 1288 1288 } 1289 1289 1290 - void hw_perf_event_setup(int cpu) 1290 + static void power_pmu_setup(int cpu) 1291 1291 { 1292 1292 struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu); 1293 1293 ··· 1295 1295 return; 1296 1296 memset(cpuhw, 0, sizeof(*cpuhw)); 1297 1297 cpuhw->mmcr[0] = MMCR0_FC; 1298 + } 1299 + 1300 + static int __cpuinit 1301 + power_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) 1302 + { 1303 + unsigned int cpu = (long)hcpu; 1304 + 1305 + switch (action & ~CPU_TASKS_FROZEN) { 1306 + case CPU_UP_PREPARE: 1307 + power_pmu_setup(cpu); 1308 + break; 1309 + 1310 + default: 1311 + break; 1312 + } 1313 + 1314 + return NOTIFY_OK; 1298 1315 } 1299 1316 1300 1317 int register_power_pmu(struct power_pmu *pmu) ··· 1330 1313 if (mfmsr() & MSR_HV) 1331 1314 freeze_events_kernel = MMCR0_FCHV; 1332 1315 #endif /* CONFIG_PPC64 */ 1316 + 1317 + perf_cpu_notifier(power_pmu_notifier); 1333 1318 1334 1319 return 0; 1335 1320 }
+19 -1
arch/sh/kernel/perf_event.c
··· 275 275 return &pmu; 276 276 } 277 277 278 - void hw_perf_event_setup(int cpu) 278 + static void sh_pmu_setup(int cpu) 279 279 { 280 280 struct cpu_hw_events *cpuhw = &per_cpu(cpu_hw_events, cpu); 281 281 282 282 memset(cpuhw, 0, sizeof(struct cpu_hw_events)); 283 + } 284 + 285 + static int __cpuinit 286 + sh_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) 287 + { 288 + unsigned int cpu = (long)hcpu; 289 + 290 + switch (action & ~CPU_TASKS_FROZEN) { 291 + case CPU_UP_PREPARE: 292 + sh_pmu_setup(cpu); 293 + break; 294 + 295 + default: 296 + break; 297 + } 298 + 299 + return NOTIFY_OK; 283 300 } 284 301 285 302 void hw_perf_enable(void) ··· 325 308 326 309 WARN_ON(pmu->num_events > MAX_HWEVENTS); 327 310 311 + perf_cpu_notifier(sh_pmu_notifier); 328 312 return 0; 329 313 }
+99 -84
arch/x86/kernel/cpu/perf_event.c
··· 133 133 int (*handle_irq)(struct pt_regs *); 134 134 void (*disable_all)(void); 135 135 void (*enable_all)(void); 136 - void (*enable)(struct hw_perf_event *, int); 137 - void (*disable)(struct hw_perf_event *, int); 136 + void (*enable)(struct perf_event *); 137 + void (*disable)(struct perf_event *); 138 138 unsigned eventsel; 139 139 unsigned perfctr; 140 140 u64 (*event_map)(int); ··· 157 157 void (*put_event_constraints)(struct cpu_hw_events *cpuc, 158 158 struct perf_event *event); 159 159 struct event_constraint *event_constraints; 160 + 161 + void (*cpu_prepare)(int cpu); 162 + void (*cpu_starting)(int cpu); 163 + void (*cpu_dying)(int cpu); 164 + void (*cpu_dead)(int cpu); 160 165 }; 161 166 162 167 static struct x86_pmu x86_pmu __read_mostly; ··· 170 165 .enabled = 1, 171 166 }; 172 167 173 - static int x86_perf_event_set_period(struct perf_event *event, 174 - struct hw_perf_event *hwc, int idx); 168 + static int x86_perf_event_set_period(struct perf_event *event); 175 169 176 170 /* 177 171 * Generalized hw caching related hw_event table, filled ··· 193 189 * Returns the delta events processed. 194 190 */ 195 191 static u64 196 - x86_perf_event_update(struct perf_event *event, 197 - struct hw_perf_event *hwc, int idx) 192 + x86_perf_event_update(struct perf_event *event) 198 193 { 194 + struct hw_perf_event *hwc = &event->hw; 199 195 int shift = 64 - x86_pmu.event_bits; 200 196 u64 prev_raw_count, new_raw_count; 197 + int idx = hwc->idx; 201 198 s64 delta; 202 199 203 200 if (idx == X86_PMC_IDX_FIXED_BTS) ··· 298 293 return x86_pmu.enable_bts != NULL; 299 294 } 300 295 301 - static inline void init_debug_store_on_cpu(int cpu) 296 + static void init_debug_store_on_cpu(int cpu) 302 297 { 303 298 struct debug_store *ds = per_cpu(cpu_hw_events, cpu).ds; 304 299 ··· 310 305 (u32)((u64)(unsigned long)ds >> 32)); 311 306 } 312 307 313 - static inline void fini_debug_store_on_cpu(int cpu) 308 + static void fini_debug_store_on_cpu(int cpu) 314 309 { 315 310 if (!per_cpu(cpu_hw_events, cpu).ds) 316 311 return; ··· 643 638 if (test_bit(hwc->idx, used_mask)) 644 639 break; 645 640 646 - set_bit(hwc->idx, used_mask); 641 + __set_bit(hwc->idx, used_mask); 647 642 if (assign) 648 643 assign[i] = hwc->idx; 649 644 } ··· 692 687 if (j == X86_PMC_IDX_MAX) 693 688 break; 694 689 695 - set_bit(j, used_mask); 690 + __set_bit(j, used_mask); 696 691 697 692 if (assign) 698 693 assign[i] = j; ··· 785 780 hwc->last_tag == cpuc->tags[i]; 786 781 } 787 782 783 + static int x86_pmu_start(struct perf_event *event); 788 784 static void x86_pmu_stop(struct perf_event *event); 789 785 790 786 void hw_perf_enable(void) ··· 802 796 return; 803 797 804 798 if (cpuc->n_added) { 799 + int n_running = cpuc->n_events - cpuc->n_added; 805 800 /* 806 801 * apply assignment obtained either from 807 802 * hw_perf_group_sched_in() or x86_pmu_enable() ··· 810 803 * step1: save events moving to new counters 811 804 * step2: reprogram moved events into new counters 812 805 */ 813 - for (i = 0; i < cpuc->n_events; i++) { 814 - 806 + for (i = 0; i < n_running; i++) { 815 807 event = cpuc->event_list[i]; 816 808 hwc = &event->hw; 817 809 ··· 825 819 continue; 826 820 827 821 x86_pmu_stop(event); 828 - 829 - hwc->idx = -1; 830 822 } 831 823 832 824 for (i = 0; i < cpuc->n_events; i++) { 833 - 834 825 event = cpuc->event_list[i]; 835 826 hwc = &event->hw; 836 827 837 - if (hwc->idx == -1) { 828 + if (!match_prev_assignment(hwc, cpuc, i)) 838 829 x86_assign_hw_event(event, cpuc, i); 839 - x86_perf_event_set_period(event, hwc, hwc->idx); 840 - } 841 - /* 842 - * need to mark as active because x86_pmu_disable() 843 - * clear active_mask and events[] yet it preserves 844 - * idx 845 - */ 846 - set_bit(hwc->idx, cpuc->active_mask); 847 - cpuc->events[hwc->idx] = event; 830 + else if (i < n_running) 831 + continue; 848 832 849 - x86_pmu.enable(hwc, hwc->idx); 850 - perf_event_update_userpage(event); 833 + x86_pmu_start(event); 851 834 } 852 835 cpuc->n_added = 0; 853 836 perf_events_lapic_init(); ··· 848 853 x86_pmu.enable_all(); 849 854 } 850 855 851 - static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, int idx) 856 + static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc) 852 857 { 853 - (void)checking_wrmsrl(hwc->config_base + idx, 858 + (void)checking_wrmsrl(hwc->config_base + hwc->idx, 854 859 hwc->config | ARCH_PERFMON_EVENTSEL_ENABLE); 855 860 } 856 861 857 - static inline void x86_pmu_disable_event(struct hw_perf_event *hwc, int idx) 862 + static inline void x86_pmu_disable_event(struct perf_event *event) 858 863 { 859 - (void)checking_wrmsrl(hwc->config_base + idx, hwc->config); 864 + struct hw_perf_event *hwc = &event->hw; 865 + (void)checking_wrmsrl(hwc->config_base + hwc->idx, hwc->config); 860 866 } 861 867 862 868 static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); ··· 867 871 * To be called with the event disabled in hw: 868 872 */ 869 873 static int 870 - x86_perf_event_set_period(struct perf_event *event, 871 - struct hw_perf_event *hwc, int idx) 874 + x86_perf_event_set_period(struct perf_event *event) 872 875 { 876 + struct hw_perf_event *hwc = &event->hw; 873 877 s64 left = atomic64_read(&hwc->period_left); 874 878 s64 period = hwc->sample_period; 875 - int err, ret = 0; 879 + int err, ret = 0, idx = hwc->idx; 876 880 877 881 if (idx == X86_PMC_IDX_FIXED_BTS) 878 882 return 0; ··· 918 922 return ret; 919 923 } 920 924 921 - static void x86_pmu_enable_event(struct hw_perf_event *hwc, int idx) 925 + static void x86_pmu_enable_event(struct perf_event *event) 922 926 { 923 927 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 924 928 if (cpuc->enabled) 925 - __x86_pmu_enable_event(hwc, idx); 929 + __x86_pmu_enable_event(&event->hw); 926 930 } 927 931 928 932 /* ··· 958 962 memcpy(cpuc->assign, assign, n*sizeof(int)); 959 963 960 964 cpuc->n_events = n; 961 - cpuc->n_added = n - n0; 965 + cpuc->n_added += n - n0; 962 966 963 967 return 0; 964 968 } 965 969 966 970 static int x86_pmu_start(struct perf_event *event) 967 971 { 968 - struct hw_perf_event *hwc = &event->hw; 972 + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 973 + int idx = event->hw.idx; 969 974 970 - if (hwc->idx == -1) 975 + if (idx == -1) 971 976 return -EAGAIN; 972 977 973 - x86_perf_event_set_period(event, hwc, hwc->idx); 974 - x86_pmu.enable(hwc, hwc->idx); 978 + x86_perf_event_set_period(event); 979 + cpuc->events[idx] = event; 980 + __set_bit(idx, cpuc->active_mask); 981 + x86_pmu.enable(event); 982 + perf_event_update_userpage(event); 975 983 976 984 return 0; 977 985 } 978 986 979 987 static void x86_pmu_unthrottle(struct perf_event *event) 980 988 { 981 - struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 982 - struct hw_perf_event *hwc = &event->hw; 983 - 984 - if (WARN_ON_ONCE(hwc->idx >= X86_PMC_IDX_MAX || 985 - cpuc->events[hwc->idx] != event)) 986 - return; 987 - 988 - x86_pmu.enable(hwc, hwc->idx); 989 + int ret = x86_pmu_start(event); 990 + WARN_ON_ONCE(ret); 989 991 } 990 992 991 993 void perf_event_print_debug(void) ··· 1043 1049 struct hw_perf_event *hwc = &event->hw; 1044 1050 int idx = hwc->idx; 1045 1051 1046 - /* 1047 - * Must be done before we disable, otherwise the nmi handler 1048 - * could reenable again: 1049 - */ 1050 - clear_bit(idx, cpuc->active_mask); 1051 - x86_pmu.disable(hwc, idx); 1052 + if (!__test_and_clear_bit(idx, cpuc->active_mask)) 1053 + return; 1054 + 1055 + x86_pmu.disable(event); 1052 1056 1053 1057 /* 1054 1058 * Drain the remaining delta count out of a event 1055 1059 * that we are disabling: 1056 1060 */ 1057 - x86_perf_event_update(event, hwc, idx); 1061 + x86_perf_event_update(event); 1058 1062 1059 1063 cpuc->events[idx] = NULL; 1060 1064 } ··· 1100 1108 event = cpuc->events[idx]; 1101 1109 hwc = &event->hw; 1102 1110 1103 - val = x86_perf_event_update(event, hwc, idx); 1111 + val = x86_perf_event_update(event); 1104 1112 if (val & (1ULL << (x86_pmu.event_bits - 1))) 1105 1113 continue; 1106 1114 ··· 1110 1118 handled = 1; 1111 1119 data.period = event->hw.last_period; 1112 1120 1113 - if (!x86_perf_event_set_period(event, hwc, idx)) 1121 + if (!x86_perf_event_set_period(event)) 1114 1122 continue; 1115 1123 1116 1124 if (perf_event_overflow(event, 1, &data, regs)) 1117 - x86_pmu.disable(hwc, idx); 1125 + x86_pmu_stop(event); 1118 1126 } 1119 1127 1120 1128 if (handled) ··· 1301 1309 memcpy(cpuc->assign, assign, n0*sizeof(int)); 1302 1310 1303 1311 cpuc->n_events = n0; 1304 - cpuc->n_added = n1; 1312 + cpuc->n_added += n1; 1305 1313 ctx->nr_active += n1; 1306 1314 1307 1315 /* ··· 1328 1336 #include "perf_event_amd.c" 1329 1337 #include "perf_event_p6.c" 1330 1338 #include "perf_event_intel.c" 1339 + 1340 + static int __cpuinit 1341 + x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) 1342 + { 1343 + unsigned int cpu = (long)hcpu; 1344 + 1345 + switch (action & ~CPU_TASKS_FROZEN) { 1346 + case CPU_UP_PREPARE: 1347 + if (x86_pmu.cpu_prepare) 1348 + x86_pmu.cpu_prepare(cpu); 1349 + break; 1350 + 1351 + case CPU_STARTING: 1352 + if (x86_pmu.cpu_starting) 1353 + x86_pmu.cpu_starting(cpu); 1354 + break; 1355 + 1356 + case CPU_DYING: 1357 + if (x86_pmu.cpu_dying) 1358 + x86_pmu.cpu_dying(cpu); 1359 + break; 1360 + 1361 + case CPU_DEAD: 1362 + if (x86_pmu.cpu_dead) 1363 + x86_pmu.cpu_dead(cpu); 1364 + break; 1365 + 1366 + default: 1367 + break; 1368 + } 1369 + 1370 + return NOTIFY_OK; 1371 + } 1331 1372 1332 1373 static void __init pmu_check_apic(void) 1333 1374 { ··· 1440 1415 pr_info("... max period: %016Lx\n", x86_pmu.max_period); 1441 1416 pr_info("... fixed-purpose events: %d\n", x86_pmu.num_events_fixed); 1442 1417 pr_info("... event mask: %016Lx\n", perf_event_mask); 1418 + 1419 + perf_cpu_notifier(x86_pmu_notifier); 1443 1420 } 1444 1421 1445 1422 static inline void x86_pmu_read(struct perf_event *event) 1446 1423 { 1447 - x86_perf_event_update(event, &event->hw, event->hw.idx); 1424 + x86_perf_event_update(event); 1448 1425 } 1449 1426 1450 1427 static const struct pmu pmu = { ··· 1702 1675 return entry; 1703 1676 } 1704 1677 1705 - void hw_perf_event_setup_online(int cpu) 1678 + #ifdef CONFIG_EVENT_TRACING 1679 + void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) 1706 1680 { 1707 - init_debug_store_on_cpu(cpu); 1708 - 1709 - switch (boot_cpu_data.x86_vendor) { 1710 - case X86_VENDOR_AMD: 1711 - amd_pmu_cpu_online(cpu); 1712 - break; 1713 - default: 1714 - return; 1715 - } 1681 + regs->ip = ip; 1682 + /* 1683 + * perf_arch_fetch_caller_regs adds another call, we need to increment 1684 + * the skip level 1685 + */ 1686 + regs->bp = rewind_frame_pointer(skip + 1); 1687 + regs->cs = __KERNEL_CS; 1688 + local_save_flags(regs->flags); 1716 1689 } 1717 - 1718 - void hw_perf_event_setup_offline(int cpu) 1719 - { 1720 - init_debug_store_on_cpu(cpu); 1721 - 1722 - switch (boot_cpu_data.x86_vendor) { 1723 - case X86_VENDOR_AMD: 1724 - amd_pmu_cpu_offline(cpu); 1725 - break; 1726 - default: 1727 - return; 1728 - } 1729 - } 1690 + #endif
+26 -36
arch/x86/kernel/cpu/perf_event_amd.c
··· 271 271 return &emptyconstraint; 272 272 } 273 273 274 - static __initconst struct x86_pmu amd_pmu = { 275 - .name = "AMD", 276 - .handle_irq = x86_pmu_handle_irq, 277 - .disable_all = x86_pmu_disable_all, 278 - .enable_all = x86_pmu_enable_all, 279 - .enable = x86_pmu_enable_event, 280 - .disable = x86_pmu_disable_event, 281 - .eventsel = MSR_K7_EVNTSEL0, 282 - .perfctr = MSR_K7_PERFCTR0, 283 - .event_map = amd_pmu_event_map, 284 - .raw_event = amd_pmu_raw_event, 285 - .max_events = ARRAY_SIZE(amd_perfmon_event_map), 286 - .num_events = 4, 287 - .event_bits = 48, 288 - .event_mask = (1ULL << 48) - 1, 289 - .apic = 1, 290 - /* use highest bit to detect overflow */ 291 - .max_period = (1ULL << 47) - 1, 292 - .get_event_constraints = amd_get_event_constraints, 293 - .put_event_constraints = amd_put_event_constraints 294 - }; 295 - 296 274 static struct amd_nb *amd_alloc_nb(int cpu, int nb_id) 297 275 { 298 276 struct amd_nb *nb; ··· 287 309 * initialize all possible NB constraints 288 310 */ 289 311 for (i = 0; i < x86_pmu.num_events; i++) { 290 - set_bit(i, nb->event_constraints[i].idxmsk); 312 + __set_bit(i, nb->event_constraints[i].idxmsk); 291 313 nb->event_constraints[i].weight = 1; 292 314 } 293 315 return nb; ··· 356 378 raw_spin_unlock(&amd_nb_lock); 357 379 } 358 380 381 + static __initconst struct x86_pmu amd_pmu = { 382 + .name = "AMD", 383 + .handle_irq = x86_pmu_handle_irq, 384 + .disable_all = x86_pmu_disable_all, 385 + .enable_all = x86_pmu_enable_all, 386 + .enable = x86_pmu_enable_event, 387 + .disable = x86_pmu_disable_event, 388 + .eventsel = MSR_K7_EVNTSEL0, 389 + .perfctr = MSR_K7_PERFCTR0, 390 + .event_map = amd_pmu_event_map, 391 + .raw_event = amd_pmu_raw_event, 392 + .max_events = ARRAY_SIZE(amd_perfmon_event_map), 393 + .num_events = 4, 394 + .event_bits = 48, 395 + .event_mask = (1ULL << 48) - 1, 396 + .apic = 1, 397 + /* use highest bit to detect overflow */ 398 + .max_period = (1ULL << 47) - 1, 399 + .get_event_constraints = amd_get_event_constraints, 400 + .put_event_constraints = amd_put_event_constraints, 401 + 402 + .cpu_prepare = amd_pmu_cpu_online, 403 + .cpu_dead = amd_pmu_cpu_offline, 404 + }; 405 + 359 406 static __init int amd_pmu_init(void) 360 407 { 361 408 /* Performance-monitoring supported from K7 and later: */ ··· 393 390 memcpy(hw_cache_event_ids, amd_hw_cache_event_ids, 394 391 sizeof(hw_cache_event_ids)); 395 392 396 - /* 397 - * explicitly initialize the boot cpu, other cpus will get 398 - * the cpu hotplug callbacks from smp_init() 399 - */ 400 - amd_pmu_cpu_online(smp_processor_id()); 401 393 return 0; 402 394 } 403 395 ··· 401 403 static int amd_pmu_init(void) 402 404 { 403 405 return 0; 404 - } 405 - 406 - static void amd_pmu_cpu_online(int cpu) 407 - { 408 - } 409 - 410 - static void amd_pmu_cpu_offline(int cpu) 411 - { 412 406 } 413 407 414 408 #endif
+28 -29
arch/x86/kernel/cpu/perf_event_intel.c
··· 548 548 } 549 549 550 550 static inline void 551 - intel_pmu_disable_fixed(struct hw_perf_event *hwc, int __idx) 551 + intel_pmu_disable_fixed(struct hw_perf_event *hwc) 552 552 { 553 - int idx = __idx - X86_PMC_IDX_FIXED; 553 + int idx = hwc->idx - X86_PMC_IDX_FIXED; 554 554 u64 ctrl_val, mask; 555 555 556 556 mask = 0xfULL << (idx * 4); ··· 621 621 } 622 622 623 623 static inline void 624 - intel_pmu_disable_event(struct hw_perf_event *hwc, int idx) 624 + intel_pmu_disable_event(struct perf_event *event) 625 625 { 626 - if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { 626 + struct hw_perf_event *hwc = &event->hw; 627 + 628 + if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) { 627 629 intel_pmu_disable_bts(); 628 630 intel_pmu_drain_bts_buffer(); 629 631 return; 630 632 } 631 633 632 634 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { 633 - intel_pmu_disable_fixed(hwc, idx); 635 + intel_pmu_disable_fixed(hwc); 634 636 return; 635 637 } 636 638 637 - x86_pmu_disable_event(hwc, idx); 639 + x86_pmu_disable_event(event); 638 640 } 639 641 640 642 static inline void 641 - intel_pmu_enable_fixed(struct hw_perf_event *hwc, int __idx) 643 + intel_pmu_enable_fixed(struct hw_perf_event *hwc) 642 644 { 643 - int idx = __idx - X86_PMC_IDX_FIXED; 645 + int idx = hwc->idx - X86_PMC_IDX_FIXED; 644 646 u64 ctrl_val, bits, mask; 645 647 int err; 646 648 ··· 672 670 err = checking_wrmsrl(hwc->config_base, ctrl_val); 673 671 } 674 672 675 - static void intel_pmu_enable_event(struct hw_perf_event *hwc, int idx) 673 + static void intel_pmu_enable_event(struct perf_event *event) 676 674 { 677 - if (unlikely(idx == X86_PMC_IDX_FIXED_BTS)) { 675 + struct hw_perf_event *hwc = &event->hw; 676 + 677 + if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) { 678 678 if (!__get_cpu_var(cpu_hw_events).enabled) 679 679 return; 680 680 ··· 685 681 } 686 682 687 683 if (unlikely(hwc->config_base == MSR_ARCH_PERFMON_FIXED_CTR_CTRL)) { 688 - intel_pmu_enable_fixed(hwc, idx); 684 + intel_pmu_enable_fixed(hwc); 689 685 return; 690 686 } 691 687 692 - __x86_pmu_enable_event(hwc, idx); 688 + __x86_pmu_enable_event(hwc); 693 689 } 694 690 695 691 /* ··· 698 694 */ 699 695 static int intel_pmu_save_and_restart(struct perf_event *event) 700 696 { 701 - struct hw_perf_event *hwc = &event->hw; 702 - int idx = hwc->idx; 703 - int ret; 704 - 705 - x86_perf_event_update(event, hwc, idx); 706 - ret = x86_perf_event_set_period(event, hwc, idx); 707 - 708 - return ret; 697 + x86_perf_event_update(event); 698 + return x86_perf_event_set_period(event); 709 699 } 710 700 711 701 static void intel_pmu_reset(void) ··· 743 745 744 746 cpuc = &__get_cpu_var(cpu_hw_events); 745 747 746 - perf_disable(); 748 + intel_pmu_disable_all(); 747 749 intel_pmu_drain_bts_buffer(); 748 750 status = intel_pmu_get_status(); 749 751 if (!status) { 750 - perf_enable(); 752 + intel_pmu_enable_all(); 751 753 return 0; 752 754 } 753 755 ··· 757 759 WARN_ONCE(1, "perfevents: irq loop stuck!\n"); 758 760 perf_event_print_debug(); 759 761 intel_pmu_reset(); 760 - perf_enable(); 761 - return 1; 762 + goto done; 762 763 } 763 764 764 765 inc_irq_stat(apic_perf_irqs); ··· 765 768 for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) { 766 769 struct perf_event *event = cpuc->events[bit]; 767 770 768 - clear_bit(bit, (unsigned long *) &status); 769 771 if (!test_bit(bit, cpuc->active_mask)) 770 772 continue; 771 773 ··· 774 778 data.period = event->hw.last_period; 775 779 776 780 if (perf_event_overflow(event, 1, &data, regs)) 777 - intel_pmu_disable_event(&event->hw, bit); 781 + x86_pmu_stop(event); 778 782 } 779 783 780 784 intel_pmu_ack_status(ack); ··· 786 790 if (status) 787 791 goto again; 788 792 789 - perf_enable(); 790 - 793 + done: 794 + intel_pmu_enable_all(); 791 795 return 1; 792 796 } 793 797 ··· 866 870 .max_period = (1ULL << 31) - 1, 867 871 .enable_bts = intel_pmu_enable_bts, 868 872 .disable_bts = intel_pmu_disable_bts, 869 - .get_event_constraints = intel_get_event_constraints 873 + .get_event_constraints = intel_get_event_constraints, 874 + 875 + .cpu_starting = init_debug_store_on_cpu, 876 + .cpu_dying = fini_debug_store_on_cpu, 870 877 }; 871 878 872 879 static __init int intel_pmu_init(void)
+6 -4
arch/x86/kernel/cpu/perf_event_p6.c
··· 77 77 } 78 78 79 79 static inline void 80 - p6_pmu_disable_event(struct hw_perf_event *hwc, int idx) 80 + p6_pmu_disable_event(struct perf_event *event) 81 81 { 82 82 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 83 + struct hw_perf_event *hwc = &event->hw; 83 84 u64 val = P6_NOP_EVENT; 84 85 85 86 if (cpuc->enabled) 86 87 val |= ARCH_PERFMON_EVENTSEL_ENABLE; 87 88 88 - (void)checking_wrmsrl(hwc->config_base + idx, val); 89 + (void)checking_wrmsrl(hwc->config_base + hwc->idx, val); 89 90 } 90 91 91 - static void p6_pmu_enable_event(struct hw_perf_event *hwc, int idx) 92 + static void p6_pmu_enable_event(struct perf_event *event) 92 93 { 93 94 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 95 + struct hw_perf_event *hwc = &event->hw; 94 96 u64 val; 95 97 96 98 val = hwc->config; 97 99 if (cpuc->enabled) 98 100 val |= ARCH_PERFMON_EVENTSEL_ENABLE; 99 101 100 - (void)checking_wrmsrl(hwc->config_base + idx, val); 102 + (void)checking_wrmsrl(hwc->config_base + hwc->idx, val); 101 103 } 102 104 103 105 static __initconst struct x86_pmu p6_pmu = {
+15
arch/x86/kernel/dumpstack.h
··· 29 29 struct stack_frame *next_frame; 30 30 unsigned long return_address; 31 31 }; 32 + 33 + static inline unsigned long rewind_frame_pointer(int n) 34 + { 35 + struct stack_frame *frame; 36 + 37 + get_bp(frame); 38 + 39 + #ifdef CONFIG_FRAME_POINTER 40 + while (n--) 41 + frame = frame->next_frame; 32 42 #endif 43 + 44 + return (unsigned long)frame; 45 + } 46 + 47 + #endif /* DUMPSTACK_H */
+2 -2
arch/x86/kernel/dumpstack_64.c
··· 208 208 if (in_irq_stack(stack, irq_stack, irq_stack_end)) { 209 209 if (ops->stack(data, "IRQ") < 0) 210 210 break; 211 - bp = print_context_stack(tinfo, stack, bp, 211 + bp = ops->walk_stack(tinfo, stack, bp, 212 212 ops, data, irq_stack_end, &graph); 213 213 /* 214 214 * We link to the next stack (which would be ··· 229 229 /* 230 230 * This handles the process stack: 231 231 */ 232 - bp = print_context_stack(tinfo, stack, bp, ops, data, NULL, &graph); 232 + bp = ops->walk_stack(tinfo, stack, bp, ops, data, NULL, &graph); 233 233 put_cpu(); 234 234 } 235 235 EXPORT_SYMBOL(dump_trace);
+13 -10
include/linux/ftrace_event.h
··· 131 131 void *mod; 132 132 void *data; 133 133 134 - int profile_count; 135 - int (*profile_enable)(struct ftrace_event_call *); 136 - void (*profile_disable)(struct ftrace_event_call *); 134 + int perf_refcount; 135 + int (*perf_event_enable)(struct ftrace_event_call *); 136 + void (*perf_event_disable)(struct ftrace_event_call *); 137 137 }; 138 138 139 - #define FTRACE_MAX_PROFILE_SIZE 2048 139 + #define PERF_MAX_TRACE_SIZE 2048 140 140 141 141 #define MAX_FILTER_PRED 32 142 142 #define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */ ··· 187 187 188 188 #ifdef CONFIG_PERF_EVENTS 189 189 struct perf_event; 190 - extern int ftrace_profile_enable(int event_id); 191 - extern void ftrace_profile_disable(int event_id); 190 + 191 + DECLARE_PER_CPU(struct pt_regs, perf_trace_regs); 192 + 193 + extern int perf_trace_enable(int event_id); 194 + extern void perf_trace_disable(int event_id); 192 195 extern int ftrace_profile_set_filter(struct perf_event *event, int event_id, 193 196 char *filter_str); 194 197 extern void ftrace_profile_free_filter(struct perf_event *event); 195 198 extern void * 196 - ftrace_perf_buf_prepare(int size, unsigned short type, int *rctxp, 199 + perf_trace_buf_prepare(int size, unsigned short type, int *rctxp, 197 200 unsigned long *irq_flags); 198 201 199 202 static inline void 200 - ftrace_perf_buf_submit(void *raw_data, int size, int rctx, u64 addr, 201 - u64 count, unsigned long irq_flags) 203 + perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr, 204 + u64 count, unsigned long irq_flags, struct pt_regs *regs) 202 205 { 203 206 struct trace_entry *entry = raw_data; 204 207 205 - perf_tp_event(entry->type, addr, count, raw_data, size); 208 + perf_tp_event(entry->type, addr, count, raw_data, size, regs); 206 209 perf_swevent_put_recursion_context(rctx); 207 210 local_irq_restore(irq_flags); 208 211 }
+58 -1
include/linux/perf_event.h
··· 452 452 #include <linux/fs.h> 453 453 #include <linux/pid_namespace.h> 454 454 #include <linux/workqueue.h> 455 + #include <linux/ftrace.h> 456 + #include <linux/cpu.h> 455 457 #include <asm/atomic.h> 456 458 457 459 #define PERF_MAX_STACK_DEPTH 255 ··· 849 847 __perf_sw_event(event_id, nr, nmi, regs, addr); 850 848 } 851 849 850 + extern void 851 + perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip); 852 + 853 + /* 854 + * Take a snapshot of the regs. Skip ip and frame pointer to 855 + * the nth caller. We only need a few of the regs: 856 + * - ip for PERF_SAMPLE_IP 857 + * - cs for user_mode() tests 858 + * - bp for callchains 859 + * - eflags, for future purposes, just in case 860 + */ 861 + static inline void perf_fetch_caller_regs(struct pt_regs *regs, int skip) 862 + { 863 + unsigned long ip; 864 + 865 + memset(regs, 0, sizeof(*regs)); 866 + 867 + switch (skip) { 868 + case 1 : 869 + ip = CALLER_ADDR0; 870 + break; 871 + case 2 : 872 + ip = CALLER_ADDR1; 873 + break; 874 + case 3 : 875 + ip = CALLER_ADDR2; 876 + break; 877 + case 4: 878 + ip = CALLER_ADDR3; 879 + break; 880 + /* No need to support further for now */ 881 + default: 882 + ip = 0; 883 + } 884 + 885 + return perf_arch_fetch_caller_regs(regs, ip, skip); 886 + } 887 + 852 888 extern void __perf_event_mmap(struct vm_area_struct *vma); 853 889 854 890 static inline void perf_event_mmap(struct vm_area_struct *vma) ··· 920 880 } 921 881 922 882 extern void perf_event_init(void); 923 - extern void perf_tp_event(int event_id, u64 addr, u64 count, void *record, int entry_size); 883 + extern void perf_tp_event(int event_id, u64 addr, u64 count, void *record, 884 + int entry_size, struct pt_regs *regs); 924 885 extern void perf_bp_event(struct perf_event *event, void *data); 925 886 926 887 #ifndef perf_misc_flags ··· 976 935 977 936 #define perf_output_put(handle, x) \ 978 937 perf_output_copy((handle), &(x), sizeof(x)) 938 + 939 + /* 940 + * This has to have a higher priority than migration_notifier in sched.c. 941 + */ 942 + #define perf_cpu_notifier(fn) \ 943 + do { \ 944 + static struct notifier_block fn##_nb __cpuinitdata = \ 945 + { .notifier_call = fn, .priority = 20 }; \ 946 + fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE, \ 947 + (void *)(unsigned long)smp_processor_id()); \ 948 + fn(&fn##_nb, (unsigned long)CPU_STARTING, \ 949 + (void *)(unsigned long)smp_processor_id()); \ 950 + fn(&fn##_nb, (unsigned long)CPU_ONLINE, \ 951 + (void *)(unsigned long)smp_processor_id()); \ 952 + register_cpu_notifier(&fn##_nb); \ 953 + } while (0) 979 954 980 955 #endif /* __KERNEL__ */ 981 956 #endif /* _LINUX_PERF_EVENT_H */
+12 -12
include/linux/syscalls.h
··· 105 105 106 106 #ifdef CONFIG_PERF_EVENTS 107 107 108 - #define TRACE_SYS_ENTER_PROFILE_INIT(sname) \ 109 - .profile_enable = prof_sysenter_enable, \ 110 - .profile_disable = prof_sysenter_disable, 108 + #define TRACE_SYS_ENTER_PERF_INIT(sname) \ 109 + .perf_event_enable = perf_sysenter_enable, \ 110 + .perf_event_disable = perf_sysenter_disable, 111 111 112 - #define TRACE_SYS_EXIT_PROFILE_INIT(sname) \ 113 - .profile_enable = prof_sysexit_enable, \ 114 - .profile_disable = prof_sysexit_disable, 112 + #define TRACE_SYS_EXIT_PERF_INIT(sname) \ 113 + .perf_event_enable = perf_sysexit_enable, \ 114 + .perf_event_disable = perf_sysexit_disable, 115 115 #else 116 - #define TRACE_SYS_ENTER_PROFILE(sname) 117 - #define TRACE_SYS_ENTER_PROFILE_INIT(sname) 118 - #define TRACE_SYS_EXIT_PROFILE(sname) 119 - #define TRACE_SYS_EXIT_PROFILE_INIT(sname) 116 + #define TRACE_SYS_ENTER_PERF(sname) 117 + #define TRACE_SYS_ENTER_PERF_INIT(sname) 118 + #define TRACE_SYS_EXIT_PERF(sname) 119 + #define TRACE_SYS_EXIT_PERF_INIT(sname) 120 120 #endif /* CONFIG_PERF_EVENTS */ 121 121 122 122 #ifdef CONFIG_FTRACE_SYSCALLS ··· 153 153 .regfunc = reg_event_syscall_enter, \ 154 154 .unregfunc = unreg_event_syscall_enter, \ 155 155 .data = (void *)&__syscall_meta_##sname,\ 156 - TRACE_SYS_ENTER_PROFILE_INIT(sname) \ 156 + TRACE_SYS_ENTER_PERF_INIT(sname) \ 157 157 } 158 158 159 159 #define SYSCALL_TRACE_EXIT_EVENT(sname) \ ··· 175 175 .regfunc = reg_event_syscall_exit, \ 176 176 .unregfunc = unreg_event_syscall_exit, \ 177 177 .data = (void *)&__syscall_meta_##sname,\ 178 - TRACE_SYS_EXIT_PROFILE_INIT(sname) \ 178 + TRACE_SYS_EXIT_PERF_INIT(sname) \ 179 179 } 180 180 181 181 #define SYSCALL_METADATA(sname, nb) \
+24 -20
include/trace/ftrace.h
··· 401 401 #undef DEFINE_EVENT 402 402 #define DEFINE_EVENT(template, name, proto, args) \ 403 403 \ 404 - static void ftrace_profile_##name(proto); \ 404 + static void perf_trace_##name(proto); \ 405 405 \ 406 406 static notrace int \ 407 - ftrace_profile_enable_##name(struct ftrace_event_call *unused) \ 407 + perf_trace_enable_##name(struct ftrace_event_call *unused) \ 408 408 { \ 409 - return register_trace_##name(ftrace_profile_##name); \ 409 + return register_trace_##name(perf_trace_##name); \ 410 410 } \ 411 411 \ 412 412 static notrace void \ 413 - ftrace_profile_disable_##name(struct ftrace_event_call *unused) \ 413 + perf_trace_disable_##name(struct ftrace_event_call *unused) \ 414 414 { \ 415 - unregister_trace_##name(ftrace_profile_##name); \ 415 + unregister_trace_##name(perf_trace_##name); \ 416 416 } 417 417 418 418 #undef DEFINE_EVENT_PRINT ··· 507 507 508 508 #ifdef CONFIG_PERF_EVENTS 509 509 510 - #define _TRACE_PROFILE_INIT(call) \ 511 - .profile_enable = ftrace_profile_enable_##call, \ 512 - .profile_disable = ftrace_profile_disable_##call, 510 + #define _TRACE_PERF_INIT(call) \ 511 + .perf_event_enable = perf_trace_enable_##call, \ 512 + .perf_event_disable = perf_trace_disable_##call, 513 513 514 514 #else 515 - #define _TRACE_PROFILE_INIT(call) 515 + #define _TRACE_PERF_INIT(call) 516 516 #endif /* CONFIG_PERF_EVENTS */ 517 517 518 518 #undef __entry ··· 638 638 .unregfunc = ftrace_raw_unreg_event_##call, \ 639 639 .print_fmt = print_fmt_##template, \ 640 640 .define_fields = ftrace_define_fields_##template, \ 641 - _TRACE_PROFILE_INIT(call) \ 641 + _TRACE_PERF_INIT(call) \ 642 642 } 643 643 644 644 #undef DEFINE_EVENT_PRINT ··· 657 657 .unregfunc = ftrace_raw_unreg_event_##call, \ 658 658 .print_fmt = print_fmt_##call, \ 659 659 .define_fields = ftrace_define_fields_##template, \ 660 - _TRACE_PROFILE_INIT(call) \ 660 + _TRACE_PERF_INIT(call) \ 661 661 } 662 662 663 663 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) 664 664 665 665 /* 666 - * Define the insertion callback to profile events 666 + * Define the insertion callback to perf events 667 667 * 668 668 * The job is very similar to ftrace_raw_event_<call> except that we don't 669 669 * insert in the ring buffer but in a perf counter. 670 670 * 671 - * static void ftrace_profile_<call>(proto) 671 + * static void ftrace_perf_<call>(proto) 672 672 * { 673 673 * struct ftrace_data_offsets_<call> __maybe_unused __data_offsets; 674 674 * struct ftrace_event_call *event_call = &event_<call>; ··· 757 757 #undef DECLARE_EVENT_CLASS 758 758 #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ 759 759 static notrace void \ 760 - ftrace_profile_templ_##call(struct ftrace_event_call *event_call, \ 760 + perf_trace_templ_##call(struct ftrace_event_call *event_call, \ 761 761 proto) \ 762 762 { \ 763 763 struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ 764 764 struct ftrace_raw_##call *entry; \ 765 765 u64 __addr = 0, __count = 1; \ 766 766 unsigned long irq_flags; \ 767 + struct pt_regs *__regs; \ 767 768 int __entry_size; \ 768 769 int __data_size; \ 769 770 int rctx; \ ··· 774 773 sizeof(u64)); \ 775 774 __entry_size -= sizeof(u32); \ 776 775 \ 777 - if (WARN_ONCE(__entry_size > FTRACE_MAX_PROFILE_SIZE, \ 776 + if (WARN_ONCE(__entry_size > PERF_MAX_TRACE_SIZE, \ 778 777 "profile buffer not large enough")) \ 779 778 return; \ 780 - entry = (struct ftrace_raw_##call *)ftrace_perf_buf_prepare( \ 779 + entry = (struct ftrace_raw_##call *)perf_trace_buf_prepare( \ 781 780 __entry_size, event_call->id, &rctx, &irq_flags); \ 782 781 if (!entry) \ 783 782 return; \ ··· 785 784 \ 786 785 { assign; } \ 787 786 \ 788 - ftrace_perf_buf_submit(entry, __entry_size, rctx, __addr, \ 789 - __count, irq_flags); \ 787 + __regs = &__get_cpu_var(perf_trace_regs); \ 788 + perf_fetch_caller_regs(__regs, 2); \ 789 + \ 790 + perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \ 791 + __count, irq_flags, __regs); \ 790 792 } 791 793 792 794 #undef DEFINE_EVENT 793 795 #define DEFINE_EVENT(template, call, proto, args) \ 794 - static notrace void ftrace_profile_##call(proto) \ 796 + static notrace void perf_trace_##call(proto) \ 795 797 { \ 796 798 struct ftrace_event_call *event_call = &event_##call; \ 797 799 \ 798 - ftrace_profile_templ_##template(event_call, args); \ 800 + perf_trace_templ_##template(event_call, args); \ 799 801 } 800 802 801 803 #undef DEFINE_EVENT_PRINT
+4 -4
include/trace/syscall.h
··· 47 47 #endif 48 48 49 49 #ifdef CONFIG_PERF_EVENTS 50 - int prof_sysenter_enable(struct ftrace_event_call *call); 51 - void prof_sysenter_disable(struct ftrace_event_call *call); 52 - int prof_sysexit_enable(struct ftrace_event_call *call); 53 - void prof_sysexit_disable(struct ftrace_event_call *call); 50 + int perf_sysenter_enable(struct ftrace_event_call *call); 51 + void perf_sysenter_disable(struct ftrace_event_call *call); 52 + int perf_sysexit_enable(struct ftrace_event_call *call); 53 + void perf_sysexit_disable(struct ftrace_event_call *call); 54 54 #endif 55 55 56 56 #endif /* _TRACE_SYSCALL_H */
+2 -1
kernel/kprobes.c
··· 259 259 struct kprobe_insn_page *kip; 260 260 261 261 list_for_each_entry(kip, &c->pages, list) { 262 - long idx = ((long)slot - (long)kip->insns) / c->insn_size; 262 + long idx = ((long)slot - (long)kip->insns) / 263 + (c->insn_size * sizeof(kprobe_opcode_t)); 263 264 if (idx >= 0 && idx < slots_per_page(c)) { 264 265 WARN_ON(kip->slot_used[idx] != SLOT_USED); 265 266 if (dirty) {
+3 -6
kernel/lockdep.c
··· 3211 3211 { 3212 3212 unsigned long flags; 3213 3213 3214 - trace_lock_acquire(lock, subclass, trylock, read, check, nest_lock, ip); 3215 - 3216 3214 if (unlikely(current->lockdep_recursion)) 3217 3215 return; 3218 3216 ··· 3218 3220 check_flags(flags); 3219 3221 3220 3222 current->lockdep_recursion = 1; 3223 + trace_lock_acquire(lock, subclass, trylock, read, check, nest_lock, ip); 3221 3224 __lock_acquire(lock, subclass, trylock, read, check, 3222 3225 irqs_disabled_flags(flags), nest_lock, ip, 0); 3223 3226 current->lockdep_recursion = 0; ··· 3231 3232 { 3232 3233 unsigned long flags; 3233 3234 3234 - trace_lock_release(lock, nested, ip); 3235 - 3236 3235 if (unlikely(current->lockdep_recursion)) 3237 3236 return; 3238 3237 3239 3238 raw_local_irq_save(flags); 3240 3239 check_flags(flags); 3241 3240 current->lockdep_recursion = 1; 3241 + trace_lock_release(lock, nested, ip); 3242 3242 __lock_release(lock, nested, ip); 3243 3243 current->lockdep_recursion = 0; 3244 3244 raw_local_irq_restore(flags); ··· 3411 3413 { 3412 3414 unsigned long flags; 3413 3415 3414 - trace_lock_contended(lock, ip); 3415 - 3416 3416 if (unlikely(!lock_stat)) 3417 3417 return; 3418 3418 ··· 3420 3424 raw_local_irq_save(flags); 3421 3425 check_flags(flags); 3422 3426 current->lockdep_recursion = 1; 3427 + trace_lock_contended(lock, ip); 3423 3428 __lock_contended(lock, ip); 3424 3429 current->lockdep_recursion = 0; 3425 3430 raw_local_irq_restore(flags);
+41 -43
kernel/perf_event.c
··· 81 81 void __weak hw_perf_disable(void) { barrier(); } 82 82 void __weak hw_perf_enable(void) { barrier(); } 83 83 84 - void __weak hw_perf_event_setup(int cpu) { barrier(); } 85 - void __weak hw_perf_event_setup_online(int cpu) { barrier(); } 86 - void __weak hw_perf_event_setup_offline(int cpu) { barrier(); } 87 - 88 84 int __weak 89 85 hw_perf_group_sched_in(struct perf_event *group_leader, 90 86 struct perf_cpu_context *cpuctx, ··· 93 97 94 98 static DEFINE_PER_CPU(int, perf_disable_count); 95 99 96 - void __perf_disable(void) 97 - { 98 - __get_cpu_var(perf_disable_count)++; 99 - } 100 - 101 - bool __perf_enable(void) 102 - { 103 - return !--__get_cpu_var(perf_disable_count); 104 - } 105 - 106 100 void perf_disable(void) 107 101 { 108 - __perf_disable(); 109 - hw_perf_disable(); 102 + if (!__get_cpu_var(perf_disable_count)++) 103 + hw_perf_disable(); 110 104 } 111 105 112 106 void perf_enable(void) 113 107 { 114 - if (__perf_enable()) 108 + if (!--__get_cpu_var(perf_disable_count)) 115 109 hw_perf_enable(); 116 110 } 117 111 ··· 1524 1538 */ 1525 1539 if (interrupts == MAX_INTERRUPTS) { 1526 1540 perf_log_throttle(event, 1); 1541 + perf_disable(); 1527 1542 event->pmu->unthrottle(event); 1543 + perf_enable(); 1528 1544 } 1529 1545 1530 1546 if (!event->attr.freq || !event->attr.sample_freq) 1531 1547 continue; 1532 1548 1549 + perf_disable(); 1533 1550 event->pmu->read(event); 1534 1551 now = atomic64_read(&event->count); 1535 1552 delta = now - hwc->freq_count_stamp; ··· 1540 1551 1541 1552 if (delta > 0) 1542 1553 perf_adjust_period(event, TICK_NSEC, delta); 1554 + perf_enable(); 1543 1555 } 1544 1556 raw_spin_unlock(&ctx->lock); 1545 1557 } ··· 1550 1560 */ 1551 1561 static void rotate_ctx(struct perf_event_context *ctx) 1552 1562 { 1553 - if (!ctx->nr_events) 1554 - return; 1555 - 1556 1563 raw_spin_lock(&ctx->lock); 1557 1564 1558 1565 /* Rotate the first entry last of non-pinned groups */ ··· 1562 1575 { 1563 1576 struct perf_cpu_context *cpuctx; 1564 1577 struct perf_event_context *ctx; 1578 + int rotate = 0; 1565 1579 1566 1580 if (!atomic_read(&nr_events)) 1567 1581 return; 1568 1582 1569 1583 cpuctx = &__get_cpu_var(perf_cpu_context); 1570 - ctx = curr->perf_event_ctxp; 1584 + if (cpuctx->ctx.nr_events && 1585 + cpuctx->ctx.nr_events != cpuctx->ctx.nr_active) 1586 + rotate = 1; 1571 1587 1572 - perf_disable(); 1588 + ctx = curr->perf_event_ctxp; 1589 + if (ctx && ctx->nr_events && ctx->nr_events != ctx->nr_active) 1590 + rotate = 1; 1573 1591 1574 1592 perf_ctx_adjust_freq(&cpuctx->ctx); 1575 1593 if (ctx) 1576 1594 perf_ctx_adjust_freq(ctx); 1577 1595 1596 + if (!rotate) 1597 + return; 1598 + 1599 + perf_disable(); 1578 1600 cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); 1579 1601 if (ctx) 1580 1602 task_ctx_sched_out(ctx, EVENT_FLEXIBLE); ··· 1595 1599 cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE); 1596 1600 if (ctx) 1597 1601 task_ctx_sched_in(curr, EVENT_FLEXIBLE); 1598 - 1599 1602 perf_enable(); 1600 1603 } 1601 1604 ··· 2785 2790 { 2786 2791 return NULL; 2787 2792 } 2793 + 2794 + #ifdef CONFIG_EVENT_TRACING 2795 + __weak 2796 + void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) 2797 + { 2798 + } 2799 + #endif 2788 2800 2789 2801 /* 2790 2802 * Output ··· 4320 4318 #ifdef CONFIG_EVENT_TRACING 4321 4319 4322 4320 void perf_tp_event(int event_id, u64 addr, u64 count, void *record, 4323 - int entry_size) 4321 + int entry_size, struct pt_regs *regs) 4324 4322 { 4325 - struct pt_regs *regs = get_irq_regs(); 4326 4323 struct perf_sample_data data; 4327 4324 struct perf_raw_record raw = { 4328 4325 .size = entry_size, ··· 4331 4330 perf_sample_data_init(&data, addr); 4332 4331 data.raw = &raw; 4333 4332 4334 - if (!regs) 4335 - regs = task_pt_regs(current); 4336 - 4337 4333 /* Trace events already protected against recursion */ 4338 4334 do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1, 4339 - &data, regs); 4335 + &data, regs); 4340 4336 } 4341 4337 EXPORT_SYMBOL_GPL(perf_tp_event); 4342 4338 ··· 4349 4351 4350 4352 static void tp_perf_event_destroy(struct perf_event *event) 4351 4353 { 4352 - ftrace_profile_disable(event->attr.config); 4354 + perf_trace_disable(event->attr.config); 4353 4355 } 4354 4356 4355 4357 static const struct pmu *tp_perf_event_init(struct perf_event *event) ··· 4363 4365 !capable(CAP_SYS_ADMIN)) 4364 4366 return ERR_PTR(-EPERM); 4365 4367 4366 - if (ftrace_profile_enable(event->attr.config)) 4368 + if (perf_trace_enable(event->attr.config)) 4367 4369 return NULL; 4368 4370 4369 4371 event->destroy = tp_perf_event_destroy; ··· 5370 5372 return ret; 5371 5373 } 5372 5374 5375 + static void __init perf_event_init_all_cpus(void) 5376 + { 5377 + int cpu; 5378 + struct perf_cpu_context *cpuctx; 5379 + 5380 + for_each_possible_cpu(cpu) { 5381 + cpuctx = &per_cpu(perf_cpu_context, cpu); 5382 + __perf_event_init_context(&cpuctx->ctx, NULL); 5383 + } 5384 + } 5385 + 5373 5386 static void __cpuinit perf_event_init_cpu(int cpu) 5374 5387 { 5375 5388 struct perf_cpu_context *cpuctx; 5376 5389 5377 5390 cpuctx = &per_cpu(perf_cpu_context, cpu); 5378 - __perf_event_init_context(&cpuctx->ctx, NULL); 5379 5391 5380 5392 spin_lock(&perf_resource_lock); 5381 5393 cpuctx->max_pertask = perf_max_events - perf_reserved_percpu; 5382 5394 spin_unlock(&perf_resource_lock); 5383 - 5384 - hw_perf_event_setup(cpu); 5385 5395 } 5386 5396 5387 5397 #ifdef CONFIG_HOTPLUG_CPU ··· 5429 5423 perf_event_init_cpu(cpu); 5430 5424 break; 5431 5425 5432 - case CPU_ONLINE: 5433 - case CPU_ONLINE_FROZEN: 5434 - hw_perf_event_setup_online(cpu); 5435 - break; 5436 - 5437 5426 case CPU_DOWN_PREPARE: 5438 5427 case CPU_DOWN_PREPARE_FROZEN: 5439 5428 perf_event_exit_cpu(cpu); 5440 - break; 5441 - 5442 - case CPU_DEAD: 5443 - hw_perf_event_setup_offline(cpu); 5444 5429 break; 5445 5430 5446 5431 default: ··· 5451 5454 5452 5455 void __init perf_event_init(void) 5453 5456 { 5457 + perf_event_init_all_cpus(); 5454 5458 perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_UP_PREPARE, 5455 5459 (void *)(long)smp_processor_id()); 5456 5460 perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_ONLINE,
+1 -1
kernel/trace/Makefile
··· 52 52 obj-$(CONFIG_EVENT_TRACING) += trace_export.o 53 53 obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o 54 54 ifeq ($(CONFIG_PERF_EVENTS),y) 55 - obj-$(CONFIG_EVENT_TRACING) += trace_event_profile.o 55 + obj-$(CONFIG_EVENT_TRACING) += trace_event_perf.o 56 56 endif 57 57 obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o 58 58 obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o
+27 -23
kernel/trace/trace_event_profile.c kernel/trace/trace_event_perf.c
··· 1 1 /* 2 - * trace event based perf counter profiling 2 + * trace event based perf event profiling/tracing 3 3 * 4 4 * Copyright (C) 2009 Red Hat Inc, Peter Zijlstra <pzijlstr@redhat.com> 5 - * 5 + * Copyright (C) 2009-2010 Frederic Weisbecker <fweisbec@gmail.com> 6 6 */ 7 7 8 8 #include <linux/module.h> 9 9 #include <linux/kprobes.h> 10 10 #include "trace.h" 11 11 12 + DEFINE_PER_CPU(struct pt_regs, perf_trace_regs); 13 + EXPORT_PER_CPU_SYMBOL_GPL(perf_trace_regs); 14 + 15 + EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs); 12 16 13 17 static char *perf_trace_buf; 14 18 static char *perf_trace_buf_nmi; 15 19 16 - typedef typeof(char [FTRACE_MAX_PROFILE_SIZE]) perf_trace_t ; 20 + typedef typeof(char [PERF_MAX_TRACE_SIZE]) perf_trace_t ; 17 21 18 22 /* Count the events in use (per event id, not per instance) */ 19 - static int total_profile_count; 23 + static int total_ref_count; 20 24 21 - static int ftrace_profile_enable_event(struct ftrace_event_call *event) 25 + static int perf_trace_event_enable(struct ftrace_event_call *event) 22 26 { 23 27 char *buf; 24 28 int ret = -ENOMEM; 25 29 26 - if (event->profile_count++ > 0) 30 + if (event->perf_refcount++ > 0) 27 31 return 0; 28 32 29 - if (!total_profile_count) { 33 + if (!total_ref_count) { 30 34 buf = (char *)alloc_percpu(perf_trace_t); 31 35 if (!buf) 32 36 goto fail_buf; ··· 44 40 rcu_assign_pointer(perf_trace_buf_nmi, buf); 45 41 } 46 42 47 - ret = event->profile_enable(event); 43 + ret = event->perf_event_enable(event); 48 44 if (!ret) { 49 - total_profile_count++; 45 + total_ref_count++; 50 46 return 0; 51 47 } 52 48 53 49 fail_buf_nmi: 54 - if (!total_profile_count) { 50 + if (!total_ref_count) { 55 51 free_percpu(perf_trace_buf_nmi); 56 52 free_percpu(perf_trace_buf); 57 53 perf_trace_buf_nmi = NULL; 58 54 perf_trace_buf = NULL; 59 55 } 60 56 fail_buf: 61 - event->profile_count--; 57 + event->perf_refcount--; 62 58 63 59 return ret; 64 60 } 65 61 66 - int ftrace_profile_enable(int event_id) 62 + int perf_trace_enable(int event_id) 67 63 { 68 64 struct ftrace_event_call *event; 69 65 int ret = -EINVAL; 70 66 71 67 mutex_lock(&event_mutex); 72 68 list_for_each_entry(event, &ftrace_events, list) { 73 - if (event->id == event_id && event->profile_enable && 69 + if (event->id == event_id && event->perf_event_enable && 74 70 try_module_get(event->mod)) { 75 - ret = ftrace_profile_enable_event(event); 71 + ret = perf_trace_event_enable(event); 76 72 break; 77 73 } 78 74 } ··· 81 77 return ret; 82 78 } 83 79 84 - static void ftrace_profile_disable_event(struct ftrace_event_call *event) 80 + static void perf_trace_event_disable(struct ftrace_event_call *event) 85 81 { 86 82 char *buf, *nmi_buf; 87 83 88 - if (--event->profile_count > 0) 84 + if (--event->perf_refcount > 0) 89 85 return; 90 86 91 - event->profile_disable(event); 87 + event->perf_event_disable(event); 92 88 93 - if (!--total_profile_count) { 89 + if (!--total_ref_count) { 94 90 buf = perf_trace_buf; 95 91 rcu_assign_pointer(perf_trace_buf, NULL); 96 92 ··· 108 104 } 109 105 } 110 106 111 - void ftrace_profile_disable(int event_id) 107 + void perf_trace_disable(int event_id) 112 108 { 113 109 struct ftrace_event_call *event; 114 110 115 111 mutex_lock(&event_mutex); 116 112 list_for_each_entry(event, &ftrace_events, list) { 117 113 if (event->id == event_id) { 118 - ftrace_profile_disable_event(event); 114 + perf_trace_event_disable(event); 119 115 module_put(event->mod); 120 116 break; 121 117 } ··· 123 119 mutex_unlock(&event_mutex); 124 120 } 125 121 126 - __kprobes void *ftrace_perf_buf_prepare(int size, unsigned short type, 127 - int *rctxp, unsigned long *irq_flags) 122 + __kprobes void *perf_trace_buf_prepare(int size, unsigned short type, 123 + int *rctxp, unsigned long *irq_flags) 128 124 { 129 125 struct trace_entry *entry; 130 126 char *trace_buf, *raw_data; ··· 165 161 local_irq_restore(*irq_flags); 166 162 return NULL; 167 163 } 168 - EXPORT_SYMBOL_GPL(ftrace_perf_buf_prepare); 164 + EXPORT_SYMBOL_GPL(perf_trace_buf_prepare);
+1 -1
kernel/trace/trace_events.c
··· 938 938 trace_create_file("enable", 0644, call->dir, call, 939 939 enable); 940 940 941 - if (call->id && call->profile_enable) 941 + if (call->id && call->perf_event_enable) 942 942 trace_create_file("id", 0444, call->dir, call, 943 943 id); 944 944
+15 -14
kernel/trace/trace_kprobe.c
··· 1214 1214 #ifdef CONFIG_PERF_EVENTS 1215 1215 1216 1216 /* Kprobe profile handler */ 1217 - static __kprobes void kprobe_profile_func(struct kprobe *kp, 1217 + static __kprobes void kprobe_perf_func(struct kprobe *kp, 1218 1218 struct pt_regs *regs) 1219 1219 { 1220 1220 struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); ··· 1227 1227 __size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args); 1228 1228 size = ALIGN(__size + sizeof(u32), sizeof(u64)); 1229 1229 size -= sizeof(u32); 1230 - if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE, 1230 + if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, 1231 1231 "profile buffer not large enough")) 1232 1232 return; 1233 1233 1234 - entry = ftrace_perf_buf_prepare(size, call->id, &rctx, &irq_flags); 1234 + entry = perf_trace_buf_prepare(size, call->id, &rctx, &irq_flags); 1235 1235 if (!entry) 1236 1236 return; 1237 1237 ··· 1240 1240 for (i = 0; i < tp->nr_args; i++) 1241 1241 entry->args[i] = call_fetch(&tp->args[i].fetch, regs); 1242 1242 1243 - ftrace_perf_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags); 1243 + perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs); 1244 1244 } 1245 1245 1246 1246 /* Kretprobe profile handler */ 1247 - static __kprobes void kretprobe_profile_func(struct kretprobe_instance *ri, 1247 + static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, 1248 1248 struct pt_regs *regs) 1249 1249 { 1250 1250 struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); ··· 1257 1257 __size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args); 1258 1258 size = ALIGN(__size + sizeof(u32), sizeof(u64)); 1259 1259 size -= sizeof(u32); 1260 - if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE, 1260 + if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, 1261 1261 "profile buffer not large enough")) 1262 1262 return; 1263 1263 1264 - entry = ftrace_perf_buf_prepare(size, call->id, &rctx, &irq_flags); 1264 + entry = perf_trace_buf_prepare(size, call->id, &rctx, &irq_flags); 1265 1265 if (!entry) 1266 1266 return; 1267 1267 ··· 1271 1271 for (i = 0; i < tp->nr_args; i++) 1272 1272 entry->args[i] = call_fetch(&tp->args[i].fetch, regs); 1273 1273 1274 - ftrace_perf_buf_submit(entry, size, rctx, entry->ret_ip, 1, irq_flags); 1274 + perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, 1275 + irq_flags, regs); 1275 1276 } 1276 1277 1277 - static int probe_profile_enable(struct ftrace_event_call *call) 1278 + static int probe_perf_enable(struct ftrace_event_call *call) 1278 1279 { 1279 1280 struct trace_probe *tp = (struct trace_probe *)call->data; 1280 1281 ··· 1287 1286 return enable_kprobe(&tp->rp.kp); 1288 1287 } 1289 1288 1290 - static void probe_profile_disable(struct ftrace_event_call *call) 1289 + static void probe_perf_disable(struct ftrace_event_call *call) 1291 1290 { 1292 1291 struct trace_probe *tp = (struct trace_probe *)call->data; 1293 1292 ··· 1312 1311 kprobe_trace_func(kp, regs); 1313 1312 #ifdef CONFIG_PERF_EVENTS 1314 1313 if (tp->flags & TP_FLAG_PROFILE) 1315 - kprobe_profile_func(kp, regs); 1314 + kprobe_perf_func(kp, regs); 1316 1315 #endif 1317 1316 return 0; /* We don't tweek kernel, so just return 0 */ 1318 1317 } ··· 1326 1325 kretprobe_trace_func(ri, regs); 1327 1326 #ifdef CONFIG_PERF_EVENTS 1328 1327 if (tp->flags & TP_FLAG_PROFILE) 1329 - kretprobe_profile_func(ri, regs); 1328 + kretprobe_perf_func(ri, regs); 1330 1329 #endif 1331 1330 return 0; /* We don't tweek kernel, so just return 0 */ 1332 1331 } ··· 1359 1358 call->unregfunc = probe_event_disable; 1360 1359 1361 1360 #ifdef CONFIG_PERF_EVENTS 1362 - call->profile_enable = probe_profile_enable; 1363 - call->profile_disable = probe_profile_disable; 1361 + call->perf_event_enable = probe_perf_enable; 1362 + call->perf_event_disable = probe_perf_disable; 1364 1363 #endif 1365 1364 call->data = tp; 1366 1365 ret = trace_add_event_call(call);
+36 -36
kernel/trace/trace_syscalls.c
··· 428 428 429 429 #ifdef CONFIG_PERF_EVENTS 430 430 431 - static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls); 432 - static DECLARE_BITMAP(enabled_prof_exit_syscalls, NR_syscalls); 433 - static int sys_prof_refcount_enter; 434 - static int sys_prof_refcount_exit; 431 + static DECLARE_BITMAP(enabled_perf_enter_syscalls, NR_syscalls); 432 + static DECLARE_BITMAP(enabled_perf_exit_syscalls, NR_syscalls); 433 + static int sys_perf_refcount_enter; 434 + static int sys_perf_refcount_exit; 435 435 436 - static void prof_syscall_enter(struct pt_regs *regs, long id) 436 + static void perf_syscall_enter(struct pt_regs *regs, long id) 437 437 { 438 438 struct syscall_metadata *sys_data; 439 439 struct syscall_trace_enter *rec; ··· 443 443 int size; 444 444 445 445 syscall_nr = syscall_get_nr(current, regs); 446 - if (!test_bit(syscall_nr, enabled_prof_enter_syscalls)) 446 + if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) 447 447 return; 448 448 449 449 sys_data = syscall_nr_to_meta(syscall_nr); ··· 455 455 size = ALIGN(size + sizeof(u32), sizeof(u64)); 456 456 size -= sizeof(u32); 457 457 458 - if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE, 459 - "profile buffer not large enough")) 458 + if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, 459 + "perf buffer not large enough")) 460 460 return; 461 461 462 - rec = (struct syscall_trace_enter *)ftrace_perf_buf_prepare(size, 462 + rec = (struct syscall_trace_enter *)perf_trace_buf_prepare(size, 463 463 sys_data->enter_event->id, &rctx, &flags); 464 464 if (!rec) 465 465 return; ··· 467 467 rec->nr = syscall_nr; 468 468 syscall_get_arguments(current, regs, 0, sys_data->nb_args, 469 469 (unsigned long *)&rec->args); 470 - ftrace_perf_buf_submit(rec, size, rctx, 0, 1, flags); 470 + perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs); 471 471 } 472 472 473 - int prof_sysenter_enable(struct ftrace_event_call *call) 473 + int perf_sysenter_enable(struct ftrace_event_call *call) 474 474 { 475 475 int ret = 0; 476 476 int num; ··· 478 478 num = ((struct syscall_metadata *)call->data)->syscall_nr; 479 479 480 480 mutex_lock(&syscall_trace_lock); 481 - if (!sys_prof_refcount_enter) 482 - ret = register_trace_sys_enter(prof_syscall_enter); 481 + if (!sys_perf_refcount_enter) 482 + ret = register_trace_sys_enter(perf_syscall_enter); 483 483 if (ret) { 484 484 pr_info("event trace: Could not activate" 485 485 "syscall entry trace point"); 486 486 } else { 487 - set_bit(num, enabled_prof_enter_syscalls); 488 - sys_prof_refcount_enter++; 487 + set_bit(num, enabled_perf_enter_syscalls); 488 + sys_perf_refcount_enter++; 489 489 } 490 490 mutex_unlock(&syscall_trace_lock); 491 491 return ret; 492 492 } 493 493 494 - void prof_sysenter_disable(struct ftrace_event_call *call) 494 + void perf_sysenter_disable(struct ftrace_event_call *call) 495 495 { 496 496 int num; 497 497 498 498 num = ((struct syscall_metadata *)call->data)->syscall_nr; 499 499 500 500 mutex_lock(&syscall_trace_lock); 501 - sys_prof_refcount_enter--; 502 - clear_bit(num, enabled_prof_enter_syscalls); 503 - if (!sys_prof_refcount_enter) 504 - unregister_trace_sys_enter(prof_syscall_enter); 501 + sys_perf_refcount_enter--; 502 + clear_bit(num, enabled_perf_enter_syscalls); 503 + if (!sys_perf_refcount_enter) 504 + unregister_trace_sys_enter(perf_syscall_enter); 505 505 mutex_unlock(&syscall_trace_lock); 506 506 } 507 507 508 - static void prof_syscall_exit(struct pt_regs *regs, long ret) 508 + static void perf_syscall_exit(struct pt_regs *regs, long ret) 509 509 { 510 510 struct syscall_metadata *sys_data; 511 511 struct syscall_trace_exit *rec; ··· 515 515 int size; 516 516 517 517 syscall_nr = syscall_get_nr(current, regs); 518 - if (!test_bit(syscall_nr, enabled_prof_exit_syscalls)) 518 + if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) 519 519 return; 520 520 521 521 sys_data = syscall_nr_to_meta(syscall_nr); ··· 530 530 * Impossible, but be paranoid with the future 531 531 * How to put this check outside runtime? 532 532 */ 533 - if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE, 534 - "exit event has grown above profile buffer size")) 533 + if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, 534 + "exit event has grown above perf buffer size")) 535 535 return; 536 536 537 - rec = (struct syscall_trace_exit *)ftrace_perf_buf_prepare(size, 537 + rec = (struct syscall_trace_exit *)perf_trace_buf_prepare(size, 538 538 sys_data->exit_event->id, &rctx, &flags); 539 539 if (!rec) 540 540 return; ··· 542 542 rec->nr = syscall_nr; 543 543 rec->ret = syscall_get_return_value(current, regs); 544 544 545 - ftrace_perf_buf_submit(rec, size, rctx, 0, 1, flags); 545 + perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs); 546 546 } 547 547 548 - int prof_sysexit_enable(struct ftrace_event_call *call) 548 + int perf_sysexit_enable(struct ftrace_event_call *call) 549 549 { 550 550 int ret = 0; 551 551 int num; ··· 553 553 num = ((struct syscall_metadata *)call->data)->syscall_nr; 554 554 555 555 mutex_lock(&syscall_trace_lock); 556 - if (!sys_prof_refcount_exit) 557 - ret = register_trace_sys_exit(prof_syscall_exit); 556 + if (!sys_perf_refcount_exit) 557 + ret = register_trace_sys_exit(perf_syscall_exit); 558 558 if (ret) { 559 559 pr_info("event trace: Could not activate" 560 560 "syscall exit trace point"); 561 561 } else { 562 - set_bit(num, enabled_prof_exit_syscalls); 563 - sys_prof_refcount_exit++; 562 + set_bit(num, enabled_perf_exit_syscalls); 563 + sys_perf_refcount_exit++; 564 564 } 565 565 mutex_unlock(&syscall_trace_lock); 566 566 return ret; 567 567 } 568 568 569 - void prof_sysexit_disable(struct ftrace_event_call *call) 569 + void perf_sysexit_disable(struct ftrace_event_call *call) 570 570 { 571 571 int num; 572 572 573 573 num = ((struct syscall_metadata *)call->data)->syscall_nr; 574 574 575 575 mutex_lock(&syscall_trace_lock); 576 - sys_prof_refcount_exit--; 577 - clear_bit(num, enabled_prof_exit_syscalls); 578 - if (!sys_prof_refcount_exit) 579 - unregister_trace_sys_exit(prof_syscall_exit); 576 + sys_perf_refcount_exit--; 577 + clear_bit(num, enabled_perf_exit_syscalls); 578 + if (!sys_perf_refcount_exit) 579 + unregister_trace_sys_exit(perf_syscall_exit); 580 580 mutex_unlock(&syscall_trace_lock); 581 581 } 582 582
+3 -1
tools/perf/Documentation/Makefile
··· 24 24 DOC_MAN5=$(patsubst %.txt,%.5,$(MAN5_TXT)) 25 25 DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT)) 26 26 27 + # Make the path relative to DESTDIR, not prefix 28 + ifndef DESTDIR 27 29 prefix?=$(HOME) 30 + endif 28 31 bindir?=$(prefix)/bin 29 32 htmldir?=$(prefix)/share/doc/perf-doc 30 33 pdfdir?=$(prefix)/share/doc/perf-doc ··· 35 32 man1dir=$(mandir)/man1 36 33 man5dir=$(mandir)/man5 37 34 man7dir=$(mandir)/man7 38 - # DESTDIR= 39 35 40 36 ASCIIDOC=asciidoc 41 37 ASCIIDOC_EXTRA = --unsafe
+5 -1
tools/perf/Makefile
··· 216 216 # runtime figures out where they are based on the path to the executable. 217 217 # This can help installing the suite in a relocatable way. 218 218 219 + # Make the path relative to DESTDIR, not to prefix 220 + ifndef DESTDIR 219 221 prefix = $(HOME) 222 + endif 220 223 bindir_relative = bin 221 224 bindir = $(prefix)/$(bindir_relative) 222 225 mandir = share/man ··· 236 233 ETC_PERFCONFIG = etc/perfconfig 237 234 endif 238 235 lib = lib 239 - # DESTDIR= 240 236 241 237 export prefix bindir sharedir sysconfdir 242 238 ··· 389 387 LIB_H += util/trace-event.h 390 388 LIB_H += util/probe-finder.h 391 389 LIB_H += util/probe-event.h 390 + LIB_H += util/cpumap.h 392 391 393 392 LIB_OBJS += util/abspath.o 394 393 LIB_OBJS += util/alias.o ··· 436 433 LIB_OBJS += util/hist.o 437 434 LIB_OBJS += util/probe-event.o 438 435 LIB_OBJS += util/util.o 436 + LIB_OBJS += util/cpumap.o 439 437 440 438 BUILTIN_OBJS += builtin-annotate.o 441 439
+3 -3
tools/perf/builtin-annotate.c
··· 116 116 return 0; 117 117 } 118 118 119 - he = __perf_session__add_hist_entry(self, al, NULL, count, &hit); 119 + he = __perf_session__add_hist_entry(&self->hists, al, NULL, count, &hit); 120 120 if (he == NULL) 121 121 return -ENOMEM; 122 122 ··· 564 564 if (verbose > 2) 565 565 dsos__fprintf(stdout); 566 566 567 - perf_session__collapse_resort(session); 568 - perf_session__output_resort(session, session->event_total[0]); 567 + perf_session__collapse_resort(&session->hists); 568 + perf_session__output_resort(&session->hists, session->event_total[0]); 569 569 perf_session__find_annotations(session); 570 570 out_delete: 571 571 perf_session__delete(session);
+8 -5
tools/perf/builtin-diff.c
··· 26 26 struct addr_location *al, u64 count) 27 27 { 28 28 bool hit; 29 - struct hist_entry *he = __perf_session__add_hist_entry(self, al, NULL, 29 + struct hist_entry *he = __perf_session__add_hist_entry(&self->hists, 30 + al, NULL, 30 31 count, &hit); 31 32 if (he == NULL) 32 33 return -ENOMEM; ··· 115 114 116 115 static void perf_session__set_hist_entries_positions(struct perf_session *self) 117 116 { 118 - perf_session__output_resort(self, self->events_stats.total); 117 + perf_session__output_resort(&self->hists, self->events_stats.total); 119 118 perf_session__resort_hist_entries(self); 120 119 } 121 120 ··· 167 166 goto out_delete; 168 167 } 169 168 170 - perf_session__output_resort(session[1], session[1]->events_stats.total); 169 + perf_session__output_resort(&session[1]->hists, 170 + session[1]->events_stats.total); 171 171 if (show_displacement) 172 172 perf_session__set_hist_entries_positions(session[0]); 173 173 174 174 perf_session__match_hists(session[0], session[1]); 175 - perf_session__fprintf_hists(session[1], session[0], 176 - show_displacement, stdout); 175 + perf_session__fprintf_hists(&session[1]->hists, session[0], 176 + show_displacement, stdout, 177 + session[1]->events_stats.total); 177 178 out_delete: 178 179 for (i = 0; i < 2; ++i) 179 180 perf_session__delete(session[i]);
+9 -4
tools/perf/builtin-record.c
··· 22 22 #include "util/debug.h" 23 23 #include "util/session.h" 24 24 #include "util/symbol.h" 25 + #include "util/cpumap.h" 25 26 26 27 #include <unistd.h> 27 28 #include <sched.h> ··· 245 244 246 245 attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; 247 246 247 + if (nr_counters > 1) 248 + attr->sample_type |= PERF_SAMPLE_ID; 249 + 248 250 if (freq) { 249 251 attr->sample_type |= PERF_SAMPLE_PERIOD; 250 252 attr->freq = 1; ··· 395 391 { 396 392 u64 size = lseek(output, 0, SEEK_CUR); 397 393 394 + if (size == 0) 395 + return 0; 396 + 398 397 session->fd = output; 399 398 return __perf_session__process_events(session, post_processing_offset, 400 399 size - post_processing_offset, ··· 425 418 char buf; 426 419 427 420 page_size = sysconf(_SC_PAGE_SIZE); 428 - nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 429 - assert(nr_cpus <= MAX_NR_CPUS); 430 - assert(nr_cpus >= 0); 431 421 432 422 atexit(sig_atexit); 433 423 signal(SIGCHLD, sig_handler); ··· 548 544 if ((!system_wide && !inherit) || profile_cpu != -1) { 549 545 open_counters(profile_cpu, target_pid); 550 546 } else { 547 + nr_cpus = read_cpu_map(); 551 548 for (i = 0; i < nr_cpus; i++) 552 - open_counters(i, target_pid); 549 + open_counters(cpumap[i], target_pid); 553 550 } 554 551 555 552 if (file_new) {
+100 -12
tools/perf/builtin-report.c
··· 45 45 46 46 static char callchain_default_opt[] = "fractal,0.5"; 47 47 48 + static struct event_stat_id *get_stats(struct perf_session *self, 49 + u64 event_stream, u32 type, u64 config) 50 + { 51 + struct rb_node **p = &self->stats_by_id.rb_node; 52 + struct rb_node *parent = NULL; 53 + struct event_stat_id *iter, *new; 54 + 55 + while (*p != NULL) { 56 + parent = *p; 57 + iter = rb_entry(parent, struct event_stat_id, rb_node); 58 + if (iter->config == config) 59 + return iter; 60 + 61 + 62 + if (config > iter->config) 63 + p = &(*p)->rb_right; 64 + else 65 + p = &(*p)->rb_left; 66 + } 67 + 68 + new = malloc(sizeof(struct event_stat_id)); 69 + if (new == NULL) 70 + return NULL; 71 + memset(new, 0, sizeof(struct event_stat_id)); 72 + new->event_stream = event_stream; 73 + new->config = config; 74 + new->type = type; 75 + rb_link_node(&new->rb_node, parent, p); 76 + rb_insert_color(&new->rb_node, &self->stats_by_id); 77 + return new; 78 + } 79 + 48 80 static int perf_session__add_hist_entry(struct perf_session *self, 49 81 struct addr_location *al, 50 - struct ip_callchain *chain, u64 count) 82 + struct sample_data *data) 51 83 { 52 84 struct symbol **syms = NULL, *parent = NULL; 53 85 bool hit; 54 86 struct hist_entry *he; 87 + struct event_stat_id *stats; 88 + struct perf_event_attr *attr; 55 89 56 - if ((sort__has_parent || symbol_conf.use_callchain) && chain) 90 + if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) 57 91 syms = perf_session__resolve_callchain(self, al->thread, 58 - chain, &parent); 59 - he = __perf_session__add_hist_entry(self, al, parent, count, &hit); 92 + data->callchain, &parent); 93 + 94 + attr = perf_header__find_attr(data->id, &self->header); 95 + if (attr) 96 + stats = get_stats(self, data->id, attr->type, attr->config); 97 + else 98 + stats = get_stats(self, data->id, 0, 0); 99 + if (stats == NULL) 100 + return -ENOMEM; 101 + he = __perf_session__add_hist_entry(&stats->hists, al, parent, 102 + data->period, &hit); 60 103 if (he == NULL) 61 104 return -ENOMEM; 62 105 63 106 if (hit) 64 - he->count += count; 107 + he->count += data->period; 65 108 66 109 if (symbol_conf.use_callchain) { 67 110 if (!hit) 68 111 callchain_init(&he->callchain); 69 - append_chain(&he->callchain, chain, syms); 112 + append_chain(&he->callchain, data->callchain, syms); 70 113 free(syms); 71 114 } 72 115 ··· 129 86 return 0; 130 87 } 131 88 89 + static int add_event_total(struct perf_session *session, 90 + struct sample_data *data, 91 + struct perf_event_attr *attr) 92 + { 93 + struct event_stat_id *stats; 94 + 95 + if (attr) 96 + stats = get_stats(session, data->id, attr->type, attr->config); 97 + else 98 + stats = get_stats(session, data->id, 0, 0); 99 + 100 + if (!stats) 101 + return -ENOMEM; 102 + 103 + stats->stats.total += data->period; 104 + session->events_stats.total += data->period; 105 + return 0; 106 + } 107 + 132 108 static int process_sample_event(event_t *event, struct perf_session *session) 133 109 { 134 110 struct sample_data data = { .period = 1, }; 135 111 struct addr_location al; 112 + struct perf_event_attr *attr; 136 113 137 114 event__parse_sample(event, session->sample_type, &data); 138 115 ··· 186 123 if (al.filtered || (hide_unresolved && al.sym == NULL)) 187 124 return 0; 188 125 189 - if (perf_session__add_hist_entry(session, &al, data.callchain, data.period)) { 126 + if (perf_session__add_hist_entry(session, &al, &data)) { 190 127 pr_debug("problem incrementing symbol count, skipping event\n"); 191 128 return -1; 192 129 } 193 130 194 - session->events_stats.total += data.period; 131 + attr = perf_header__find_attr(data.id, &session->header); 132 + 133 + if (add_event_total(session, &data, attr)) { 134 + pr_debug("problem adding event count\n"); 135 + return -1; 136 + } 137 + 195 138 return 0; 196 139 } 197 140 ··· 266 197 { 267 198 int ret = -EINVAL; 268 199 struct perf_session *session; 200 + struct rb_node *next; 269 201 270 202 session = perf_session__new(input_name, O_RDONLY, force); 271 203 if (session == NULL) ··· 294 224 if (verbose > 2) 295 225 dsos__fprintf(stdout); 296 226 297 - perf_session__collapse_resort(session); 298 - perf_session__output_resort(session, session->events_stats.total); 299 - fprintf(stdout, "# Samples: %Ld\n#\n", session->events_stats.total); 300 - perf_session__fprintf_hists(session, NULL, false, stdout); 227 + next = rb_first(&session->stats_by_id); 228 + while (next) { 229 + struct event_stat_id *stats; 230 + 231 + stats = rb_entry(next, struct event_stat_id, rb_node); 232 + perf_session__collapse_resort(&stats->hists); 233 + perf_session__output_resort(&stats->hists, stats->stats.total); 234 + if (rb_first(&session->stats_by_id) == 235 + rb_last(&session->stats_by_id)) 236 + fprintf(stdout, "# Samples: %Ld\n#\n", 237 + stats->stats.total); 238 + else 239 + fprintf(stdout, "# Samples: %Ld %s\n#\n", 240 + stats->stats.total, 241 + __event_name(stats->type, stats->config)); 242 + 243 + perf_session__fprintf_hists(&stats->hists, NULL, false, stdout, 244 + stats->stats.total); 245 + fprintf(stdout, "\n\n"); 246 + next = rb_next(&stats->rb_node); 247 + } 248 + 301 249 if (sort_order == default_sort_order && 302 250 parent_pattern == default_parent_pattern) 303 251 fprintf(stdout, "#\n# (For a higher level overview, try: perf report --sort comm,dso)\n#\n");
+6 -4
tools/perf/builtin-stat.c
··· 45 45 #include "util/event.h" 46 46 #include "util/debug.h" 47 47 #include "util/header.h" 48 + #include "util/cpumap.h" 48 49 49 50 #include <sys/prctl.h> 50 51 #include <math.h> ··· 152 151 unsigned int cpu; 153 152 154 153 for (cpu = 0; cpu < nr_cpus; cpu++) { 155 - fd[cpu][counter] = sys_perf_event_open(attr, -1, cpu, -1, 0); 154 + fd[cpu][counter] = sys_perf_event_open(attr, -1, cpumap[cpu], -1, 0); 156 155 if (fd[cpu][counter] < 0 && verbose) 157 156 fprintf(stderr, ERR_PERF_OPEN, counter, 158 157 fd[cpu][counter], strerror(errno)); ··· 520 519 nr_counters = ARRAY_SIZE(default_attrs); 521 520 } 522 521 523 - nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 524 - assert(nr_cpus <= MAX_NR_CPUS); 525 - assert((int)nr_cpus >= 0); 522 + if (system_wide) 523 + nr_cpus = read_cpu_map(); 524 + else 525 + nr_cpus = 1; 526 526 527 527 /* 528 528 * We dont want to block the signals - that would cause
+4 -5
tools/perf/builtin-top.c
··· 28 28 #include <linux/rbtree.h> 29 29 #include "util/parse-options.h" 30 30 #include "util/parse-events.h" 31 + #include "util/cpumap.h" 31 32 32 33 #include "util/debug.h" 33 34 ··· 1124 1123 1125 1124 cpu = profile_cpu; 1126 1125 if (target_pid == -1 && profile_cpu == -1) 1127 - cpu = i; 1126 + cpu = cpumap[i]; 1128 1127 1129 1128 attr = attrs + counter; 1130 1129 ··· 1348 1347 attrs[counter].sample_period = default_interval; 1349 1348 } 1350 1349 1351 - nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 1352 - assert(nr_cpus <= MAX_NR_CPUS); 1353 - assert(nr_cpus >= 0); 1354 - 1355 1350 if (target_pid != -1 || profile_cpu != -1) 1356 1351 nr_cpus = 1; 1352 + else 1353 + nr_cpus = read_cpu_map(); 1357 1354 1358 1355 get_term_dimensions(&winsize); 1359 1356 if (print_entries == 0) {
+59
tools/perf/util/cpumap.c
··· 1 + #include "util.h" 2 + #include "../perf.h" 3 + #include "cpumap.h" 4 + #include <assert.h> 5 + #include <stdio.h> 6 + 7 + int cpumap[MAX_NR_CPUS]; 8 + 9 + static int default_cpu_map(void) 10 + { 11 + int nr_cpus, i; 12 + 13 + nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); 14 + assert(nr_cpus <= MAX_NR_CPUS); 15 + assert((int)nr_cpus >= 0); 16 + 17 + for (i = 0; i < nr_cpus; ++i) 18 + cpumap[i] = i; 19 + 20 + return nr_cpus; 21 + } 22 + 23 + int read_cpu_map(void) 24 + { 25 + FILE *onlnf; 26 + int nr_cpus = 0; 27 + int n, cpu, prev; 28 + char sep; 29 + 30 + onlnf = fopen("/sys/devices/system/cpu/online", "r"); 31 + if (!onlnf) 32 + return default_cpu_map(); 33 + 34 + sep = 0; 35 + prev = -1; 36 + for (;;) { 37 + n = fscanf(onlnf, "%u%c", &cpu, &sep); 38 + if (n <= 0) 39 + break; 40 + if (prev >= 0) { 41 + assert(nr_cpus + cpu - prev - 1 < MAX_NR_CPUS); 42 + while (++prev < cpu) 43 + cpumap[nr_cpus++] = prev; 44 + } 45 + assert (nr_cpus < MAX_NR_CPUS); 46 + cpumap[nr_cpus++] = cpu; 47 + if (n == 2 && sep == '-') 48 + prev = cpu; 49 + else 50 + prev = -1; 51 + if (n == 1 || sep == '\n') 52 + break; 53 + } 54 + fclose(onlnf); 55 + if (nr_cpus > 0) 56 + return nr_cpus; 57 + 58 + return default_cpu_map(); 59 + }
+7
tools/perf/util/cpumap.h
··· 1 + #ifndef __PERF_CPUMAP_H 2 + #define __PERF_CPUMAP_H 3 + 4 + extern int read_cpu_map(void); 5 + extern int cpumap[]; 6 + 7 + #endif /* __PERF_CPUMAP_H */
+9
tools/perf/util/event.h
··· 99 99 u64 lost; 100 100 }; 101 101 102 + struct event_stat_id { 103 + struct rb_node rb_node; 104 + struct rb_root hists; 105 + struct events_stats stats; 106 + u64 config; 107 + u64 event_stream; 108 + u32 type; 109 + }; 110 + 102 111 void event__print_totals(void); 103 112 104 113 struct perf_session;
+28 -22
tools/perf/util/hist.c
··· 12 12 * histogram, sorted on item, collects counts 13 13 */ 14 14 15 - struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self, 15 + struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, 16 16 struct addr_location *al, 17 17 struct symbol *sym_parent, 18 18 u64 count, bool *hit) 19 19 { 20 - struct rb_node **p = &self->hists.rb_node; 20 + struct rb_node **p = &hists->rb_node; 21 21 struct rb_node *parent = NULL; 22 22 struct hist_entry *he; 23 23 struct hist_entry entry = { ··· 53 53 return NULL; 54 54 *he = entry; 55 55 rb_link_node(&he->rb_node, parent, p); 56 - rb_insert_color(&he->rb_node, &self->hists); 56 + rb_insert_color(&he->rb_node, hists); 57 57 *hit = false; 58 58 return he; 59 59 } ··· 130 130 rb_insert_color(&he->rb_node, root); 131 131 } 132 132 133 - void perf_session__collapse_resort(struct perf_session *self) 133 + void perf_session__collapse_resort(struct rb_root *hists) 134 134 { 135 135 struct rb_root tmp; 136 136 struct rb_node *next; ··· 140 140 return; 141 141 142 142 tmp = RB_ROOT; 143 - next = rb_first(&self->hists); 143 + next = rb_first(hists); 144 144 145 145 while (next) { 146 146 n = rb_entry(next, struct hist_entry, rb_node); 147 147 next = rb_next(&n->rb_node); 148 148 149 - rb_erase(&n->rb_node, &self->hists); 149 + rb_erase(&n->rb_node, hists); 150 150 collapse__insert_entry(&tmp, n); 151 151 } 152 152 153 - self->hists = tmp; 153 + *hists = tmp; 154 154 } 155 155 156 156 /* ··· 183 183 rb_insert_color(&he->rb_node, root); 184 184 } 185 185 186 - void perf_session__output_resort(struct perf_session *self, u64 total_samples) 186 + void perf_session__output_resort(struct rb_root *hists, u64 total_samples) 187 187 { 188 188 struct rb_root tmp; 189 189 struct rb_node *next; ··· 194 194 total_samples * (callchain_param.min_percent / 100); 195 195 196 196 tmp = RB_ROOT; 197 - next = rb_first(&self->hists); 197 + next = rb_first(hists); 198 198 199 199 while (next) { 200 200 n = rb_entry(next, struct hist_entry, rb_node); 201 201 next = rb_next(&n->rb_node); 202 202 203 - rb_erase(&n->rb_node, &self->hists); 203 + rb_erase(&n->rb_node, hists); 204 204 perf_session__insert_output_hist_entry(&tmp, n, 205 205 min_callchain_hits); 206 206 } 207 207 208 - self->hists = tmp; 208 + *hists = tmp; 209 209 } 210 210 211 211 static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) ··· 456 456 } 457 457 458 458 static size_t hist_entry__fprintf(struct hist_entry *self, 459 - struct perf_session *session, 460 459 struct perf_session *pair_session, 461 460 bool show_displacement, 462 - long displacement, FILE *fp) 461 + long displacement, FILE *fp, 462 + u64 session_total) 463 463 { 464 464 struct sort_entry *se; 465 465 u64 count, total; ··· 474 474 total = pair_session->events_stats.total; 475 475 } else { 476 476 count = self->count; 477 - total = session->events_stats.total; 477 + total = session_total; 478 478 } 479 479 480 480 if (total) ··· 496 496 497 497 if (total > 0) 498 498 old_percent = (count * 100.0) / total; 499 - if (session->events_stats.total > 0) 500 - new_percent = (self->count * 100.0) / session->events_stats.total; 499 + if (session_total > 0) 500 + new_percent = (self->count * 100.0) / session_total; 501 501 502 502 diff = new_percent - old_percent; 503 503 ··· 544 544 left_margin -= thread__comm_len(self->thread); 545 545 } 546 546 547 - hist_entry_callchain__fprintf(fp, self, session->events_stats.total, 547 + hist_entry_callchain__fprintf(fp, self, session_total, 548 548 left_margin); 549 549 } 550 550 551 551 return ret; 552 552 } 553 553 554 - size_t perf_session__fprintf_hists(struct perf_session *self, 554 + size_t perf_session__fprintf_hists(struct rb_root *hists, 555 555 struct perf_session *pair, 556 - bool show_displacement, FILE *fp) 556 + bool show_displacement, FILE *fp, 557 + u64 session_total) 557 558 { 558 559 struct sort_entry *se; 559 560 struct rb_node *nd; ··· 642 641 fprintf(fp, "\n#\n"); 643 642 644 643 print_entries: 645 - for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) { 644 + for (nd = rb_first(hists); nd; nd = rb_next(nd)) { 646 645 struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); 647 646 648 647 if (show_displacement) { ··· 653 652 displacement = 0; 654 653 ++position; 655 654 } 656 - ret += hist_entry__fprintf(h, self, pair, show_displacement, 657 - displacement, fp); 655 + ret += hist_entry__fprintf(h, pair, show_displacement, 656 + displacement, fp, session_total); 657 + if (h->map == NULL && verbose > 1) { 658 + __map_groups__fprintf_maps(&h->thread->mg, 659 + MAP__FUNCTION, fp); 660 + fprintf(fp, "%.10s end\n", graph_dotted_line); 661 + } 658 662 } 659 663 660 664 free(rem_sq_bracket);
+7 -5
tools/perf/util/hist.h
··· 10 10 struct hist_entry; 11 11 struct addr_location; 12 12 struct symbol; 13 + struct rb_root; 13 14 14 - struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self, 15 + struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, 15 16 struct addr_location *al, 16 17 struct symbol *parent, 17 18 u64 count, bool *hit); ··· 20 19 extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); 21 20 void hist_entry__free(struct hist_entry *); 22 21 23 - void perf_session__output_resort(struct perf_session *self, u64 total_samples); 24 - void perf_session__collapse_resort(struct perf_session *self); 25 - size_t perf_session__fprintf_hists(struct perf_session *self, 22 + void perf_session__output_resort(struct rb_root *hists, u64 total_samples); 23 + void perf_session__collapse_resort(struct rb_root *hists); 24 + size_t perf_session__fprintf_hists(struct rb_root *hists, 26 25 struct perf_session *pair, 27 - bool show_displacement, FILE *fp); 26 + bool show_displacement, FILE *fp, 27 + u64 session_total); 28 28 #endif /* __PERF_HIST_H */
+1 -1
tools/perf/util/probe-finder.c
··· 169 169 { 170 170 Dwarf_Files *files; 171 171 size_t nfiles, i; 172 - const char *src; 172 + const char *src = NULL; 173 173 int ret; 174 174 175 175 if (!fname)
+1
tools/perf/util/session.c
··· 70 70 71 71 memcpy(self->filename, filename, len); 72 72 self->threads = RB_ROOT; 73 + self->stats_by_id = RB_ROOT; 73 74 self->last_match = NULL; 74 75 self->mmap_window = 32; 75 76 self->cwd = NULL;
+1
tools/perf/util/session.h
··· 20 20 struct thread *last_match; 21 21 struct map *vmlinux_maps[MAP__NR_TYPES]; 22 22 struct events_stats events_stats; 23 + struct rb_root stats_by_id; 23 24 unsigned long event_total[PERF_RECORD_MAX]; 24 25 unsigned long unknown_events; 25 26 struct rb_root hists;
+35 -6
tools/perf/util/thread.c
··· 79 79 return self->comm_len; 80 80 } 81 81 82 - static size_t __map_groups__fprintf_maps(struct map_groups *self, 83 - enum map_type type, FILE *fp) 82 + size_t __map_groups__fprintf_maps(struct map_groups *self, 83 + enum map_type type, FILE *fp) 84 84 { 85 85 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); 86 86 struct rb_node *nd; ··· 89 89 struct map *pos = rb_entry(nd, struct map, rb_node); 90 90 printed += fprintf(fp, "Map:"); 91 91 printed += map__fprintf(pos, fp); 92 - if (verbose > 1) { 92 + if (verbose > 2) { 93 93 printed += dso__fprintf(pos->dso, type, fp); 94 94 printed += fprintf(fp, "--\n"); 95 95 } ··· 183 183 return th; 184 184 } 185 185 186 - static void map_groups__remove_overlappings(struct map_groups *self, 187 - struct map *map) 186 + static int map_groups__fixup_overlappings(struct map_groups *self, 187 + struct map *map) 188 188 { 189 189 struct rb_root *root = &self->maps[map->type]; 190 190 struct rb_node *next = rb_first(root); ··· 209 209 * list. 210 210 */ 211 211 list_add_tail(&pos->node, &self->removed_maps[map->type]); 212 + /* 213 + * Now check if we need to create new maps for areas not 214 + * overlapped by the new map: 215 + */ 216 + if (map->start > pos->start) { 217 + struct map *before = map__clone(pos); 218 + 219 + if (before == NULL) 220 + return -ENOMEM; 221 + 222 + before->end = map->start - 1; 223 + map_groups__insert(self, before); 224 + if (verbose >= 2) 225 + map__fprintf(before, stderr); 226 + } 227 + 228 + if (map->end < pos->end) { 229 + struct map *after = map__clone(pos); 230 + 231 + if (after == NULL) 232 + return -ENOMEM; 233 + 234 + after->start = map->end + 1; 235 + map_groups__insert(self, after); 236 + if (verbose >= 2) 237 + map__fprintf(after, stderr); 238 + } 212 239 } 240 + 241 + return 0; 213 242 } 214 243 215 244 void maps__insert(struct rb_root *maps, struct map *map) ··· 283 254 284 255 void thread__insert_map(struct thread *self, struct map *map) 285 256 { 286 - map_groups__remove_overlappings(&self->mg, map); 257 + map_groups__fixup_overlappings(&self->mg, map); 287 258 map_groups__insert(&self->mg, map); 288 259 } 289 260
+3
tools/perf/util/thread.h
··· 10 10 struct list_head removed_maps[MAP__NR_TYPES]; 11 11 }; 12 12 13 + size_t __map_groups__fprintf_maps(struct map_groups *self, 14 + enum map_type type, FILE *fp); 15 + 13 16 struct thread { 14 17 struct rb_node rb_node; 15 18 struct map_groups mg;