aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2010-01-29 07:25:31 -0500
committerIngo Molnar <mingo@elte.hu>2010-02-04 03:59:49 -0500
commit8c48e444191de0ff84e85d41180d7bc3e74f14ef (patch)
tree73d8f6eec69b43568d942f8a75ef4cd9666e1d7e
parent9717e6cd3db22eade7dbae0fc9235c66325a7132 (diff)
perf_events, x86: Implement intel core solo/duo support
Implement Intel Core Solo/Duo, aka. Intel Architectural Performance Monitoring Version 1. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Arjan van de Ven <arjan@linux.intel.com> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/kernel/cpu/perf_event.c133
1 files changed, 61 insertions, 72 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 1846ead0576b..5b91992b6b25 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -228,6 +228,17 @@ static const u64 intel_perfmon_event_map[] =
228 228
229static struct event_constraint intel_core_event_constraints[] = 229static struct event_constraint intel_core_event_constraints[] =
230{ 230{
231 INTEL_EVENT_CONSTRAINT(0x11, 0x2), /* FP_ASSIST */
232 INTEL_EVENT_CONSTRAINT(0x12, 0x2), /* MUL */
233 INTEL_EVENT_CONSTRAINT(0x13, 0x2), /* DIV */
234 INTEL_EVENT_CONSTRAINT(0x14, 0x1), /* CYCLES_DIV_BUSY */
235 INTEL_EVENT_CONSTRAINT(0x19, 0x2), /* DELAYED_BYPASS */
236 INTEL_EVENT_CONSTRAINT(0xc1, 0x1), /* FP_COMP_INSTR_RET */
237 EVENT_CONSTRAINT_END
238};
239
240static struct event_constraint intel_core2_event_constraints[] =
241{
231 FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */ 242 FIXED_EVENT_CONSTRAINT(0xc0, (0x3|(1ULL<<32))), /* INSTRUCTIONS_RETIRED */
232 FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */ 243 FIXED_EVENT_CONSTRAINT(0x3c, (0x3|(1ULL<<33))), /* UNHALTED_CORE_CYCLES */
233 INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */ 244 INTEL_EVENT_CONSTRAINT(0x10, 0x1), /* FP_COMP_OPS_EXE */
@@ -1216,7 +1227,7 @@ static void intel_pmu_disable_all(void)
1216 intel_pmu_disable_bts(); 1227 intel_pmu_disable_bts();
1217} 1228}
1218 1229
1219static void amd_pmu_disable_all(void) 1230static void x86_pmu_disable_all(void)
1220{ 1231{
1221 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 1232 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
1222 int idx; 1233 int idx;
@@ -1226,11 +1237,11 @@ static void amd_pmu_disable_all(void)
1226 1237
1227 if (!test_bit(idx, cpuc->active_mask)) 1238 if (!test_bit(idx, cpuc->active_mask))
1228 continue; 1239 continue;
1229 rdmsrl(MSR_K7_EVNTSEL0 + idx, val); 1240 rdmsrl(x86_pmu.eventsel + idx, val);
1230 if (!(val & ARCH_PERFMON_EVENTSEL0_ENABLE)) 1241 if (!(val & ARCH_PERFMON_EVENTSEL0_ENABLE))
1231 continue; 1242 continue;
1232 val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE; 1243 val &= ~ARCH_PERFMON_EVENTSEL0_ENABLE;
1233 wrmsrl(MSR_K7_EVNTSEL0 + idx, val); 1244 wrmsrl(x86_pmu.eventsel + idx, val);
1234 } 1245 }
1235} 1246}
1236 1247
@@ -1278,7 +1289,7 @@ static void intel_pmu_enable_all(void)
1278 } 1289 }
1279} 1290}
1280 1291
1281static void amd_pmu_enable_all(void) 1292static void x86_pmu_enable_all(void)
1282{ 1293{
1283 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 1294 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
1284 int idx; 1295 int idx;
@@ -1292,7 +1303,7 @@ static void amd_pmu_enable_all(void)
1292 1303
1293 val = event->hw.config; 1304 val = event->hw.config;
1294 val |= ARCH_PERFMON_EVENTSEL0_ENABLE; 1305 val |= ARCH_PERFMON_EVENTSEL0_ENABLE;
1295 wrmsrl(MSR_K7_EVNTSEL0 + idx, val); 1306 wrmsrl(x86_pmu.eventsel + idx, val);
1296 } 1307 }
1297} 1308}
1298 1309
@@ -1546,7 +1557,7 @@ static inline void intel_pmu_ack_status(u64 ack)
1546 wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack); 1557 wrmsrl(MSR_CORE_PERF_GLOBAL_OVF_CTRL, ack);
1547} 1558}
1548 1559
1549static inline void x86_pmu_enable_event(struct hw_perf_event *hwc, int idx) 1560static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc, int idx)
1550{ 1561{
1551 (void)checking_wrmsrl(hwc->config_base + idx, 1562 (void)checking_wrmsrl(hwc->config_base + idx,
1552 hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE); 1563 hwc->config | ARCH_PERFMON_EVENTSEL0_ENABLE);
@@ -1598,12 +1609,6 @@ intel_pmu_disable_event(struct hw_perf_event *hwc, int idx)
1598 x86_pmu_disable_event(hwc, idx); 1609 x86_pmu_disable_event(hwc, idx);
1599} 1610}
1600 1611
1601static inline void
1602amd_pmu_disable_event(struct hw_perf_event *hwc, int idx)
1603{
1604 x86_pmu_disable_event(hwc, idx);
1605}
1606
1607static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left); 1612static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left);
1608 1613
1609/* 1614/*
@@ -1723,15 +1728,14 @@ static void intel_pmu_enable_event(struct hw_perf_event *hwc, int idx)
1723 return; 1728 return;
1724 } 1729 }
1725 1730
1726 x86_pmu_enable_event(hwc, idx); 1731 __x86_pmu_enable_event(hwc, idx);
1727} 1732}
1728 1733
1729static void amd_pmu_enable_event(struct hw_perf_event *hwc, int idx) 1734static void x86_pmu_enable_event(struct hw_perf_event *hwc, int idx)
1730{ 1735{
1731 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); 1736 struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
1732
1733 if (cpuc->enabled) 1737 if (cpuc->enabled)
1734 x86_pmu_enable_event(hwc, idx); 1738 __x86_pmu_enable_event(hwc, idx);
1735} 1739}
1736 1740
1737/* 1741/*
@@ -1988,50 +1992,6 @@ static void intel_pmu_reset(void)
1988 local_irq_restore(flags); 1992 local_irq_restore(flags);
1989} 1993}
1990 1994
1991static int p6_pmu_handle_irq(struct pt_regs *regs)
1992{
1993 struct perf_sample_data data;
1994 struct cpu_hw_events *cpuc;
1995 struct perf_event *event;
1996 struct hw_perf_event *hwc;
1997 int idx, handled = 0;
1998 u64 val;
1999
2000 data.addr = 0;
2001 data.raw = NULL;
2002
2003 cpuc = &__get_cpu_var(cpu_hw_events);
2004
2005 for (idx = 0; idx < x86_pmu.num_events; idx++) {
2006 if (!test_bit(idx, cpuc->active_mask))
2007 continue;
2008
2009 event = cpuc->events[idx];
2010 hwc = &event->hw;
2011
2012 val = x86_perf_event_update(event, hwc, idx);
2013 if (val & (1ULL << (x86_pmu.event_bits - 1)))
2014 continue;
2015
2016 /*
2017 * event overflow
2018 */
2019 handled = 1;
2020 data.period = event->hw.last_period;
2021
2022 if (!x86_perf_event_set_period(event, hwc, idx))
2023 continue;
2024
2025 if (perf_event_overflow(event, 1, &data, regs))
2026 p6_pmu_disable_event(hwc, idx);
2027 }
2028
2029 if (handled)
2030 inc_irq_stat(apic_perf_irqs);
2031
2032 return handled;
2033}
2034
2035/* 1995/*
2036 * This handler is triggered by the local APIC, so the APIC IRQ handling 1996 * This handler is triggered by the local APIC, so the APIC IRQ handling
2037 * rules apply: 1997 * rules apply:
@@ -2098,7 +2058,7 @@ again:
2098 return 1; 2058 return 1;
2099} 2059}
2100 2060
2101static int amd_pmu_handle_irq(struct pt_regs *regs) 2061static int x86_pmu_handle_irq(struct pt_regs *regs)
2102{ 2062{
2103 struct perf_sample_data data; 2063 struct perf_sample_data data;
2104 struct cpu_hw_events *cpuc; 2064 struct cpu_hw_events *cpuc;
@@ -2133,7 +2093,7 @@ static int amd_pmu_handle_irq(struct pt_regs *regs)
2133 continue; 2093 continue;
2134 2094
2135 if (perf_event_overflow(event, 1, &data, regs)) 2095 if (perf_event_overflow(event, 1, &data, regs))
2136 amd_pmu_disable_event(hwc, idx); 2096 x86_pmu.disable(hwc, idx);
2137 } 2097 }
2138 2098
2139 if (handled) 2099 if (handled)
@@ -2374,7 +2334,7 @@ static __read_mostly struct notifier_block perf_event_nmi_notifier = {
2374 2334
2375static __initconst struct x86_pmu p6_pmu = { 2335static __initconst struct x86_pmu p6_pmu = {
2376 .name = "p6", 2336 .name = "p6",
2377 .handle_irq = p6_pmu_handle_irq, 2337 .handle_irq = x86_pmu_handle_irq,
2378 .disable_all = p6_pmu_disable_all, 2338 .disable_all = p6_pmu_disable_all,
2379 .enable_all = p6_pmu_enable_all, 2339 .enable_all = p6_pmu_enable_all,
2380 .enable = p6_pmu_enable_event, 2340 .enable = p6_pmu_enable_event,
@@ -2401,6 +2361,29 @@ static __initconst struct x86_pmu p6_pmu = {
2401 .event_constraints = intel_p6_event_constraints 2361 .event_constraints = intel_p6_event_constraints
2402}; 2362};
2403 2363
2364static __initconst struct x86_pmu core_pmu = {
2365 .name = "core",
2366 .handle_irq = x86_pmu_handle_irq,
2367 .disable_all = x86_pmu_disable_all,
2368 .enable_all = x86_pmu_enable_all,
2369 .enable = x86_pmu_enable_event,
2370 .disable = x86_pmu_disable_event,
2371 .eventsel = MSR_ARCH_PERFMON_EVENTSEL0,
2372 .perfctr = MSR_ARCH_PERFMON_PERFCTR0,
2373 .event_map = intel_pmu_event_map,
2374 .raw_event = intel_pmu_raw_event,
2375 .max_events = ARRAY_SIZE(intel_perfmon_event_map),
2376 .apic = 1,
2377 /*
2378 * Intel PMCs cannot be accessed sanely above 32 bit width,
2379 * so we install an artificial 1<<31 period regardless of
2380 * the generic event period:
2381 */
2382 .max_period = (1ULL << 31) - 1,
2383 .get_event_constraints = intel_get_event_constraints,
2384 .event_constraints = intel_core_event_constraints,
2385};
2386
2404static __initconst struct x86_pmu intel_pmu = { 2387static __initconst struct x86_pmu intel_pmu = {
2405 .name = "Intel", 2388 .name = "Intel",
2406 .handle_irq = intel_pmu_handle_irq, 2389 .handle_irq = intel_pmu_handle_irq,
@@ -2427,11 +2410,11 @@ static __initconst struct x86_pmu intel_pmu = {
2427 2410
2428static __initconst struct x86_pmu amd_pmu = { 2411static __initconst struct x86_pmu amd_pmu = {
2429 .name = "AMD", 2412 .name = "AMD",
2430 .handle_irq = amd_pmu_handle_irq, 2413 .handle_irq = x86_pmu_handle_irq,
2431 .disable_all = amd_pmu_disable_all, 2414 .disable_all = x86_pmu_disable_all,
2432 .enable_all = amd_pmu_enable_all, 2415 .enable_all = x86_pmu_enable_all,
2433 .enable = amd_pmu_enable_event, 2416 .enable = x86_pmu_enable_event,
2434 .disable = amd_pmu_disable_event, 2417 .disable = x86_pmu_disable_event,
2435 .eventsel = MSR_K7_EVNTSEL0, 2418 .eventsel = MSR_K7_EVNTSEL0,
2436 .perfctr = MSR_K7_PERFCTR0, 2419 .perfctr = MSR_K7_PERFCTR0,
2437 .event_map = amd_pmu_event_map, 2420 .event_map = amd_pmu_event_map,
@@ -2498,9 +2481,10 @@ static __init int intel_pmu_init(void)
2498 2481
2499 version = eax.split.version_id; 2482 version = eax.split.version_id;
2500 if (version < 2) 2483 if (version < 2)
2501 return -ENODEV; 2484 x86_pmu = core_pmu;
2485 else
2486 x86_pmu = intel_pmu;
2502 2487
2503 x86_pmu = intel_pmu;
2504 x86_pmu.version = version; 2488 x86_pmu.version = version;
2505 x86_pmu.num_events = eax.split.num_events; 2489 x86_pmu.num_events = eax.split.num_events;
2506 x86_pmu.event_bits = eax.split.bit_width; 2490 x86_pmu.event_bits = eax.split.bit_width;
@@ -2510,12 +2494,17 @@ static __init int intel_pmu_init(void)
2510 * Quirk: v2 perfmon does not report fixed-purpose events, so 2494 * Quirk: v2 perfmon does not report fixed-purpose events, so
2511 * assume at least 3 events: 2495 * assume at least 3 events:
2512 */ 2496 */
2513 x86_pmu.num_events_fixed = max((int)edx.split.num_events_fixed, 3); 2497 if (version > 1)
2498 x86_pmu.num_events_fixed = max((int)edx.split.num_events_fixed, 3);
2514 2499
2515 /* 2500 /*
2516 * Install the hw-cache-events table: 2501 * Install the hw-cache-events table:
2517 */ 2502 */
2518 switch (boot_cpu_data.x86_model) { 2503 switch (boot_cpu_data.x86_model) {
2504 case 14: /* 65 nm core solo/duo, "Yonah" */
2505 pr_cont("Core events, ");
2506 break;
2507
2519 case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */ 2508 case 15: /* original 65 nm celeron/pentium/core2/xeon, "Merom"/"Conroe" */
2520 case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */ 2509 case 22: /* single-core 65 nm celeron/core2solo "Merom-L"/"Conroe-L" */
2521 case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */ 2510 case 23: /* current 45 nm celeron/core2/xeon "Penryn"/"Wolfdale" */
@@ -2523,7 +2512,7 @@ static __init int intel_pmu_init(void)
2523 memcpy(hw_cache_event_ids, core2_hw_cache_event_ids, 2512 memcpy(hw_cache_event_ids, core2_hw_cache_event_ids,
2524 sizeof(hw_cache_event_ids)); 2513 sizeof(hw_cache_event_ids));
2525 2514
2526 x86_pmu.event_constraints = intel_core_event_constraints; 2515 x86_pmu.event_constraints = intel_core2_event_constraints;
2527 pr_cont("Core2 events, "); 2516 pr_cont("Core2 events, ");
2528 break; 2517 break;
2529 2518