/* * kdb_trap - field a TRACE or BPT trap * Return non-zero if we "handled" the trap. */ int kdb_trap(int type, db_regs_t *regs) { switch (type) { case T_TRACE: /* single-step */ case T_BREAKPOINT: /* breakpoint */ /* case T_WATCHPOINT:*/ break; case -1: break; default: kdbprinttrap(type, 0); if (db_recover != 0) { /* This will longjmp back to db_command_loop */ db_error("Caught exception in ddb.\n"); /*NOTREACHED*/ } /* * Tell caller "We did NOT handle the trap." * Caller should panic or whatever. */ return 0; } /* * We'd like to be on a separate debug stack here, but * that's easier to do in locore.s before we get here. * See sun3/locore.s:T_TRACE for stack switch code. */ ddb_regs = *regs; db_active++; cnpollc(true); /* set polling mode, unblank video */ db_trap(type, 0); /* where the work happens */ cnpollc(false); /* resume interrupt mode */ db_active--; *regs = ddb_regs; /* * Indicate that single_step is for KDB. * But lock out interrupts to prevent TRACE_KDB from setting the * trace bit in the current SR (and trapping while exiting KDB). */ (void)spl7(); /* * Tell caller "We HAVE handled the trap." * Caller will return to locore and rte. */ return 1; }
boolean_t kdb_trap( int type, int code, struct i386_saved_state *regs) { spl_t s; s = splhigh(); saved_ipl[cpu_number()] = s; switch (type) { case T_DEBUG: /* single_step */ { int addr; int status = get_dr6(); if (status & 0xf) { /* hmm hdw break */ addr = status & 0x8 ? get_dr3() : status & 0x4 ? get_dr2() : status & 0x2 ? get_dr1() : get_dr0(); regs->efl |= EFL_RF; db_single_step_cmd(addr, 0, 1, "p"); } } case T_INT3: /* breakpoint */ case T_WATCHPOINT: /* watchpoint */ case -1: /* keyboard interrupt */ break; default: if (db_recover) { i386_nested_saved_state = *regs; db_printf("Caught %s (%d), code = %x, pc = %x\n", trap_name(type), type, code, regs->eip); db_error(""); /*NOTREACHED*/ } kdbprinttrap(type, code); } #if NCPUS > 1 if (db_enter()) #endif /* NCPUS > 1 */ { i386_last_saved_statep = regs; i386_last_kdb_sp = (unsigned) &type; /* XXX Should switch to ddb`s own stack here. */ ddb_regs = *regs; if ((regs->cs & 0x3) == KERNEL_RING) { /* * Kernel mode - esp and ss not saved */ ddb_regs.uesp = (int)®s->uesp; /* kernel stack pointer */ ddb_regs.ss = KERNEL_DS; } cnpollc(TRUE); db_task_trap(type, code, (regs->cs & 0x3) != 0); cnpollc(FALSE); regs->eip = ddb_regs.eip; regs->efl = ddb_regs.efl; regs->eax = ddb_regs.eax; regs->ecx = ddb_regs.ecx; regs->edx = ddb_regs.edx; regs->ebx = ddb_regs.ebx; if ((regs->cs & 0x3) != KERNEL_RING) { /* * user mode - saved esp and ss valid */ regs->uesp = ddb_regs.uesp; /* user stack pointer */ regs->ss = ddb_regs.ss & 0xffff; /* user stack segment */ } regs->ebp = ddb_regs.ebp; regs->esi = ddb_regs.esi; regs->edi = ddb_regs.edi; regs->es = ddb_regs.es & 0xffff; regs->cs = ddb_regs.cs & 0xffff; regs->ds = ddb_regs.ds & 0xffff; regs->fs = ddb_regs.fs & 0xffff; regs->gs = ddb_regs.gs & 0xffff; if ((type == T_INT3) && (db_get_task_value(regs->eip, BKPT_SIZE, FALSE, TASK_NULL) == BKPT_INST)) regs->eip += BKPT_SIZE; } #if NCPUS > 1 db_leave(); #endif /* NCPUS > 1 */ splx(s); return 1; }
/* * kdb_trap - field a TRACE or BPT trap */ void kdb_trap( int type, struct savearea *regs) { boolean_t trap_from_user; int previous_console_device; int code=0; previous_console_device=switch_to_serial_console(); switch (type) { case T_TRACE: /* single_step */ case T_PROGRAM: /* breakpoint */ #if 0 case T_WATCHPOINT: /* watchpoint */ #endif case -1: /* keyboard interrupt */ break; default: if (db_recover) { ppc_nested_saved_state = *regs; db_printf("Caught "); if (type > TRAP_TYPES) db_printf("type %d", type); else db_printf("%s", trap_type[type]); db_printf(" trap, pc = %x\n", regs->save_srr0); db_error(""); /*NOTREACHED*/ } kdbprinttrap(type, code, (int *)®s->save_srr0, regs->save_r1); } saved_state[cpu_number()] = regs; ppc_last_saved_statep = regs; ppc_last_kdb_sp = (unsigned) &type; if (!IS_USER_TRAP(regs)) { bzero((char *)&ddb_regs, sizeof (ddb_regs)); ddb_regs = *regs; trap_from_user = FALSE; } else { ddb_regs = *regs; trap_from_user = TRUE; } db_task_trap(type, code, trap_from_user); *regs = ddb_regs; if ((type == T_PROGRAM) && (db_get_task_value(regs->save_srr0, BKPT_SIZE, FALSE, db_target_space(current_act(), trap_from_user)) == BKPT_INST)) regs->save_srr0 += BKPT_SIZE; kdb_exit: saved_state[cpu_number()] = 0; switch_to_old_console(previous_console_device); }