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