xref: /original-bsd/sys/pmax/pmax/kadb.s (revision ce06cd54)
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Ralph Campbell.
7 *
8 * %sccs.include.redist.c%
9 *
10 *	@(#)kadb.s	7.1 (Berkeley) 03/01/92
11 */
12
13/*
14 * Define machine dependent primitives for kdb.
15 */
16
17#include "kdb/defs.h"
18#undef SP
19#include "machine/reg.h"
20#include "machine/trap.h"
21#include "machine/mips_opcode.h"
22
23REGLIST	kdbreglist[] = {
24	/* register_name, address */
25	"AT", &kdbpcb.pcb_regs[AST],
26	"v0", &kdbpcb.pcb_regs[V0],
27	"v1", &kdbpcb.pcb_regs[V1],
28	"t0", &kdbpcb.pcb_regs[T0],
29	"t1", &kdbpcb.pcb_regs[T1],
30	"t2", &kdbpcb.pcb_regs[T2],
31	"t3", &kdbpcb.pcb_regs[T3],
32	"t4", &kdbpcb.pcb_regs[T4],
33	"t5", &kdbpcb.pcb_regs[T5],
34	"t6", &kdbpcb.pcb_regs[T6],
35	"t7", &kdbpcb.pcb_regs[T7],
36	"t8", &kdbpcb.pcb_regs[T8],
37	"t9", &kdbpcb.pcb_regs[T9],
38	"s0", &kdbpcb.pcb_regs[S0],
39	"s1", &kdbpcb.pcb_regs[S1],
40	"s2", &kdbpcb.pcb_regs[S2],
41	"s3", &kdbpcb.pcb_regs[S3],
42	"s4", &kdbpcb.pcb_regs[S4],
43	"s5", &kdbpcb.pcb_regs[S5],
44	"s6", &kdbpcb.pcb_regs[S6],
45	"s7", &kdbpcb.pcb_regs[S7],
46	"s8", &kdbpcb.pcb_regs[S8],
47	"sp", &kdbpcb.pcb_regs[SP],
48	"gp", &kdbpcb.pcb_regs[GP],
49	"ra", &kdbpcb.pcb_regs[RA],
50	"mullo", &kdbpcb.pcb_regs[MULLO],
51	"mulhi", &kdbpcb.pcb_regs[MULHI],
52	"SR", &kdbpcb.pcb_regs[SR],
53	"pc", &kdbpcb.pcb_regs[PC],
54	"f0", &kdbpcb.pcb_regs[F0],
55	"f1", &kdbpcb.pcb_regs[F1],
56	"f2", &kdbpcb.pcb_regs[F2],
57	"f3", &kdbpcb.pcb_regs[F3],
58	"f4", &kdbpcb.pcb_regs[F4],
59	"f5", &kdbpcb.pcb_regs[F5],
60	"f6", &kdbpcb.pcb_regs[F6],
61	"f7", &kdbpcb.pcb_regs[F7],
62	"f8", &kdbpcb.pcb_regs[F8],
63	"f9", &kdbpcb.pcb_regs[F9],
64	"f10", &kdbpcb.pcb_regs[F10],
65	"f11", &kdbpcb.pcb_regs[F11],
66	"f12", &kdbpcb.pcb_regs[F12],
67	"f13", &kdbpcb.pcb_regs[F13],
68	"f14", &kdbpcb.pcb_regs[F14],
69	"f15", &kdbpcb.pcb_regs[F15],
70	"f16", &kdbpcb.pcb_regs[F16],
71	"f17", &kdbpcb.pcb_regs[F17],
72	"f18", &kdbpcb.pcb_regs[F18],
73	"f19", &kdbpcb.pcb_regs[F19],
74	"f20", &kdbpcb.pcb_regs[F20],
75	"f21", &kdbpcb.pcb_regs[F21],
76	"f22", &kdbpcb.pcb_regs[F22],
77	"f23", &kdbpcb.pcb_regs[F23],
78	"f24", &kdbpcb.pcb_regs[F24],
79	"f25", &kdbpcb.pcb_regs[F25],
80	"f26", &kdbpcb.pcb_regs[F26],
81	"f27", &kdbpcb.pcb_regs[F27],
82	"f28", &kdbpcb.pcb_regs[F28],
83	"f29", &kdbpcb.pcb_regs[F29],
84	"f30", &kdbpcb.pcb_regs[F30],
85	"f31", &kdbpcb.pcb_regs[F31],
86	0, 0
87};
88
89static char *op_name[64] = {
90/* 0 */	"spec",	"bcond","j",	"jal",	"beq",	"bne",	"blez",	"bgtz",
91/* 8 */	"addi",	"addiu","slti",	"sltiu","andi",	"ori",	"xori",	"lui",
92/*16 */	"cop0",	"cop1",	"cop2",	"cop3",	"op24",	"op25",	"op26",	"op27",
93/*24 */	"op30",	"op31",	"op32",	"op33",	"op34",	"op35",	"op36",	"op37",
94/*32 */	"lb",	"lh",	"lwl",	"lw",	"lbu",	"lhu",	"lwr",	"ld",
95/*40 */	"sb",	"sh",	"swl",	"sw",	"op54",	"op55",	"swr",	"sd",
96/*48 */	"lwc0",	"lwc1",	"lwc2",	"lwc3",	"ldc0",	"ldc1",	"ldc2",	"ldc3",
97/*56 */	"swc0",	"swc1",	"swc2",	"swc3",	"sdc0",	"sdc1",	"sdc2",	"sdc3"
98};
99
100static char *spec_name[64] = {
101/* 0 */	"sll",	"spec01","srl",	"sra",	"sllv",	"spec05","srlv","srav",
102/* 8 */	"jr",	"jalr",	"spec12","spec13","syscall","break","spec16","tas",
103/*16 */	"mfhi",	"mthi",	"mflo",	"mtlo",	"spec24","spec25","spec26","spec27",
104/*24 */	"mult",	"multu","div",	"divu",	"spec34","spec35","spec36","spec37",
105/*32 */	"add",	"addu",	"sub",	"subu",	"and",	"or",	"xor",	"nor",
106/*40 */	"spec50","spec51","slt","sltu",	"spec54","spec55","spec56","spec57",
107/*48 */	"spec60","spec61","spec62","spec63","spec64","spec65","spec66","spec67",
108/*56 */	"spec70","spec71","spec72","spec73","spec74","spec75","spec76","spec77"
109};
110
111static char *bcond_name[32] = {
112/* 0 */	"bltz",	"bgez", "?", "?", "?", "?", "?", "?",
113/* 8 */	"?", "?", "?", "?", "?", "?", "?", "?",
114/*16 */	"bltzal", "bgezal", "?", "?", "?", "?", "?", "?",
115/*24 */	"?", "?", "?", "?", "?", "?", "?", "?",
116};
117
118static char *cop1_name[64] = {
119/* 0 */	"fadd",	"fsub",	"fmpy",	"fdiv",	"fsqrt","fabs",	"fmov",	"fneg",
120/* 8 */	"fop08","fop09","fop0a","fop0b","fop0c","fop0d","fop0e","fop0f",
121/*16 */	"fop10","fop11","fop12","fop13","fop14","fop15","fop16","fop17",
122/*24 */	"fop18","fop19","fop1a","fop1b","fop1c","fop1d","fop1e","fop1f",
123/*32 */	"fcvts","fcvtd","fcvte","fop23","fcvtw","fop25","fop26","fop27",
124/*40 */	"fop28","fop29","fop2a","fop2b","fop2c","fop2d","fop2e","fop2f",
125/*48 */	"fcmp.f","fcmp.un","fcmp.eq","fcmp.ueq","fcmp.olt","fcmp.ult",
126	"fcmp.ole","fcmp.ule",
127/*56 */	"fcmp.sf","fcmp.ngle","fcmp.seq","fcmp.ngl","fcmp.lt","fcmp.nge",
128	"fcmp.le","fcmp.ngt"
129};
130
131static char *fmt_name[16] = {
132	"s",	"d",	"e",	"fmt3",
133	"w",	"fmt5",	"fmt6",	"fmt7",
134	"fmt8",	"fmt9",	"fmta",	"fmtb",
135	"fmtc",	"fmtd",	"fmte",	"fmtf"
136};
137
138static char *reg_name[32] = {
139	"zero",	"at",	"v0",	"v1",	"a0",	"a1",	"a2",	"a3",
140	"t0",	"t1",	"t2",	"t3",	"t4",	"t5",	"t6",	"t7",
141	"s0",	"s1",	"s2",	"s3",	"s4",	"s5",	"s6",	"s7",
142	"t8",	"t9",	"k0",	"k1",	"gp",	"sp",	"s8",	"ra"
143};
144
145static char *c0_opname[64] = {
146	"c0op00","tlbr",  "tlbwi", "c0op03","c0op04","c0op05","tlbwr", "c0op07",
147	"tlbp",  "c0op11","c0op12","c0op13","c0op14","c0op15","c0op16","c0op17",
148	"rfe",   "c0op21","c0op22","c0op23","c0op24","c0op25","c0op26","c0op27",
149	"c0op30","c0op31","c0op32","c0op33","c0op34","c0op35","c0op36","c0op37",
150	"c0op40","c0op41","c0op42","c0op43","c0op44","c0op45","c0op46","c0op47",
151	"c0op50","c0op51","c0op52","c0op53","c0op54","c0op55","c0op56","c0op57",
152	"c0op60","c0op61","c0op62","c0op63","c0op64","c0op65","c0op66","c0op67",
153	"c0op70","c0op71","c0op72","c0op73","c0op74","c0op75","c0op77","c0op77",
154};
155
156static char *c0_reg[32] = {
157	"index","random","tlblo","c0r3","context","c0r5","c0r6","c0r7",
158	"badvaddr","c0r9","tlbhi","c0r11","sr",	"cause","epc",	"c0r15",
159	"c0r16","c0r17","c0r18","c0r19","c0r20","c0r21","c0r22","c0r23",
160	"c0r24","c0r25","c0r26","c0r27","c0r28","c0r29","c0r30","c0r31"
161};
162
163/*
164 * Print the cause of the trap to kdb.
165 */
166void
167kdbprinttrap(causeReg, vadr)
168	unsigned causeReg, vadr;
169{
170	int type, pc;
171	extern char *trap_type[];
172
173	type = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
174
175	/* check to see if we are entering kdb via kdbpanic() */
176	pc = kdbpcb.pcb_regs[PC];
177	if (type == T_BREAK && pc < 0) {
178		if (kdbpeek(pc) == MACH_BREAK_KDB)
179			kdbpcb.pcb_regs[PC] = pc + 4;
180	}
181
182	kdbprintf("trap: %s\n", trap_type[type]);
183}
184
185unsigned kdb_ss_addr;
186unsigned kdb_ss_instr;
187
188void
189kdbsetsstep()
190{
191	register unsigned va;
192	register int *locr0 = kdbpcb.pcb_regs;
193	int i;
194
195	/* compute next address after current location */
196	va = MachEmulateBranch(locr0, locr0[PC], 0, 1);
197	if (kdb_ss_addr) {
198		kdbprintf("kdbsetsstep: breakpoint already set at %x (va %x)\n",
199			kdb_ss_addr, va);
200		return;
201	}
202	kdb_ss_addr = va;
203
204	if ((int)va < 0) {
205		/* kernel address */
206		kdb_ss_instr = kdbpeek(va);
207		kdbpoke((caddr_t)va, MACH_BREAK_SSTEP);
208		kdbprintf("SS: breakpoint set at %x: %x (pc %x)\n",
209			kdb_ss_addr, kdb_ss_instr, locr0[PC]); /* XXX */
210		return;
211	}
212
213	kdb_ss_instr = fuiword(va);
214	i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
215	if (i < 0) {
216		register struct proc *p = curproc;
217		vm_offset_t sa, ea;
218		int rv;
219
220		sa = trunc_page((vm_offset_t)va);
221		ea = round_page((vm_offset_t)va+sizeof(int)-1);
222		rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
223			VM_PROT_DEFAULT, FALSE);
224		if (rv == KERN_SUCCESS) {
225			i = suiword((caddr_t)va, MACH_BREAK_SSTEP);
226			(void) vm_map_protect(&p->p_vmspace->vm_map,
227				sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);
228		}
229	}
230	if (i < 0)
231		return;
232	kdbprintf("SS: breakpoint set at %x: %x (pc %x)\n",
233		kdb_ss_addr, kdb_ss_instr, locr0[PC]); /* XXX */
234}
235
236void
237kdbclrsstep()
238{
239	register unsigned cr, pc, va;
240	unsigned instr;
241	int i;
242
243	/* ignore this trap if it is not a break trap */
244	cr = kdbvar[kdbvarchk('t')];
245	if ((cr & MACH_CR_EXC_CODE) != (T_BREAK << MACH_CR_EXC_CODE_SHIFT))
246		return;
247
248	/* fix pc if break instruction is in the delay slot */
249	pc = kdbpcb.pcb_regs[PC];
250	if ((int)cr < 0)
251		pc += 4;
252
253	/* check to be sure its the one we are expecting */
254	va = kdb_ss_addr;
255	if (!va || va != pc)
256		return;
257
258	/* read break instruction */
259	instr = kdbpeek(va);
260	printf("BREAK %x: %x\n", va, instr); /* XXX */
261	if (instr != MACH_BREAK_SSTEP)
262		return;
263
264	if ((int)va < 0) {
265		/* kernel address */
266		kdbpoke((caddr_t)va, kdb_ss_instr);
267		kdb_ss_addr = 0;
268		return;
269	}
270
271	/* restore original instruction and clear BP */
272	i = suiword((caddr_t)va, kdb_ss_instr);
273	if (i < 0) {
274		register struct proc *p = curproc;
275		vm_offset_t sa, ea;
276		int rv;
277
278		sa = trunc_page((vm_offset_t)va);
279		ea = round_page((vm_offset_t)va+sizeof(int)-1);
280		rv = vm_map_protect(&p->p_vmspace->vm_map, sa, ea,
281			VM_PROT_DEFAULT, FALSE);
282		if (rv == KERN_SUCCESS) {
283			i = suiword((caddr_t)va, p->p_md.md_ss_instr);
284			(void) vm_map_protect(&p->p_vmspace->vm_map,
285				sa, ea, VM_PROT_READ|VM_PROT_EXECUTE,
286				FALSE);
287		}
288	}
289	if (i < 0)
290		kdbprintf("can't clear break at %x\n", va);
291	kdb_ss_addr = 0;
292}
293
294void
295kdbreadc(lp)
296	char *lp;
297{
298	int c;
299
300	c = cngetc();
301	if (c == '\r')
302		c = '\n';
303	*lp = c;
304}
305
306void
307kdbwrite(lp, len)
308	char *lp;
309	int len;
310{
311	while (len-- > 0)
312		cnputc(*lp++);
313}
314
315/* ARGSUSED */
316void
317kdbprintins(space, ins)
318	int space;
319	long ins;
320{
321	InstFmt i;
322
323	i.word = ins;
324
325	switch (i.JType.op) {
326	case OP_SPECIAL:
327		if (i.word == 0) {
328			kdbprintf("nop");
329			break;
330		}
331		if (i.RType.func == OP_ADDU && i.RType.rt == 0) {
332			kdbprintf("move\t%s,%s",
333				reg_name[i.RType.rd],
334				reg_name[i.RType.rs]);
335			break;
336		}
337		kdbprintf("%s", spec_name[i.RType.func]);
338		switch (i.RType.func) {
339		case OP_SLL:
340		case OP_SRL:
341		case OP_SRA:
342			kdbprintf("\t%s,%s,%d",
343				reg_name[i.RType.rd],
344				reg_name[i.RType.rt],
345				i.RType.shamt);
346			break;
347
348		case OP_SLLV:
349		case OP_SRLV:
350		case OP_SRAV:
351			kdbprintf("\t%s,%s,%s",
352				reg_name[i.RType.rd],
353				reg_name[i.RType.rt],
354				reg_name[i.RType.rs]);
355			break;
356
357		case OP_MFHI:
358		case OP_MFLO:
359			kdbprintf("\t%s", reg_name[i.RType.rd]);
360			break;
361
362		case OP_JR:
363		case OP_JALR:
364		case OP_MTLO:
365		case OP_MTHI:
366			kdbprintf("\t%s", reg_name[i.RType.rs]);
367			break;
368
369		case OP_MULT:
370		case OP_MULTU:
371		case OP_DIV:
372		case OP_DIVU:
373			kdbprintf("\t%s,%s",
374				reg_name[i.RType.rs],
375				reg_name[i.RType.rt]);
376			break;
377
378		case OP_SYSCALL:
379			break;
380		case OP_BREAK:
381			kdbprintf("\t%d", (i.RType.rs << 5) | i.RType.rt);
382			break;
383
384		default:
385			kdbprintf("\t%s,%s,%s",
386				reg_name[i.RType.rd],
387				reg_name[i.RType.rs],
388				reg_name[i.RType.rt]);
389		};
390		break;
391
392	case OP_BCOND:
393		kdbprintf("%s\t%s,", bcond_name[i.IType.rt],
394			reg_name[i.IType.rs]);
395		goto pr_displ;
396
397	case OP_BLEZ:
398	case OP_BGTZ:
399		kdbprintf("%s\t%s,", op_name[i.IType.op],
400			reg_name[i.IType.rs]);
401		goto pr_displ;
402
403	case OP_BEQ:
404		if (i.IType.rs == 0 && i.IType.rt == 0) {
405			kdbprintf("b\t");
406			goto pr_displ;
407		}
408		/* FALLTHROUGH */
409	case OP_BNE:
410		kdbprintf("%s\t%s,%s,", op_name[i.IType.op],
411			reg_name[i.IType.rs],
412			reg_name[i.IType.rt]);
413	pr_displ:
414		kdbpsymoff(kdbdot + 4 + ((short)i.IType.imm << 2), ISYM, "");
415		break;
416
417	case OP_COP0:
418		switch (i.RType.rs) {
419		case OP_BCx:
420		case OP_BCy:
421			kdbprintf("bc0%c\t",
422				"ft"[i.RType.rt & COPz_BC_TF_MASK]);
423			goto pr_displ;
424
425		case OP_MT:
426			kdbprintf("mtc0\t%s,%s",
427				reg_name[i.RType.rt],
428				c0_reg[i.RType.rd]);
429			break;
430
431		case OP_MF:
432			kdbprintf("mfc0\t%s,%s",
433				reg_name[i.RType.rt],
434				c0_reg[i.RType.rd]);
435			break;
436
437		default:
438			kdbprintf("%s", c0_opname[i.FRType.func]);
439		};
440		break;
441
442	case OP_COP1:
443		switch (i.RType.rs) {
444		case OP_BCx:
445		case OP_BCy:
446			kdbprintf("bc1%c\t",
447				"ft"[i.RType.rt & COPz_BC_TF_MASK]);
448			goto pr_displ;
449
450		case OP_MT:
451			kdbprintf("mtc1\t%s,f%d",
452				reg_name[i.RType.rt],
453				i.RType.rd);
454			break;
455
456		case OP_MF:
457			kdbprintf("mfc1\t%s,f%d",
458				reg_name[i.RType.rt],
459				i.RType.rd);
460			break;
461
462		case OP_CT:
463			kdbprintf("ctc1\t%s,f%d",
464				reg_name[i.RType.rt],
465				i.RType.rd);
466			break;
467
468		case OP_CF:
469			kdbprintf("cfc1\t%s,f%d",
470				reg_name[i.RType.rt],
471				i.RType.rd);
472			break;
473
474		default:
475			kdbprintf("%s.%s\tf%d,f%d,f%d",
476				cop1_name[i.FRType.func],
477				fmt_name[i.FRType.fmt],
478				i.FRType.fd, i.FRType.fs, i.FRType.ft);
479		};
480		break;
481
482	case OP_J:
483	case OP_JAL:
484		kdbprintf("%s\t", op_name[i.JType.op]);
485		kdbpsymoff((kdbdot & 0xF0000000) | (i.JType.target << 2),
486			ISYM, "");
487		break;
488
489	case OP_LWC1:
490	case OP_SWC1:
491		kdbprintf("%s\tf%d,", op_name[i.IType.op],
492			i.IType.rt);
493		goto loadstore;
494
495	case OP_LB:
496	case OP_LH:
497	case OP_LW:
498	case OP_LBU:
499	case OP_LHU:
500	case OP_SB:
501	case OP_SH:
502	case OP_SW:
503		kdbprintf("%s\t%s,", op_name[i.IType.op],
504			reg_name[i.IType.rt]);
505	loadstore:
506		kdbprintf("%d(%s)", (short)i.IType.imm,
507			reg_name[i.IType.rs]);
508		break;
509
510	case OP_ORI:
511	case OP_XORI:
512		if (i.IType.rs == 0) {
513			kdbprintf("li\t%s,0x%X",
514				reg_name[i.IType.rt],
515				i.IType.imm);
516			break;
517		}
518		/* FALLTHROUGH */
519	case OP_ANDI:
520		kdbprintf("%s\t%s,%s,0x%X", op_name[i.IType.op],
521			reg_name[i.IType.rt],
522			reg_name[i.IType.rs],
523			i.IType.imm);
524		break;
525
526	case OP_LUI:
527		kdbprintf("%s\t%s,0x%X", op_name[i.IType.op],
528			reg_name[i.IType.rt],
529			i.IType.imm);
530		break;
531
532	case OP_ADDI:
533	case OP_ADDIU:
534		if (i.IType.rs == 0) {
535 			kdbprintf("li\t%s,%D",
536				reg_name[i.IType.rt],
537				(short)i.IType.imm);
538			break;
539		}
540		/* FALLTHROUGH */
541	default:
542		kdbprintf("%s\t%s,%s,%D", op_name[i.IType.op],
543			reg_name[i.IType.rt],
544			reg_name[i.IType.rs],
545			(short)i.IType.imm);
546	}
547	kdbdotinc = 4;
548}
549
550/*
551 * Print a stack backtrace.
552 */
553void
554kdbstacktrace(printlocals)
555	int printlocals;
556{
557}
558
559/*
560 * Very simple memory allocator for kdb.
561 */
562char *
563kdbmalloc(size)
564	int size;
565{
566	static char buffer[4096];
567	static char *bufp = buffer;
568	char *p;
569
570	/* round size up to sizeof(int) */
571	size = (size + sizeof(int) - 1) & ~(sizeof(int) - 1);
572	p = bufp;
573	bufp = p + size;
574	return (p);
575}
576
577/*
578 * Machine dependent printing '$'.
579 * Return zero if modif character not recognized.
580 */
581kdbprintmachdep(modif)
582{
583	register int i, j;
584	extern int tlbhi, tlblo;
585
586	switch (modif) {
587	case 'p':
588	case 'P': /* print TLB entries */
589		if (kdbadrflg) {
590			i = kdbadrval;
591			if (i < 0 || i > VMMACH_NUM_TLB_ENTRIES) {
592				extern char *kdbBADMOD;
593
594				kdberror(kdbBADMOD);
595				break;
596			}
597			if (kdbcntflg == 0)
598				j = i + 1;
599			else {
600				j = i + kdbcntval;
601				if (j > VMMACH_NUM_TLB_ENTRIES)
602					j = VMMACH_NUM_TLB_ENTRIES;
603			}
604		} else {
605			i = 0;
606			j = VMMACH_NUM_TLB_ENTRIES;
607		}
608		for (; i < j; i++) {
609			MachTLBRead(i);
610			if (modif == 'p' && !(tlblo & PG_V))
611				continue;
612			kdbprintf("TLB %2d: hi %8X low %8X\n", i, tlbhi, tlblo);
613		}
614		kdbprintf("TLB PID %x\n", MachTLBGetPID());
615		break;
616
617	case 'f': /* find a TLB entry by virtaddr */
618	case 'F': /* find a TLB entry by physaddr */
619		j = kdbdot & PG_FRAME;
620		for (i = 0; i < VMMACH_NUM_TLB_ENTRIES; i++) {
621			MachTLBRead(i);
622			if (modif == 'f') {
623				if ((tlbhi & PG_FRAME) != j)
624					continue;
625			} else {
626				if ((tlblo & PG_FRAME) != j)
627					continue;
628			}
629			kdbprintf("TLB %2d: hi %8X low %8X\n", i, tlbhi, tlblo);
630		}
631		break;
632
633	default:
634		return (0);
635	}
636	return (1);
637}
638