aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64
diff options
context:
space:
mode:
authorDon Zickus <dzickus@redhat.com>2006-09-26 04:52:26 -0400
committerAndi Kleen <andi@basil.nowhere.org>2006-09-26 04:52:26 -0400
commitf2802e7f571c05f9a901b1f5bd144aa730ccc88e (patch)
tree68a2c4dd80dbf2e01f048b46460517b15cda63c0 /arch/x86_64
parentcb9c448c661d40ce2efbce8e9c19cc4d420d8ccc (diff)
[PATCH] Add SMP support on x86_64 to reservation framework
This patch includes the changes to make the nmi watchdog on x86_64 SMP aware. A bunch of code was moved around to make it simpler to read. In addition, it is now possible to determine if a particular NMI was the result of the watchdog or not. This feature allows the kernel to filter out unknown NMIs easier. Signed-off-by: Don Zickus <dzickus@redhat.com> Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/x86_64')
-rw-r--r--arch/x86_64/kernel/apic.c3
-rw-r--r--arch/x86_64/kernel/nmi.c426
2 files changed, 288 insertions, 141 deletions
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 2b8cef037a65..692e9b579743 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -479,8 +479,7 @@ void __cpuinit setup_local_APIC (void)
479 } 479 }
480 480
481 nmi_watchdog_default(); 481 nmi_watchdog_default();
482 if (nmi_watchdog == NMI_LOCAL_APIC) 482 setup_apic_nmi_watchdog(NULL);
483 setup_apic_nmi_watchdog();
484 apic_pm_activate(); 483 apic_pm_activate();
485} 484}
486 485
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index b7a7c9973849..d42374a952d7 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -56,53 +56,29 @@ static unsigned int lapic_nmi_owner;
56#define LAPIC_NMI_RESERVED (1<<1) 56#define LAPIC_NMI_RESERVED (1<<1)
57 57
58/* nmi_active: 58/* nmi_active:
59 * +1: the lapic NMI watchdog is active, but can be disabled 59 * >0: the lapic NMI watchdog is active, but can be disabled
60 * 0: the lapic NMI watchdog has not been set up, and cannot 60 * <0: the lapic NMI watchdog has not been set up, and cannot
61 * be enabled 61 * be enabled
62 * -1: the lapic NMI watchdog is disabled, but can be enabled 62 * 0: the lapic NMI watchdog is disabled, but can be enabled
63 */ 63 */
64int nmi_active; /* oprofile uses this */ 64atomic_t nmi_active = ATOMIC_INIT(0); /* oprofile uses this */
65int panic_on_timeout; 65int panic_on_timeout;
66 66
67unsigned int nmi_watchdog = NMI_DEFAULT; 67unsigned int nmi_watchdog = NMI_DEFAULT;
68static unsigned int nmi_hz = HZ; 68static unsigned int nmi_hz = HZ;
69static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
70static unsigned int nmi_p4_cccr_val;
71 69
72/* Note that these events don't tick when the CPU idles. This means 70struct nmi_watchdog_ctlblk {
73 the frequency varies with CPU load. */ 71 int enabled;
74 72 u64 check_bit;
75#define K7_EVNTSEL_ENABLE (1 << 22) 73 unsigned int cccr_msr;
76#define K7_EVNTSEL_INT (1 << 20) 74 unsigned int perfctr_msr; /* the MSR to reset in NMI handler */
77#define K7_EVNTSEL_OS (1 << 17) 75 unsigned int evntsel_msr; /* the MSR to select the events to handle */
78#define K7_EVNTSEL_USR (1 << 16) 76};
79#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76 77static DEFINE_PER_CPU(struct nmi_watchdog_ctlblk, nmi_watchdog_ctlblk);
80#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
81 78
82#define MSR_P4_MISC_ENABLE 0x1A0 79/* local prototypes */
83#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7) 80static void stop_apic_nmi_watchdog(void *unused);
84#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL (1<<12) 81static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu);
85#define MSR_P4_PERFCTR0 0x300
86#define MSR_P4_CCCR0 0x360
87#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
88#define P4_ESCR_OS (1<<3)
89#define P4_ESCR_USR (1<<2)
90#define P4_CCCR_OVF_PMI0 (1<<26)
91#define P4_CCCR_OVF_PMI1 (1<<27)
92#define P4_CCCR_THRESHOLD(N) ((N)<<20)
93#define P4_CCCR_COMPLEMENT (1<<19)
94#define P4_CCCR_COMPARE (1<<18)
95#define P4_CCCR_REQUIRED (3<<16)
96#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
97#define P4_CCCR_ENABLE (1<<12)
98/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
99 CRU_ESCR0 (with any non-null event selector) through a complemented
100 max threshold. [IA32-Vol3, Section 14.9.9] */
101#define MSR_P4_IQ_COUNTER0 0x30C
102#define P4_NMI_CRU_ESCR0 (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
103#define P4_NMI_IQ_CCCR0 \
104 (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
105 P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
106 82
107/* converts an msr to an appropriate reservation bit */ 83/* converts an msr to an appropriate reservation bit */
108static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr) 84static inline unsigned int nmi_perfctr_msr_to_bit(unsigned int msr)
@@ -241,6 +217,12 @@ int __init check_nmi_watchdog (void)
241 int *counts; 217 int *counts;
242 int cpu; 218 int cpu;
243 219
220 if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT))
221 return 0;
222
223 if (!atomic_read(&nmi_active))
224 return 0;
225
244 counts = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL); 226 counts = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
245 if (!counts) 227 if (!counts)
246 return -1; 228 return -1;
@@ -258,19 +240,22 @@ int __init check_nmi_watchdog (void)
258 mdelay((10*1000)/nmi_hz); // wait 10 ticks 240 mdelay((10*1000)/nmi_hz); // wait 10 ticks
259 241
260 for_each_online_cpu(cpu) { 242 for_each_online_cpu(cpu) {
243 if (!per_cpu(nmi_watchdog_ctlblk, cpu).enabled)
244 continue;
261 if (cpu_pda(cpu)->__nmi_count - counts[cpu] <= 5) { 245 if (cpu_pda(cpu)->__nmi_count - counts[cpu] <= 5) {
262 endflag = 1;
263 printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n", 246 printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
264 cpu, 247 cpu,
265 counts[cpu], 248 counts[cpu],
266 cpu_pda(cpu)->__nmi_count); 249 cpu_pda(cpu)->__nmi_count);
267 nmi_active = 0; 250 per_cpu(nmi_watchdog_ctlblk, cpu).enabled = 0;
268 lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG; 251 atomic_dec(&nmi_active);
269 nmi_perfctr_msr = 0;
270 kfree(counts);
271 return -1;
272 } 252 }
273 } 253 }
254 if (!atomic_read(&nmi_active)) {
255 kfree(counts);
256 atomic_set(&nmi_active, -1);
257 return -1;
258 }
274 endflag = 1; 259 endflag = 1;
275 printk("OK.\n"); 260 printk("OK.\n");
276 261
@@ -297,8 +282,11 @@ int __init setup_nmi_watchdog(char *str)
297 282
298 get_option(&str, &nmi); 283 get_option(&str, &nmi);
299 284
300 if (nmi >= NMI_INVALID) 285 if ((nmi >= NMI_INVALID) || (nmi < NMI_NONE))
301 return 0; 286 return 0;
287
288 if ((nmi == NMI_LOCAL_APIC) && (nmi_known_cpu() == 0))
289 return 0; /* no lapic support */
302 nmi_watchdog = nmi; 290 nmi_watchdog = nmi;
303 return 1; 291 return 1;
304} 292}
@@ -307,31 +295,30 @@ __setup("nmi_watchdog=", setup_nmi_watchdog);
307 295
308static void disable_lapic_nmi_watchdog(void) 296static void disable_lapic_nmi_watchdog(void)
309{ 297{
310 if (nmi_active <= 0) 298 BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
299
300 if (atomic_read(&nmi_active) <= 0)
311 return; 301 return;
312 switch (boot_cpu_data.x86_vendor) { 302
313 case X86_VENDOR_AMD: 303 on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
314 wrmsr(MSR_K7_EVNTSEL0, 0, 0); 304
315 break; 305 BUG_ON(atomic_read(&nmi_active) != 0);
316 case X86_VENDOR_INTEL:
317 if (boot_cpu_data.x86 == 15) {
318 wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
319 wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
320 }
321 break;
322 }
323 nmi_active = -1;
324 /* tell do_nmi() and others that we're not active any more */
325 nmi_watchdog = 0;
326} 306}
327 307
328static void enable_lapic_nmi_watchdog(void) 308static void enable_lapic_nmi_watchdog(void)
329{ 309{
330 if (nmi_active < 0) { 310 BUG_ON(nmi_watchdog != NMI_LOCAL_APIC);
331 nmi_watchdog = NMI_LOCAL_APIC; 311
332 touch_nmi_watchdog(); 312 /* are we already enabled */
333 setup_apic_nmi_watchdog(); 313 if (atomic_read(&nmi_active) != 0)
334 } 314 return;
315
316 /* are we lapic aware */
317 if (nmi_known_cpu() <= 0)
318 return;
319
320 on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
321 touch_nmi_watchdog();
335} 322}
336 323
337int reserve_lapic_nmi(void) 324int reserve_lapic_nmi(void)
@@ -363,21 +350,24 @@ void release_lapic_nmi(void)
363 350
364void disable_timer_nmi_watchdog(void) 351void disable_timer_nmi_watchdog(void)
365{ 352{
366 if ((nmi_watchdog != NMI_IO_APIC) || (nmi_active <= 0)) 353 BUG_ON(nmi_watchdog != NMI_IO_APIC);
354
355 if (atomic_read(&nmi_active) <= 0)
367 return; 356 return;
368 357
369 disable_irq(0); 358 disable_irq(0);
370 unset_nmi_callback(); 359 on_each_cpu(stop_apic_nmi_watchdog, NULL, 0, 1);
371 nmi_active = -1; 360
372 nmi_watchdog = NMI_NONE; 361 BUG_ON(atomic_read(&nmi_active) != 0);
373} 362}
374 363
375void enable_timer_nmi_watchdog(void) 364void enable_timer_nmi_watchdog(void)
376{ 365{
377 if (nmi_active < 0) { 366 BUG_ON(nmi_watchdog != NMI_IO_APIC);
378 nmi_watchdog = NMI_IO_APIC; 367
368 if (atomic_read(&nmi_active) == 0) {
379 touch_nmi_watchdog(); 369 touch_nmi_watchdog();
380 nmi_active = 1; 370 on_each_cpu(setup_apic_nmi_watchdog, NULL, 0, 1);
381 enable_irq(0); 371 enable_irq(0);
382 } 372 }
383} 373}
@@ -388,7 +378,7 @@ static int nmi_pm_active; /* nmi_active before suspend */
388 378
389static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state) 379static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state)
390{ 380{
391 nmi_pm_active = nmi_active; 381 nmi_pm_active = atomic_read(&nmi_active);
392 disable_lapic_nmi_watchdog(); 382 disable_lapic_nmi_watchdog();
393 return 0; 383 return 0;
394} 384}
@@ -396,7 +386,7 @@ static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state)
396static int lapic_nmi_resume(struct sys_device *dev) 386static int lapic_nmi_resume(struct sys_device *dev)
397{ 387{
398 if (nmi_pm_active > 0) 388 if (nmi_pm_active > 0)
399 enable_lapic_nmi_watchdog(); 389 enable_lapic_nmi_watchdog();
400 return 0; 390 return 0;
401} 391}
402 392
@@ -415,7 +405,13 @@ static int __init init_lapic_nmi_sysfs(void)
415{ 405{
416 int error; 406 int error;
417 407
418 if (nmi_active == 0 || nmi_watchdog != NMI_LOCAL_APIC) 408 /* should really be a BUG_ON but b/c this is an
409 * init call, it just doesn't work. -dcz
410 */
411 if (nmi_watchdog != NMI_LOCAL_APIC)
412 return 0;
413
414 if ( atomic_read(&nmi_active) < 0 )
419 return 0; 415 return 0;
420 416
421 error = sysdev_class_register(&nmi_sysclass); 417 error = sysdev_class_register(&nmi_sysclass);
@@ -428,100 +424,232 @@ late_initcall(init_lapic_nmi_sysfs);
428 424
429#endif /* CONFIG_PM */ 425#endif /* CONFIG_PM */
430 426
427/*
428 * Activate the NMI watchdog via the local APIC.
429 * Original code written by Keith Owens.
430 */
431
432/* Note that these events don't tick when the CPU idles. This means
433 the frequency varies with CPU load. */
434
435#define K7_EVNTSEL_ENABLE (1 << 22)
436#define K7_EVNTSEL_INT (1 << 20)
437#define K7_EVNTSEL_OS (1 << 17)
438#define K7_EVNTSEL_USR (1 << 16)
439#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76
440#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
441
431static int setup_k7_watchdog(void) 442static int setup_k7_watchdog(void)
432{ 443{
444 unsigned int perfctr_msr, evntsel_msr;
433 unsigned int evntsel; 445 unsigned int evntsel;
446 struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
434 447
435 nmi_perfctr_msr = MSR_K7_PERFCTR0; 448 perfctr_msr = MSR_K7_PERFCTR0;
436 449 evntsel_msr = MSR_K7_EVNTSEL0;
437 if (!reserve_perfctr_nmi(nmi_perfctr_msr)) 450 if (!reserve_perfctr_nmi(perfctr_msr))
438 goto fail; 451 goto fail;
439 452
440 if (!reserve_evntsel_nmi(MSR_K7_EVNTSEL0)) 453 if (!reserve_evntsel_nmi(evntsel_msr))
441 goto fail1; 454 goto fail1;
442 455
443 /* Simulator may not support it */ 456 /* Simulator may not support it */
444 if (checking_wrmsrl(MSR_K7_EVNTSEL0, 0UL)) 457 if (checking_wrmsrl(evntsel_msr, 0UL))
445 goto fail2; 458 goto fail2;
446 wrmsrl(MSR_K7_PERFCTR0, 0UL); 459 wrmsrl(perfctr_msr, 0UL);
447 460
448 evntsel = K7_EVNTSEL_INT 461 evntsel = K7_EVNTSEL_INT
449 | K7_EVNTSEL_OS 462 | K7_EVNTSEL_OS
450 | K7_EVNTSEL_USR 463 | K7_EVNTSEL_USR
451 | K7_NMI_EVENT; 464 | K7_NMI_EVENT;
452 465
453 wrmsr(MSR_K7_EVNTSEL0, evntsel, 0); 466 /* setup the timer */
454 wrmsrl(MSR_K7_PERFCTR0, -((u64)cpu_khz * 1000 / nmi_hz)); 467 wrmsr(evntsel_msr, evntsel, 0);
468 wrmsrl(perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
455 apic_write(APIC_LVTPC, APIC_DM_NMI); 469 apic_write(APIC_LVTPC, APIC_DM_NMI);
456 evntsel |= K7_EVNTSEL_ENABLE; 470 evntsel |= K7_EVNTSEL_ENABLE;
457 wrmsr(MSR_K7_EVNTSEL0, evntsel, 0); 471 wrmsr(evntsel_msr, evntsel, 0);
472
473 wd->perfctr_msr = perfctr_msr;
474 wd->evntsel_msr = evntsel_msr;
475 wd->cccr_msr = 0; //unused
476 wd->check_bit = 1ULL<<63;
458 return 1; 477 return 1;
459fail2: 478fail2:
460 release_evntsel_nmi(MSR_K7_EVNTSEL0); 479 release_evntsel_nmi(evntsel_msr);
461fail1: 480fail1:
462 release_perfctr_nmi(nmi_perfctr_msr); 481 release_perfctr_nmi(perfctr_msr);
463fail: 482fail:
464 return 0; 483 return 0;
465} 484}
466 485
486static void stop_k7_watchdog(void)
487{
488 struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
489
490 wrmsr(wd->evntsel_msr, 0, 0);
491
492 release_evntsel_nmi(wd->evntsel_msr);
493 release_perfctr_nmi(wd->perfctr_msr);
494}
495
496/* Note that these events don't tick when the CPU idles. This means
497 the frequency varies with CPU load. */
498
499#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7)
500#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
501#define P4_ESCR_OS (1<<3)
502#define P4_ESCR_USR (1<<2)
503#define P4_CCCR_OVF_PMI0 (1<<26)
504#define P4_CCCR_OVF_PMI1 (1<<27)
505#define P4_CCCR_THRESHOLD(N) ((N)<<20)
506#define P4_CCCR_COMPLEMENT (1<<19)
507#define P4_CCCR_COMPARE (1<<18)
508#define P4_CCCR_REQUIRED (3<<16)
509#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
510#define P4_CCCR_ENABLE (1<<12)
511#define P4_CCCR_OVF (1<<31)
512/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
513 CRU_ESCR0 (with any non-null event selector) through a complemented
514 max threshold. [IA32-Vol3, Section 14.9.9] */
467 515
468static int setup_p4_watchdog(void) 516static int setup_p4_watchdog(void)
469{ 517{
518 unsigned int perfctr_msr, evntsel_msr, cccr_msr;
519 unsigned int evntsel, cccr_val;
470 unsigned int misc_enable, dummy; 520 unsigned int misc_enable, dummy;
521 unsigned int ht_num;
522 struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
471 523
472 rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy); 524 rdmsr(MSR_IA32_MISC_ENABLE, misc_enable, dummy);
473 if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL)) 525 if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
474 return 0; 526 return 0;
475 527
476 nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
477 nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;
478#ifdef CONFIG_SMP 528#ifdef CONFIG_SMP
479 if (smp_num_siblings == 2) 529 /* detect which hyperthread we are on */
480 nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1; 530 if (smp_num_siblings == 2) {
531 unsigned int ebx, apicid;
532
533 ebx = cpuid_ebx(1);
534 apicid = (ebx >> 24) & 0xff;
535 ht_num = apicid & 1;
536 } else
481#endif 537#endif
538 ht_num = 0;
539
540 /* performance counters are shared resources
541 * assign each hyperthread its own set
542 * (re-use the ESCR0 register, seems safe
543 * and keeps the cccr_val the same)
544 */
545 if (!ht_num) {
546 /* logical cpu 0 */
547 perfctr_msr = MSR_P4_IQ_PERFCTR0;
548 evntsel_msr = MSR_P4_CRU_ESCR0;
549 cccr_msr = MSR_P4_IQ_CCCR0;
550 cccr_val = P4_CCCR_OVF_PMI0 | P4_CCCR_ESCR_SELECT(4);
551 } else {
552 /* logical cpu 1 */
553 perfctr_msr = MSR_P4_IQ_PERFCTR1;
554 evntsel_msr = MSR_P4_CRU_ESCR0;
555 cccr_msr = MSR_P4_IQ_CCCR1;
556 cccr_val = P4_CCCR_OVF_PMI1 | P4_CCCR_ESCR_SELECT(4);
557 }
482 558
483 if (!reserve_perfctr_nmi(nmi_perfctr_msr)) 559 if (!reserve_perfctr_nmi(perfctr_msr))
484 goto fail; 560 goto fail;
485 561
486 if (!reserve_evntsel_nmi(MSR_P4_CRU_ESCR0)) 562 if (!reserve_evntsel_nmi(evntsel_msr))
487 goto fail1; 563 goto fail1;
488 564
489 wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0); 565 evntsel = P4_ESCR_EVENT_SELECT(0x3F)
490 wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0); 566 | P4_ESCR_OS
491 Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz * 1000UL / nmi_hz)); 567 | P4_ESCR_USR;
492 wrmsrl(MSR_P4_IQ_COUNTER0, -((u64)cpu_khz * 1000 / nmi_hz)); 568
569 cccr_val |= P4_CCCR_THRESHOLD(15)
570 | P4_CCCR_COMPLEMENT
571 | P4_CCCR_COMPARE
572 | P4_CCCR_REQUIRED;
573
574 wrmsr(evntsel_msr, evntsel, 0);
575 wrmsr(cccr_msr, cccr_val, 0);
576 wrmsrl(perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
493 apic_write(APIC_LVTPC, APIC_DM_NMI); 577 apic_write(APIC_LVTPC, APIC_DM_NMI);
494 wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0); 578 cccr_val |= P4_CCCR_ENABLE;
579 wrmsr(cccr_msr, cccr_val, 0);
580
581 wd->perfctr_msr = perfctr_msr;
582 wd->evntsel_msr = evntsel_msr;
583 wd->cccr_msr = cccr_msr;
584 wd->check_bit = 1ULL<<39;
495 return 1; 585 return 1;
496fail1: 586fail1:
497 release_perfctr_nmi(nmi_perfctr_msr); 587 release_perfctr_nmi(perfctr_msr);
498fail: 588fail:
499 return 0; 589 return 0;
500} 590}
501 591
502void setup_apic_nmi_watchdog(void) 592static void stop_p4_watchdog(void)
503{ 593{
504 switch (boot_cpu_data.x86_vendor) { 594 struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
505 case X86_VENDOR_AMD: 595
506 if (boot_cpu_data.x86 != 15) 596 wrmsr(wd->cccr_msr, 0, 0);
507 return; 597 wrmsr(wd->evntsel_msr, 0, 0);
508 if (strstr(boot_cpu_data.x86_model_id, "Screwdriver")) 598
509 return; 599 release_evntsel_nmi(wd->evntsel_msr);
510 if (!setup_k7_watchdog()) 600 release_perfctr_nmi(wd->perfctr_msr);
511 return; 601}
512 break; 602
513 case X86_VENDOR_INTEL: 603void setup_apic_nmi_watchdog(void *unused)
514 if (boot_cpu_data.x86 != 15) 604{
515 return; 605 /* only support LOCAL and IO APICs for now */
516 if (!setup_p4_watchdog()) 606 if ((nmi_watchdog != NMI_LOCAL_APIC) &&
607 (nmi_watchdog != NMI_IO_APIC))
608 return;
609
610 if (nmi_watchdog == NMI_LOCAL_APIC) {
611 switch (boot_cpu_data.x86_vendor) {
612 case X86_VENDOR_AMD:
613 if (strstr(boot_cpu_data.x86_model_id, "Screwdriver"))
614 return;
615 if (!setup_k7_watchdog())
616 return;
617 break;
618 case X86_VENDOR_INTEL:
619 if (!setup_p4_watchdog())
620 return;
621 break;
622 default:
517 return; 623 return;
518 break; 624 }
625 }
626 __get_cpu_var(nmi_watchdog_ctlblk.enabled) = 1;
627 atomic_inc(&nmi_active);
628}
519 629
520 default: 630static void stop_apic_nmi_watchdog(void *unused)
521 return; 631{
632 /* only support LOCAL and IO APICs for now */
633 if ((nmi_watchdog != NMI_LOCAL_APIC) &&
634 (nmi_watchdog != NMI_IO_APIC))
635 return;
636
637 if (nmi_watchdog == NMI_LOCAL_APIC) {
638 switch (boot_cpu_data.x86_vendor) {
639 case X86_VENDOR_AMD:
640 if (strstr(boot_cpu_data.x86_model_id, "Screwdriver"))
641 return;
642 stop_k7_watchdog();
643 break;
644 case X86_VENDOR_INTEL:
645 stop_p4_watchdog();
646 break;
647 default:
648 return;
649 }
522 } 650 }
523 lapic_nmi_owner = LAPIC_NMI_WATCHDOG; 651 __get_cpu_var(nmi_watchdog_ctlblk.enabled) = 0;
524 nmi_active = 1; 652 atomic_dec(&nmi_active);
525} 653}
526 654
527/* 655/*
@@ -558,50 +686,70 @@ void __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)
558{ 686{
559 int sum; 687 int sum;
560 int touched = 0; 688 int touched = 0;
689 struct nmi_watchdog_ctlblk *wd = &__get_cpu_var(nmi_watchdog_ctlblk);
690 u64 dummy;
691
692 /* check for other users first */
693 if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
694 == NOTIFY_STOP) {
695 touched = 1;
696 }
561 697
562 sum = read_pda(apic_timer_irqs); 698 sum = read_pda(apic_timer_irqs);
563 if (__get_cpu_var(nmi_touch)) { 699 if (__get_cpu_var(nmi_touch)) {
564 __get_cpu_var(nmi_touch) = 0; 700 __get_cpu_var(nmi_touch) = 0;
565 touched = 1; 701 touched = 1;
566 } 702 }
703
567#ifdef CONFIG_X86_MCE 704#ifdef CONFIG_X86_MCE
568 /* Could check oops_in_progress here too, but it's safer 705 /* Could check oops_in_progress here too, but it's safer
569 not too */ 706 not too */
570 if (atomic_read(&mce_entry) > 0) 707 if (atomic_read(&mce_entry) > 0)
571 touched = 1; 708 touched = 1;
572#endif 709#endif
710 /* if the apic timer isn't firing, this cpu isn't doing much */
573 if (!touched && __get_cpu_var(last_irq_sum) == sum) { 711 if (!touched && __get_cpu_var(last_irq_sum) == sum) {
574 /* 712 /*
575 * Ayiee, looks like this CPU is stuck ... 713 * Ayiee, looks like this CPU is stuck ...
576 * wait a few IRQs (5 seconds) before doing the oops ... 714 * wait a few IRQs (5 seconds) before doing the oops ...
577 */ 715 */
578 local_inc(&__get_cpu_var(alert_counter)); 716 local_inc(&__get_cpu_var(alert_counter));
579 if (local_read(&__get_cpu_var(alert_counter)) == 5*nmi_hz) { 717 if (local_read(&__get_cpu_var(alert_counter)) == 5*nmi_hz)
580 if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
581 == NOTIFY_STOP) {
582 local_set(&__get_cpu_var(alert_counter), 0);
583 return;
584 }
585 die_nmi("NMI Watchdog detected LOCKUP on CPU %d\n", regs); 718 die_nmi("NMI Watchdog detected LOCKUP on CPU %d\n", regs);
586 }
587 } else { 719 } else {
588 __get_cpu_var(last_irq_sum) = sum; 720 __get_cpu_var(last_irq_sum) = sum;
589 local_set(&__get_cpu_var(alert_counter), 0); 721 local_set(&__get_cpu_var(alert_counter), 0);
590 } 722 }
591 if (nmi_perfctr_msr) { 723
592 if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) { 724 /* see if the nmi watchdog went off */
593 /* 725 if (wd->enabled) {
594 * P4 quirks: 726 if (nmi_watchdog == NMI_LOCAL_APIC) {
595 * - An overflown perfctr will assert its interrupt 727 rdmsrl(wd->perfctr_msr, dummy);
596 * until the OVF flag in its CCCR is cleared. 728 if (dummy & wd->check_bit){
597 * - LVTPC is masked on interrupt and must be 729 /* this wasn't a watchdog timer interrupt */
598 * unmasked by the LVTPC handler. 730 goto done;
599 */ 731 }
600 wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0); 732
601 apic_write(APIC_LVTPC, APIC_DM_NMI); 733 /* only Intel uses the cccr msr */
602 } 734 if (wd->cccr_msr != 0) {
603 wrmsrl(nmi_perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz)); 735 /*
736 * P4 quirks:
737 * - An overflown perfctr will assert its interrupt
738 * until the OVF flag in its CCCR is cleared.
739 * - LVTPC is masked on interrupt and must be
740 * unmasked by the LVTPC handler.
741 */
742 rdmsrl(wd->cccr_msr, dummy);
743 dummy &= ~P4_CCCR_OVF;
744 wrmsrl(wd->cccr_msr, dummy);
745 apic_write(APIC_LVTPC, APIC_DM_NMI);
746 }
747 /* start the cycle over again */
748 wrmsrl(wd->perfctr_msr, -((u64)cpu_khz * 1000 / nmi_hz));
749 }
604 } 750 }
751done:
752 return;
605} 753}
606 754
607static __kprobes int dummy_nmi_callback(struct pt_regs * regs, int cpu) 755static __kprobes int dummy_nmi_callback(struct pt_regs * regs, int cpu)