Index: 2.6.x-xfs/arch/i386/Kconfig =================================================================== --- 2.6.x-xfs.orig/arch/i386/Kconfig Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/arch/i386/Kconfig Tue May 11 16:22:02 2004 @@ -1284,6 +1284,85 @@ on the VM subsystem for higher order allocations. This option will also use IRQ stacks to compensate for the reduced stackspace. +config KDB + bool "Built-in Kernel Debugger support" + depends on DEBUG_KERNEL + help + This option provides a built-in kernel debugger. The built-in + kernel debugger contains commands which allow memory to be examined, + instructions to be disassembled and breakpoints to be set. For details, + see Documentation/kdb/kdb.mm and the manual pages kdb_bt, kdb_ss, etc. + Kdb can also be used via the serial port. Set up the system to + have a serial console (see Documentation/serial-console.txt). + The Control-A key sequence on the serial port will cause the + kernel debugger to be entered with input from the serial port and + output to the serial console. If unsure, say N. + +config KDB_MODULES + tristate "KDB modules" + depends on KDB + help + KDB can be extended by adding your own modules, in directory + kdb/modules. This option selects the way that these modules should + be compiled, as free standing modules (select M) or built into the + kernel (select Y). If unsure say M. + +config KDB_OFF + bool "KDB off by default" + depends on KDB + help + Normally kdb is activated by default, as long as CONFIG_KDB is set. + If you want to ship a kernel with kdb support but only have kdb + turned on when the user requests it then select this option. When + compiled with CONFIG_KDB_OFF, kdb ignores all events unless you boot + with kdb=on or you echo "1" > /proc/sys/kernel/kdb. This option also + works in reverse, if kdb is normally activated, you can boot with + kdb=off or echo "0" > /proc/sys/kernel/kdb to deactivate kdb. If + unsure, say N. + +config KDB_CONTINUE_CATASTROPHIC + int "KDB continues after catastrophic errors" + depends on KDB + default "0" + help + This integer controls the behaviour of kdb when the kernel gets a + catastrophic error, i.e. for a panic, oops, NMI or other watchdog + tripping. CONFIG_KDB_CONTINUE_CATASTROPHIC interacts with + /proc/sys/kernel/kdb and CONFIG_DUMP (if your kernel has the LKCD + patch). + When KDB is active (/proc/sys/kernel/kdb == 1) and a catastrophic + error occurs, nothing extra happens until you type 'go'. + CONFIG_KDB_CONTINUE_CATASTROPHIC == 0 (default). The first time + you type 'go', kdb warns you. The second time you type 'go', KDB + tries to continue - no guarantees that the kernel is still usable. + CONFIG_KDB_CONTINUE_CATASTROPHIC == 1. KDB tries to continue - no + guarantees that the kernel is still usable. + CONFIG_KDB_CONTINUE_CATASTROPHIC == 2. If your kernel has the LKCD + patch and LKCD is configured to take a dump then KDB forces a dump. + Whether or not a dump is taken, KDB forces a reboot. + When KDB is not active (/proc/sys/kernel/kdb == 0) and a catastrophic + error occurs, the following steps are automatic, no human + intervention is required. + CONFIG_KDB_CONTINUE_CATASTROPHIC == 0 (default) or 1. KDB attempts + to continue - no guarantees that the kernel is still usable. + CONFIG_KDB_CONTINUE_CATASTROPHIC == 2. If your kernel has the LKCD + patch and LKCD is configured to take a dump then KDB automatically + forces a dump. Whether or not a dump is taken, KDB forces a + reboot. + If you are not sure, say 0. Read Documentation/kdb/dump.txt before + setting to 2. + +# KDB_USB does not work, the usb code needs to be +# converted from 2.4.19 to 2.5.40 APIs. Omit it until somebody +# fixes CONFIG_KDB_USB. +#config KDB_USB +# bool "Support for USB Keyboard in KDB" +# depends on KDB && USB +# help +# If you want to use kdb from a USB keyboard then say Y here. If you +# say N then kdb can only be used from a PC (AT) keyboard or a serial +# console. + config X86_FIND_SMP_CONFIG bool depends on X86_LOCAL_APIC || X86_VOYAGER Index: 2.6.x-xfs/arch/i386/Makefile =================================================================== --- 2.6.x-xfs.orig/arch/i386/Makefile Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/arch/i386/Makefile Tue May 11 16:22:02 2004 @@ -47,6 +47,7 @@ cflags-$(CONFIG_MWINCHIP3D) += $(call check_gcc,-march=winchip2,-march=i586) cflags-$(CONFIG_MCYRIXIII) += $(call check_gcc,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 cflags-$(CONFIG_MVIAC3_2) += $(call check_gcc,-march=c3-2,-march=i686) +cflags-$(CONFIG_KDB) += $(call check_gcc,-fno-optimize-sibling-calls,) # AMD Elan support cflags-$(CONFIG_X86_ELAN) += -march=i486 @@ -108,6 +109,7 @@ # must be linked after kernel/ drivers-$(CONFIG_OPROFILE) += arch/i386/oprofile/ drivers-$(CONFIG_PM) += arch/i386/power/ +drivers-$(CONFIG_KDB) += arch/i386/kdb/ CFLAGS += $(mflags-y) AFLAGS += $(mflags-y) Index: 2.6.x-xfs/arch/i386/kernel/entry.S =================================================================== --- 2.6.x-xfs.orig/arch/i386/kernel/entry.S Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/arch/i386/kernel/entry.S Tue May 11 16:22:02 2004 @@ -187,6 +187,18 @@ popl %eax jmp syscall_exit +#if defined(CONFIG_KDB) +ENTRY(kdb_call) + pushl %eax # save orig EAX + SAVE_ALL + pushl %esp # struct pt_regs + pushl $0 # error_code + pushl $7 # KDB_REASON_ENTRY + call kdb + addl $12,%esp # remove args + RESTORE_ALL +#endif + /* * Return to user mode is not as complex as all this looks, * but we want the default path for a system call return to @@ -590,6 +602,22 @@ pushl $do_alignment_check jmp error_code +#if defined(CONFIG_KDB) +ENTRY(page_fault_mca) + pushl %ecx + pushl %edx + pushl %eax + movl $473,%ecx + rdmsr + andl $0xfffffffe,%eax /* Disable last branch recording */ + wrmsr + popl %eax + popl %edx + popl %ecx + pushl $do_page_fault + jmp error_code +#endif + ENTRY(page_fault) pushl $do_page_fault jmp error_code Index: 2.6.x-xfs/arch/i386/kernel/i8259.c =================================================================== --- 2.6.x-xfs.orig/arch/i386/kernel/i8259.c Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/arch/i386/kernel/i8259.c Tue May 11 16:22:02 2004 @@ -423,6 +423,10 @@ int vector = FIRST_EXTERNAL_VECTOR + i; if (i >= NR_IRQS) break; +#ifdef CONFIG_KDB + if (vector == KDBENTER_VECTOR) + continue; +#endif if (vector != SYSCALL_VECTOR) set_intr_gate(vector, interrupt[i]); } Index: 2.6.x-xfs/arch/i386/kernel/io_apic.c =================================================================== --- 2.6.x-xfs.orig/arch/i386/kernel/io_apic.c Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/arch/i386/kernel/io_apic.c Tue May 11 16:22:02 2004 @@ -27,6 +27,9 @@ #include #include #include +#ifdef CONFIG_KDB +#include +#endif /* CONFIG_KDB */ #include #include #include @@ -1164,6 +1167,10 @@ 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++; Index: 2.6.x-xfs/arch/i386/kernel/nmi.c =================================================================== --- 2.6.x-xfs.orig/arch/i386/kernel/nmi.c Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/arch/i386/kernel/nmi.c Tue May 11 16:22:02 2004 @@ -25,6 +25,9 @@ #include #include #include +#ifdef CONFIG_KDB +#include +#endif /* CONFIG_KDB */ #include #include @@ -480,6 +483,9 @@ printk("NMI Watchdog detected LOCKUP on CPU%d, eip %08lx, registers:\n", cpu, 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); Index: 2.6.x-xfs/arch/i386/kernel/reboot.c =================================================================== --- 2.6.x-xfs.orig/arch/i386/kernel/reboot.c Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/arch/i386/kernel/reboot.c Tue May 11 16:22:02 2004 @@ -3,6 +3,10 @@ */ #include +#include +#ifdef CONFIG_KDB +#include +#endif /* CONFIG_KDB */ #include #include #include @@ -252,6 +256,14 @@ * Stop all CPUs and turn off local APICs and the IO-APIC, so * other OSs see a clean IRQ state. */ +#ifdef CONFIG_KDB + /* + * If this restart is occuring while kdb is running (e.g. reboot + * command), the other CPU's are already stopped. Don't try to + * stop them yet again. + */ + if (!KDB_IS_RUNNING()) +#endif /* CONFIG_KDB */ smp_send_stop(); #elif defined(CONFIG_X86_LOCAL_APIC) if (cpu_has_apic) { Index: 2.6.x-xfs/arch/i386/kernel/smp.c =================================================================== --- 2.6.x-xfs.orig/arch/i386/kernel/smp.c Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/arch/i386/kernel/smp.c Tue May 11 16:22:02 2004 @@ -26,6 +26,11 @@ #include #include +#include +#ifdef CONFIG_KDB +#include +#endif /* CONFIG_KDB */ + /* * Some notes on x86 processor bugs affecting SMP operation: * @@ -144,6 +149,15 @@ */ cfg = __prepare_ICR(shortcut, vector); +#ifdef CONFIG_KDB + if (vector == KDB_VECTOR) { + /* + * Setup KDB IPI to be delivered as an NMI + */ + cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI; + } +#endif /* CONFIG_KDB */ + /* * Send the IPI. The write to APIC_ICR fires this off. */ @@ -221,6 +235,15 @@ * program the ICR */ cfg = __prepare_ICR(0, vector); + +#ifdef CONFIG_KDB + if (vector == KDB_VECTOR) { + /* + * Setup KDB IPI to be delivered as an NMI + */ + cfg = (cfg&~APIC_VECTOR_MASK)|APIC_DM_NMI; + } +#endif /* CONFIG_KDB */ /* * Send the IPI. The write to APIC_ICR fires this off. @@ -467,6 +490,15 @@ on_each_cpu(do_flush_tlb_all, 0, 1, 1); } +#ifdef CONFIG_KDB +void +smp_kdb_stop(void) +{ + if (!KDB_FLAG(NOIPI)) + send_IPI_allbutself(KDB_VECTOR); +} +#endif /* CONFIG_KDB */ + /* * this function sends a 'reschedule' IPI to another CPU. * it goes straight through and wastes no time serializing Index: 2.6.x-xfs/arch/i386/kernel/smpboot.c =================================================================== --- 2.6.x-xfs.orig/arch/i386/kernel/smpboot.c Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/arch/i386/kernel/smpboot.c Tue May 11 16:22:02 2004 @@ -43,6 +43,9 @@ #include #include #include +#ifdef CONFIG_KDB +#include +#endif /* CONFIG_KDB */ #include #include @@ -420,6 +423,11 @@ */ cpu_set(cpuid, cpu_callin_map); +#ifdef CONFIG_KDB + /* Activate any preset global breakpoints on this cpu */ + kdb(KDB_REASON_SILENT, 0, 0); +#endif /* CONFIG_KDB */ + /* * Synchronize the TSC with the BP */ Index: 2.6.x-xfs/arch/i386/kernel/traps.c =================================================================== --- 2.6.x-xfs.orig/arch/i386/kernel/traps.c Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/arch/i386/kernel/traps.c Tue May 11 16:22:02 2004 @@ -36,6 +36,10 @@ #include #endif +#ifdef CONFIG_KDB +#include +#endif /* CONFIG_KDB */ + #include #include #include @@ -56,6 +60,9 @@ #include "mach_traps.h" asmlinkage int system_call(void); +#ifdef CONFIG_KDB +asmlinkage int kdb_call(void); +#endif /* CONFIG_KDB */ asmlinkage void lcall7(void); asmlinkage void lcall27(void); @@ -86,6 +93,9 @@ asmlinkage void stack_segment(void); asmlinkage void general_protection(void); asmlinkage void page_fault(void); +#ifdef CONFIG_KDB +asmlinkage void page_fault_mca(void); +#endif /* CONFIG_KDB */ asmlinkage void coprocessor_error(void); asmlinkage void simd_coprocessor_error(void); asmlinkage void alignment_check(void); @@ -279,6 +289,10 @@ show_registers(regs); bust_spinlocks(0); 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"); @@ -377,7 +391,9 @@ } DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->eip) +#ifndef CONFIG_KDB DO_VM86_ERROR( 3, SIGTRAP, "int3", int3) +#endif /* !CONFIG_KDB */ DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip) @@ -448,16 +464,37 @@ return; } #endif +#ifdef CONFIG_KDB + (void)kdb(KDB_REASON_NMI, reason, regs); +#endif /* CONFIG_KDB */ printk("Uhhuh. NMI received for unknown reason %02x on CPU %d.\n", reason, smp_processor_id()); printk("Dazed and confused, but trying to continue\n"); printk("Do you have a strange power saving mode enabled?\n"); } +#if defined(CONFIG_SMP) && defined(CONFIG_KDB) +static void +do_ack_apic_irq(void) +{ + ack_APIC_irq(); +} +#endif /* defined(CONFIG_SMP) && defined(CONFIG_KDB) */ + static void default_do_nmi(struct pt_regs * regs) { unsigned char 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, do_ack_apic_irq)) { + return; + } +#endif /* defined(CONFIG_SMP) && defined(CONFIG_KDB) */ + if (!(reason & 0xc0)) { #ifdef CONFIG_X86_LOCAL_APIC /* @@ -545,6 +582,11 @@ __asm__ __volatile__("movl %%db6,%0" : "=r" (condition)); +#ifdef CONFIG_KDB + if (kdb(KDB_REASON_DEBUG, error_code, regs)) + return; +#endif /* CONFIG_KDB */ + /* It's safe to allow irq's after DR6 has been saved */ if (regs->eflags & X86_EFLAGS_IF) local_irq_enable(); @@ -612,6 +654,16 @@ return; } +#ifdef CONFIG_KDB +asmlinkage 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 @@ -880,7 +932,17 @@ set_trap_gate(11,&segment_not_present); set_trap_gate(12,&stack_segment); set_trap_gate(13,&general_protection); +#ifdef CONFIG_KDB + if (test_bit(X86_FEATURE_MCE, boot_cpu_data.x86_capability) && + test_bit(X86_FEATURE_MCA, boot_cpu_data.x86_capability)) { + set_intr_gate(14,&page_fault_mca); + } + else { + set_intr_gate(14,&page_fault); + } +#else /* !CONFIG_KDB */ set_intr_gate(14,&page_fault); +#endif /* CONFIG_KDB */ set_trap_gate(15,&spurious_interrupt_bug); set_trap_gate(16,&coprocessor_error); set_trap_gate(17,&alignment_check); @@ -890,6 +952,14 @@ 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 */ /* * default LDT is a single-entry callgate to lcall7 for iBCS Index: 2.6.x-xfs/arch/i386/kernel/vmlinux.lds.S =================================================================== --- 2.6.x-xfs.orig/arch/i386/kernel/vmlinux.lds.S Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/arch/i386/kernel/vmlinux.lds.S Tue May 11 16:22:02 2004 @@ -83,6 +83,9 @@ __con_initcall_start = .; .con_initcall.init : { *(.con_initcall.init) } __con_initcall_end = .; + __kdb_initcall_start = .; + .kdb_initcall.init : { *(.kdb_initcall.init) } + __kdb_initcall_end = .; SECURITY_INIT . = ALIGN(4); __alt_instructions = .; Index: 2.6.x-xfs/include/asm-i386/kmap_types.h =================================================================== --- 2.6.x-xfs.orig/include/asm-i386/kmap_types.h Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/include/asm-i386/kmap_types.h Tue May 11 16:22:02 2004 @@ -24,7 +24,8 @@ D(11) KM_IRQ1, D(12) KM_SOFTIRQ0, D(13) KM_SOFTIRQ1, -D(14) KM_TYPE_NR +D(14) KM_KDB, +D(15) KM_TYPE_NR }; #undef D Index: 2.6.x-xfs/include/asm-i386/mach-default/irq_vectors.h =================================================================== --- 2.6.x-xfs.orig/include/asm-i386/mach-default/irq_vectors.h Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/include/asm-i386/mach-default/irq_vectors.h Tue May 11 16:22:02 2004 @@ -29,6 +29,7 @@ #define FIRST_EXTERNAL_VECTOR 0x20 #define SYSCALL_VECTOR 0x80 +#define KDBENTER_VECTOR 0x81 /* * Vectors 0x20-0x2f are used for ISA interrupts. @@ -48,6 +49,7 @@ #define INVALIDATE_TLB_VECTOR 0xfd #define RESCHEDULE_VECTOR 0xfc #define CALL_FUNCTION_VECTOR 0xfb +#define KDB_VECTOR 0xf9 #define THERMAL_APIC_VECTOR 0xf0 /* Index: 2.6.x-xfs/include/asm-i386/ptrace.h =================================================================== --- 2.6.x-xfs.orig/include/asm-i386/ptrace.h Tue May 11 16:21:55 2004 +++ 2.6.x-xfs/include/asm-i386/ptrace.h Tue May 11 16:22:02 2004 @@ -54,6 +54,29 @@ #define PTRACE_GET_THREAD_AREA 25 #define PTRACE_SET_THREAD_AREA 26 +enum EFLAGS { + EF_CF = 0x00000001, + EF_PF = 0x00000004, + EF_AF = 0x00000010, + EF_ZF = 0x00000040, + EF_SF = 0x00000080, + EF_TF = 0x00000100, + EF_IE = 0x00000200, + EF_DF = 0x00000400, + EF_OF = 0x00000800, + EF_IOPL = 0x00003000, + EF_IOPL_RING0 = 0x00000000, + EF_IOPL_RING1 = 0x00001000, + EF_IOPL_RING2 = 0x00002000, + EF_NT = 0x00004000, /* nested task */ + EF_RF = 0x00010000, /* resume */ + EF_VM = 0x00020000, /* virtual mode */ + EF_AC = 0x00040000, /* alignment */ + EF_VIF = 0x00080000, /* virtual interrupt */ + EF_VIP = 0x00100000, /* virtual interrupt pending */ + EF_ID = 0x00200000, /* id */ +}; + #ifdef __KERNEL__ #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs)) #define instruction_pointer(regs) ((regs)->eip)