1 /* $NetBSD: kgdb_machdep.c,v 1.22 2011/04/03 22:29:26 dyoung 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.22 2011/04/03 22:29:26 dyoung 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.
67 */
68
69 #include <sys/param.h>
70 #include <sys/kgdb.h>
71 #include <sys/systm.h>
72
73 #include <uvm/uvm_extern.h>
74
75 #include <machine/pte.h>
76 #include <machine/reg.h>
77 #include <machine/trap.h>
78
79 /*
80 * Determine if the memory at va..(va+len) is valid.
81 */
82 int
kgdb_acc(vaddr_t va,size_t len)83 kgdb_acc(vaddr_t va, size_t len)
84 {
85 vaddr_t last_va;
86 pt_entry_t *pte;
87
88 last_va = va + len;
89 va &= ~PGOFSET;
90 last_va &= ~PGOFSET;
91
92 do {
93 if (va < VM_MIN_KERNEL_ADDRESS)
94 pte = vtopte(va);
95 else
96 pte = kvtopte(va);
97 if ((*pte & PG_V) == 0)
98 return (0);
99 if (*pte & PG_PS)
100 va = (va & PG_LGFRAME) + NBPD_L2;
101 else
102 va += PAGE_SIZE;
103 } while (va < last_va);
104
105 return (1);
106 }
107
108 void
kgdb_entry_notice(int type,db_regs_t * regs)109 kgdb_entry_notice(int type, db_regs_t *regs)
110 {
111 if (type == T_NMI)
112 printf("NMI ... going to debugger\n");
113 }
114
115 /*
116 * Translate a trap number into a unix compatible signal value.
117 * (gdb only understands unix signal numbers).
118 */
119 int
kgdb_signal(int type)120 kgdb_signal(int type)
121 {
122 switch (type) {
123 case T_NMI:
124 return (SIGINT);
125
126 case T_ALIGNFLT:
127 return (SIGILL);
128
129 case T_BPTFLT:
130 case T_TRCTRAP:
131 return (SIGTRAP);
132
133 case T_ASTFLT:
134 case T_DOUBLEFLT:
135 return (SIGEMT);
136
137 case T_ARITHTRAP:
138 case T_DIVIDE:
139 case T_OFLOW:
140 case T_DNA:
141 case T_FPOPFLT:
142 return (SIGFPE);
143
144 case T_PRIVINFLT:
145 case T_PROTFLT:
146 case T_PAGEFLT:
147 case T_TSSFLT:
148 case T_SEGNPFLT:
149 case T_STKFLT:
150 return (SIGSEGV);
151
152 case T_BOUND:
153 return (SIGURG);
154
155 default:
156 return (SIGEMT);
157 }
158 }
159
160 /*
161 * Translate the values stored in the kernel regs struct to the format
162 * understood by gdb.
163 */
164 void
kgdb_getregs(db_regs_t * regs,kgdb_reg_t * gdb_regs)165 kgdb_getregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
166 {
167
168 gdb_regs[ 0] = regs->tf_eax;
169 gdb_regs[ 1] = regs->tf_ecx;
170 gdb_regs[ 2] = regs->tf_edx;
171 gdb_regs[ 3] = regs->tf_ebx;
172 gdb_regs[ 5] = regs->tf_ebp;
173 gdb_regs[ 6] = regs->tf_esi;
174 gdb_regs[ 7] = regs->tf_edi;
175 gdb_regs[ 8] = regs->tf_eip;
176 gdb_regs[ 9] = regs->tf_eflags;
177 gdb_regs[10] = regs->tf_cs;
178 gdb_regs[12] = regs->tf_ds;
179 gdb_regs[13] = regs->tf_es;
180 gdb_regs[14] = regs->tf_fs;
181 gdb_regs[15] = regs->tf_gs;
182
183 if (KERNELMODE(regs->tf_cs, regs->tf_eflags)) {
184 /*
185 * Kernel mode - esp and ss not saved.
186 */
187 gdb_regs[ 4] = (kgdb_reg_t)®s->tf_esp; /* kernel stack
188 pointer */
189 gdb_regs[11] = x86_getss();
190 }
191 }
192
193 /*
194 * Reverse the above.
195 */
196 void
kgdb_setregs(db_regs_t * regs,kgdb_reg_t * gdb_regs)197 kgdb_setregs(db_regs_t *regs, kgdb_reg_t *gdb_regs)
198 {
199
200 regs->tf_eax = gdb_regs[ 0];
201 regs->tf_ecx = gdb_regs[ 1];
202 regs->tf_edx = gdb_regs[ 2];
203 regs->tf_ebx = gdb_regs[ 3];
204 regs->tf_ebp = gdb_regs[ 5];
205 regs->tf_esi = gdb_regs[ 6];
206 regs->tf_edi = gdb_regs[ 7];
207 regs->tf_eip = gdb_regs[ 8];
208 regs->tf_eflags = gdb_regs[ 9];
209 regs->tf_cs = gdb_regs[10];
210 regs->tf_ds = gdb_regs[12];
211 regs->tf_es = gdb_regs[13];
212
213 if (KERNELMODE(regs->tf_cs, regs->tf_eflags) == 0) {
214 /*
215 * Trapped in user mode - restore esp and ss.
216 */
217 regs->tf_esp = gdb_regs[ 4];
218 regs->tf_ss = gdb_regs[11];
219 }
220 }
221
222 /*
223 * Trap into kgdb to wait for debugger to connect,
224 * noting on the console why nothing else is going on.
225 */
226 void
kgdb_connect(int verbose)227 kgdb_connect(int verbose)
228 {
229 if (kgdb_dev == NODEV)
230 return;
231
232 if (verbose)
233 printf("kgdb waiting...");
234
235 breakpoint();
236
237 if (verbose)
238 printf("connected.\n");
239
240 kgdb_debug_panic = 1;
241 }
242
243 /*
244 * Decide what to do on panic.
245 * (This is called by panic, like Debugger())
246 */
247 void
kgdb_panic(void)248 kgdb_panic(void)
249 {
250 if (kgdb_dev != NODEV && kgdb_debug_panic) {
251 printf("entering kgdb\n");
252 kgdb_connect(kgdb_active == 0);
253 }
254 }
255