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/vkernel/i386/db_interface.c,v 1.3 2007/01/09 01:20:17 dillon Exp $
31 * Interface to new debugger.
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/reboot.h>
37 #include <sys/vkernel.h>
39 #include <machine/cpu.h>
40 #include <machine/smp.h>
41 #include <machine/globaldata.h>
42 #include <machine/md_var.h>
51 static jmp_buf *db_nofault
= 0;
52 extern jmp_buf db_jmpbuf
;
54 extern void gdb_handle_exception (db_regs_t
*, int, int);
59 static jmp_buf db_global_jmpbuf
;
60 static int db_global_jmpbuf_valid
;
63 #define rss() ({u_short ss; __asm __volatile("mov %%ss,%0" : "=r" (ss)); ss;})
67 * kdb_trap - field a TRACE or BPT trap
70 kdb_trap(int type
, int code
, struct i386_saved_state
*regs
)
72 volatile int ddb_mode
= !(boothowto
& RB_GDB
);
75 * XXX try to do nothing if the console is in graphics mode.
76 * Handle trace traps (and hardware breakpoints...) by ignoring
77 * them except for forgetting about them. Return 0 for other
78 * traps to say that we haven't done anything. The trap handler
79 * will usually panic. We should handle breakpoint traps for
80 * our breakpoints by disarming our breakpoints and fixing up
83 if (cons_unavail
&& ddb_mode
) {
84 if (type
== T_TRCTRAP
) {
85 regs
->tf_eflags
&= ~PSL_T
;
92 case T_BPTFLT
: /* breakpoint */
93 case T_TRCTRAP
: /* debug exception */
98 * XXX this is almost useless now. In most cases,
99 * trap_fatal() has already printed a much more verbose
100 * message. However, it is dangerous to print things in
101 * trap_fatal() - kprintf() might be reentered and trap.
102 * The debugger should be given control first.
105 db_printf("kernel: type %d trap, code=%x\n", type
, code
);
108 jmp_buf *no_fault
= db_nofault
;
110 longjmp(*no_fault
, 1);
115 * This handles unexpected traps in ddb commands, including calls to
116 * non-ddb functions. db_nofault only applies to memory accesses by
117 * internal ddb commands.
119 if (db_global_jmpbuf_valid
)
120 longjmp(db_global_jmpbuf
, 1);
123 * XXX We really should switch to a local stack here.
128 * If in kernel mode, esp and ss are not saved, so dummy them up.
130 if (ISPL(regs
->tf_cs
) == 0) {
131 ddb_regs
.tf_esp
= (int)®s
->tf_esp
;
132 ddb_regs
.tf_ss
= rss();
136 db_printf("\nCPU%d stopping CPUs: 0x%08x\n",
137 mycpu
->gd_cpuid
, mycpu
->gd_other_cpus
);
139 /* We stop all CPUs except ourselves (obviously) */
140 stop_cpus(mycpu
->gd_other_cpus
);
142 db_printf(" stopped\n");
145 setjmp(db_global_jmpbuf
);
146 db_global_jmpbuf_valid
= TRUE
;
154 gdb_handle_exception(&ddb_regs
, type
, code
);
157 db_global_jmpbuf_valid
= FALSE
;
160 db_printf("\nCPU%d restarting CPUs: 0x%08x\n",
161 mycpu
->gd_cpuid
, stopped_cpus
);
163 /* Restart all the CPUs we previously stopped */
164 if (stopped_cpus
!= mycpu
->gd_other_cpus
) {
165 db_printf("whoa, other_cpus: 0x%08x, stopped_cpus: 0x%08x\n",
166 mycpu
->gd_other_cpus
, stopped_cpus
);
167 panic("stop_cpus() failed");
169 restart_cpus(stopped_cpus
);
171 db_printf(" restarted\n");
174 regs
->tf_eip
= ddb_regs
.tf_eip
;
175 regs
->tf_eflags
= ddb_regs
.tf_eflags
;
176 regs
->tf_eax
= ddb_regs
.tf_eax
;
177 regs
->tf_ecx
= ddb_regs
.tf_ecx
;
178 regs
->tf_edx
= ddb_regs
.tf_edx
;
179 regs
->tf_ebx
= ddb_regs
.tf_ebx
;
182 * If in user mode, the saved ESP and SS were valid, restore them.
184 if (ISPL(regs
->tf_cs
)) {
185 regs
->tf_esp
= ddb_regs
.tf_esp
;
186 regs
->tf_ss
= ddb_regs
.tf_ss
& 0xffff;
189 regs
->tf_ebp
= ddb_regs
.tf_ebp
;
190 regs
->tf_esi
= ddb_regs
.tf_esi
;
191 regs
->tf_edi
= ddb_regs
.tf_edi
;
192 regs
->tf_es
= ddb_regs
.tf_es
& 0xffff;
193 regs
->tf_fs
= ddb_regs
.tf_fs
& 0xffff;
194 regs
->tf_gs
= ddb_regs
.tf_gs
& 0xffff;
195 regs
->tf_cs
= ddb_regs
.tf_cs
& 0xffff;
196 regs
->tf_ds
= ddb_regs
.tf_ds
& 0xffff;
201 * Read bytes from kernel address space for debugger.
204 db_read_bytes(vm_offset_t addr
, size_t size
, char *data
)
208 db_nofault
= &db_jmpbuf
;
218 * Write bytes to kernel address space for debugger.
221 db_write_bytes(vm_offset_t addr
, size_t size
, char *data
)
225 vpte_t
*ptep0
= NULL
;
228 vpte_t
*ptep1
= NULL
;
232 db_nofault
= &db_jmpbuf
;
234 if (addr
> trunc_page((vm_offset_t
)btext
) - size
&&
235 addr
< round_page((vm_offset_t
)etext
)) {
237 ptep0
= pmap_kpte(addr
);
241 /* Map another page if the data crosses a page boundary. */
242 if ((*ptep0
& PG_PS
) == 0) {
243 addr1
= trunc_page(addr
+ size
- 1);
244 if (trunc_page(addr
) != addr1
) {
245 ptep1
= pmap_kpte(addr1
);
250 addr1
= trunc_4mpage(addr
+ size
- 1);
251 if (trunc_4mpage(addr
) != addr1
) {
252 ptep1
= pmap_kpte(addr1
);
282 * The debugger sometimes needs to know the actual KVM address represented
283 * by the instruction pointer, stack pointer, or base pointer. Normally
284 * the actual KVM address is simply the contents of the register. However,
285 * if the debugger is entered from the BIOS or VM86 we need to figure out
286 * the offset from the segment register.
289 PC_REGS(db_regs_t
*regs
)
291 return(regs
->tf_eip
);
295 SP_REGS(db_regs_t
*regs
)
297 return(regs
->tf_esp
);
301 BP_REGS(db_regs_t
*regs
)
303 return(regs
->tf_ebp
);
308 * Move this to machdep.c and allow it to be called if any debugger is
312 Debugger(const char *msg
)
314 static volatile u_char in_Debugger
;
318 * Do nothing if the console is in graphics mode. This is
319 * OK if the call is for the debugger hotkey but not if the call
320 * is a weak form of panicing.
322 if (cons_unavail
&& !(boothowto
& RB_GDB
))
327 db_printf("Debugger(\"%s\")\n", msg
);