int kdb(int reason, int error, struct pt_regs *regs) { char cmdbuf[255]; char *cmd; int diag; unsigned long flags; struct pt_regs func_regs; kdb_new_cpu = -1; /* * Remove the breakpoints to prevent double-faults * if kdb happens to use a function where a breakpoint * has been enabled. */ kdb_bp_remove(); if (reason != KDB_REASON_DEBUG) { kdb_printf("Entering kdb "); #if defined(__SMP__) kdb_printf("on processor %d ", smp_processor_id()); #endif } switch (reason) { case KDB_REASON_DEBUG: /* * If re-entering kdb after a single step * command, don't print the message. */ diag = kdb_db_trap(regs); if (diag == 0) { kdb_printf("Entering kdb "); #if defined(__SMP__) kdb_printf("on processor %d ", smp_processor_id()); #endif } else if (diag == 2) { /* * in middle of ssb command. Just return. */ return 0; } break; case KDB_REASON_FAULT: break; case KDB_REASON_INT: kdb_printf("due to KDB_ENTER() call\n"); break; case KDB_REASON_KEYBOARD: kdb_printf("due to Keyboard Entry\n"); break; case KDB_REASON_SWITCH: kdb_printf("due to cpu switch\n"); break; case KDB_REASON_ENTER: kdb_printf("due to function call\n"); regs = &func_regs; regs->xcs = 0; #if defined(CONFIG_KDB_FRAMEPTR) asm volatile("movl %%ebp,%0":"=m" (*(int *)®s->ebp)); #endif asm volatile("movl %%esp,%0":"=m" (*(int *)®s->esp)); regs->eip = (long) &kdb; /* for traceback. */ break; case KDB_REASON_PANIC: kdb_printf("due to panic @ 0x%8.8x\n", regs->eip); kdbdumpregs(regs, NULL, NULL); break; case KDB_REASON_BREAK: kdb_printf("due to Breakpoint @ 0x%8.8x\n", regs->eip); break; default: break; } #if defined(__SMP__) /* * If SMP, stop other processors */ if (smp_num_cpus > 1) { /* * Stop all other processors */ smp_kdb_stop(1); } #endif /* __SMP__ */ /* * Disable interrupts during kdb command processing */ __save_flags(flags); __cli(); while (1) { /* * Initialize pager context. */ kdb_nextline = 1; /* * Use kdb_setjmp/kdb_longjmp to break out of * the pager early. */ if (kdb_setjmp(&kdbjmpbuf)) { /* * Command aborted (usually in pager) */ /* * XXX - need to abort a SSB ? */ continue; } /* * Fetch command from keyboard */ cmd = kbd_getstr(cmdbuf, sizeof(cmdbuf), kdbgetenv("PROMPT")); diag = kdb_parse(cmd, regs); if (diag == KDB_NOTFOUND) { kdb_printf("Unknown kdb command: '%s'\n", cmd); diag = 0; } if ((diag == KDB_GO) || (diag == KDB_CPUSWITCH)) break; /* Go or cpu switch command */ if (diag) kdb_cmderror(diag); } /* * Set up debug registers. */ kdb_bp_install(); #if defined(__SMP__) if ((diag == KDB_CPUSWITCH) && (kdb_new_cpu != -1)) { /* * Leaving the other CPU's at the barrier, except the * one we are switching to, we'll send ourselves a * kdb IPI before allowing interrupts so it will get * caught ASAP and get this CPU back waiting at the barrier. */ smp_kdb_stop(0); /* Stop ourself */ /* * let the new cpu go. */ clear_bit(kdb_new_cpu, &smp_kdb_wait); } else { /* * Let the other processors continue. */ smp_kdb_wait = 0; } #endif kdb_flags &= ~(KDB_FLAG_SUPRESS|KDB_FLAG_FAULT); __restore_flags(flags); return 0; }
int kdb_stub(struct kgdb_state *ks) { int error = 0; kdb_bp_t *bp; unsigned long addr = kgdb_arch_pc(ks->ex_vector, ks->linux_regs); kdb_reason_t reason = KDB_REASON_OOPS; kdb_dbtrap_t db_result = KDB_DB_NOBPT; int i; if (KDB_STATE(REENTRY)) { reason = KDB_REASON_SWITCH; KDB_STATE_CLEAR(REENTRY); addr = instruction_pointer(ks->linux_regs); } ks->pass_exception = 0; if (atomic_read(&kgdb_setting_breakpoint)) reason = KDB_REASON_KEYBOARD; for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) { if ((bp->bp_enabled) && (bp->bp_addr == addr)) { reason = KDB_REASON_BREAK; db_result = KDB_DB_BPT; if (addr != instruction_pointer(ks->linux_regs)) kgdb_arch_set_pc(ks->linux_regs, addr); break; } } if (reason == KDB_REASON_BREAK || reason == KDB_REASON_SWITCH) { for (i = 0, bp = kdb_breakpoints; i < KDB_MAXBPT; i++, bp++) { if (bp->bp_free) continue; if (bp->bp_addr == addr) { bp->bp_delay = 1; bp->bp_delayed = 1; /* * SSBPT is set when the kernel debugger must single step a * task in order to re-establish an instruction breakpoint * which uses the instruction replacement mechanism. It is * cleared by any action that removes the need to single-step * the breakpoint. */ reason = KDB_REASON_BREAK; db_result = KDB_DB_BPT; KDB_STATE_SET(SSBPT); break; } } } if (reason != KDB_REASON_BREAK && ks->ex_vector == 0 && ks->signo == SIGTRAP) { reason = KDB_REASON_SSTEP; db_result = KDB_DB_BPT; } /* Set initial kdb state variables */ KDB_STATE_CLEAR(KGDB_TRANS); kdb_initial_cpu = ks->cpu; kdb_current_task = kgdb_info[ks->cpu].task; kdb_current_regs = kgdb_info[ks->cpu].debuggerinfo; /* Remove any breakpoints as needed by kdb and clear single step */ kdb_bp_remove(); KDB_STATE_CLEAR(DOING_SS); KDB_STATE_CLEAR(DOING_SSB); KDB_STATE_SET(PAGER); /* zero out any offline cpu data */ for_each_present_cpu(i) { if (!cpu_online(i)) { kgdb_info[i].debuggerinfo = NULL; kgdb_info[i].task = NULL; } } if (ks->err_code == DIE_OOPS || reason == KDB_REASON_OOPS) { ks->pass_exception = 1; KDB_FLAG_SET(CATASTROPHIC); } kdb_initial_cpu = ks->cpu; if (KDB_STATE(SSBPT) && reason == KDB_REASON_SSTEP) { KDB_STATE_CLEAR(SSBPT); KDB_STATE_CLEAR(DOING_SS); } else { /* Start kdb main loop */ error = kdb_main_loop(KDB_REASON_ENTER, reason, ks->err_code, db_result, ks->linux_regs); } /* * Upon exit from the kdb main loop setup break points and restart * the system based on the requested continue state */ kdb_initial_cpu = -1; kdb_current_task = NULL; kdb_current_regs = NULL; KDB_STATE_CLEAR(PAGER); kdbnearsym_cleanup(); if (error == KDB_CMD_KGDB) { if (KDB_STATE(DOING_KGDB) || KDB_STATE(DOING_KGDB2)) { /* * This inteface glue which allows kdb to transition in into * the gdb stub. In order to do this the '?' or '' gdb serial * packet response is processed here. And then control is * passed to the gdbstub. */ if (KDB_STATE(DOING_KGDB)) gdbstub_state(ks, "?"); else gdbstub_state(ks, ""); KDB_STATE_CLEAR(DOING_KGDB); KDB_STATE_CLEAR(DOING_KGDB2); } return DBG_PASS_EVENT; } kdb_bp_install(ks->linux_regs); dbg_activate_sw_breakpoints(); /* Set the exit state to a single step or a continue */ if (KDB_STATE(DOING_SS)) gdbstub_state(ks, "s"); else gdbstub_state(ks, "c"); KDB_FLAG_CLEAR(CATASTROPHIC); /* Invoke arch specific exception handling prior to system resume */ kgdb_info[ks->cpu].ret_state = gdbstub_state(ks, "e"); if (ks->pass_exception) kgdb_info[ks->cpu].ret_state = 1; if (error == KDB_CMD_CPU) { KDB_STATE_SET(REENTRY); /* * Force clear the single step bit because kdb emulates this * differently vs the gdbstub */ kgdb_single_step = 0; dbg_deactivate_sw_breakpoints(); return DBG_SWITCH_CPU_EVENT; } return kgdb_info[ks->cpu].ret_state; }