1 /*	$NetBSD: kgdb_machdep.c,v 1.10 2015/11/22 13:41:24 maxv Exp $	*/
2 
3 /*-
4  * Copyright (c) 1997 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.10 2015/11/22 13:41:24 maxv 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/pte.h>
74 #include <machine/trap.h>
75 
76 /*
77  * Determine if the memory at va..(va+len) is valid.
78  */
79 int
kgdb_acc(vaddr_t va,size_t len)80 kgdb_acc(vaddr_t va, size_t len)
81 {
82 	vaddr_t last_va;
83 	pt_entry_t *pte;
84 
85 	last_va = va + len;
86 	va  &= ~PGOFSET;
87 	last_va &= ~PGOFSET;
88 
89 	do {
90 		if (va < VM_MIN_KERNEL_ADDRESS)
91 			pte = vtopte(va);
92 		else
93 			pte = kvtopte(va);
94 		if ((*pte & PG_V) == 0)
95 			return (0);
96 		va += PAGE_SIZE;
97 	} while (va < last_va);
98 
99 	return (1);
100 }
101 
102 void
kgdb_entry_notice(int type,db_regs_t * regs)103 kgdb_entry_notice(int type, db_regs_t *regs)
104 {
105 	if (type == T_NMI)
106 		printf("NMI ... going to debugger\n");
107 }
108 
109 /*
110  * Translate a trap number into a unix compatible signal value.
111  * (gdb only understands unix signal numbers).
112  */
113 int
kgdb_signal(int type)114 kgdb_signal(int type)
115 {
116 	switch (type) {
117 	case T_NMI:
118 		return (SIGINT);
119 
120 	case T_ALIGNFLT:
121 		return (SIGILL);
122 
123 	case T_BPTFLT:
124 	case T_TRCTRAP:
125 		return (SIGTRAP);
126 
127 	case T_ASTFLT:
128 	case T_DOUBLEFLT:
129 		return (SIGEMT);
130 
131 	case T_ARITHTRAP:
132 	case T_DIVIDE:
133 	case T_OFLOW:
134 	case T_DNA:
135 	case T_FPOPFLT:
136 		return (SIGFPE);
137 
138 	case T_PRIVINFLT:
139 	case T_PROTFLT:
140 	case T_PAGEFLT:
141 	case T_TSSFLT:
142 	case T_SEGNPFLT:
143 	case T_STKFLT:
144 		return (SIGSEGV);
145 
146 	case T_BOUND:
147 		return (SIGURG);
148 
149 	default:
150 		return (SIGEMT);
151 	}
152 }
153 
154 /*
155  * Translate the values stored in the kernel regs struct to the format
156  * understood by gdb.
157  */
158 void
kgdb_getregs(db_regs_t * regs,kgdb_reg_t * gdb_regs)159 kgdb_getregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
160 {
161 
162 	gdb_regs[ 0] = regs->tf_rax;
163 	gdb_regs[ 1] = regs->tf_rbx;
164 	gdb_regs[ 2] = regs->tf_rcx;
165 	gdb_regs[ 3] = regs->tf_rdx;
166 	gdb_regs[ 4] = regs->tf_rsi;
167 	gdb_regs[ 5] = regs->tf_rdi;
168 	gdb_regs[ 6] = regs->tf_rbp;
169 	gdb_regs[ 7] = regs->tf_rsp;
170 	gdb_regs[ 8] = regs->tf_r8;
171 	gdb_regs[ 9] = regs->tf_r9;
172 	gdb_regs[10] = regs->tf_r10;
173 	gdb_regs[11] = regs->tf_r11;
174 	gdb_regs[12] = regs->tf_r12;
175 	gdb_regs[13] = regs->tf_r13;
176 	gdb_regs[14] = regs->tf_r14;
177 	gdb_regs[15] = regs->tf_r15;
178 	gdb_regs[16] = regs->tf_rip;
179 	gdb_regs[17] = regs->tf_rflags;
180 	gdb_regs[18] = regs->tf_cs;
181 	gdb_regs[19] = regs->tf_ss;
182 }
183 
184 /*
185  * Reverse the above.
186  */
187 void
kgdb_setregs(db_regs_t * regs,kgdb_reg_t * gdb_regs)188 kgdb_setregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
189 {
190 
191 	regs->tf_rax = gdb_regs[ 0];
192 	regs->tf_rbx = gdb_regs[ 1];
193 	regs->tf_rcx = gdb_regs[ 2];
194 	regs->tf_rdx = gdb_regs[ 3];
195 	regs->tf_rsi = gdb_regs[ 4];
196 	regs->tf_rdi = gdb_regs[ 5];
197 	regs->tf_rbp = gdb_regs[ 6];
198 	regs->tf_rsp = gdb_regs[ 7];
199 	regs->tf_r8  = gdb_regs[ 8];
200 	regs->tf_r9  = gdb_regs[ 9];
201 	regs->tf_r10 = gdb_regs[10];
202 	regs->tf_r11 = gdb_regs[11];
203 	regs->tf_r12 = gdb_regs[12];
204 	regs->tf_r13 = gdb_regs[13];
205 	regs->tf_r14 = gdb_regs[14];
206 	regs->tf_r15 = gdb_regs[15];
207 	regs->tf_rip = gdb_regs[16];
208 	regs->tf_rflags = gdb_regs[17];
209 	regs->tf_cs  = gdb_regs[18];
210 	regs->tf_ss  = gdb_regs[19];
211 }
212 
213 /*
214  * Trap into kgdb to wait for debugger to connect,
215  * noting on the console why nothing else is going on.
216  */
217 void
kgdb_connect(int verbose)218 kgdb_connect(int verbose)
219 {
220 
221 	if (kgdb_dev == NODEV)
222 		return;
223 
224 	if (verbose)
225 		printf("kgdb waiting...");
226 
227 	breakpoint();
228 
229 	if (verbose)
230 		printf("connected.\n");
231 
232 	kgdb_debug_panic = 1;
233 }
234 
235 /*
236  * Decide what to do on panic.
237  * (This is called by panic, like Debugger())
238  */
239 void
kgdb_panic(void)240 kgdb_panic(void)
241 {
242 	if (kgdb_dev != NODEV && kgdb_debug_panic) {
243 		printf("entering kgdb\n");
244 		kgdb_connect(kgdb_active == 0);
245 	}
246 }
247