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.