diff options
| author | David Vrabel <david.vrabel@citrix.com> | 2014-04-07 08:52:12 -0400 |
|---|---|---|
| committer | David Vrabel <david.vrabel@citrix.com> | 2014-04-07 08:52:12 -0400 |
| commit | 2c5cb2770392fb9c5d8518688c8bc61986d70dc6 (patch) | |
| tree | b19210e709de6ee0d22b67ef605a569500cf1a18 /arch/x86/kernel/cpu/perf_event_p4.c | |
| parent | cd979883b9ede90643e019f33cb317933eb867b4 (diff) | |
| parent | 683b6c6f82a60fabf47012581c2cfbf1b037ab95 (diff) | |
Merge commit '683b6c6f82a60fabf47012581c2cfbf1b037ab95' into stable/for-linus-3.15
This merge of the irq-core-for-linus branch broke the ARM build when
Xen is enabled.
Conflicts:
drivers/xen/events/events_base.c
Diffstat (limited to 'arch/x86/kernel/cpu/perf_event_p4.c')
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event_p4.c | 34 |
1 files changed, 33 insertions, 1 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_p4.c b/arch/x86/kernel/cpu/perf_event_p4.c index 3486e6660357..5d466b7d8609 100644 --- a/arch/x86/kernel/cpu/perf_event_p4.c +++ b/arch/x86/kernel/cpu/perf_event_p4.c | |||
| @@ -1257,7 +1257,24 @@ again: | |||
| 1257 | pass++; | 1257 | pass++; |
| 1258 | goto again; | 1258 | goto again; |
| 1259 | } | 1259 | } |
| 1260 | 1260 | /* | |
| 1261 | * Perf does test runs to see if a whole group can be assigned | ||
| 1262 | * together succesfully. There can be multiple rounds of this. | ||
| 1263 | * Unfortunately, p4_pmu_swap_config_ts touches the hwc->config | ||
| 1264 | * bits, such that the next round of group assignments will | ||
| 1265 | * cause the above p4_should_swap_ts to pass instead of fail. | ||
| 1266 | * This leads to counters exclusive to thread0 being used by | ||
| 1267 | * thread1. | ||
| 1268 | * | ||
| 1269 | * Solve this with a cheap hack, reset the idx back to -1 to | ||
| 1270 | * force a new lookup (p4_next_cntr) to get the right counter | ||
| 1271 | * for the right thread. | ||
| 1272 | * | ||
| 1273 | * This probably doesn't comply with the general spirit of how | ||
| 1274 | * perf wants to work, but P4 is special. :-( | ||
| 1275 | */ | ||
| 1276 | if (p4_should_swap_ts(hwc->config, cpu)) | ||
| 1277 | hwc->idx = -1; | ||
| 1261 | p4_pmu_swap_config_ts(hwc, cpu); | 1278 | p4_pmu_swap_config_ts(hwc, cpu); |
| 1262 | if (assign) | 1279 | if (assign) |
| 1263 | assign[i] = cntr_idx; | 1280 | assign[i] = cntr_idx; |
| @@ -1322,6 +1339,7 @@ static __initconst const struct x86_pmu p4_pmu = { | |||
| 1322 | __init int p4_pmu_init(void) | 1339 | __init int p4_pmu_init(void) |
| 1323 | { | 1340 | { |
| 1324 | unsigned int low, high; | 1341 | unsigned int low, high; |
| 1342 | int i, reg; | ||
| 1325 | 1343 | ||
| 1326 | /* If we get stripped -- indexing fails */ | 1344 | /* If we get stripped -- indexing fails */ |
| 1327 | BUILD_BUG_ON(ARCH_P4_MAX_CCCR > INTEL_PMC_MAX_GENERIC); | 1345 | BUILD_BUG_ON(ARCH_P4_MAX_CCCR > INTEL_PMC_MAX_GENERIC); |
| @@ -1340,5 +1358,19 @@ __init int p4_pmu_init(void) | |||
| 1340 | 1358 | ||
| 1341 | x86_pmu = p4_pmu; | 1359 | x86_pmu = p4_pmu; |
| 1342 | 1360 | ||
| 1361 | /* | ||
| 1362 | * Even though the counters are configured to interrupt a particular | ||
| 1363 | * logical processor when an overflow happens, testing has shown that | ||
| 1364 | * on kdump kernels (which uses a single cpu), thread1's counter | ||
| 1365 | * continues to run and will report an NMI on thread0. Due to the | ||
| 1366 | * overflow bug, this leads to a stream of unknown NMIs. | ||
| 1367 | * | ||
| 1368 | * Solve this by zero'ing out the registers to mimic a reset. | ||
| 1369 | */ | ||
| 1370 | for (i = 0; i < x86_pmu.num_counters; i++) { | ||
| 1371 | reg = x86_pmu_config_addr(i); | ||
| 1372 | wrmsrl_safe(reg, 0ULL); | ||
| 1373 | } | ||
| 1374 | |||
| 1343 | return 0; | 1375 | return 0; |
| 1344 | } | 1376 | } |
