diff options
Diffstat (limited to 'arch/x86/kernel/cpu/perf_counter.c')
| -rw-r--r-- | arch/x86/kernel/cpu/perf_counter.c | 30 |
1 files changed, 17 insertions, 13 deletions
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c index 76dfef23f789..36c3dc7b8991 100644 --- a/arch/x86/kernel/cpu/perf_counter.c +++ b/arch/x86/kernel/cpu/perf_counter.c | |||
| @@ -401,7 +401,7 @@ static const u64 amd_hw_cache_event_ids | |||
| 401 | [ C(RESULT_MISS) ] = 0x0041, /* Data Cache Misses */ | 401 | [ C(RESULT_MISS) ] = 0x0041, /* Data Cache Misses */ |
| 402 | }, | 402 | }, |
| 403 | [ C(OP_WRITE) ] = { | 403 | [ C(OP_WRITE) ] = { |
| 404 | [ C(RESULT_ACCESS) ] = 0x0042, /* Data Cache Refills from L2 */ | 404 | [ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */ |
| 405 | [ C(RESULT_MISS) ] = 0, | 405 | [ C(RESULT_MISS) ] = 0, |
| 406 | }, | 406 | }, |
| 407 | [ C(OP_PREFETCH) ] = { | 407 | [ C(OP_PREFETCH) ] = { |
| @@ -912,6 +912,8 @@ x86_perf_counter_set_period(struct perf_counter *counter, | |||
| 912 | err = checking_wrmsrl(hwc->counter_base + idx, | 912 | err = checking_wrmsrl(hwc->counter_base + idx, |
| 913 | (u64)(-left) & x86_pmu.counter_mask); | 913 | (u64)(-left) & x86_pmu.counter_mask); |
| 914 | 914 | ||
| 915 | perf_counter_update_userpage(counter); | ||
| 916 | |||
| 915 | return ret; | 917 | return ret; |
| 916 | } | 918 | } |
| 917 | 919 | ||
| @@ -969,13 +971,6 @@ fixed_mode_idx(struct perf_counter *counter, struct hw_perf_counter *hwc) | |||
| 969 | if (!x86_pmu.num_counters_fixed) | 971 | if (!x86_pmu.num_counters_fixed) |
| 970 | return -1; | 972 | return -1; |
| 971 | 973 | ||
| 972 | /* | ||
| 973 | * Quirk, IA32_FIXED_CTRs do not work on current Atom processors: | ||
| 974 | */ | ||
| 975 | if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && | ||
| 976 | boot_cpu_data.x86_model == 28) | ||
| 977 | return -1; | ||
| 978 | |||
| 979 | event = hwc->config & ARCH_PERFMON_EVENT_MASK; | 974 | event = hwc->config & ARCH_PERFMON_EVENT_MASK; |
| 980 | 975 | ||
| 981 | if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS))) | 976 | if (unlikely(event == x86_pmu.event_map(PERF_COUNT_HW_INSTRUCTIONS))) |
| @@ -1041,6 +1036,8 @@ try_generic: | |||
| 1041 | x86_perf_counter_set_period(counter, hwc, idx); | 1036 | x86_perf_counter_set_period(counter, hwc, idx); |
| 1042 | x86_pmu.enable(hwc, idx); | 1037 | x86_pmu.enable(hwc, idx); |
| 1043 | 1038 | ||
| 1039 | perf_counter_update_userpage(counter); | ||
| 1040 | |||
| 1044 | return 0; | 1041 | return 0; |
| 1045 | } | 1042 | } |
| 1046 | 1043 | ||
| @@ -1133,6 +1130,8 @@ static void x86_pmu_disable(struct perf_counter *counter) | |||
| 1133 | x86_perf_counter_update(counter, hwc, idx); | 1130 | x86_perf_counter_update(counter, hwc, idx); |
| 1134 | cpuc->counters[idx] = NULL; | 1131 | cpuc->counters[idx] = NULL; |
| 1135 | clear_bit(idx, cpuc->used_mask); | 1132 | clear_bit(idx, cpuc->used_mask); |
| 1133 | |||
| 1134 | perf_counter_update_userpage(counter); | ||
| 1136 | } | 1135 | } |
| 1137 | 1136 | ||
| 1138 | /* | 1137 | /* |
| @@ -1428,8 +1427,6 @@ static int intel_pmu_init(void) | |||
| 1428 | */ | 1427 | */ |
| 1429 | x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3); | 1428 | x86_pmu.num_counters_fixed = max((int)edx.split.num_counters_fixed, 3); |
| 1430 | 1429 | ||
| 1431 | rdmsrl(MSR_CORE_PERF_GLOBAL_CTRL, x86_pmu.intel_ctrl); | ||
| 1432 | |||
| 1433 | /* | 1430 | /* |
| 1434 | * Install the hw-cache-events table: | 1431 | * Install the hw-cache-events table: |
| 1435 | */ | 1432 | */ |
| @@ -1499,21 +1496,22 @@ void __init init_hw_perf_counters(void) | |||
| 1499 | pr_cont("%s PMU driver.\n", x86_pmu.name); | 1496 | pr_cont("%s PMU driver.\n", x86_pmu.name); |
| 1500 | 1497 | ||
| 1501 | if (x86_pmu.num_counters > X86_PMC_MAX_GENERIC) { | 1498 | if (x86_pmu.num_counters > X86_PMC_MAX_GENERIC) { |
| 1502 | x86_pmu.num_counters = X86_PMC_MAX_GENERIC; | ||
| 1503 | WARN(1, KERN_ERR "hw perf counters %d > max(%d), clipping!", | 1499 | WARN(1, KERN_ERR "hw perf counters %d > max(%d), clipping!", |
| 1504 | x86_pmu.num_counters, X86_PMC_MAX_GENERIC); | 1500 | x86_pmu.num_counters, X86_PMC_MAX_GENERIC); |
| 1501 | x86_pmu.num_counters = X86_PMC_MAX_GENERIC; | ||
| 1505 | } | 1502 | } |
| 1506 | perf_counter_mask = (1 << x86_pmu.num_counters) - 1; | 1503 | perf_counter_mask = (1 << x86_pmu.num_counters) - 1; |
| 1507 | perf_max_counters = x86_pmu.num_counters; | 1504 | perf_max_counters = x86_pmu.num_counters; |
| 1508 | 1505 | ||
| 1509 | if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) { | 1506 | if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) { |
| 1510 | x86_pmu.num_counters_fixed = X86_PMC_MAX_FIXED; | ||
| 1511 | WARN(1, KERN_ERR "hw perf counters fixed %d > max(%d), clipping!", | 1507 | WARN(1, KERN_ERR "hw perf counters fixed %d > max(%d), clipping!", |
| 1512 | x86_pmu.num_counters_fixed, X86_PMC_MAX_FIXED); | 1508 | x86_pmu.num_counters_fixed, X86_PMC_MAX_FIXED); |
| 1509 | x86_pmu.num_counters_fixed = X86_PMC_MAX_FIXED; | ||
| 1513 | } | 1510 | } |
| 1514 | 1511 | ||
| 1515 | perf_counter_mask |= | 1512 | perf_counter_mask |= |
| 1516 | ((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED; | 1513 | ((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED; |
| 1514 | x86_pmu.intel_ctrl = perf_counter_mask; | ||
| 1517 | 1515 | ||
| 1518 | perf_counters_lapic_init(); | 1516 | perf_counters_lapic_init(); |
| 1519 | register_die_notifier(&perf_counter_nmi_notifier); | 1517 | register_die_notifier(&perf_counter_nmi_notifier); |
| @@ -1563,6 +1561,7 @@ void callchain_store(struct perf_callchain_entry *entry, u64 ip) | |||
| 1563 | 1561 | ||
| 1564 | static DEFINE_PER_CPU(struct perf_callchain_entry, irq_entry); | 1562 | static DEFINE_PER_CPU(struct perf_callchain_entry, irq_entry); |
| 1565 | static DEFINE_PER_CPU(struct perf_callchain_entry, nmi_entry); | 1563 | static DEFINE_PER_CPU(struct perf_callchain_entry, nmi_entry); |
| 1564 | static DEFINE_PER_CPU(int, in_nmi_frame); | ||
| 1566 | 1565 | ||
| 1567 | 1566 | ||
| 1568 | static void | 1567 | static void |
| @@ -1578,7 +1577,9 @@ static void backtrace_warning(void *data, char *msg) | |||
| 1578 | 1577 | ||
| 1579 | static int backtrace_stack(void *data, char *name) | 1578 | static int backtrace_stack(void *data, char *name) |
| 1580 | { | 1579 | { |
| 1581 | /* Process all stacks: */ | 1580 | per_cpu(in_nmi_frame, smp_processor_id()) = |
| 1581 | x86_is_stack_id(NMI_STACK, name); | ||
| 1582 | |||
| 1582 | return 0; | 1583 | return 0; |
| 1583 | } | 1584 | } |
| 1584 | 1585 | ||
| @@ -1586,6 +1587,9 @@ static void backtrace_address(void *data, unsigned long addr, int reliable) | |||
| 1586 | { | 1587 | { |
| 1587 | struct perf_callchain_entry *entry = data; | 1588 | struct perf_callchain_entry *entry = data; |
| 1588 | 1589 | ||
| 1590 | if (per_cpu(in_nmi_frame, smp_processor_id())) | ||
| 1591 | return; | ||
| 1592 | |||
| 1589 | if (reliable) | 1593 | if (reliable) |
| 1590 | callchain_store(entry, addr); | 1594 | callchain_store(entry, addr); |
| 1591 | } | 1595 | } |
