/* * kdb_trap - field a TRACE or BPT trap */ int kdb_trap(int type, int code, struct i386_saved_state *regs) { volatile int ddb_mode = !(boothowto & RB_GDB); /* * XXX try to do nothing if the console is in graphics mode. * Handle trace traps (and hardware breakpoints...) by ignoring * them except for forgetting about them. Return 0 for other * traps to say that we haven't done anything. The trap handler * will usually panic. We should handle breakpoint traps for * our breakpoints by disarming our breakpoints and fixing up * %eip. */ if (cons_unavail && ddb_mode) { if (type == T_TRCTRAP) { regs->tf_eflags &= ~PSL_T; return (1); } return (0); } switch (type) { case T_BPTFLT: /* breakpoint */ case T_TRCTRAP: /* debug exception */ break; default: /* * XXX this is almost useless now. In most cases, * trap_fatal() has already printed a much more verbose * message. However, it is dangerous to print things in * trap_fatal() - kprintf() might be reentered and trap. * The debugger should be given control first. */ if (ddb_mode) db_printf("kernel: type %d trap, code=%x\n", type, code); if (db_nofault) { jmp_buf *no_fault = db_nofault; db_nofault = NULL; longjmp(*no_fault, 1); } } /* * This handles unexpected traps in ddb commands, including calls to * non-ddb functions. db_nofault only applies to memory accesses by * internal ddb commands. */ if (db_global_jmpbuf_valid) longjmp(db_global_jmpbuf, 1); /* * XXX We really should switch to a local stack here. */ ddb_regs = *regs; /* * If in kernel mode, esp and ss are not saved, so dummy them up. */ if (ISPL(regs->tf_cs) == 0) { ddb_regs.tf_esp = (int)®s->tf_esp; ddb_regs.tf_ss = rss(); } crit_enter(); #ifdef SMP db_printf("\nCPU%d stopping CPUs: 0x%08x\n", mycpu->gd_cpuid, mycpu->gd_other_cpus); /* We stop all CPUs except ourselves (obviously) */ stop_cpus(mycpu->gd_other_cpus); db_printf(" stopped\n"); #endif /* SMP */ setjmp(db_global_jmpbuf); db_global_jmpbuf_valid = TRUE; db_active++; if (ddb_mode) { cndbctl(TRUE); db_trap(type, code); cndbctl(FALSE); } else gdb_handle_exception(&ddb_regs, type, code); db_active--; db_global_jmpbuf_valid = FALSE; #ifdef SMP db_printf("\nCPU%d restarting CPUs: 0x%08x\n", mycpu->gd_cpuid, stopped_cpus); /* Restart all the CPUs we previously stopped */ if (stopped_cpus != mycpu->gd_other_cpus) { db_printf("whoa, other_cpus: 0x%08x, stopped_cpus: 0x%08x\n", mycpu->gd_other_cpus, stopped_cpus); panic("stop_cpus() failed"); } restart_cpus(stopped_cpus); db_printf(" restarted\n"); #endif /* SMP */ crit_exit(); regs->tf_eip = ddb_regs.tf_eip; regs->tf_eflags = ddb_regs.tf_eflags; regs->tf_eax = ddb_regs.tf_eax; regs->tf_ecx = ddb_regs.tf_ecx; regs->tf_edx = ddb_regs.tf_edx; regs->tf_ebx = ddb_regs.tf_ebx; /* * If in user mode, the saved ESP and SS were valid, restore them. */ if (ISPL(regs->tf_cs)) { regs->tf_esp = ddb_regs.tf_esp; regs->tf_ss = ddb_regs.tf_ss & 0xffff; } regs->tf_ebp = ddb_regs.tf_ebp; regs->tf_esi = ddb_regs.tf_esi; regs->tf_edi = ddb_regs.tf_edi; regs->tf_es = ddb_regs.tf_es & 0xffff; regs->tf_fs = ddb_regs.tf_fs & 0xffff; regs->tf_gs = ddb_regs.tf_gs & 0xffff; regs->tf_cs = ddb_regs.tf_cs & 0xffff; regs->tf_ds = ddb_regs.tf_ds & 0xffff; return (1); }
/* * kdb_trap - field a TRACE or BPT trap */ int kdb_trap(int type, int code, struct x86_64_saved_state *regs) { volatile int ddb_mode = !(boothowto & RB_GDB); /* * XXX try to do nothing if the console is in graphics mode. * Handle trace traps (and hardware breakpoints...) by ignoring * them except for forgetting about them. Return 0 for other * traps to say that we haven't done anything. The trap handler * will usually panic. We should handle breakpoint traps for * our breakpoints by disarming our breakpoints and fixing up * %eip. */ if (cons_unavail && ddb_mode) { if (type == T_TRCTRAP) { regs->tf_rflags &= ~PSL_T; return (1); } return (0); } switch (type) { case T_BPTFLT: /* breakpoint */ case T_TRCTRAP: /* debug exception */ break; default: /* * XXX this is almost useless now. In most cases, * trap_fatal() has already printed a much more verbose * message. However, it is dangerous to print things in * trap_fatal() - kprintf() might be reentered and trap. * The debugger should be given control first. */ if (ddb_mode) db_printf("kernel: type %d trap, code=%x\n", type, code); if (db_nofault) { jmp_buf *no_fault = db_nofault; db_nofault = NULL; longjmp(*no_fault, 1); } } /* * This handles unexpected traps in ddb commands, including calls to * non-ddb functions. db_nofault only applies to memory accesses by * internal ddb commands. */ if (db_global_jmpbuf_valid) longjmp(db_global_jmpbuf, 1); /* * XXX We really should switch to a local stack here. */ ddb_regs = *regs; crit_enter(); db_printf("\nCPU%d stopping CPUs: 0x%016jx\n", mycpu->gd_cpuid, (uintmax_t)CPUMASK_LOWMASK(mycpu->gd_other_cpus)); /* We stop all CPUs except ourselves (obviously) */ stop_cpus(mycpu->gd_other_cpus); db_printf(" stopped\n"); setjmp(db_global_jmpbuf); db_global_jmpbuf_valid = TRUE; db_active++; vcons_set_mode(1); if (ddb_mode) { cndbctl(TRUE); db_trap(type, code); cndbctl(FALSE); } else gdb_handle_exception(&ddb_regs, type, code); db_active--; vcons_set_mode(0); db_global_jmpbuf_valid = FALSE; db_printf("\nCPU%d restarting CPUs: 0x%016jx\n", mycpu->gd_cpuid, (uintmax_t)CPUMASK_LOWMASK(stopped_cpus)); /* Restart all the CPUs we previously stopped */ if (CPUMASK_CMPMASKNEQ(stopped_cpus, mycpu->gd_other_cpus)) { db_printf("whoa, other_cpus: 0x%016jx, " "stopped_cpus: 0x%016jx\n", (uintmax_t)CPUMASK_LOWMASK(mycpu->gd_other_cpus), (uintmax_t)CPUMASK_LOWMASK(stopped_cpus)); panic("stop_cpus() failed"); } restart_cpus(stopped_cpus); db_printf(" restarted\n"); crit_exit(); regs->tf_rip = ddb_regs.tf_rip; regs->tf_rflags = ddb_regs.tf_rflags; regs->tf_rax = ddb_regs.tf_rax; regs->tf_rcx = ddb_regs.tf_rcx; regs->tf_rdx = ddb_regs.tf_rdx; regs->tf_rbx = ddb_regs.tf_rbx; regs->tf_rsp = ddb_regs.tf_rsp; regs->tf_ss = ddb_regs.tf_ss & 0xffff; regs->tf_rbp = ddb_regs.tf_rbp; regs->tf_rsi = ddb_regs.tf_rsi; regs->tf_rdi = ddb_regs.tf_rdi; regs->tf_r8 = ddb_regs.tf_r8; regs->tf_r9 = ddb_regs.tf_r9; regs->tf_r10 = ddb_regs.tf_r10; regs->tf_r11 = ddb_regs.tf_r11; regs->tf_r12 = ddb_regs.tf_r12; regs->tf_r13 = ddb_regs.tf_r13; regs->tf_r14 = ddb_regs.tf_r14; regs->tf_r15 = ddb_regs.tf_r15; /* regs->tf_es = ddb_regs.tf_es & 0xffff; */ /* regs->tf_fs = ddb_regs.tf_fs & 0xffff; */ /* regs->tf_gs = ddb_regs.tf_gs & 0xffff; */ regs->tf_cs = ddb_regs.tf_cs & 0xffff; /* regs->tf_ds = ddb_regs.tf_ds & 0xffff; */ return (1); }
/* * ddb_trap - field a kernel trap */ int kdb_trap(int vector, struct trapframe *regs) { int ddb_mode = !(boothowto & RB_GDB); register_t s; /* * Don't bother checking for usermode, since a benign entry * by the kernel (call to Debugger() or a breakpoint) has * already checked for usermode. If neither of those * conditions exist, something Bad has happened. */ if (vector != IA64_VEC_BREAK && vector != IA64_VEC_SINGLE_STEP_TRAP) { #if 0 if (ddb_mode) { db_printf("ddbprinttrap from 0x%lx\n", /* XXX */ regs->tf_regs[FRAME_PC]); ddbprinttrap(a0, a1, a2, entry); /* * Tell caller "We did NOT handle the trap." * Caller should panic, or whatever. */ return (0); } #endif if (db_nofault) { jmp_buf *no_fault = db_nofault; db_nofault = 0; longjmp(*no_fault, 1); } } /* * XXX Should switch to DDB's own stack, here. */ s = intr_disable(); #ifdef SMP #ifdef CPUSTOP_ON_DDBBREAK #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) db_printf("CPU%d stopping CPUs: 0x%08x...", PCPU_GET(cpuid), PCPU_GET(other_cpus)); #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ /* We stop all CPUs except ourselves (obviously) */ stop_cpus(PCPU_GET(other_cpus)); #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) db_printf(" stopped.\n"); #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ #endif /* CPUSTOP_ON_DDBBREAK */ #endif /* SMP */ ddb_regs = *regs; /* * XXX pretend that registers outside the current frame don't exist. */ db_eregs = db_regs + DB_MISC_REGS + 8 + 32 + (ddb_regs.tf_cr_ifs & 0x7f); __asm __volatile("flushrs"); /* so we can look at them */ db_active++; if (ddb_mode) { cndbctl(TRUE); /* DDB active, unblank video */ db_trap(vector, 0); /* Where the work happens */ cndbctl(FALSE); /* DDB inactive */ } else gdb_handle_exception(&ddb_regs, vector); db_active--; #ifdef SMP #ifdef CPUSTOP_ON_DDBBREAK #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) db_printf("CPU%d restarting CPUs: 0x%08x...", PCPU_GET(cpuid), stopped_cpus); #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ /* Restart all the CPUs we previously stopped */ if (stopped_cpus != PCPU_GET(other_cpus) && smp_started != 0) { db_printf("whoa, other_cpus: 0x%08x, stopped_cpus: 0x%08x\n", PCPU_GET(other_cpus), stopped_cpus); panic("stop_cpus() failed"); } restart_cpus(stopped_cpus); #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) db_printf(" restarted.\n"); #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ #endif /* CPUSTOP_ON_DDBBREAK */ #endif /* SMP */ *regs = ddb_regs; intr_restore(s); /* * Tell caller "We HAVE handled the trap." */ return (1); }