From: Andrew Morton Signed-off-by: Andrew Morton --- i386/kgdb/andthen | 0 i386/kgdb/debug-nmi.txt | 0 i386/kgdb/gdb-globals.txt | 0 i386/kgdb/gdbinit | 0 i386/kgdb/gdbinit-modules | 0 i386/kgdb/gdbinit.hw | 0 i386/kgdb/kgdb.txt | 0 i386/kgdb/loadmodule.sh | 0 MAINTAINERS | 0 i386/Kconfig.debug | 0 i386/Kconfig.kgdb | 0 i386/Makefile | 0 i386/kernel/Makefile | 0 i386/kernel/entry.S | 0 i386/kernel/nmi.c | 0 i386/kernel/smp.c | 0 i386/kernel/traps.c | 0 i386/lib/Makefile | 0 i386/lib/kgdb_serial.c | 0 i386/mm/fault.c | 0 x86_64/boot/compressed/head.S | 0 arch/i386/kernel/kgdb_stub.c | 173 +++++++++++++------------------- kernel/sched.c | 1 char/keyboard.c | 0 char/sysrq.c | 0 serial/8250.c | 0 serial/serial_core.c | 0 asm-i386/bugs.h | 0 asm-i386/kgdb.h | 0 asm-i386/kgdb_local.h | 0 linux/config.h | 0 linux/dwarf2-lang.h | 0 linux/dwarf2.h | 0 linux/serial_core.h | 0 pid.c | 0 35 files changed, 73 insertions(+), 101 deletions(-) diff -puN arch/i386/Kconfig.debug~kgdb-convert-for-cpu-helpers arch/i386/Kconfig.debug diff -puN arch/i386/Kconfig.kgdb~kgdb-convert-for-cpu-helpers arch/i386/Kconfig.kgdb diff -puN arch/i386/kernel/entry.S~kgdb-convert-for-cpu-helpers arch/i386/kernel/entry.S diff -puN arch/i386/kernel/kgdb_stub.c~kgdb-convert-for-cpu-helpers arch/i386/kernel/kgdb_stub.c --- devel/arch/i386/kernel/kgdb_stub.c~kgdb-convert-for-cpu-helpers 2006-02-27 03:49:29.000000000 -0800 +++ devel-akpm/arch/i386/kernel/kgdb_stub.c 2006-02-27 04:04:45.000000000 -0800 @@ -106,10 +106,11 @@ #include #include #include +#include #include + #include #include - #include #include #include /* for linux pt_regs struct */ @@ -199,17 +200,17 @@ enum regnames { _EAX, /* 0 */ * word generator coming out with just what we want. AND it does * not matter if clustered_apic_mode is set or not. */ -void smp_send_nmi_allbutself(void) +static void smp_send_nmi_allbutself(void) { send_IPI_allbutself(APIC_DM_NMI); } #else -void smp_send_nmi_allbutself(void) +static void smp_send_nmi_allbutself(void) { } #endif -struct kgdb_info { +static struct kgdb_info { int used_malloc; void *called_from; long long entry_tsc; @@ -376,6 +377,7 @@ spinlock_t kgdb_spinlock = SPIN_LOCK_UNL static spinlock_t waitlocks[NR_CPUS] = {[0 ... NR_CPUS - 1] = SPIN_LOCK_UNLOCKED }; volatile struct pt_regs *in_kgdb_here_log[NR_CPUS]; + /* * The following array has the thread pointer of each of the "other" * cpus. We make it global so it can be seen by gdb. @@ -498,15 +500,13 @@ static char remcomInBuffer[BUFMAX]; static char remcomOutBuffer[BUFMAX]; static short error; -void -debug_error(char *format, char *parm) +static void debug_error(char *format, char *parm) { if (kgdb_info.print_debug_info) printk(format, parm); } -static void -print_regs(struct pt_regs *regs) +static void print_regs(struct pt_regs *regs) { printk("EAX=%08lx ", regs->eax); printk("EBX=%08lx ", regs->ebx); @@ -525,18 +525,11 @@ print_regs(struct pt_regs *regs) printk("\n"); printk(" CS=%08x ", regs->xcs); printk(" IP=%08lx ", regs->eip); -#if 0 - printk(" FS=%08x ", regs->fs); - printk(" GS=%08x ", regs->gs); -#endif printk("\n"); -} /* print_regs */ - -#define NEW_esp fn_call_lookaside[trap_cpu].esp +} -static void -regs_to_gdb_regs(int *gdb_regs, struct pt_regs *regs) +static void regs_to_gdb_regs(int *gdb_regs, struct pt_regs *regs) { gdb_regs[_EAX] = regs->eax; gdb_regs[_EBX] = regs->ebx; @@ -564,16 +557,16 @@ regs_to_gdb_regs(int *gdb_regs, struct p * as double fault. Stuart Hughes, Zentropix. * original code: gdb_regs[_ESP] = (int) (regs + 1) ; - * this is now done on entry and moved to OLD_esp (as well as NEW_esp). + * this is now done on entry and moved to OLD_esp (as well as + * fn_call_lookaside[trap_cpu].esp). */ - gdb_regs[_ESP] = NEW_esp; + gdb_regs[_ESP] = fn_call_lookaside[trap_cpu].esp; gdb_regs[_SS] = __KERNEL_DS; gdb_regs[_FS] = 0xFFFF; gdb_regs[_GS] = 0xFFFF; -} /* regs_to_gdb_regs */ +} -static void -gdb_regs_to_regs(int *gdb_regs, struct pt_regs *regs) +static void gdb_regs_to_regs(int *gdb_regs, struct pt_regs *regs) { regs->eax = gdb_regs[_EAX]; regs->ebx = gdb_regs[_EBX]; @@ -587,42 +580,34 @@ gdb_regs_to_regs(int *gdb_regs, struct p regs->eflags = gdb_regs[_PS]; regs->xcs = gdb_regs[_CS]; regs->eip = gdb_regs[_PC]; - NEW_esp = gdb_regs[_ESP]; /* keep the value */ -#if 0 /* can't change these */ + fn_call_lookaside[trap_cpu].esp = gdb_regs[_ESP]; /* keep value */ +#if 0 /* can't change these */ regs->esp = gdb_regs[_ESP]; regs->xss = gdb_regs[_SS]; regs->fs = gdb_regs[_FS]; regs->gs = gdb_regs[_GS]; #endif -} /* gdb_regs_to_regs */ +} -int thread_list = 0; +static int thread_list = 0; -void -get_gdb_regs(struct task_struct *p, struct pt_regs *regs, int *gdb_regs) +void get_gdb_regs(struct task_struct *p, struct pt_regs *regs, int *gdb_regs) { unsigned long stack_page; - int count = 0; + int i; if (!p || p == current) { regs_to_gdb_regs(gdb_regs, regs); return; } #ifdef CONFIG_SMP - { - int i; - - for (i = 0; i < NR_CPUS; i++) { - if (p == kgdb_info.cpus_waiting[i].task) { - regs_to_gdb_regs(gdb_regs, - kgdb_info.cpus_waiting[i].regs); - gdb_regs[_ESP] = - (int) &kgdb_info.cpus_waiting[i].regs->esp; - - return; - } - } + for_each_online_cpu(i) { + if (p != kgdb_info.cpus_waiting[i].task) + continue; + regs_to_gdb_regs(gdb_regs, kgdb_info.cpus_waiting[i].regs); + gdb_regs[_ESP] = (int)&kgdb_info.cpus_waiting[i].regs->esp; + return; } #endif memset(gdb_regs, 0, NUMREGBYTES); @@ -632,55 +617,51 @@ get_gdb_regs(struct task_struct *p, stru gdb_regs[_EDI] = *(int *) (gdb_regs[_ESP] + 4); gdb_regs[_ESI] = *(int *) (gdb_regs[_ESP] + 8); -/* - * This code is to give a more informative notion of where a process - * is waiting. It is used only when the user asks for a thread info - * list. If he then switches to the thread, s/he will find the task - * is in schedule, but a back trace should show the same info we come - * up with. This code was shamelessly purloined from process.c. It was - * then enhanced to provide more registers than simply the program - * counter. - */ - - if (!thread_list) { + /* + * This code is to give a more informative notion of where a process + * is waiting. It is used only when the user asks for a thread info + * list. If he then switches to the thread, s/he will find the task + * is in schedule, but a back trace should show the same info we come + * up with. This code was shamelessly purloined from process.c. It was + * then enhanced to provide more registers than simply the program + * counter. + */ + if (!thread_list) return; - } if (p->state == TASK_RUNNING) return; - stack_page = (unsigned long) p->thread_info; - if (gdb_regs[_ESP] < stack_page || gdb_regs[_ESP] > - THREAD_SIZE - sizeof(long) + stack_page) + stack_page = (unsigned long)p->thread_info; + if (gdb_regs[_ESP] < stack_page || + gdb_regs[_ESP] > THREAD_SIZE-sizeof(long)+stack_page) return; /* include/asm-i386/system.h:switch_to() pushes ebp last. */ + i = 0; do { if (gdb_regs[_EBP] < stack_page || gdb_regs[_EBP] > THREAD_SIZE - 2*sizeof(long) + stack_page) return; - gdb_regs[_PC] = *(unsigned long *) (gdb_regs[_EBP] + 4); + gdb_regs[_PC] = *(unsigned long *)(gdb_regs[_EBP] + 4); gdb_regs[_ESP] = gdb_regs[_EBP] + 8; - gdb_regs[_EBP] = *(unsigned long *) gdb_regs[_EBP]; + gdb_regs[_EBP] = *(unsigned long *)gdb_regs[_EBP]; if (!in_sched_functions(gdb_regs[_PC])) return; - } while (count++ < 16); + } while (i++ < 16); return; } -/* Indicate to caller of mem2hex or hex2mem that there has been an - error. */ +/* Indicate to caller of mem2hex or hex2mem that there has been an error */ static volatile int mem_err = 0; static volatile int mem_err_expected = 0; static volatile int mem_err_cnt = 0; static int garbage_loc = -1; -int -get_char(char *addr) +static int get_char(char *addr) { return *addr; } -void -set_char(char *addr, int val, int may_fault) +static void set_char(char *addr, int val, int may_fault) { /* * This code traps references to the area mapped to the kernel @@ -780,16 +761,13 @@ static int hexToInt(char **ptr, int *int return (numChars); } - -#define BUF_THREAD_ID_SIZE 16 - static char *pack_threadid(char *pkt, threadref *id) { char *limit; unsigned char *altid; - altid = (unsigned char *) id; - limit = pkt + BUF_THREAD_ID_SIZE; + altid = (unsigned char *)id; + limit = pkt + 16; while (pkt < limit) pkt = pack_hex_byte(pkt, *altid++); return pkt; @@ -800,7 +778,7 @@ static void int_to_threadref(threadref * unsigned char *scan; int i; - scan = (unsigned char *) id; + scan = (unsigned char *)id; i = 4; while (i--) *scan++ = 0; @@ -836,16 +814,12 @@ static int cmp_str(char *s1, char *s2, i return 1; } -extern struct task_struct *kgdb_get_idle(int cpu); -#define idle_task(cpu) kgdb_get_idle(cpu) - -extern int kgdb_pid_init_done; - struct task_struct *getthread(int pid) { struct task_struct *thread; + if (pid >= PID_MAX && pid <= (PID_MAX + NR_CPUS)) { - return idle_task(pid - PID_MAX); + return kgdb_get_idle(pid - PID_MAX); } else { /* * find_task_by_pid is relatively safe all the time @@ -927,9 +901,8 @@ static void correct_hw_break(void) dr7 &= ~(0xf0000 << (breakno << 2)); } } - if (correctit) { + if (correctit) asm volatile ("movl %0, %%db7\n"::"r" (dr7)); - } } static int remove_hw_break(unsigned breakno) @@ -1012,7 +985,7 @@ int in_kgdb(struct pt_regs *regs) kgdb_info.cpus_waiting[cpu].pid = 0; kgdb_info.cpus_waiting[cpu].regs = 0; correct_hw_break(); - exit_in_kgdb: +exit_in_kgdb: in_kgdb_here_log[cpu] = 0; local_irq_restore(flags); return 1; @@ -1029,11 +1002,11 @@ int in_kgdb(struct pt_regs *regs) } #endif -void -printexceptioninfo(int exceptionNo, int errorcode, char *buffer) +static void printexceptioninfo(int exceptionNo, int errorcode, char *buffer) { unsigned dr6; int i; + switch (exceptionNo) { case 1: /* debug exception */ break; @@ -1044,8 +1017,7 @@ printexceptioninfo(int exceptionNo, int sprintf(buffer, "Details not available"); return; } - asm volatile ("movl %%db6, %0\n":"=r" (dr6) - :); + asm volatile ("movl %%db6, %0\n":"=r" (dr6) :); if (dr6 & 0x4000) { sprintf(buffer, "Single step"); return; @@ -1127,7 +1099,7 @@ void kgdb_handle_exception(int exception if (kgdb_info.print_debug_info) printk("kgdb : cpu %d entry, syncing others\n", smp_processor_id()); - for (i = 0; i < NR_CPUS; i++) { + for_each_online_cpu(i) { /* * Use trylock as we may already hold the lock if * we are holding the cpu. Net result is all @@ -1135,7 +1107,7 @@ void kgdb_handle_exception(int exception */ spin_trylock(&waitlocks[i]); } - for (i = 0; i < NR_CPUS; i++) + for_each_online_cpu(i) cpu_logged_in[i] = 0; /* * Wait for their arrival. We know the watch dog is active if @@ -1150,7 +1122,8 @@ void kgdb_handle_exception(int exception smp_send_nmi_allbutself(); while (i < num_online_cpus() && time != end_time) { int j; - for (j = 0; j < NR_CPUS; j++) { + + for_each_online_cpu(j) { if (kgdb_info.cpus_waiting[j].task && !cpu_logged_in[j]) { i++; @@ -1319,7 +1292,7 @@ void kgdb_handle_exception(int exception * Set up the gdb function call area. */ trap_cpu = smp_processor_id(); - OLD_esp = NEW_esp = (int)(®s->esp); + OLD_esp = fn_call_lookaside[trap_cpu].esp = (int)(®s->esp); once_again: /* reply to host that an exception has occurred */ @@ -1577,7 +1550,7 @@ once_again: threadid < PID_MAX + NR_CPUS; threadid++) { if (current == - idle_task(threadid-PID_MAX)) + kgdb_get_idle(threadid-PID_MAX)) break; } } @@ -1733,28 +1706,28 @@ once_again: */ exit_kgdb: /* - * Here is where we set up to trap a gdb function call. NEW_esp + * Here is where we set up to trap a gdb function call. fn_call_lookaside[trap_cpu].esp * will be changed if we are trying to do this. We handle both * adding and subtracting, thus allowing gdb to put grung on * the stack which it removes later. */ - if (NEW_esp != OLD_esp) { + if (fn_call_lookaside[trap_cpu].esp != OLD_esp) { int *ptr = END_OF_LOOKASIDE; - if (NEW_esp < OLD_esp) - ptr -= (OLD_esp - NEW_esp) / sizeof (int); + if (fn_call_lookaside[trap_cpu].esp < OLD_esp) + ptr -= (OLD_esp - fn_call_lookaside[trap_cpu].esp) / sizeof (int); *--ptr = regs->eflags; *--ptr = regs->xcs; *--ptr = regs->eip; *--ptr = regs->ecx; *--ptr = regs->ebx; *--ptr = regs->eax; - regs->ecx = NEW_esp - (sizeof (int) * 6); + regs->ecx = fn_call_lookaside[trap_cpu].esp - (sizeof (int) * 6); regs->ebx = (unsigned int) END_OF_LOOKASIDE; - if (NEW_esp < OLD_esp) { + if (fn_call_lookaside[trap_cpu].esp < OLD_esp) { regs->eip = (unsigned int) fn_call_stub; } else { regs->eip = (unsigned int) fn_rtn_stub; - regs->eax = NEW_esp; + regs->eax = fn_call_lookaside[trap_cpu].esp; } regs->eflags &= ~(IF_BIT | TF_BIT); } @@ -1770,9 +1743,7 @@ exit_kgdb: int cpu_avail = 0; int i; - for (i = 0; i < NR_CPUS; i++) { - if (!cpu_online(i)) - break; + for_each_online_cpu(i) { if (!kgdb_info.cpus_waiting[i].hold) cpu_avail = 1; } @@ -1790,7 +1761,7 @@ exit_kgdb: goto once_again; } if (!ss_hold) { - for (i = 0; i < NR_CPUS; i++) { + for_each_online_cpu(i) { if (!kgdb_info.cpus_waiting[i].hold) spin_unlock(&waitlocks[i]); } diff -puN arch/i386/kernel/Makefile~kgdb-convert-for-cpu-helpers arch/i386/kernel/Makefile diff -puN arch/i386/kernel/nmi.c~kgdb-convert-for-cpu-helpers arch/i386/kernel/nmi.c diff -puN arch/i386/kernel/smp.c~kgdb-convert-for-cpu-helpers arch/i386/kernel/smp.c diff -puN arch/i386/kernel/traps.c~kgdb-convert-for-cpu-helpers arch/i386/kernel/traps.c diff -puN arch/i386/lib/kgdb_serial.c~kgdb-convert-for-cpu-helpers arch/i386/lib/kgdb_serial.c diff -puN arch/i386/lib/Makefile~kgdb-convert-for-cpu-helpers arch/i386/lib/Makefile diff -puN arch/i386/Makefile~kgdb-convert-for-cpu-helpers arch/i386/Makefile diff -puN arch/i386/mm/fault.c~kgdb-convert-for-cpu-helpers arch/i386/mm/fault.c diff -puN arch/x86_64/boot/compressed/head.S~kgdb-convert-for-cpu-helpers arch/x86_64/boot/compressed/head.S diff -puN Documentation/i386/kgdb/andthen~kgdb-convert-for-cpu-helpers Documentation/i386/kgdb/andthen diff -puN Documentation/i386/kgdb/debug-nmi.txt~kgdb-convert-for-cpu-helpers Documentation/i386/kgdb/debug-nmi.txt diff -puN Documentation/i386/kgdb/gdb-globals.txt~kgdb-convert-for-cpu-helpers Documentation/i386/kgdb/gdb-globals.txt diff -puN Documentation/i386/kgdb/gdbinit~kgdb-convert-for-cpu-helpers Documentation/i386/kgdb/gdbinit diff -puN Documentation/i386/kgdb/gdbinit.hw~kgdb-convert-for-cpu-helpers Documentation/i386/kgdb/gdbinit.hw diff -puN Documentation/i386/kgdb/gdbinit-modules~kgdb-convert-for-cpu-helpers Documentation/i386/kgdb/gdbinit-modules diff -puN Documentation/i386/kgdb/kgdb.txt~kgdb-convert-for-cpu-helpers Documentation/i386/kgdb/kgdb.txt diff -puN Documentation/i386/kgdb/loadmodule.sh~kgdb-convert-for-cpu-helpers Documentation/i386/kgdb/loadmodule.sh diff -puN drivers/char/keyboard.c~kgdb-convert-for-cpu-helpers drivers/char/keyboard.c diff -puN drivers/char/sysrq.c~kgdb-convert-for-cpu-helpers drivers/char/sysrq.c diff -puN drivers/serial/8250.c~kgdb-convert-for-cpu-helpers drivers/serial/8250.c diff -puN drivers/serial/serial_core.c~kgdb-convert-for-cpu-helpers drivers/serial/serial_core.c diff -puN include/asm-i386/bugs.h~kgdb-convert-for-cpu-helpers include/asm-i386/bugs.h diff -puN include/asm-i386/kgdb.h~kgdb-convert-for-cpu-helpers include/asm-i386/kgdb.h diff -puN include/asm-i386/kgdb_local.h~kgdb-convert-for-cpu-helpers include/asm-i386/kgdb_local.h diff -puN include/linux/config.h~kgdb-convert-for-cpu-helpers include/linux/config.h diff -puN include/linux/dwarf2.h~kgdb-convert-for-cpu-helpers include/linux/dwarf2.h diff -puN include/linux/dwarf2-lang.h~kgdb-convert-for-cpu-helpers include/linux/dwarf2-lang.h diff -puN include/linux/serial_core.h~kgdb-convert-for-cpu-helpers include/linux/serial_core.h diff -puN kernel/pid.c~kgdb-convert-for-cpu-helpers kernel/pid.c diff -puN kernel/sched.c~kgdb-convert-for-cpu-helpers kernel/sched.c --- devel/kernel/sched.c~kgdb-convert-for-cpu-helpers 2006-02-27 03:49:30.000000000 -0800 +++ devel-akpm/kernel/sched.c 2006-02-27 04:01:55.000000000 -0800 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include diff -puN MAINTAINERS~kgdb-convert-for-cpu-helpers MAINTAINERS _