2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
16 * Carnegie Mellon requests users of this software to return to
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
26 * $FreeBSD: src/sys/i386/i386/db_interface.c,v 1.48.2.1 2000/07/07 00:38:46 obrien Exp $
27 * $DragonFly: src/sys/platform/pc32/i386/db_interface.c,v 1.10 2004/02/21 06:37:07 dillon Exp $
31 * Interface to new debugger.
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/reboot.h>
38 #include <machine/cpu.h>
39 #include <machine/smp.h>
40 #include <machine/smptests.h> /** CPUSTOP_ON_DDBBREAK */
41 #include <machine/globaldata.h>
50 static jmp_buf *db_nofault = 0;
51 extern jmp_buf db_jmpbuf;
53 extern void gdb_handle_exception (db_regs_t *, int, int);
58 static jmp_buf db_global_jmpbuf;
59 static int db_global_jmpbuf_valid;
62 #define rss() ({u_short ss; __asm __volatile("mov %%ss,%0" : "=r" (ss)); ss;})
65 #define VERBOSE_CPUSTOP_ON_DDBBREAK
68 * kdb_trap - field a TRACE or BPT trap
71 kdb_trap(type, code, regs)
73 struct i386_saved_state *regs;
75 volatile int ddb_mode = !(boothowto & RB_GDB);
78 * XXX try to do nothing if the console is in graphics mode.
79 * Handle trace traps (and hardware breakpoints...) by ignoring
80 * them except for forgetting about them. Return 0 for other
81 * traps to say that we haven't done anything. The trap handler
82 * will usually panic. We should handle breakpoint traps for
83 * our breakpoints by disarming our breakpoints and fixing up
86 if (cons_unavail && ddb_mode) {
87 if (type == T_TRCTRAP) {
88 regs->tf_eflags &= ~PSL_T;
95 case T_BPTFLT: /* breakpoint */
96 case T_TRCTRAP: /* debug exception */
101 * XXX this is almost useless now. In most cases,
102 * trap_fatal() has already printed a much more verbose
103 * message. However, it is dangerous to print things in
104 * trap_fatal() - printf() might be reentered and trap.
105 * The debugger should be given control first.
108 db_printf("kernel: type %d trap, code=%x\n", type, code);
111 jmp_buf *no_fault = db_nofault;
113 longjmp(*no_fault, 1);
118 * This handles unexpected traps in ddb commands, including calls to
119 * non-ddb functions. db_nofault only applies to memory accesses by
120 * internal ddb commands.
122 if (db_global_jmpbuf_valid)
123 longjmp(db_global_jmpbuf, 1);
126 * XXX We really should switch to a local stack here.
131 * If in kernel mode, esp and ss are not saved, so dummy them up.
133 if (ISPL(regs->tf_cs) == 0) {
134 ddb_regs.tf_esp = (int)®s->tf_esp;
135 ddb_regs.tf_ss = rss();
139 #ifdef CPUSTOP_ON_DDBBREAK
141 #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
142 db_printf("\nCPU%d stopping CPUs: 0x%08x\n",
143 mycpu->gd_cpuid, mycpu->gd_other_cpus);
144 #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
146 /* We stop all CPUs except ourselves (obviously) */
147 stop_cpus(mycpu->gd_other_cpus);
149 #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
150 db_printf(" stopped\n");
151 #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
153 #endif /* CPUSTOP_ON_DDBBREAK */
156 (void) setjmp(db_global_jmpbuf);
157 db_global_jmpbuf_valid = TRUE;
164 gdb_handle_exception(&ddb_regs, type, code);
166 db_global_jmpbuf_valid = FALSE;
169 #ifdef CPUSTOP_ON_DDBBREAK
171 #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
172 db_printf("\nCPU%d restarting CPUs: 0x%08x\n",
173 mycpu->gd_cpuid, stopped_cpus);
174 #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
176 /* Restart all the CPUs we previously stopped */
177 if (stopped_cpus != mycpu->gd_other_cpus) {
178 db_printf("whoa, other_cpus: 0x%08x, stopped_cpus: 0x%08x\n",
179 mycpu->gd_other_cpus, stopped_cpus);
180 panic("stop_cpus() failed");
182 restart_cpus(stopped_cpus);
184 #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
185 db_printf(" restarted\n");
186 #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
188 #endif /* CPUSTOP_ON_DDBBREAK */
191 regs->tf_eip = ddb_regs.tf_eip;
192 regs->tf_eflags = ddb_regs.tf_eflags;
193 regs->tf_eax = ddb_regs.tf_eax;
194 regs->tf_ecx = ddb_regs.tf_ecx;
195 regs->tf_edx = ddb_regs.tf_edx;
196 regs->tf_ebx = ddb_regs.tf_ebx;
199 * If in user mode, the saved ESP and SS were valid, restore them.
201 if (ISPL(regs->tf_cs)) {
202 regs->tf_esp = ddb_regs.tf_esp;
203 regs->tf_ss = ddb_regs.tf_ss & 0xffff;
206 regs->tf_ebp = ddb_regs.tf_ebp;
207 regs->tf_esi = ddb_regs.tf_esi;
208 regs->tf_edi = ddb_regs.tf_edi;
209 regs->tf_es = ddb_regs.tf_es & 0xffff;
210 regs->tf_fs = ddb_regs.tf_fs & 0xffff;
211 regs->tf_cs = ddb_regs.tf_cs & 0xffff;
212 regs->tf_ds = ddb_regs.tf_ds & 0xffff;
217 * Read bytes from kernel address space for debugger.
220 db_read_bytes(addr, size, data)
227 db_nofault = &db_jmpbuf;
237 * Write bytes to kernel address space for debugger.
240 db_write_bytes(addr, size, data)
247 unsigned *ptep0 = NULL;
248 unsigned oldmap0 = 0;
250 unsigned *ptep1 = NULL;
251 unsigned oldmap1 = 0;
253 db_nofault = &db_jmpbuf;
255 if (addr > trunc_page((vm_offset_t)btext) - size &&
256 addr < round_page((vm_offset_t)etext)) {
258 ptep0 = pmap_pte(kernel_pmap, addr);
262 /* Map another page if the data crosses a page boundary. */
263 if ((*ptep0 & PG_PS) == 0) {
264 addr1 = trunc_page(addr + size - 1);
265 if (trunc_page(addr) != addr1) {
266 ptep1 = pmap_pte(kernel_pmap, addr1);
271 addr1 = trunc_4mpage(addr + size - 1);
272 if (trunc_4mpage(addr) != addr1) {
273 ptep1 = pmap_pte(kernel_pmap, addr1);
300 * The debugger sometimes needs to know the actual KVM address represented
301 * by the instruction pointer, stack pointer, or base pointer. Normally
302 * the actual KVM address is simply the contents of the register. However,
303 * if the debugger is entered from the BIOS or VM86 we need to figure out
304 * the offset from the segment register.
307 PC_REGS(db_regs_t *regs)
309 struct soft_segment_descriptor softseg;
311 sdtossd(&gdt[mycpu->gd_cpuid * NGDT + IDXSEL(regs->tf_cs & 0xffff)].sd, &softseg);
312 return(regs->tf_eip + softseg.ssd_base);
316 SP_REGS(db_regs_t *regs)
318 struct soft_segment_descriptor softseg;
320 sdtossd(&gdt[mycpu->gd_cpuid * NGDT + IDXSEL(regs->tf_ss & 0xffff)].sd, &softseg);
321 return(regs->tf_esp + softseg.ssd_base);
325 BP_REGS(db_regs_t *regs)
327 struct soft_segment_descriptor softseg;
329 sdtossd(&gdt[mycpu->gd_cpuid * NGDT + IDXSEL(regs->tf_ds & 0xffff)].sd, &softseg);
330 return(regs->tf_ebp + softseg.ssd_base);
335 * Move this to machdep.c and allow it to be called if any debugger is
342 static volatile u_char in_Debugger;
346 * Do nothing if the console is in graphics mode. This is
347 * OK if the call is for the debugger hotkey but not if the call
348 * is a weak form of panicing.
350 if (cons_unavail && !(boothowto & RB_GDB))
355 db_printf("Debugger(\"%s\")\n", msg);