xref: /netbsd-src/sys/arch/x86/x86/kgdb_machdep.c (revision b48aa25305a81d0918b5aa0ed20eb7937b98196b)
1 /*	$NetBSD: kgdb_machdep.c,v 1.6 2022/08/22 13:57:24 hannken Exp $	*/
2 
3 /*
4  * Copyright (c) 1997, 2017 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9  * NASA Ames Research Center.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /*
34  * Copyright (c) 1996 Matthias Pfaller.
35  * All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  *
46  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
47  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
50  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
52  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
53  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
55  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56  */
57 
58 #include <sys/cdefs.h>
59 __KERNEL_RCSID(0, "$NetBSD: kgdb_machdep.c,v 1.6 2022/08/22 13:57:24 hannken Exp $");
60 
61 #include "opt_ddb.h"
62 
63 /*
64  * Machine-dependent functions for remote KGDB.  Originally written
65  * for NetBSD/pc532 by Matthias Pfaller.  Modified for NetBSD/i386
66  * by Jason R. Thorpe. Modified for NetBSD/amd64 by Frank van der Linden.
67  */
68 
69 #include <sys/param.h>
70 #include <sys/kgdb.h>
71 #include <sys/systm.h>
72 
73 #include <machine/pmap_private.h>
74 #include <machine/pte.h>
75 #include <machine/trap.h>
76 
77 /*
78  * Determine if the memory at va..(va+len) is valid.
79  */
80 int
kgdb_acc(vaddr_t va,size_t len)81 kgdb_acc(vaddr_t va, size_t len)
82 {
83 	vaddr_t last_va;
84 	pt_entry_t *pte;
85 
86 	last_va = va + len;
87 	va  &= ~PGOFSET;
88 	last_va &= ~PGOFSET;
89 
90 	do {
91 		if (va < VM_MIN_KERNEL_ADDRESS)
92 			pte = vtopte(va);
93 		else
94 			pte = kvtopte(va);
95 		if ((*pte & PTE_P) == 0)
96 			return 0;
97 		if (*pte & PTE_PS)
98 			va = (va & PTE_LGFRAME) + NBPD_L2;
99 		else
100 			va += PAGE_SIZE;
101 	} while (va < last_va);
102 
103 	return 1;
104 }
105 
106 void
kgdb_entry_notice(int type,db_regs_t * regs)107 kgdb_entry_notice(int type, db_regs_t *regs)
108 {
109 	if (type == T_NMI)
110 		printf("NMI ... going to debugger\n");
111 }
112 
113 /*
114  * Translate a trap number into a unix compatible signal value.
115  * (gdb only understands unix signal numbers).
116  */
117 int
kgdb_signal(int type)118 kgdb_signal(int type)
119 {
120 	switch (type) {
121 	case T_NMI:
122 		return SIGINT;
123 
124 	case T_ALIGNFLT:
125 		return SIGILL;
126 
127 	case T_BPTFLT:
128 	case T_TRCTRAP:
129 		return SIGTRAP;
130 
131 	case T_ASTFLT:
132 	case T_DOUBLEFLT:
133 		return SIGEMT;
134 
135 	case T_ARITHTRAP:
136 	case T_DIVIDE:
137 	case T_OFLOW:
138 	case T_DNA:
139 	case T_FPOPFLT:
140 		return SIGFPE;
141 
142 	case T_PRIVINFLT:
143 	case T_PROTFLT:
144 	case T_PAGEFLT:
145 	case T_TSSFLT:
146 	case T_SEGNPFLT:
147 	case T_STKFLT:
148 		return SIGSEGV;
149 
150 	case T_BOUND:
151 		return SIGURG;
152 
153 	default:
154 		return SIGEMT;
155 	}
156 }
157 
158 /*
159  * Translate the values stored in the kernel regs struct to the format
160  * understood by gdb.
161  */
162 void
kgdb_getregs(db_regs_t * regs,kgdb_reg_t * gdb_regs)163 kgdb_getregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
164 {
165 #ifdef __x86_64__
166 	gdb_regs[ 0] = regs->tf_rax;
167 	gdb_regs[ 1] = regs->tf_rbx;
168 	gdb_regs[ 2] = regs->tf_rcx;
169 	gdb_regs[ 3] = regs->tf_rdx;
170 	gdb_regs[ 4] = regs->tf_rsi;
171 	gdb_regs[ 5] = regs->tf_rdi;
172 	gdb_regs[ 6] = regs->tf_rbp;
173 	gdb_regs[ 7] = regs->tf_rsp;
174 	gdb_regs[ 8] = regs->tf_r8;
175 	gdb_regs[ 9] = regs->tf_r9;
176 	gdb_regs[10] = regs->tf_r10;
177 	gdb_regs[11] = regs->tf_r11;
178 	gdb_regs[12] = regs->tf_r12;
179 	gdb_regs[13] = regs->tf_r13;
180 	gdb_regs[14] = regs->tf_r14;
181 	gdb_regs[15] = regs->tf_r15;
182 	gdb_regs[16] = regs->tf_rip;
183 	gdb_regs[17] = regs->tf_rflags;
184 	gdb_regs[18] = regs->tf_cs;
185 	gdb_regs[19] = regs->tf_ss;
186 #else
187 	gdb_regs[ 0] = regs->tf_eax;
188 	gdb_regs[ 1] = regs->tf_ecx;
189 	gdb_regs[ 2] = regs->tf_edx;
190 	gdb_regs[ 3] = regs->tf_ebx;
191 	gdb_regs[ 5] = regs->tf_ebp;
192 	gdb_regs[ 6] = regs->tf_esi;
193 	gdb_regs[ 7] = regs->tf_edi;
194 	gdb_regs[ 8] = regs->tf_eip;
195 	gdb_regs[ 9] = regs->tf_eflags;
196 	gdb_regs[10] = regs->tf_cs;
197 	gdb_regs[12] = regs->tf_ds;
198 	gdb_regs[13] = regs->tf_es;
199 	gdb_regs[14] = regs->tf_fs;
200 	gdb_regs[15] = regs->tf_gs;
201 
202 	if (KERNELMODE(regs->tf_cs)) {
203 		/*
204 		 * Kernel mode - esp and ss not saved.
205 		 */
206 		gdb_regs[ 4] = (kgdb_reg_t)&regs->tf_esp; /* kernel stack
207 							     pointer */
208 		gdb_regs[11] = x86_getss();
209 	}
210 #endif
211 }
212 
213 /*
214  * Reverse the above.
215  */
216 void
kgdb_setregs(db_regs_t * regs,kgdb_reg_t * gdb_regs)217 kgdb_setregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
218 {
219 #ifdef __x86_64__
220 	regs->tf_rax = gdb_regs[ 0];
221 	regs->tf_rbx = gdb_regs[ 1];
222 	regs->tf_rcx = gdb_regs[ 2];
223 	regs->tf_rdx = gdb_regs[ 3];
224 	regs->tf_rsi = gdb_regs[ 4];
225 	regs->tf_rdi = gdb_regs[ 5];
226 	regs->tf_rbp = gdb_regs[ 6];
227 	regs->tf_rsp = gdb_regs[ 7];
228 	regs->tf_r8  = gdb_regs[ 8];
229 	regs->tf_r9  = gdb_regs[ 9];
230 	regs->tf_r10 = gdb_regs[10];
231 	regs->tf_r11 = gdb_regs[11];
232 	regs->tf_r12 = gdb_regs[12];
233 	regs->tf_r13 = gdb_regs[13];
234 	regs->tf_r14 = gdb_regs[14];
235 	regs->tf_r15 = gdb_regs[15];
236 	regs->tf_rip = gdb_regs[16];
237 	regs->tf_rflags = gdb_regs[17];
238 	regs->tf_cs  = gdb_regs[18];
239 	regs->tf_ss  = gdb_regs[19];
240 #else
241 	regs->tf_eax    = gdb_regs[ 0];
242 	regs->tf_ecx    = gdb_regs[ 1];
243 	regs->tf_edx    = gdb_regs[ 2];
244 	regs->tf_ebx    = gdb_regs[ 3];
245 	regs->tf_ebp    = gdb_regs[ 5];
246 	regs->tf_esi    = gdb_regs[ 6];
247 	regs->tf_edi    = gdb_regs[ 7];
248 	regs->tf_eip    = gdb_regs[ 8];
249 	regs->tf_eflags = gdb_regs[ 9];
250 	regs->tf_cs     = gdb_regs[10];
251 	regs->tf_ds     = gdb_regs[12];
252 	regs->tf_es     = gdb_regs[13];
253 
254 	if (KERNELMODE(regs->tf_cs) == 0) {
255 		/*
256 		 * Trapped in user mode - restore esp and ss.
257 		 */
258 		regs->tf_esp = gdb_regs[ 4];
259 		regs->tf_ss  = gdb_regs[11];
260 	}
261 #endif
262 }
263 
264 /*
265  * Trap into kgdb to wait for debugger to connect,
266  * noting on the console why nothing else is going on.
267  */
268 void
kgdb_connect(int verbose)269 kgdb_connect(int verbose)
270 {
271 	if (kgdb_dev == NODEV)
272 		return;
273 
274 	if (verbose)
275 		printf("kgdb waiting...");
276 
277 	breakpoint();
278 
279 	if (verbose)
280 		printf("connected.\n");
281 
282 	kgdb_debug_panic = 1;
283 }
284 
285 /*
286  * Decide what to do on panic.
287  * (This is called by panic, like Debugger())
288  */
289 void
kgdb_panic(void)290 kgdb_panic(void)
291 {
292 	if (kgdb_dev != NODEV && kgdb_debug_panic) {
293 		printf("entering kgdb\n");
294 		kgdb_connect(kgdb_active == 0);
295 	}
296 }
297