kgdb for 2.6.3
PATCH 2/3 kgdb for 2.6.3
Hi!
This adds some more intrusive features to kgdb (thread display, kgdb-over-netconsole), and support for non-i386 architectures (core + i386 + x86_64 + ppc). Probably good enough for -mm but not for vanilla.
Pavel
include/linux/sched.h +12 -1
@@ -173,7 +173,9 @@#define MAX_SCHEDULE_TIMEOUT LONG_MAXextern signed long FASTCALL (schedule_timeout (signed long timeout)); -asmlinkage void schedule(void); +asmlinkage void do_schedule(void); +asmlinkage void kern_schedule(void); +asmlinkage void kern_do_schedule(struct pt_regs);struct namespace ;
@@ -907,6 +909,15 @@#endif /* CONFIG_SMP */ +static inline void schedule (void ) +{ +#ifdef CONFIG_KGDB_THREAD +kern_schedule (); +#else +do_schedule (); +#endif +} +#endif /* __KERNEL__ */ #endif
kernel/module.c +10 -0
@@ -727,6 +727,11 @@ mod->state =MODULE_STATE_GOING ;restart_refcounts (); +down (¬ify_mutex); +notifier_call_chain (&module_notify_list,MODULE_STATE_GOING , + mod); +up (¬ify_mutex); +/* Never wait if forced. */ if (!forced &&module_refcount (mod) !=0 )wait_for_zero_refcount (mod);
@@ -1758,7 +1763,12 @@if (ret <0 ) {/* Init routine failed: abort. Try to protect us from buggy refcounters. */ + mod->state =MODULE_STATE_GOING ; +down (¬ify_mutex); +notifier_call_chain (&module_notify_list,MODULE_STATE_GOING , + mod); +up (¬ify_mutex);synchronize_kernel ();if (mod->unsafe) printk(KERN_ERR "%s: module is now stuck!\n",
kernel/sched.c +18 -1
@@ -1592,7 +1592,7 @@/* * schedule() is the main scheduler function. */ -asmlinkage void schedule(void) +asmlinkage void do_schedule(void) {long *switch_count;task_t *prev, *next;
@@ -1764,6 +1764,23 @@EXPORT_SYMBOL (default_wake_function); +asmlinkage void user_schedule(void) +{ +#ifdef CONFIG_KGDB_THREAD + current->thread.debuggerinfo =NULL ; +#endif +do_schedule (); +} + +#ifdef CONFIG_KGDB_THREAD +asmlinkage void kern_do_schedule(struct pt_regs regs) +{ + current->thread.debuggerinfo = ®s; +do_schedule (); + current->thread.debuggerinfo =NULL ; +} +#endif +/* * The core wakeup function. Non-exclusive wakeups (nr_exclusive == 0) just * wake everything up. If it's an exclusive wakeup (nr_exclusive == small +ve
arch/i386/Kconfig +17 -0
@@ -1267,6 +1267,23 @@ http://kgdb.sourceforge.net This is only useful for kernel hackers. If unsure, say N. +config KGDB_THREAD + bool "KGDB: Thread analysis" + depends on KGDB + help + With thread analysis enabled, gdb can talk to kgdb stub to list + threads and to get stack trace for a thread. This option also enables + some code which helps gdb get exact status of thread. Thread analysis + adds some overhead to schedule and down functions. You can disable + this option if you do not want to compromise on speed. + +config KGDB_CONSOLE + bool "KGDB: Console messages through gdb" + depends on KGDB + help + If you say Y here, console messages will appear through gdb. + Other consoles such as tty or ttyS will continue to work as usual. + config FRAME_POINTER bool "Compile the kernel with frame pointers" help
arch/i386/kernel/entry.S +27 -2
@@ -226,7 +226,7 @@ jz restore_all movl $PREEMPT_ACTIVE,TI_PRE_COUNT(%ebp) sti - call schedule + call user_schedule movl $0,TI_PRE_COUNT(%ebp) cli jmp need_resched
@@ -308,7 +308,7 @@ testb $_TIF_NEED_RESCHED, %cl jz work_notifysig work_resched: - call schedule + call user_schedule cli # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret
@@ -606,6 +606,31 @@ pushl $do_spurious_interrupt_bug jmp error_code +#ifdef CONFIG_KGDB_THREAD +ENTRY(kern_schedule) + pushl %ebp + movl %esp, %ebp + pushl %ss + pushl %ebp + pushfl + pushl %cs + pushl 4(%ebp) + pushl %eax + pushl %es + pushl %ds + pushl %eax + pushl (%ebp) + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + pushl %ebx + call kern_do_schedule + movl %ebp, %esp + pop %ebp + ret +#endif + .data ENTRY(sys_call_table) .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
arch/x86_64/Kconfig +30 -2
@@ -465,8 +465,36 @@ Add a simple leak tracer to the IOMMU code. This is useful when you are debugging a buggy device driver that leaks IOMMU mappings. -#config X86_REMOTE_DEBUG -# bool "kgdb debugging stub" +config KGDB + bool "KGDB: kernel debugging with remote gdb" + depends on DEBUG_KERNEL + select DEBUG_INFO + select FRAME_POINTER + help + If you say Y here, it will be possible to remotely debug the + kernel using gdb. This enlarges your kernel image disk size by + several megabytes and requires a machine with more than 128 MB + RAM to avoid excessive linking time. + Documentation of kernel debugger available at + http://kgdb.sourceforge.net + This is only useful for kernel hackers. If unsure, say N. + +config KGDB_THREAD + bool "KGDB: Thread analysis" + depends on KGDB + help + With thread analysis enabled, gdb can talk to kgdb stub to list + threads and to get stack trace for a thread. This option also enables + some code which helps gdb get exact status of thread. Thread analysis + adds some overhead to schedule and down functions. You can disable + this option if you do not want to compromise on speed. + +config KGDB_CONSOLE + bool "KGDB: Console messages through gdb" + depends on KGDB + help + If you say Y here, console messages will appear through gdb. + Other consoles such as tty or ttyS will continue to work as usual. endmenu
arch/x86_64/kernel/entry.S +38 -3
62 lines not on this page · raw message
arch/x86_64/kernel/Makefile +1 -0
@@ -24,6 +24,7 @@ obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_KGDB) += x86_64-stub.o obj-y += topology.o
arch/x86_64/kernel/nmi.c +15 -1
@@ -24,6 +24,7 @@#include <linux/module.h> #include <linux/sysdev.h> #include <linux/nmi.h> +#include <linux/debugger.h> #include <asm/smp.h> #include <asm/mtrr.h>
@@ -317,13 +318,26 @@return ; sum =read_pda (apic_timer_irqs); -if (last_irq_sums[cpu] == sum) { +if (atomic_read (&debugger_active)) { + +/* +* The machine is in debugger, hold this cpu if already +* not held. +*/ +debugger_nmihook (cpu, regs); + alert_counter[cpu] =0 ; + + }else if (last_irq_sums[cpu] == sum) { +/* * Ayiee, looks like this CPU is stuck ... * wait a few IRQs (5 seconds) before doing the oops ... */ alert_counter[cpu]++;if (alert_counter[cpu] ==5 *nmi_hz) { + + CHK_DEBUGGER(2,SIGSEGV,0,regs,) + if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT) == NOTIFY_BAD) { alert_counter[cpu] = 0; return;
arch/x86_64/kernel/traps.c +5 -1
@@ -28,6 +28,7 @@#include <linux/interrupt.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/debugger.h> #include <asm/system.h> #include <asm/uaccess.h>
@@ -363,6 +364,7 @@void die (const char * str,struct pt_regs * regs,long err) { + CHK_DEBUGGER(1,SIGTRAP,err,regs,) oops_begin(); handle_BUG(regs); __die(str, regs, err);
@@ -436,6 +438,7 @@#define DO_ERROR (trapnr, signr, str, name) \ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \ { \ + CHK_DEBUGGER(1,SIGTRAP,error_code,regs,return) \ if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) == NOTIFY_BAD) \ return; \ do_trap(trapnr, signr, str, regs, error_code, NULL); \
@@ -614,7 +617,7 @@ tsk->thread.debugreg6 = condition;/* Mask out spurious TF errors due to lazy TF clearing */ -if (condition &DR_STEP ) { +if (condition &DR_STEP && !debugger_step) {/* * The TF error should be masked out only if the current * process is not traced and if the TRAP flag has been set
@@ -643,6 +646,7 @@force_sig_info (SIGTRAP , &info, tsk); clear_dr7: asmvolatile ("movq %0,%%db7" ::"r" (0UL )); + CHK_DEBUGGER(1,SIGTRAP,error_code,regs,return)notify_die (DIE_DEBUG ,"debug" , regs, error_code,1 ,SIGTRAP );return ;
arch/x86_64/kernel/x86_64-stub.c +454 -0
454 lines not on this page · raw message
arch/x86_64/mm/fault.c +2 -0
@@ -23,6 +23,7 @@#include <linux/vt_kern.h> /* For unblank_screen() */ #include <linux/compiler.h> #include <linux/module.h> +#include <linux/debugger.h> #include <asm/system.h> #include <asm/uaccess.h>
@@ -407,6 +408,7 @@if (is_prefetch (regs, address))return ; + CHK_DEBUGGER(14, SIGSEGV,error_code, regs,) if (is_errata93(regs, address)) return;
include/asm-x86_64/calling.h +1 -1
@@ -12,7 +12,7 @@#define RBX 40/* arguments: interrupts/non tracing syscalls only save upto here*/ #define R11 48 -#define R10 56 +#define R10 56#define R9 64#define R8 72#define RAX 80
include/asm-x86_64/kgdb.h +53 -0
53 lines not on this page · raw message
include/asm-x86_64/processor.h +1 -0
@@ -252,6 +252,7 @@unsigned long *io_bitmap_ptr;/* cached TLS descriptors. */ u64 tls_array[GDT_ENTRY_TLS_ENTRIES ]; +void *debuggerinfo; };#define INIT_THREAD {}
arch/ppc/8260_io/uart.c +18 -5
@@ -43,6 +43,7 @@#include <linux/slab.h> #include <linux/init.h> #include <linux/delay.h> +#include <linux/kgdb.h> #include <asm/uaccess.h> #include <asm/immap_8260.h> #include <asm/mpc8260.h>
@@ -394,8 +395,21 @@ status = bdp->cbd_sc;#ifdef CONFIG_KGDB if (info->state->smc_scc_num ==KGDB_SER_IDX ) { -if (*cp ==0x03 || *cp =='$' ) -breakpoint (); +while (i-- >0 ) { +if (*cp ==0x03 ) { +breakpoint (); +return ; + } +if (*cp =='$' ) { +atomic_set (&kgdb_might_be_resumed,1 ); +breakpoint (); +atomic_set (&kgdb_might_be_resumed,0 ); +return ; + } + cp++; + } + bdp->cbd_sc |=BD_SC_EMPTY ; + bdp->cbd_sc &= ~(BD_SC_BR |BD_SC_FR |BD_SC_PR |BD_SC_OV );return ; }#endif
@@ -2275,9 +2289,8 @@static void serial_console_write (struct console *c,const char *s,unsigned count) { -#if defined(CONFIG_KGDB_CONSOLE ) && !defined(CONFIG_USE_SERIAL2_KGDB ) -/* Try to let stub handle output. Returns true if it did. */ -if (kgdb_output_string (s, count)) +#ifdef CONFIG_KGDB +if (kgdb_initialized)return ;#endif my_console_write (c->index, s, count);
arch/ppc/Kconfig +11 -0
@@ -1174,6 +1174,7 @@ bool "Include kgdb kernel debugger" depends on DEBUG_KERNEL select DEBUG_INFO + select FRAME_POINTER help Include in-kernel hooks for kgdb, the Linux kernel source level debugger. See <http://kgdb.sourceforge.net/> for more information.
@@ -1198,6 +1199,16 @@ endchoice +config KGDB_THREAD + bool "KGDB: Thread analysis" + depends on KGDB + help + With thread analysis enabled, gdb can talk to kgdb stub to list + threads and to get stack trace for a thread. This option also enables + some code which helps gdb get exact status of thread. Thread analysis + adds some overhead to schedule and down functions. You can disable + this option if you do not want to compromise on speed. + config KGDB_CONSOLE bool "Enable serial console thru kgdb port" depends on KGDB && 8xx || 8260
arch/ppc/kernel/entry.S +66 -3
93 lines not on this page · raw message
arch/ppc/kernel/irq.c +6 -0
@@ -513,6 +513,12 @@void do_IRQ (struct pt_regs *regs) {int irq, first =1 ; +unsigned long *lrptr; +if (!(regs->msr &MSR_PR )) { +/* Came in from the kernel. Save call link. */ + lrptr = (unsigned long *)(regs->gpr[1 ] +4 ); + *lrptr = regs->nip; + }irq_enter ();/*
arch/ppc/kernel/ppc-stub.c +225 -772
1,082 lines not on this page · raw message
arch/ppc/kernel/setup.c +1 -9
@@ -643,15 +643,7 @@if ( ppc_md.progress ) ppc_md.progress ("setup_arch: enter" ,0x3eab );#if defined(CONFIG_KGDB ) -if (ppc_md.kgdb_map_scc) - ppc_md.kgdb_map_scc (); -set_debug_traps (); -if (strstr (cmd_line,"gdb" )) { -if (ppc_md.progress) - ppc_md.progress ("setup_arch: kgdb breakpoint" ,0x4000 ); -printk ("kgdb breakpoint activated\n" ); -breakpoint (); - } +kgdbppc_init ();#endif /*
arch/ppc/mm/fault.c +13 -1
@@ -28,6 +28,7 @@#include <linux/interrupt.h> #include <linux/highmem.h> #include <linux/module.h> +#include <linux/debugger.h> #include <asm/page.h> #include <asm/pgtable.h>
@@ -139,6 +140,13 @@bad_page_fault (regs, address,SIGSEGV );return ; } + +if (debugger_memerr_expected) { +/* This fault was caused by memory access through a debugger. +* Don't handle it like user accesses */ + goto no_context; + } +down_read (&mm->mmap_sem); vma =find_vma (mm, address);if (!vma)
@@ -293,6 +301,7 @@return ; } +no_context:bad_page_fault (regs, address,SIGSEGV );return ;
@@ -342,10 +351,13 @@ }/* kernel has accessed a bad area */ -#if defined(CONFIG_XMON ) || defined(CONFIG_KGDB ) +#if defined(CONFIG_XMON )if (debugger_kernel_faults)debugger (regs);#endif + + CHK_DEBUGGER(14, sig,0, regs,) + die("kernel access of bad area", regs, sig); }
arch/ppc/platforms/sandpoint.c +0 -32
@@ -252,38 +252,6 @@return ; } -#if defined(CONFIG_SERIAL_8250 ) && \ - (defined(CONFIG_KGDB ) || defined(CONFIG_SERIAL_TEXT_DEBUG )) -static void __init -sandpoint_early_serial_map (void ) -{ -struct uart_port serial_req; - -/* Setup serial port access */ -memset (&serial_req,0 ,sizeof (serial_req)); - serial_req.uartclk =UART_CLK ; - serial_req.irq =4 ; - serial_req.flags =STD_COM_FLAGS ; - serial_req.iotype =SERIAL_IO_MEM ; - serial_req.membase = (u_char *)SANDPOINT_SERIAL_0 ; - -gen550_init (0 , &serial_req); - -if (early_serial_setup (&serial_req) !=0 ) -printk (KERN_ERR "Early serial init of port 0 failed\n" ); - -/* Assume early_serial_setup() doesn't modify serial_req */ - serial_req.line =1 ; - serial_req.irq =3 ;/* XXXX */ - serial_req.membase = (u_char *)SANDPOINT_SERIAL_1 ; - -gen550_init (1 , &serial_req); - -if (early_serial_setup (&serial_req) !=0 ) -printk (KERN_ERR "Early serial init of port 1 failed\n" ); -} -#endif -static void __init sandpoint_setup_arch (void ) {
Signature · 2 lines
When do you have a heart between your knees? [Johanka's followup: and *two* hearts?]