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