This is an experimental patch that I did to switch the i386
kernel to use notify_die(), it is based on the x86_64 version
that I wrote.
This patch is designed to apply over the top of the common and
i386 2.6.11 patches.
From my point of view the goal is to reduce KDB source intrusion
to minimal in the main kernel source, and this patch takes a
step in that direction, it is by no means complete.
I have built, booted, and minimally tested this, it needs more
testing, but I thought I'd give it to you Keith to polish and
tweak to your own tastes.
Cheers,
Jack
-- Attached file included as plaintext by Ecartis --
diff -Naur linux-2.6.11/arch/i386/kdb/kdbasupport.c
linux-2.6.11-jfv/arch/i386/kdb/kdbasupport.c
--- linux-2.6.11/arch/i386/kdb/kdbasupport.c 2005-03-15 03:53:52.000000000
-0800
+++ linux-2.6.11-jfv/arch/i386/kdb/kdbasupport.c 2005-03-15
03:28:34.000000000 -0800
@@ -20,7 +20,7 @@
#include <linux/sched.h>
#include <linux/kdb.h>
#include <linux/kdbprivate.h>
-
+#include <asm/kdebug.h>
#include <asm/processor.h>
#include <asm/msr.h>
#include <asm/uaccess.h>
@@ -1434,6 +1434,54 @@
}
/*
+ * kdba_entry
+ *
+ * This is the interface routine between
+ * the notifier die_chain and kdb
+ */
+static int kdba_entry( struct notifier_block *b, unsigned long val, void *v)
+{
+ struct die_args *args = v;
+ int err, trap, ret = 0;
+ struct pt_regs *regs;
+
+ regs = args->regs;
+ err = args->err;
+ trap = args->trapnr;
+ switch (val){
+#if defined(CONFIG_SMP)
+ case DIE_NMI_IPI:
+ ret = kdb_ipi(regs, NULL);
+ break;
+#endif
+ case DIE_OOPS:
+ ret = kdb(KDB_REASON_OOPS, err, regs);
+ break;
+ case DIE_CALL:
+ ret = kdb(KDB_REASON_ENTER, err, regs);
+ break;
+ case DIE_DEBUG:
+ ret = kdb(KDB_REASON_DEBUG, err, regs);
+ break;
+ case DIE_TRAP:
+ if (trap == 3) // breakpoint
+ ret = kdb(KDB_REASON_BREAK, err, regs);
+ // falls thru
+ default:
+ break;
+ }
+ return (ret ? NOTIFY_BAD : NOTIFY_DONE);
+}
+
+/*
+ * notifier block for kdb entry
+ */
+static struct notifier_block kdba_notifier = {
+ .notifier_call = kdba_entry
+};
+
+
+/*
* kdba_init
*
* Architecture specific initialization.
@@ -1454,7 +1502,7 @@
kdba_enable_lbr();
kdb_register("pt_regs", kdba_pt_regs, "address", "Format struct
pt_regs", 0);
kdb_register("stackdepth", kdba_stackdepth, "[percentage]", "Print
processes using >= stack percentage", 0);
-
+ notifier_chain_register(&i386die_chain, &kdba_notifier);
return;
}
diff -Naur linux-2.6.11/arch/i386/kernel/entry.S
linux-2.6.11-jfv/arch/i386/kernel/entry.S
--- linux-2.6.11/arch/i386/kernel/entry.S 2005-03-15 03:53:52.000000000
-0800
+++ linux-2.6.11-jfv/arch/i386/kernel/entry.S 2005-03-14 06:42:01.000000000
-0800
@@ -147,17 +147,15 @@
popl %eax
jmp syscall_exit
-#if defined(CONFIG_KDB)
-ENTRY(kdb_call)
+ENTRY(call_debug)
pushl %eax # save orig EAX
SAVE_ALL
pushl %esp # struct pt_regs
pushl $0 # error_code
- pushl $7 # KDB_REASON_ENTRY
- call kdb
+ pushl $7 # REASON_ENTRY
+ call do_call_debug
addl $12,%esp # remove args
jmp restore_all
-#endif
/*
* Return to user mode is not as complex as all this looks,
diff -Naur linux-2.6.11/arch/i386/kernel/i8259.c
linux-2.6.11-jfv/arch/i386/kernel/i8259.c
--- linux-2.6.11/arch/i386/kernel/i8259.c 2005-03-15 03:53:52.000000000
-0800
+++ linux-2.6.11-jfv/arch/i386/kernel/i8259.c 2005-03-15 02:55:46.000000000
-0800
@@ -24,6 +24,7 @@
#include <asm/apic.h>
#include <asm/arch_hooks.h>
#include <asm/i8259.h>
+#include <asm/kdebug.h>
#include <linux/irq.h>
@@ -404,11 +405,7 @@
int vector = FIRST_EXTERNAL_VECTOR + i;
if (i >= NR_IRQS)
break;
-#ifdef CONFIG_KDB
- if (vector == KDBENTER_VECTOR)
- continue;
-#endif
- if (vector != SYSCALL_VECTOR)
+ if (vector != SYSCALL_VECTOR && vector != KDB_VECTOR)
set_intr_gate(vector, interrupt[i]);
}
diff -Naur linux-2.6.11/arch/i386/kernel/io_apic.c
linux-2.6.11-jfv/arch/i386/kernel/io_apic.c
--- linux-2.6.11/arch/i386/kernel/io_apic.c 2005-03-15 03:53:52.000000000
-0800
+++ linux-2.6.11-jfv/arch/i386/kernel/io_apic.c 2005-03-15 02:52:59.000000000
-0800
@@ -27,9 +27,6 @@
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/config.h>
-#ifdef CONFIG_KDB
-#include <linux/kdb.h>
-#endif /* CONFIG_KDB */
#include <linux/smp_lock.h>
#include <linux/mc146818rtc.h>
#include <linux/compiler.h>
@@ -1141,10 +1138,6 @@
current_vector += 8;
if (current_vector == SYSCALL_VECTOR)
goto next;
-#ifdef CONFIG_KDB
- if (current_vector == KDBENTER_VECTOR)
- goto next;
-#endif /* CONFIG_KDB */
if (current_vector >= FIRST_SYSTEM_VECTOR) {
offset++;
diff -Naur linux-2.6.11/arch/i386/kernel/nmi.c
linux-2.6.11-jfv/arch/i386/kernel/nmi.c
--- linux-2.6.11/arch/i386/kernel/nmi.c 2005-03-01 23:38:10.000000000 -0800
+++ linux-2.6.11-jfv/arch/i386/kernel/nmi.c 2005-03-15 03:08:29.000000000
-0800
@@ -31,6 +31,7 @@
#include <asm/mtrr.h>
#include <asm/mpspec.h>
#include <asm/nmi.h>
+#include <asm/kdebug.h>
#include "mach_traps.h"
@@ -491,8 +492,13 @@
* wait a few IRQs (5 seconds) before doing the oops ...
*/
alert_counter[cpu]++;
- if (alert_counter[cpu] == 5*nmi_hz)
+ if (alert_counter[cpu] == 5*nmi_hz) {
+ if (notify_die(DIE_NMI, "nmi", regs, 0, 2, SIGINT) ==
NOTIFY_BAD) {
+ alert_counter[cpu] = 0;
+ return;
+ }
die_nmi(regs, "NMI Watchdog detected LOCKUP");
+ }
} else {
last_irq_sums[cpu] = sum;
alert_counter[cpu] = 0;
diff -Naur linux-2.6.11/arch/i386/kernel/smp.c
linux-2.6.11-jfv/arch/i386/kernel/smp.c
--- linux-2.6.11/arch/i386/kernel/smp.c 2005-03-15 03:53:52.000000000 -0800
+++ linux-2.6.11-jfv/arch/i386/kernel/smp.c 2005-03-15 02:45:22.000000000
-0800
@@ -25,6 +25,7 @@
#include <mach_apic.h>
#include <linux/config.h>
+#include <asm/kdebug.h>
#ifdef CONFIG_KDB
#include <linux/kdb.h>
#endif /* CONFIG_KDB */
diff -Naur linux-2.6.11/arch/i386/kernel/traps.c
linux-2.6.11-jfv/arch/i386/kernel/traps.c
--- linux-2.6.11/arch/i386/kernel/traps.c 2005-03-15 03:53:52.000000000
-0800
+++ linux-2.6.11-jfv/arch/i386/kernel/traps.c 2005-03-15 03:36:16.000000000
-0800
@@ -61,9 +61,6 @@
#include "mach_traps.h"
asmlinkage int system_call(void);
-#ifdef CONFIG_KDB
-asmlinkage int kdb_call(void);
-#endif /* CONFIG_KDB */
struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
{ 0, 0 }, { 0, 0 } };
@@ -100,6 +97,7 @@
asmlinkage void alignment_check(void);
asmlinkage void spurious_interrupt_bug(void);
asmlinkage void machine_check(void);
+asmlinkage void call_debug(void);
static int kstack_depth_to_print = 24;
struct notifier_block *i386die_chain;
@@ -350,10 +348,6 @@
bust_spinlocks(0);
die.lock_owner = -1;
spin_unlock_irq(&die.lock);
-#ifdef CONFIG_KDB
- kdb_diemsg = str;
- kdb(KDB_REASON_OOPS, err, regs);
-#endif /* CONFIG_KDB */
if (in_interrupt())
panic("Fatal exception in interrupt");
@@ -455,7 +449,7 @@
}
DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV,
regs->eip)
-#if !defined(CONFIG_KPROBES) && !defined(CONFIG_KDB)
+#if !defined(CONFIG_KPROBES)
DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
#endif
DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
@@ -551,9 +545,6 @@
static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
{
-#ifdef CONFIG_KDB
- (void)kdb(KDB_REASON_NMI, reason, regs);
-#endif /* CONFIG_KDB */
#ifdef CONFIG_MCA
/* Might actually be able to figure out what the guilty party
* is. */
@@ -583,9 +574,6 @@
smp_processor_id(), regs->eip);
show_registers(regs);
printk("console shuts up ...\n");
-#ifdef CONFIG_KDB
- kdb(KDB_REASON_NMI, 0, regs);
-#endif /* CONFIG_KDB */
console_silent();
spin_unlock(&nmi_print_lock);
bust_spinlocks(0);
@@ -600,16 +588,6 @@
if (!smp_processor_id())
reason = get_nmi_reason();
-#if defined(CONFIG_SMP) && defined(CONFIG_KDB)
- /*
- * Call the kernel debugger to see if this NMI is due
- * to an KDB requested IPI. If so, kdb will handle it.
- */
- if (kdb_ipi(regs, NULL)) {
- return;
- }
-#endif /* defined(CONFIG_SMP) && defined(CONFIG_KDB) */
-
if (!(reason & 0xc0)) {
if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
== NOTIFY_STOP)
@@ -715,11 +693,6 @@
__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
-#ifdef CONFIG_KDB
- if (kdb(KDB_REASON_DEBUG, error_code, regs))
- return;
-#endif /* CONFIG_KDB */
-
if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
SIGTRAP) == NOTIFY_STOP)
return;
@@ -782,16 +755,6 @@
return;
}
-#ifdef CONFIG_KDB
-fastcall void do_int3(struct pt_regs * regs, long error_code)
-{
- if (kdb(KDB_REASON_BREAK, error_code, regs))
- return;
- do_trap(3, SIGTRAP, "int3", 1, regs, error_code, NULL);
-}
-#endif /* CONFIG_KDB */
-
-
/*
* Note that we play around with the 'TS' bit in an attempt to get
* the correct behaviour even in the presence of the asynchronous
@@ -1085,14 +1048,13 @@
set_trap_gate(19,&simd_coprocessor_error);
set_system_gate(SYSCALL_VECTOR,&system_call);
-#ifdef CONFIG_KDB
kdb_enablehwfault();
+
/*
* A trap gate, used by the kernel to enter the
* debugger, preserving all registers.
*/
- set_trap_gate(KDBENTER_VECTOR, &kdb_call);
-#endif /* CONFIG_KDB */
+ set_trap_gate(KDB_VECTOR, call_debug);
/*
* Should be a barrier for any external CPU state.
@@ -1101,3 +1063,9 @@
trap_init_hook();
}
+
+void do_call_debug(struct pt_regs *regs)
+{
+ notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT);
+}
+
diff -Naur linux-2.6.11/include/asm-i386/kdb.h
linux-2.6.11-jfv/include/asm-i386/kdb.h
--- linux-2.6.11/include/asm-i386/kdb.h 2005-03-15 03:53:52.000000000 -0800
+++ linux-2.6.11-jfv/include/asm-i386/kdb.h 2005-03-15 02:47:40.000000000
-0800
@@ -17,7 +17,7 @@
* is intended to be used from interrupt level, it must use
* a non-maskable entry method.
*/
-#define KDB_ENTER() do {if (kdb_on && !KDB_IS_RUNNING()) { asm("\tint
$129\n"); }} while(0)
+#define KDB_ENTER() do {if (kdb_on && !KDB_IS_RUNNING()) { asm("\tint
$249\n"); }} while(0)
/*
* Needed for exported symbols.
---------------------------
Use http://oss.sgi.com/ecartis to modify your settings or to unsubscribe.
|