lkml.org 
[lkml]   [1999]   [Dec]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: wait_on_irq, CPU1
On Wed, 29 Dec 1999, Manfred Spraul wrote:

>This fix is incomplete: a few lines later 4095 is used again.

In my previous mail I have not quoted all the changes. These are the
complete i386/*/traps.c changes in 2.2.13-ikd1.bz2:

diff -urN 2.2.13/arch/i386/kernel/traps.c 2.2.13-ikd/arch/i386/kernel/traps.c
--- 2.2.13/arch/i386/kernel/traps.c Sun Oct 31 23:31:21 1999
+++ 2.2.13-ikd/arch/i386/kernel/traps.c Wed Nov 10 19:03:24 1999
@@ -2,6 +2,8 @@
* linux/arch/i386/traps.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * 1998, Ingo Molnar, added NMI-Watchdog driver
*/

/*
@@ -20,12 +22,18 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/kernel_stat.h> /* NMI oopser watchdog */
+#include <linux/profiler.h> /* mcount debugger */

#ifdef CONFIG_MCA
#include <linux/mca.h>
#include <asm/processor.h>
#endif

+#if defined(CONFIG_KDB)
+#include <linux/kdb.h>
+#endif
+
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -45,6 +53,9 @@
#include "irq.h"

asmlinkage int system_call(void);
+#if defined(CONFIG_KDB)
+asmlinkage int kdb_call(void);
+#endif
asmlinkage void lcall7(void);

struct desc_struct default_ldt = { 0, 0 };
@@ -117,9 +128,55 @@
* segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
* a guess of how much space is likely to be vmalloced.
*/
-#define VMALLOC_OFFSET (8*1024*1024)
#define MODULE_RANGE (8*1024*1024)

