Deleted Added
full compact
db_interface.c (127813) db_interface.c (131952)
1/*
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
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

--- 11 unchanged lines hidden (view full) ---

20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
25 */
26
27#include <sys/cdefs.h>
1/*
2 * Mach Operating System
3 * Copyright (c) 1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
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

--- 11 unchanged lines hidden (view full) ---

20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie the
24 * rights to redistribute these changes.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/i386/i386/db_interface.c 127813 2004-04-03 22:23:36Z marcel $");
28__FBSDID("$FreeBSD: head/sys/i386/i386/db_interface.c 131952 2004-07-10 23:47:20Z marcel $");
29
30/*
31 * Interface to new debugger.
32 */
33#include <sys/param.h>
34#include <sys/systm.h>
29
30/*
31 * Interface to new debugger.
32 */
33#include <sys/param.h>
34#include <sys/systm.h>
35#include <sys/reboot.h>
36#include <sys/cons.h>
35#include <sys/cons.h>
36#include <sys/kdb.h>
37#include <sys/pcpu.h>
38#include <sys/proc.h>
37#include <sys/pcpu.h>
38#include <sys/proc.h>
39#include <sys/smp.h>
40
41#include <machine/cpu.h>
39
40#include <machine/cpu.h>
42#ifdef SMP
43#include <machine/smptests.h> /** CPUSTOP_ON_DDBBREAK */
44#endif
45
46#include <vm/vm.h>
47#include <vm/pmap.h>
48
49#include <ddb/ddb.h>
50
41
42#include <vm/vm.h>
43#include <vm/pmap.h>
44
45#include <ddb/ddb.h>
46
51#include <machine/setjmp.h>
52
53static jmp_buf *db_nofault = 0;
54extern jmp_buf db_jmpbuf;
55
56extern void gdb_handle_exception(db_regs_t *, int, int);
57
58int db_active;
59db_regs_t ddb_regs;
60
61static jmp_buf db_global_jmpbuf;
62
63/*
47/*
64 * kdb_trap - field a TRACE or BPT trap
48 * Read bytes from kernel address space for debugger.
65 */
66int
49 */
50int
67kdb_trap(int type, int code, struct i386_saved_state *regs)
51db_read_bytes(vm_offset_t addr, size_t size, char *data)
68{
52{
69 u_int ef;
70 volatile int ddb_mode = !(boothowto & RB_GDB);
53 jmp_buf jb;
54 void *prev_jb;
55 char *src;
56 int ret;
71
57
72 /*
73 * XXX try to do nothing if the console is in graphics mode.
74 * Handle trace traps (and hardware breakpoints...) by ignoring
75 * them except for forgetting about them. Return 0 for other
76 * traps to say that we haven't done anything. The trap handler
77 * will usually panic. We should handle breakpoint traps for
78 * our breakpoints by disarming our breakpoints and fixing up
79 * %eip.
80 */
81 if (cnunavailable() != 0 && ddb_mode) {
82 if (type == T_TRCTRAP) {
83 regs->tf_eflags &= ~PSL_T;
84 return (1);
85 }
86 return (0);
58 prev_jb = kdb_jmpbuf(jb);
59 ret = setjmp(jb);
60 if (ret == 0) {
61 src = (char *)addr;
62 while (size-- > 0)
63 *data++ = *src++;
87 }
64 }
88
89 ef = read_eflags();
90 disable_intr();
91
92#ifdef SMP
93#ifdef CPUSTOP_ON_DDBBREAK
94
95#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
96 db_printf("\nCPU%d stopping CPUs: 0x%08x...", PCPU_GET(cpuid),
97 PCPU_GET(other_cpus));
98#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
99
100 /* We stop all CPUs except ourselves (obviously) */
101 stop_cpus(PCPU_GET(other_cpus));
102
103#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
104 db_printf(" stopped.\n");
105#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
106
107#endif /* CPUSTOP_ON_DDBBREAK */
108#endif /* SMP */
109
110 switch (type) {
111 case T_BPTFLT: /* breakpoint */
112 case T_TRCTRAP: /* debug exception */
113 break;
114
115 default:
116 /*
117 * XXX this is almost useless now. In most cases,
118 * trap_fatal() has already printed a much more verbose
119 * message. However, it is dangerous to print things in
120 * trap_fatal() - printf() might be reentered and trap.
121 * The debugger should be given control first.
122 */
123 if (ddb_mode)
124 db_printf("kernel: type %d trap, code=%x\n", type, code);
125
126 if (db_nofault) {
127 jmp_buf *no_fault = db_nofault;
128 db_nofault = 0;
129 longjmp(*no_fault, 1);
130 }
131 }
132
133 /*
134 * This handles unexpected traps in ddb commands, including calls to
135 * non-ddb functions. db_nofault only applies to memory accesses by
136 * internal ddb commands.
137 */
138 if (db_active)
139 longjmp(db_global_jmpbuf, 1);
140
141 /*
142 * XXX We really should switch to a local stack here.
143 */
144 ddb_regs = *regs;
145
146 /*
147 * If in kernel mode, esp and ss are not saved, so dummy them up.
148 */
149 if (ISPL(regs->tf_cs) == 0) {
150 ddb_regs.tf_esp = (int)&regs->tf_esp;
151 ddb_regs.tf_ss = rss();
152 }
153
154 (void) setjmp(db_global_jmpbuf);
155 if (ddb_mode) {
156 if (!db_active)
157 cndbctl(TRUE);
158 db_active = 1;
159 db_trap(type, code);
160 cndbctl(FALSE);
161 } else {
162 db_active = 1;
163 gdb_handle_exception(&ddb_regs, type, code);
164 }
165 db_active = 0;
166
167 regs->tf_eip = ddb_regs.tf_eip;
168 regs->tf_eflags = ddb_regs.tf_eflags;
169 regs->tf_eax = ddb_regs.tf_eax;
170 regs->tf_ecx = ddb_regs.tf_ecx;
171 regs->tf_edx = ddb_regs.tf_edx;
172 regs->tf_ebx = ddb_regs.tf_ebx;
173
174 /*
175 * If in user mode, the saved ESP and SS were valid, restore them.
176 */
177 if (ISPL(regs->tf_cs)) {
178 regs->tf_esp = ddb_regs.tf_esp;
179 regs->tf_ss = ddb_regs.tf_ss & 0xffff;
180 }
181
182 regs->tf_ebp = ddb_regs.tf_ebp;
183 regs->tf_esi = ddb_regs.tf_esi;
184 regs->tf_edi = ddb_regs.tf_edi;
185 regs->tf_es = ddb_regs.tf_es & 0xffff;
186 regs->tf_fs = ddb_regs.tf_fs & 0xffff;
187 regs->tf_cs = ddb_regs.tf_cs & 0xffff;
188 regs->tf_ds = ddb_regs.tf_ds & 0xffff;
189
190#ifdef SMP
191#ifdef CPUSTOP_ON_DDBBREAK
192
193#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
194 db_printf("\nCPU%d restarting CPUs: 0x%08x...", PCPU_GET(cpuid),
195 stopped_cpus);
196#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
197
198 /* Restart all the CPUs we previously stopped */
199 if (stopped_cpus != PCPU_GET(other_cpus) && smp_started != 0) {
200 db_printf("whoa, other_cpus: 0x%08x, stopped_cpus: 0x%08x\n",
201 PCPU_GET(other_cpus), stopped_cpus);
202 panic("stop_cpus() failed");
203 }
204 restart_cpus(stopped_cpus);
205
206#if defined(VERBOSE_CPUSTOP_ON_DDBBREAK)
207 db_printf(" restarted.\n");
208#endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */
209
210#endif /* CPUSTOP_ON_DDBBREAK */
211#endif /* SMP */
212
213 write_eflags(ef);
214
215 return (1);
65 (void)kdb_jmpbuf(prev_jb);
66 return (ret);
216}
217
218/*
67}
68
69/*
219 * Read bytes from kernel address space for debugger.
220 */
221void
222db_read_bytes(vm_offset_t addr, size_t size, char *data)
223{
224 char *src;
225
226 db_nofault = &db_jmpbuf;
227
228 src = (char *)addr;
229 while (size-- > 0)
230 *data++ = *src++;
231
232 db_nofault = 0;
233}
234
235/*
236 * Write bytes to kernel address space for debugger.
237 */
70 * Write bytes to kernel address space for debugger.
71 */
238void
72int
239db_write_bytes(vm_offset_t addr, size_t size, char *data)
240{
73db_write_bytes(vm_offset_t addr, size_t size, char *data)
74{
241 char *dst;
75 jmp_buf jb;
76 void *prev_jb;
77 char *dst;
78 pt_entry_t *ptep0 = NULL;
79 pt_entry_t oldmap0 = 0;
80 vm_offset_t addr1;
81 pt_entry_t *ptep1 = NULL;
82 pt_entry_t oldmap1 = 0;
83 int ret;
242
84
243 pt_entry_t *ptep0 = NULL;
244 pt_entry_t oldmap0 = 0;
245 vm_offset_t addr1;
246 pt_entry_t *ptep1 = NULL;
247 pt_entry_t oldmap1 = 0;
85 prev_jb = kdb_jmpbuf(jb);
86 ret = setjmp(jb);
87 if (ret == 0) {
88 if (addr > trunc_page((vm_offset_t)btext) - size &&
89 addr < round_page((vm_offset_t)etext)) {
248
90
249 db_nofault = &db_jmpbuf;
91 ptep0 = pmap_pte(kernel_pmap, addr);
92 oldmap0 = *ptep0;
93 *ptep0 |= PG_RW;
250
94
251 if (addr > trunc_page((vm_offset_t)btext) - size &&
252 addr < round_page((vm_offset_t)etext)) {
95 /*
96 * Map another page if the data crosses a page
97 * boundary.
98 */
99 if ((*ptep0 & PG_PS) == 0) {
100 addr1 = trunc_page(addr + size - 1);
101 if (trunc_page(addr) != addr1) {
102 ptep1 = pmap_pte(kernel_pmap, addr1);
103 oldmap1 = *ptep1;
104 *ptep1 |= PG_RW;
105 }
106 } else {
107 addr1 = trunc_4mpage(addr + size - 1);
108 if (trunc_4mpage(addr) != addr1) {
109 ptep1 = pmap_pte(kernel_pmap, addr1);
110 oldmap1 = *ptep1;
111 *ptep1 |= PG_RW;
112 }
113 }
253
114
254 ptep0 = pmap_pte(kernel_pmap, addr);
255 oldmap0 = *ptep0;
256 *ptep0 |= PG_RW;
257
258 /* Map another page if the data crosses a page boundary. */
259 if ((*ptep0 & PG_PS) == 0) {
260 addr1 = trunc_page(addr + size - 1);
261 if (trunc_page(addr) != addr1) {
262 ptep1 = pmap_pte(kernel_pmap, addr1);
263 oldmap1 = *ptep1;
264 *ptep1 |= PG_RW;
265 }
266 } else {
267 addr1 = trunc_4mpage(addr + size - 1);
268 if (trunc_4mpage(addr) != addr1) {
269 ptep1 = pmap_pte(kernel_pmap, addr1);
270 oldmap1 = *ptep1;
271 *ptep1 |= PG_RW;
115 invltlb();
272 }
116 }
273 }
274
117
275 invltlb();
118 dst = (char *)addr;
119
120 while (size-- > 0)
121 *dst++ = *data++;
276 }
277
122 }
123
278 dst = (char *)addr;
124 (void)kdb_jmpbuf(prev_jb);
279
125
280 while (size-- > 0)
281 *dst++ = *data++;
282
283 db_nofault = 0;
284
285 if (ptep0) {
126 if (ptep0) {
286 *ptep0 = oldmap0;
127 *ptep0 = oldmap0;
287
128
288 if (ptep1)
289 *ptep1 = oldmap1;
129 if (ptep1)
130 *ptep1 = oldmap1;
290
131
291 invltlb();
132 invltlb();
292 }
133 }
293}
294
134
295/*
296 * XXX
297 * Move this to machdep.c and allow it to be called if any debugger is
298 * installed.
299 */
300void
301Debugger(const char *msg)
302{
303 static volatile u_int in_Debugger;
304
305 /*
306 * XXX
307 * Do nothing if the console is in graphics mode. This is
308 * OK if the call is for the debugger hotkey but not if the call
309 * is a weak form of panicing.
310 */
311 if (cnunavailable() != 0 && !(boothowto & RB_GDB))
312 return;
313
314 if (atomic_cmpset_acq_int(&in_Debugger, 0, 1)) {
315 db_printf("Debugger(\"%s\")\n", msg);
316 breakpoint();
317 atomic_store_rel_int(&in_Debugger, 0);
318 }
135 return (ret);
319}
320
321void
322db_show_mdpcpu(struct pcpu *pc)
323{
324
325 db_printf("APIC ID = %d\n", pc->pc_apic_id);
326 db_printf("currentldt = 0x%x\n", pc->pc_currentldt);
327}
136}
137
138void
139db_show_mdpcpu(struct pcpu *pc)
140{
141
142 db_printf("APIC ID = %d\n", pc->pc_apic_id);
143 db_printf("currentldt = 0x%x\n", pc->pc_currentldt);
144}