need param.h for mbuf.h now
[unix-history] / usr / src / sys / vax / vax / kdb_machdep.c
CommitLineData
90e45b34 1/* @(#)kdb_machdep.c 7.3 (Berkeley) %G% */
ac6d052c
MK
2
3#include "param.h"
4#include "conf.h"
5#include "dir.h"
6#include "user.h"
7#include "proc.h"
8#include "uio.h"
9#include "systm.h"
10#include "reboot.h"
11#include "vmmac.h"
12#include "ioctl.h"
13#include "tty.h"
14
bd20ba5c
MK
15#include "cpu.h"
16#include "mtpr.h"
17#include "psl.h"
18#include "pte.h"
19#include "reg.h"
20#include "trap.h"
21#include "kdbparam.h"
ac6d052c
MK
22
23#define KDBSPACE 1024 /* 1K of memory for breakpoint table */
24static char kdbbuf[KDBSPACE];
25static char *kdbend = kdbbuf;
26/*
27 * Dynamically allocate space for the debugger.
28 */
29char *
30kdbmalloc(n)
31 u_int n;
32{
33 char *old = kdbend;
34
35 if (kdbend+n >= kdbbuf+KDBSPACE) {
36 printf("kdb: Out of space\n");
37 return ((char *)-1);
38 }
39 kdbend += n;
40 return (old);
41}
42
43/*
44 * Initialize the kernel debugger.
45 */
46kdb_init()
47{
48 char *symtab, *strtab;
49 int strsize;
50 extern int end;
51
52 kdbsetup();
53 if (bootesym > (char *)&end) {
54 symtab = (char *)&end + sizeof (int);
55#define symsize *(int *)&end
56 strtab = symtab + symsize;
57 strsize = roundup(*(int *)strtab, sizeof (int));
58 if (strtab + strsize == bootesym) {
59 printf("[Preserving %d bytes of symbol information]\n",
60 symsize + strsize);
61 kdbsetsym(symtab, strtab, strtab, strsize);
62 } else
63 printf("kdb_init: bad bootesym %x, calculated %x\n",
64 bootesym, strtab + strsize);
65 }
66 /*
67 * If boot flags indicate, force entry into the debugger.
68 */
69 if ((boothowto&(RB_HALT|RB_KDB)) == (RB_HALT|RB_KDB))
70 setsoftkdb();
71#undef symsize
72}
73
74int kdbactive = 0;
90e45b34 75#define ESC '\033'
bd20ba5c 76
ac6d052c
MK
77/*
78 * Process a keyboard interrupt from the console.
79 * We look for an escape sequence which signals
80 * a request to enter the debugger.
81 */
82kdbrintr(c, tp)
83 int c;
84 struct tty *tp;
85{
86 static int escape = 0;
87
88 c &= 0177; /* strip parity also */
89 if (!escape)
90 return (c == ESC && ++escape);
91 escape = 0;
92 /*
93 * Transfer control to the debugger only if the
94 * system was booted with RB_KDB and the trap
95 * enable flag (RB_NOYSNC) is set.
96 */
97 if ((boothowto&(RB_KDB|RB_NOSYNC)) != (RB_KDB|RB_NOSYNC) ||
bd20ba5c 98 (c != 'k' && c != 'K' && c != CTRL('k'))) {
ac6d052c
MK
99 (*linesw[tp->t_line].l_rint)(ESC, tp);
100 return (0);
101 }
102 if (!kdbactive)
103 setsoftkdb();
104 return (1);
105}
106
bd20ba5c
MK
107static int
108movpsl()
109{
110
111 asm(" movpsl r0"); /* XXX */
112}
113
ac6d052c
MK
114#define TYPE SP+1
115#define CODE PC-1
116#define USER 040
117static caddr_t kdbnofault; /* label for peek & poke */
118/*
119 * Field a kdb-related trap or fault.
120 */
121kdb_trap(apsl)
122 register int *apsl;
123{
124 register int *locr0, type;
125 int code, retval;
126 static int prevtype = -1, prevcode;
127 extern char *trap_type[];
128 extern int TRAP_TYPES;
129
130 /*
131 * Allow panic if the debugger is not enabled.
132 */
133 if ((boothowto&RB_KDB) == 0)
134 return (0);
135 locr0 = apsl - PS;
136 type = locr0[TYPE], code = locr0[CODE];
137 if (type == T_KDBTRAP && prevtype != -1) {
138 type = prevtype, code = prevcode;
139 prevtype = -1;
140 }
141 if (type != T_TRCTRAP && type != T_BPTFLT) {
142 /*
143 * Catch traps from kdbpeek and kdbpoke and perform
144 * non-local goto to error label setup in routines.
145 */
146 if (kdbnofault) {
147 locr0[PC] = (int)kdbnofault;
148 return (1);
149 }
150 type &= ~USER;
151 }
152 /*
153 * We prefer to run the debugger from the interrupt stack to
154 * avoid overflowing the kernel stack. Thus, if we're not
155 * currently on the interrupt stack and the ipl is low, schedule
156 * a software interrupt to force reentry on the interrupt stack
157 * immediately after the rei that'll take place on return.
158 */
159 if ((movpsl()&PSL_IS) == 0) {
160 int s = splhigh();
161 if (s < KDB_IPL) {
162 prevtype = type, prevcode = code;
163 setsoftkdb();
164 return (1);
165 }
166 splx(s);
167 printf("(from kernel stack)\n");
168 }
169 getpcb(locr0);
170 /*
171 * Mark debugger active and initiate input
172 * polling in the console device driver.
173 */
174 cnpoll(kdbactive = 1);
175 retval = kdb(type, code, noproc ? (struct proc *)0 : u.u_procp);
176 cnpoll(kdbactive = 0);
177 setpcb(locr0);
178 return (retval);
179}
180
181static char *codenames[] = {
182 "code = 0",
183 "integer overflow",
184 "integer divide by zero",
185 "floating overflow",
186 "floating/decimal divide by zero",
187 "floating underflow",
188 "decimal overflow",
189 "subscript out of range",
190 "floating overflow",
191 "floating divide by zero",
192 "floating undeflow"
193};
194#define NCODES (sizeof (codenames) / sizeof (codenames[0]))
195
196/*
197 * Announce a trap.
198 */
199kdbprinttrap(type, code)
200 int type, code;
201{
202
203 extern int TRAP_TYPES;
204 extern char *trap_type[];
205
206 if (type != T_TRCTRAP && type != T_BPTFLT) {
207 if (type < TRAP_TYPES && trap_type[type])
208 printf(trap_type[type]);
209 else
210 printf("trap type %d", type);
211 if (type == T_ARITHTRAP && (unsigned)code < NCODES)
212 printf(", %s", code);
213 else if (code)
214 printf(", code = %d", code);
215 printf("\n");
216 }
217}
218
219/*
220 * Read character from the console.
221 */
222kdbreadc(cp)
223 char *cp;
224{
225
226 *cp = cngetc();
227 return (1);
228}
229
230/*
231 * Write characters to the console.
232 */
233kdbwrite(cp, len)
234 register char *cp;
235 register int len;
236{
237
238 while (len-- > 0)
239 cnputc(*cp++);
240}
241
242/*
243 * Fetch a longword carefully.
244 */
245kdbpeek(addr)
246 register caddr_t addr;
247{
248 register long v = 0;
249
250 asm("movab 1f,_kdbnofault");
251 v = *(long *)addr;
252asm("1:");
253 kdbnofault = 0;
254 return (v);
255}
256
257/*
258 * Put a longword carefully.
259 */
260kdbpoke(addr, v)
261 register caddr_t addr;
262 long v;
263{
264 register int pn, *pte, opte = 0;
265 extern char Sysbase[], etext;
266
267 /*
268 * If we're writing to the kernel's text space,
269 * make the page writeable for the duration of
270 * the access.
271 */
272 if ((caddr_t)Sysbase <= addr && addr <= (caddr_t)&etext) {
273 pn = btop((int)addr &~ 0x80000000);
274 pte = (int *)&Sysmap[pn];
275 opte = *pte;
276 *pte = (*pte &~ PG_PROT)|PG_KW;
277 mtpr(TBIS, addr);
278 }
279 asm("movab 1f,_kdbnofault");
280 *(long *)addr = v;
281asm("1:");
282 kdbnofault = 0;
283 if (opte) {
284 *pte = opte;
285 mtpr(TBIS, addr);
286 }
287}
288
289static
290getpcb(locr0)
291 register int *locr0;
292{
293 extern struct pcb kdbpcb;
294 register struct pcb *pcb = &kdbpcb;
295
296 pcb->pcb_r0 = locr0[R0];
297 pcb->pcb_r1 = locr0[R1];
298 pcb->pcb_r2 = locr0[R2];
299 pcb->pcb_r3 = locr0[R3];
300 pcb->pcb_r4 = locr0[R4];
301 pcb->pcb_r5 = locr0[R5];
302 pcb->pcb_r6 = locr0[R6];
303 pcb->pcb_r7 = locr0[R7];
304 pcb->pcb_r8 = locr0[R8];
305 pcb->pcb_r9 = locr0[R9];
306 pcb->pcb_r10 = locr0[R10];
307 pcb->pcb_r11 = locr0[R11];
308 pcb->pcb_ap = locr0[AP];
309 pcb->pcb_fp = locr0[FP];
310 pcb->pcb_usp = locr0[SP];
311 pcb->pcb_pc = locr0[PC];
312 pcb->pcb_psl = locr0[PS];
313 pcb->pcb_ksp = mfpr(KSP);
314 pcb->pcb_esp = mfpr(ISP);
315 pcb->pcb_p0br = (struct pte *)mfpr(P0BR);
316 pcb->pcb_p0lr = mfpr(P0LR);
317 pcb->pcb_p1br = (struct pte *)mfpr(P1BR);
318 pcb->pcb_p1lr = mfpr(P1LR);
319}
320
321static
322setpcb(locr0)
323 register int *locr0;
324{
325 extern struct pcb kdbpcb;
326 register struct pcb *pcb = &kdbpcb;
327
328 locr0[R0] = pcb->pcb_r0;
329 locr0[R1] = pcb->pcb_r1;
330 locr0[R2] = pcb->pcb_r2;
331 locr0[R3] = pcb->pcb_r3;
332 locr0[R4] = pcb->pcb_r4;
333 locr0[R5] = pcb->pcb_r5;
334 locr0[R6] = pcb->pcb_r6;
335 locr0[R7] = pcb->pcb_r7;
336 locr0[R8] = pcb->pcb_r8;
337 locr0[R9] = pcb->pcb_r9;
338 locr0[R10] = pcb->pcb_r10;
339 locr0[R11] = pcb->pcb_r11;
bd20ba5c 340 locr0[AP] = pcb->pcb_ap;
ac6d052c
MK
341 locr0[FP] = pcb->pcb_fp;
342 locr0[SP] = pcb->pcb_usp;
343 locr0[PC] = pcb->pcb_pc;
344 locr0[PS] = pcb->pcb_psl;
ac6d052c 345}