diff options
-rw-r--r-- | arch/x86/kernel/cpu/perfctr-watchdog.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c index 05cc22dbd4ff..62c010063974 100644 --- a/arch/x86/kernel/cpu/perfctr-watchdog.c +++ b/arch/x86/kernel/cpu/perfctr-watchdog.c | |||
@@ -432,6 +432,27 @@ static const struct wd_ops p6_wd_ops = { | |||
432 | #define P4_CCCR_ENABLE (1 << 12) | 432 | #define P4_CCCR_ENABLE (1 << 12) |
433 | #define P4_CCCR_OVF (1 << 31) | 433 | #define P4_CCCR_OVF (1 << 31) |
434 | 434 | ||
435 | #define P4_CONTROLS 18 | ||
436 | static unsigned int p4_controls[18] = { | ||
437 | MSR_P4_BPU_CCCR0, | ||
438 | MSR_P4_BPU_CCCR1, | ||
439 | MSR_P4_BPU_CCCR2, | ||
440 | MSR_P4_BPU_CCCR3, | ||
441 | MSR_P4_MS_CCCR0, | ||
442 | MSR_P4_MS_CCCR1, | ||
443 | MSR_P4_MS_CCCR2, | ||
444 | MSR_P4_MS_CCCR3, | ||
445 | MSR_P4_FLAME_CCCR0, | ||
446 | MSR_P4_FLAME_CCCR1, | ||
447 | MSR_P4_FLAME_CCCR2, | ||
448 | MSR_P4_FLAME_CCCR3, | ||
449 | MSR_P4_IQ_CCCR0, | ||
450 | MSR_P4_IQ_CCCR1, | ||
451 | MSR_P4_IQ_CCCR2, | ||
452 | MSR_P4_IQ_CCCR3, | ||
453 | MSR_P4_IQ_CCCR4, | ||
454 | MSR_P4_IQ_CCCR5, | ||
455 | }; | ||
435 | /* | 456 | /* |
436 | * Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter | 457 | * Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter |
437 | * CRU_ESCR0 (with any non-null event selector) through a complemented | 458 | * CRU_ESCR0 (with any non-null event selector) through a complemented |
@@ -473,6 +494,26 @@ static int setup_p4_watchdog(unsigned nmi_hz) | |||
473 | evntsel_msr = MSR_P4_CRU_ESCR0; | 494 | evntsel_msr = MSR_P4_CRU_ESCR0; |
474 | cccr_msr = MSR_P4_IQ_CCCR0; | 495 | cccr_msr = MSR_P4_IQ_CCCR0; |
475 | cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4); | 496 | cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4); |
497 | |||
498 | /* | ||
499 | * If we're on the kdump kernel or other situation, we may | ||
500 | * still have other performance counter registers set to | ||
501 | * interrupt and they'll keep interrupting forever because | ||
502 | * of the P4_CCCR_OVF quirk. So we need to ACK all the | ||
503 | * pending interrupts and disable all the registers here, | ||
504 | * before reenabling the NMI delivery. Refer to p4_rearm() | ||
505 | * about the P4_CCCR_OVF quirk. | ||
506 | */ | ||
507 | if (reset_devices) { | ||
508 | unsigned int low, high; | ||
509 | int i; | ||
510 | |||
511 | for (i = 0; i < P4_CONTROLS; i++) { | ||
512 | rdmsr(p4_controls[i], low, high); | ||
513 | low &= ~(P4_CCCR_ENABLE | P4_CCCR_OVF); | ||
514 | wrmsr(p4_controls[i], low, high); | ||
515 | } | ||
516 | } | ||
476 | } else { | 517 | } else { |
477 | /* logical cpu 1 */ | 518 | /* logical cpu 1 */ |
478 | perfctr_msr = MSR_P4_IQ_PERFCTR1; | 519 | perfctr_msr = MSR_P4_IQ_PERFCTR1; |