+#ifdef CONFIG_KERNEL_DEBUGGING
+inline void print_call_trace_exact (struct pt_regs * regs, unsigned long esp)
+{
+ int i=1;
+ unsigned long *this_stack, *prev_stack, prev_addr, *prev_bp, framesize;
+
+ printk("\nCall Trace: ");
+
+ /*
+ * the stack layout: /----- *this_stack
+ * V
+ * [this_frame][prev_bp][prev_addr][prev_frame][...]
+ */
+
+ this_stack = (unsigned long *) regs->ebp;
+ framesize=0;
+
+ while ((unsigned long) this_stack >= (esp & ~0x1fffUL) &&
+ (unsigned long) (this_stack+1) <
+ (esp & ~0x1fffUL)+0x2000UL)
+ {
+ prev_addr = *(this_stack+1);
+
+ if (!(i++ % 8))
+ printk("\n ");
+ /* ksymoops expects [<xxx>] */
+ printk("[<%08lx>] (%lu) ", prev_addr, framesize);
+
+ prev_bp = (unsigned long *)(*this_stack);
+ prev_stack = this_stack;
+ this_stack = prev_bp;
+
+ if (i > 100)
+ {
+ printk("WARNING: something fishy with the stack frame?\n");
+ printk("this_stack: [<%08lx>]\n",
+ (unsigned long)this_stack);
+ break;
+ }
+ framesize = (unsigned long)this_stack-(unsigned long)prev_stack;
+ }
+#ifdef CONFIG_TRACE
+ print_emergency_trace();
+#endif
+}
+#endif /* CONFIG_KERNEL_DEBUGGING */
+
static void show_registers(struct pt_regs *regs)
{
int i;
@@ -155,19 +212,27 @@
printk("\nStack: ");
stack = (unsigned long *) esp;
for(i=0; i < kstack_depth_to_print; i++) {
- if (((long) stack & 4095) == 0)
+ if (((long) stack & 8191) == 0)
break;
if (i && ((i % 8) == 0))
printk("\n ");
printk("%08lx ", *stack++);
}
+
+/*
+ * If tracing is switched on then we can walk the stack frame. Otherwise we
+ * can only guess.
+ */
+#ifdef CONFIG_KERNEL_DEBUGGING
+ print_call_trace_exact(regs, esp);
+#else
printk("\nCall Trace: ");
stack = (unsigned long *) esp;
i = 1;
module_start = PAGE_OFFSET + (max_mapnr << PAGE_SHIFT);
module_start = ((module_start + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
module_end = module_start + MODULE_RANGE;
- while (((long) stack & 4095) != 0) {
+ while (((long) stack & 8191) != 0) {
addr = *stack++;
/*
* If the address is either in the text segment of the
@@ -186,6 +251,7 @@
i++;
}
}
+#endif /* CONFIG_KERNEL_DEBUGGING */
printk("\nCode: ");
for(i=0;i<20;i++)
printk("%02x ", ((unsigned char *)regs->eip)[i]);
@@ -199,6 +265,9 @@
{
console_verbose();
spin_lock_irq(&die_lock);
+#if defined(CONFIG_KDB)
+ kdb(KDB_REASON_PANIC, err, regs);
+#endif
printk("%s: %04lx\n", str, err & 0xffff);
show_registers(regs);
spin_unlock_irq(&die_lock);
@@ -285,6 +354,7 @@
}
}

+#ifndef CONFIG_NMI_WATCHDOG
static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
{
printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n");
@@ -335,6 +405,73 @@
if (!(reason & 0xc0))
unknown_nmi_error(reason, regs);
}
+#else /* CONFIG_NMI_WATCHDOG */
+
+extern atomic_t nmi_counter;
+
+/*
+ * FIXME: we assume here that the NMI came from the IO-APIC. It's a quite safe
+ * assumption in most cases, but if anyone knows a way to distinguish between
+ * NMI reasons, please speak up ... [i doubt that the IO-APIC does IO port 0x61
+ * correctly]
+ */
+
+extern atomic_t apic_timer_irqs [NR_CPUS];
+extern spinlock_t console_lock;
+static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED;
+
+asmlinkage void do_nmi(struct pt_regs * regs, long error_code)
+{
+ /*
+ * the best way to detect wether a CPU has a 'hard lockup' problem
+ * is to check it's local APIC timer IRQ counts. If they are not
+ * changing then that CPU has some problem.
+ *
+ * as these watchdog NMI IRQs are broadcasted to every CPU, here
+ * we only have to check the current processor.
+ *
+ * since NMIs dont listen to _any_ locks, we have to be extremely
+ * careful not to rely on unsafe variables. The printk might lock
+ * up though, so we have to break up console_lock first ...
+ * [when there will be more tty-related locks, break them up
+ * here too!]
+ */
+
+ static atomic_t last_irq_sums [NR_CPUS] = { ATOMIC_INIT(0), };
+ static atomic_t alert_counter [NR_CPUS] = { ATOMIC_INIT(0), };
+
+ /*
+ * Since current-> is always on the stack, and we always switch
+ * the stack NMI-atomically, it's safe to use smp_processor_id().
+ */
+ int sum, cpu = smp_processor_id();
+
+ atomic_inc(&nmi_counter);
+ sum = atomic_read(apic_timer_irqs+cpu);
+
+ if (atomic_read(last_irq_sums+cpu) == sum) {
+ /*
+ * Ayiee, looks like this CPU is stuck ...
+ * wait a few IRQs (5 seconds) before doing the oops ...
+ */
+ atomic_inc(alert_counter+cpu);
+ if (atomic_read(alert_counter+cpu) == HZ/10) {
+#ifdef CONFIG_DEBUG_MCOUNT
+ extern int sysctl_disable_mcount;
+ sysctl_disable_mcount = 1;
+#endif
+ spin_lock(&nmi_print_lock);
+ printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu);
+ show_registers(regs);
+ spin_unlock(&nmi_print_lock);
+ do_exit(SIGSEGV);
+ }
+ } else {
+ atomic_set(last_irq_sums+cpu,sum);
+ atomic_set(alert_counter+cpu,0);
+ }
+}
+#endif /* CONFIG_NMI_WATCHDOG */

/*
* Careful - we must not do a lock-kernel until we have checked that the
@@ -397,9 +534,15 @@
return;

clear_dr7:
+
+#if defined(CONFIG_KDB)
+ kdb(KDB_REASON_DEBUG, error_code, regs);
+#else
+
__asm__("movl %0,%%db7"
: /* no output */
: "r" (0));
+#endif /* CONFIG_KDB */
return;

clear_TF:
@@ -692,6 +835,13 @@
set_trap_gate(16,&coprocessor_error);
set_trap_gate(17,&alignment_check);
set_system_gate(SYSCALL_VECTOR,&system_call);
+#if defined(CONFIG_KDB)
+ /*
+ * A trap gate, used by the kernel to enter the
+ * debugger preserving all registers.
+ */
+ set_trap_gate(KDBENTER_VECTOR,&kdb_call);
+#endif

/* set up GDT task & ldt entries */
set_tss_desc(0, &init_task.tss);
Andrea


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:55    [W:0.264 / U:1.920 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site