xref: /openbsd-src/sys/arch/i386/i386/db_interface.c (revision f4e7063748a2ac72b2bab4389c0a7efc72d82189)
1 /*	$OpenBSD: db_interface.c,v 1.45 2023/01/30 10:49:05 jsg Exp $	*/
2 /*	$NetBSD: db_interface.c,v 1.22 1996/05/03 19:42:00 christos Exp $	*/
3 
4 /*
5  * Mach Operating System
6  * Copyright (c) 1991,1990 Carnegie Mellon University
7  * All Rights Reserved.
8  *
9  * Permission to use, copy, modify and distribute this software and its
10  * documentation is hereby granted, provided that both the copyright
11  * notice and this permission notice appear in all copies of the
12  * software, derivative works or modified versions, and any portions
13  * thereof, and that both notices appear in supporting documentation.
14  *
15  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
16  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18  *
19  * Carnegie Mellon requests users of this software to return to
20  *
21  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
22  *  School of Computer Science
23  *  Carnegie Mellon University
24  *  Pittsburgh PA 15213-3890
25  *
26  * any improvements or extensions that they make and grant Carnegie Mellon
27  * the rights to redistribute these changes.
28  *
29  *	db_interface.c,v 2.4 1991/02/05 17:11:13 mrt (CMU)
30  */
31 
32 /*
33  * Interface to new debugger.
34  */
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 
38 #include <dev/cons.h>
39 
40 #include <machine/db_machdep.h>
41 
42 #include <ddb/db_command.h>
43 #include <ddb/db_extern.h>
44 #include <ddb/db_output.h>
45 #include <ddb/db_run.h>
46 #include <ddb/db_var.h>
47 
48 #include "acpi.h"
49 #if NACPI > 0
50 #include <dev/acpi/acpidebug.h>
51 #endif /* NACPI > 0 */
52 
53 #include "wsdisplay.h"
54 #if NWSDISPLAY > 0
55 #include <dev/wscons/wsdisplayvar.h>
56 #endif
57 
58 extern label_t	*db_recover;
59 extern char *trap_type[];
60 extern int trap_types;
61 
62 #ifdef MULTIPROCESSOR
63 extern volatile int ddb_state;
64 int		 db_switch_cpu;
65 long		 db_switch_to_cpu;
66 #endif
67 
68 db_regs_t	ddb_regs;
69 
70 void kdbprinttrap(int, int);
71 void db_sysregs_cmd(db_expr_t, int, db_expr_t, char *);
72 #ifdef MULTIPROCESSOR
73 void db_cpuinfo_cmd(db_expr_t, int, db_expr_t, char *);
74 void db_startproc_cmd(db_expr_t, int, db_expr_t, char *);
75 void db_stopproc_cmd(db_expr_t, int, db_expr_t, char *);
76 void db_ddbproc_cmd(db_expr_t, int, db_expr_t, char *);
77 #endif /* MULTIPROCESSOR */
78 
79 /*
80  * Print trap reason.
81  */
82 void
kdbprinttrap(int type,int code)83 kdbprinttrap(int type, int code)
84 {
85 	db_printf("kernel: ");
86 	if (type >= trap_types || type < 0)
87 		db_printf("type %d", type);
88 	else
89 		db_printf("%s", trap_type[type]);
90 	db_printf(" trap, code=%x\n", code);
91 }
92 
93 /*
94  *  db_ktrap - field a TRACE or BPT trap
95  */
96 int
db_ktrap(int type,int code,db_regs_t * regs)97 db_ktrap(int type, int code, db_regs_t *regs)
98 {
99 	int s;
100 
101 #if NWSDISPLAY > 0
102 	wsdisplay_enter_ddb();
103 #endif
104 
105 	switch (type) {
106 	case T_BPTFLT:	/* breakpoint */
107 	case T_TRCTRAP:	/* single_step */
108 	case T_NMI:	/* NMI */
109 	case T_NMI|T_USER:
110 	case -1:	/* keyboard interrupt */
111 		break;
112 	default:
113 		if (!db_panic)
114 			return (0);
115 
116 		kdbprinttrap(type, code);
117 		if (db_recover != 0) {
118 			db_error("Faulted in DDB; continuing...\n");
119 			/*NOTREACHED*/
120 		}
121 	}
122 
123 #ifdef MULTIPROCESSOR
124 	db_mtx_enter(&ddb_mp_mutex);
125 	if (ddb_state == DDB_STATE_EXITING)
126 		ddb_state = DDB_STATE_NOT_RUNNING;
127 	db_mtx_leave(&ddb_mp_mutex);
128 	while (db_enter_ddb()) {
129 #endif /* MULTIPROCESSOR */
130 
131 	/* XXX Should switch to kdb`s own stack here. */
132 
133 	ddb_regs = *regs;
134 	if (KERNELMODE(regs->tf_cs, regs->tf_eflags)) {
135 		/*
136 		 * Kernel mode - esp and ss not saved
137 		 */
138 		ddb_regs.tf_esp = (int)&regs->tf_esp;	/* kernel stack pointer */
139 		__asm__("movw %%ss,%w0" : "=r" (ddb_regs.tf_ss));
140 	}
141 	ddb_regs.tf_cs &= 0xffff;
142 	ddb_regs.tf_ds &= 0xffff;
143 	ddb_regs.tf_es &= 0xffff;
144 	ddb_regs.tf_fs &= 0xffff;
145 	ddb_regs.tf_gs &= 0xffff;
146 	ddb_regs.tf_ss &= 0xffff;
147 
148 	s = splhigh();
149 	db_active++;
150 	cnpollc(1);
151 	db_trap(type, code);
152 	cnpollc(0);
153 	db_active--;
154 	splx(s);
155 
156 	regs->tf_fs     = ddb_regs.tf_fs & 0xffff;
157 	regs->tf_gs     = ddb_regs.tf_gs & 0xffff;
158 	regs->tf_es     = ddb_regs.tf_es & 0xffff;
159 	regs->tf_ds     = ddb_regs.tf_ds & 0xffff;
160 	regs->tf_edi    = ddb_regs.tf_edi;
161 	regs->tf_esi    = ddb_regs.tf_esi;
162 	regs->tf_ebp    = ddb_regs.tf_ebp;
163 	regs->tf_ebx    = ddb_regs.tf_ebx;
164 	regs->tf_edx    = ddb_regs.tf_edx;
165 	regs->tf_ecx    = ddb_regs.tf_ecx;
166 	regs->tf_eax    = ddb_regs.tf_eax;
167 	regs->tf_eip    = ddb_regs.tf_eip;
168 	regs->tf_cs     = ddb_regs.tf_cs & 0xffff;
169 	regs->tf_eflags = ddb_regs.tf_eflags;
170 	if (!KERNELMODE(regs->tf_cs, regs->tf_eflags)) {
171 		/* ring transit - saved esp and ss valid */
172 		regs->tf_esp    = ddb_regs.tf_esp;
173 		regs->tf_ss     = ddb_regs.tf_ss & 0xffff;
174 	}
175 
176 
177 #ifdef MULTIPROCESSOR
178 		if (!db_switch_cpu)
179 			ddb_state = DDB_STATE_EXITING;
180 	}
181 #endif /* MULTIPROCESSOR */
182 	return (1);
183 }
184 
185 void
db_sysregs_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)186 db_sysregs_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
187 {
188 	int64_t idtr, gdtr;
189 	uint32_t cr;
190 	uint16_t ldtr, tr;
191 
192 	__asm__ volatile("sidt %0" : "=m" (idtr));
193 	db_printf("idtr:   0x%08llx/%04llx\n", idtr >> 16, idtr & 0xffff);
194 
195 	__asm__ volatile("sgdt %0" : "=m" (gdtr));
196 	db_printf("gdtr:   0x%08llx/%04llx\n", gdtr >> 16, gdtr & 0xffff);
197 
198 	__asm__ volatile("sldt %0" : "=g" (ldtr));
199 	db_printf("ldtr:   0x%04x\n", ldtr);
200 
201 	__asm__ volatile("str %0" : "=g" (tr));
202 	db_printf("tr:     0x%04x\n", tr);
203 
204 	__asm__ volatile("movl %%cr0,%0" : "=r" (cr));
205 	db_printf("cr0:    0x%08x\n", cr);
206 
207 	__asm__ volatile("movl %%cr2,%0" : "=r" (cr));
208 	db_printf("cr2:    0x%08x\n", cr);
209 
210 	__asm__ volatile("movl %%cr3,%0" : "=r" (cr));
211 	db_printf("cr3:    0x%08x\n", cr);
212 
213 	__asm__ volatile("movl %%cr4,%0" : "=r" (cr));
214 	db_printf("cr4:    0x%08x\n", cr);
215 }
216 
217 #ifdef MULTIPROCESSOR
218 void
db_cpuinfo_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)219 db_cpuinfo_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
220 {
221 	int i;
222 
223 	for (i = 0; i < MAXCPUS; i++) {
224 		if (cpu_info[i] != NULL) {
225 			db_printf("%c%4d: ", (i == cpu_number()) ? '*' : ' ',
226 			    cpu_info[i]->ci_dev->dv_unit);
227 			switch(cpu_info[i]->ci_ddb_paused) {
228 			case CI_DDB_RUNNING:
229 				db_printf("running\n");
230 				break;
231 			case CI_DDB_SHOULDSTOP:
232 				db_printf("stopping\n");
233 				break;
234 			case CI_DDB_STOPPED:
235 				db_printf("stopped\n");
236 				break;
237 			case CI_DDB_ENTERDDB:
238 				db_printf("entering ddb\n");
239 				break;
240 			case CI_DDB_INDDB:
241 				db_printf("ddb\n");
242 				break;
243 			default:
244 				db_printf("? (%d)\n",
245 				    cpu_info[i]->ci_ddb_paused);
246 				break;
247 			}
248 		}
249 	}
250 }
251 
252 void
db_startproc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)253 db_startproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
254 {
255 	int i;
256 
257 	if (have_addr) {
258 		if (addr >= 0 && addr < MAXCPUS &&
259 		    cpu_info[addr] != NULL && addr != cpu_number())
260 			db_startcpu(addr);
261 		else
262 			db_printf("Invalid cpu %d\n", (int)addr);
263 	} else {
264 		for (i = 0; i < MAXCPUS; i++) {
265 			if (cpu_info[i] != NULL && i != cpu_number())
266 				db_startcpu(i);
267 		}
268 	}
269 }
270 
271 void
db_stopproc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)272 db_stopproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
273 {
274 	int i;
275 
276 	if (have_addr) {
277 		if (addr >= 0 && addr < MAXCPUS &&
278 		    cpu_info[addr] != NULL && addr != cpu_number())
279 			db_stopcpu(addr);
280 		else
281 			db_printf("Invalid cpu %d\n", (int)addr);
282 	} else {
283 		for (i = 0; i < MAXCPUS; i++) {
284 			if (cpu_info[i] != NULL && i != cpu_number()) {
285 				db_stopcpu(i);
286 			}
287 		}
288 	}
289 }
290 
291 void
db_ddbproc_cmd(db_expr_t addr,int have_addr,db_expr_t count,char * modif)292 db_ddbproc_cmd(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
293 {
294 	if (have_addr) {
295 		if (addr >= 0 && addr < MAXCPUS &&
296 		    cpu_info[addr] != NULL && addr != cpu_number()) {
297 			db_stopcpu(addr);
298 			db_switch_to_cpu = addr;
299 			db_switch_cpu = 1;
300 			db_cmd_loop_done = 1;
301 		} else {
302 			db_printf("Invalid cpu %d\n", (int)addr);
303 		}
304 	} else {
305 		db_printf("CPU not specified\n");
306 	}
307 }
308 #endif /* MULTIPROCESSOR */
309 
310 #if NACPI > 0
311 const struct db_command db_acpi_cmds[] = {
312 	{ "disasm",	db_acpi_disasm,		CS_OWN,	NULL },
313 	{ "showval",	db_acpi_showval,	CS_OWN,	NULL },
314 	{ "tree",	db_acpi_tree,		0,	NULL },
315 	{ "trace",	db_acpi_trace,		0,	NULL },
316 	{ NULL,		NULL,			0,	NULL }
317 };
318 #endif /* NACPI > 0 */
319 
320 const struct db_command db_machine_command_table[] = {
321 	{ "sysregs",	db_sysregs_cmd,		0,	0 },
322 #ifdef MULTIPROCESSOR
323 	{ "cpuinfo",	db_cpuinfo_cmd,		0,	0 },
324 	{ "startcpu",	db_startproc_cmd,	0,	0 },
325 	{ "stopcpu",	db_stopproc_cmd,	0,	0 },
326 	{ "ddbcpu",	db_ddbproc_cmd,		0,	0 },
327 #endif /* MULTIPROCESSOR */
328 #if NACPI > 0
329 	{ "acpi",	NULL,			0,	db_acpi_cmds },
330 #endif /* NACPI > 0 */
331 	{ NULL, }
332 };
333 
334 void
db_machine_init(void)335 db_machine_init(void)
336 {
337 #ifdef MULTIPROCESSOR
338 	int i;
339 
340 	for (i = 0; i < MAXCPUS; i++) {
341 		if (cpu_info[i] != NULL)
342 			cpu_info[i]->ci_ddb_paused = CI_DDB_RUNNING;
343 	}
344 #endif /* MULTIPROCESSOR */
345 }
346 
347 void
db_enter(void)348 db_enter(void)
349 {
350 	__asm__("int $3");
351 }
352