xref: /plan9/sys/src/9/omap/trap.c (revision 9b7bf7df4595c26f1e9b67beb0c6e44c9876fb05)
1 /*
2  * omap3530 traps, exceptions, interrupts, system calls.
3  */
4 #include "u.h"
5 #include "../port/lib.h"
6 #include "mem.h"
7 #include "dat.h"
8 #include "fns.h"
9 #include "../port/error.h"
10 
11 #include "ureg.h"
12 #include "arm.h"
13 
14 enum {
15 	Nirqs = 96,
16 	Nvec = 8,		/* # of vectors at start of lexception.s */
17 	Bi2long = BI2BY * sizeof(long),
18 };
19 
20 extern int notify(Ureg*);
21 
22 extern int ldrexvalid;
23 
24 /* omap35x intc (aka mpu_intc) */
25 typedef struct Intrregs Intrregs;
26 struct Intrregs {
27 	/*
28 	 * the manual inserts "INTCPS_" before each register name;
29 	 * we'll just assume the prefix.
30 	 */
31 	uchar	_pad0[4*4];
32 	ulong	sysconfig;
33 	ulong	sysstatus;		/* ro */
34 	uchar	_pad1[0x40 - 0x18];
35 	ulong	sir_irq;		/* ro */
36 	ulong	sir_fiq;		/* ro */
37 	ulong	control;
38 	ulong	protection;
39 	ulong	idle;
40 	uchar	_pad2[0x60 - 0x54];
41 	ulong	irq_priority;
42 	ulong	fiq_priority;
43 	ulong	threshold;
44 	uchar	_pad3[0x80 - 0x6c];
45 	struct Bits {			/* bitmaps */
46 		ulong	itr;		/* ro: pending intrs (no mask) */
47 		ulong	mir;		/* interrupt mask: 1 means masked */
48 		ulong	mir_clear;	/* wo: 1 sets the bit */
49 		ulong	mir_set;	/* wo: 1 clears the bit */
50 		ulong	isr_set;	/* software interrupts */
51 		ulong	isr_clear;	/* wo */
52 		ulong	pending_irq;	/* ro */
53 		ulong	pending_fiq;	/* ro */
54 	} bits[3];			/* 3*32 = 96 (Nirqs) */
55 	ulong	ilr[Nirqs];
56 };
57 
58 enum {
59 	/* sysconfig bits */
60 	Softreset	= 1<<1,
61 
62 	/* sysstatus bits */
63 	Resetdone	= 1<<0,
64 
65 	/* sir_irq/fiq bits */
66 	Activeirq	= MASK(7),
67 
68 	/* control bits */
69 	Newirqagr	= 1<<0,
70 
71 	/* protection bits */
72 	Protection	= 1<<0,
73 
74 	/* irq/fiq_priority bits */
75 	Irqpriority	= MASK(6),
76 
77 	/* threshold bits */
78 	Prioritythreshold = MASK(8),
79 
80 	/* ilr bits */
81 	Priority	= MASK(8) - MASK(2),
82 };
83 
84 typedef struct Vctl Vctl;
85 typedef struct Vctl {
86 	Vctl*	next;		/* handlers on this vector */
87 	char	*name;		/* of driver, xallocated */
88 	void	(*f)(Ureg*, void*);	/* handler to call */
89 	void*	a;		/* argument to call it with */
90 } Vctl;
91 
92 static Lock vctllock;
93 static Vctl* vctl[Nirqs];
94 
95 /*
96  *   Layout at virtual address 0.
97  */
98 typedef struct Vpage0 {
99 	void	(*vectors[Nvec])(void);
100 	u32int	vtable[Nvec];
101 } Vpage0;
102 static Vpage0 *vpage0;
103 
104 uvlong ninterrupt;
105 uvlong ninterruptticks;
106 int irqtooearly = 1;
107 
108 static volatile int probing, trapped;
109 
110 static int
irqinuse(uint irq)111 irqinuse(uint irq)
112 {
113 	Intrregs *ip = (Intrregs *)PHYSINTC;
114 
115 	/*
116 	 * mir registers are odd: a 0 bit means intr unmasked (i.e.,
117 	 * we've unmasked it because it's in use).
118 	 */
119 	return (ip->bits[irq / Bi2long].mir & (1 << (irq % Bi2long))) == 0;
120 }
121 
122 static void
intcmask(uint irq)123 intcmask(uint irq)
124 {
125 	Intrregs *ip = (Intrregs *)PHYSINTC;
126 
127 	ip->bits[irq / Bi2long].mir_set = 1 << (irq % Bi2long);
128 	coherence();
129 }
130 
131 static void
intcunmask(uint irq)132 intcunmask(uint irq)
133 {
134 	Intrregs *ip = (Intrregs *)PHYSINTC;
135 
136 	ip->bits[irq / Bi2long].mir_clear = 1 << (irq % Bi2long);
137 	coherence();
138 }
139 
140 static void
intcmaskall(void)141 intcmaskall(void)
142 {
143 	int i;
144 	Intrregs *ip = (Intrregs *)PHYSINTC;
145 
146 	for (i = 0; i < 3; i++)
147 		ip->bits[i].mir_set = ~0;
148 	coherence();
149 }
150 
151 static void
intcunmaskall(void)152 intcunmaskall(void)
153 {
154 	int i;
155 	Intrregs *ip = (Intrregs *)PHYSINTC;
156 
157 	for (i = 0; i < 3; i++)
158 		ip->bits[i].mir_clear = ~0;
159 	coherence();
160 }
161 
162 static void
intcinvertall(void)163 intcinvertall(void)
164 {
165 	int i, s;
166 	ulong bits;
167 	Intrregs *ip = (Intrregs *)PHYSINTC;
168 
169 	s = splhi();
170 	for (i = 0; i < 3; i++) {
171 		bits = ip->bits[i].mir;
172 		ip->bits[i].mir_set = ~0;	/* mask all */
173 		coherence();
174 		/* clearing enables only those intrs. that were disabled */
175 		ip->bits[i].mir_clear = bits;
176 	}
177 	coherence();
178 	splx(s);
179 }
180 
181 static void
intrsave(ulong buf[3])182 intrsave(ulong buf[3])
183 {
184 	int i;
185 	Intrregs *ip = (Intrregs *)PHYSINTC;
186 
187 	for (i = 0; i < nelem(buf); i++)
188 		buf[i] = ip->bits[i].mir;
189 	coherence();
190 }
191 
192 static void
intrrestore(ulong buf[3])193 intrrestore(ulong buf[3])
194 {
195 	int i, s;
196 	Intrregs *ip = (Intrregs *)PHYSINTC;
197 
198 	s = splhi();
199 	for (i = 0; i < nelem(buf); i++) {
200 		ip->bits[i].mir_clear = ~0;	/* unmask all */
201 		coherence();
202 		ip->bits[i].mir_set = buf[i];	/* mask previously disabled */
203 	}
204 	coherence();
205 	splx(s);
206 }
207 
208 /*
209  *  set up for exceptions
210  */
211 void
trapinit(void)212 trapinit(void)
213 {
214 	int i;
215 	Intrregs *ip = (Intrregs *)PHYSINTC;
216 
217 	/* set up the exception vectors */
218 	vpage0 = (Vpage0*)HVECTORS;
219 	memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
220 	memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
221 	cacheuwbinv();
222 	l2cacheuwbinv();
223 
224 	/* set up the stacks for the interrupt modes */
225 	setr13(PsrMfiq, m->sfiq);
226 	setr13(PsrMirq, m->sirq);
227 	setr13(PsrMabt, m->sabt);
228 	setr13(PsrMund, m->sund);
229 #ifdef HIGH_SECURITY
230 	setr13(PsrMmon, m->smon);
231 #endif
232 	setr13(PsrMsys, m->ssys);
233 
234 	intcmaskall();
235 	ip->control = 0;
236 	ip->threshold = Prioritythreshold;	/* disable threshold */
237 	for (i = 0; i < Nirqs; i++)
238 		ip->ilr[i] = 0<<2 | 0;	/* all intrs pri 0 & to irq, not fiq */
239 	irqtooearly = 0;
240 	coherence();
241 }
242 
243 void
intrsoff(void)244 intrsoff(void)
245 {
246 	Intrregs *ip = (Intrregs *)PHYSINTC;
247 
248 	intcmaskall();
249 	ip->control = Newirqagr;	/* dismiss interrupt */
250 	coherence();
251 }
252 
253 /*
254  *  enable an irq interrupt
255  */
256 int
irqenable(int irq,void (* f)(Ureg *,void *),void * a,char * name)257 irqenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
258 {
259 	Vctl *v;
260 
261 	if(irq >= nelem(vctl) || irq < 0)
262 		panic("irqenable irq %d", irq);
263 
264 	if (irqtooearly) {
265 		iprint("irqenable for %d %s called too early\n", irq, name);
266 		return -1;
267 	}
268 	if(irqinuse(irq))
269 		print("irqenable: %s: irq %d already in use, chaining\n",
270 			name, irq);
271 	v = malloc(sizeof(Vctl));
272 	if (v == nil)
273 		panic("irqenable: malloc Vctl");
274 	v->f = f;
275 	v->a = a;
276 	v->name = malloc(strlen(name)+1);
277 	if (v->name == nil)
278 		panic("irqenable: malloc name");
279 	strcpy(v->name, name);
280 
281 	lock(&vctllock);
282 	v->next = vctl[irq];
283 	vctl[irq] = v;
284 
285 	intcunmask(irq);
286 	unlock(&vctllock);
287 	return 0;
288 }
289 
290 /*
291  *  disable an irq interrupt
292  */
293 int
irqdisable(int irq,void (* f)(Ureg *,void *),void * a,char * name)294 irqdisable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
295 {
296 	Vctl **vp, *v;
297 
298 	if(irq >= nelem(vctl) || irq < 0)
299 		panic("irqdisable irq %d", irq);
300 
301 	lock(&vctllock);
302 	for(vp = &vctl[irq]; v = *vp; vp = &v->next)
303 		if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
304 			print("irqdisable: remove %s\n", name);
305 			*vp = v->next;
306 			free(v);
307 			break;
308 		}
309 
310 	if(v == nil)
311 		print("irqdisable: irq %d, name %s not enabled\n", irq, name);
312 	if(vctl[irq] == nil){
313 		print("irqdisable: clear icmr bit %d\n", irq);
314 		intcmask(irq);
315 	}
316 	unlock(&vctllock);
317 
318 	return 0;
319 }
320 
321 /*
322  *  called by trap to handle access faults
323  */
324 static void
faultarm(Ureg * ureg,uintptr va,int user,int read)325 faultarm(Ureg *ureg, uintptr va, int user, int read)
326 {
327 	int n, insyscall;
328 	char buf[ERRMAX];
329 
330 	if(up == nil) {
331 		dumpregs(ureg);
332 		panic("fault: nil up in faultarm, accessing %#p", va);
333 	}
334 	insyscall = up->insyscall;
335 	up->insyscall = 1;
336 	n = fault(va, read);
337 	if(n < 0){
338 		if(!user){
339 			dumpregs(ureg);
340 			panic("fault: kernel accessing %#p", va);
341 		}
342 		/* don't dump registers; programs suicide all the time */
343 		snprint(buf, sizeof buf, "sys: trap: fault %s va=%#p",
344 			read? "read": "write", va);
345 		postnote(up, 1, buf, NDebug);
346 	}
347 	up->insyscall = insyscall;
348 }
349 
350 /*
351  *  called by trap to handle interrupts.
352  *  returns true iff a clock interrupt, thus maybe reschedule.
353  */
354 static int
irq(Ureg * ureg)355 irq(Ureg* ureg)
356 {
357 	int clockintr;
358 	uint irqno, handled, t, ticks = perfticks();
359 	Intrregs *ip = (Intrregs *)PHYSINTC;
360 	Vctl *v;
361 	static int nesting, lastirq = -1;
362 
363 	handled = 0;
364 	irqno = ip->sir_irq & Activeirq;
365 
366 	if (irqno >= 37 && irqno <= 47)		/* this is a clock intr? */
367 		m->inclockintr++;		/* yes, count nesting */
368 	lastirq = irqno;
369 
370 	if (irqno >= nelem(vctl)) {
371 		iprint("trap: irq %d >= # vectors (%d)\n", irqno, nelem(vctl));
372 		ip->control = Newirqagr;	/* dismiss interrupt */
373 		return 0;
374 	}
375 
376 	++nesting;
377 	for(v = vctl[irqno]; v != nil; v = v->next)
378 		if (v->f) {
379 			if (islo())
380 				panic("trap: pl0 before trap handler for %s",
381 					v->name);
382 			v->f(ureg, v->a);
383 			if (islo())
384 				panic("trap: %s lowered pl", v->name);
385 //			splhi();		/* in case v->f lowered pl */
386 			handled++;
387 		}
388 	if(!handled) {
389 		iprint("unexpected interrupt: irq %d", irqno);
390 		switch (irqno) {
391 		case 56:
392 		case 57:
393 			iprint(" (I⁲C)");
394 			break;
395 		case 83:
396 		case 86:
397 		case 94:
398 			iprint(" (MMC)");
399 			break;
400 		}
401 
402 		if(irqno < nelem(vctl)) {
403 			intcmask(irqno);
404 			iprint(", now masked");
405 		}
406 		iprint("\n");
407 	}
408 	t = perfticks();
409 	ninterrupt++;
410 	if(t < ticks)
411 		ninterruptticks += ticks-t;
412 	else
413 		ninterruptticks += t-ticks;
414 	ip->control = Newirqagr;	/* dismiss interrupt */
415 	coherence();
416 
417 	--nesting;
418 	clockintr = m->inclockintr == 1;
419 	if (irqno >= 37 && irqno <= 47)
420 		m->inclockintr--;
421 	return clockintr;
422 }
423 
424 /*
425  *  returns 1 if the instruction writes memory, 0 otherwise
426  */
427 int
writetomem(ulong inst)428 writetomem(ulong inst)
429 {
430 	/* swap always write memory */
431 	if((inst & 0x0FC00000) == 0x01000000)
432 		return 1;
433 
434 	/* loads and stores are distinguished by bit 20 */
435 	if(inst & (1<<20))
436 		return 0;
437 
438 	return 1;
439 }
440 
441 void	prgpmcerrs(void);
442 
443 /*
444  *  here on all exceptions other than syscall (SWI)
445  */
446 void
trap(Ureg * ureg)447 trap(Ureg *ureg)
448 {
449 	int clockintr, user, x, rv, rem;
450 	ulong inst, fsr;
451 	uintptr va;
452 	char buf[ERRMAX];
453 
454 	splhi();			/* paranoia */
455 	if(up != nil)
456 		rem = ((char*)ureg)-up->kstack;
457 	else
458 		rem = ((char*)ureg)-((char*)m+sizeof(Mach));
459 	if(rem < 1024) {
460 		iprint("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux\n",
461 			rem, up, ureg, ureg->pc);
462 		delay(1000);
463 		dumpstack();
464 		panic("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux",
465 			rem, up, ureg, ureg->pc);
466 	}
467 
468 	user = (ureg->psr & PsrMask) == PsrMusr;
469 	if(user){
470 		up->dbgreg = ureg;
471 		cycles(&up->kentry);
472 	}
473 
474 	/*
475 	 * All interrupts/exceptions should be resumed at ureg->pc-4,
476 	 * except for Data Abort which resumes at ureg->pc-8.
477 	 */
478 	if(ureg->type == (PsrMabt+1))
479 		ureg->pc -= 8;
480 	else
481 		ureg->pc -= 4;
482 
483 	clockintr = 0;		/* if set, may call sched() before return */
484 	switch(ureg->type){
485 	default:
486 		panic("unknown trap; type %#lux, psr mode %#lux", ureg->type,
487 			ureg->psr & PsrMask);
488 		break;
489 	case PsrMirq:
490 		ldrexvalid = 0;
491 		clockintr = irq(ureg);
492 		m->intr++;
493 		break;
494 	case PsrMabt:			/* prefetch fault */
495 		ldrexvalid = 0;
496 		x = ifsrget();
497 		fsr = (x>>7) & 0x8 | x & 0x7;
498 		switch(fsr){
499 		case 0x02:		/* instruction debug event (BKPT) */
500 			if(user){
501 				snprint(buf, sizeof buf, "sys: breakpoint");
502 				postnote(up, 1, buf, NDebug);
503 			}else{
504 				iprint("kernel bkpt: pc %#lux inst %#ux\n",
505 					ureg->pc, *(u32int*)ureg->pc);
506 				panic("kernel bkpt");
507 			}
508 			break;
509 		default:
510 			faultarm(ureg, ureg->pc, user, 1);
511 			break;
512 		}
513 		break;
514 	case PsrMabt+1:			/* data fault */
515 		ldrexvalid = 0;
516 		va = farget();
517 		inst = *(ulong*)(ureg->pc);
518 		/* bits 12 and 10 have to be concatenated with status */
519 		x = fsrget();
520 		fsr = (x>>7) & 0x20 | (x>>6) & 0x10 | x & 0xf;
521 		if (probing && !user) {
522 			if (trapped++ > 0)
523 				panic("trap: recursive probe %#lux", va);
524 			ureg->pc += 4;	/* continue at next instruction */
525 			break;
526 		}
527 		switch(fsr){
528 		default:
529 		case 0xa:		/* ? was under external abort */
530 			panic("unknown data fault, 6b fsr %#lux", fsr);
531 			break;
532 		case 0x0:
533 			panic("vector exception at %#lux", ureg->pc);
534 			break;
535 		case 0x1:		/* alignment fault */
536 		case 0x3:		/* access flag fault (section) */
537 			if(user){
538 				snprint(buf, sizeof buf,
539 					"sys: alignment: pc %#lux va %#p\n",
540 					ureg->pc, va);
541 				postnote(up, 1, buf, NDebug);
542 			} else
543 				panic("kernel alignment: pc %#lux va %#p", ureg->pc, va);
544 			break;
545 		case 0x2:
546 			panic("terminal exception at %#lux", ureg->pc);
547 			break;
548 		case 0x4:		/* icache maint fault */
549 		case 0x6:		/* access flag fault (page) */
550 		case 0x8:		/* precise external abort, non-xlat'n */
551 		case 0x28:
552 		case 0xc:		/* l1 translation, precise ext. abort */
553 		case 0x2c:
554 		case 0xe:		/* l2 translation, precise ext. abort */
555 		case 0x2e:
556 		case 0x16:		/* imprecise ext. abort, non-xlt'n */
557 		case 0x36:
558 			panic("external abort %#lux pc %#lux addr %#p",
559 				fsr, ureg->pc, va);
560 			break;
561 		case 0x1c:		/* l1 translation, precise parity err */
562 		case 0x1e:		/* l2 translation, precise parity err */
563 		case 0x18:		/* imprecise parity or ecc err */
564 			panic("translation parity error %#lux pc %#lux addr %#p",
565 				fsr, ureg->pc, va);
566 			break;
567 		case 0x5:		/* translation fault, no section entry */
568 		case 0x7:		/* translation fault, no page entry */
569 			faultarm(ureg, va, user, !writetomem(inst));
570 			break;
571 		case 0x9:
572 		case 0xb:
573 			/* domain fault, accessing something we shouldn't */
574 			if(user){
575 				snprint(buf, sizeof buf,
576 					"sys: access violation: pc %#lux va %#p\n",
577 					ureg->pc, va);
578 				postnote(up, 1, buf, NDebug);
579 			} else
580 				panic("kernel access violation: pc %#lux va %#p",
581 					ureg->pc, va);
582 			break;
583 		case 0xd:
584 		case 0xf:
585 			/* permission error, copy on write or real permission error */
586 			faultarm(ureg, va, user, !writetomem(inst));
587 			break;
588 		}
589 		break;
590 	case PsrMund:			/* undefined instruction */
591 		if(user){
592 			if(seg(up, ureg->pc, 0) != nil &&
593 			   *(u32int*)ureg->pc == 0xD1200070){
594 				snprint(buf, sizeof buf, "sys: breakpoint");
595 				postnote(up, 1, buf, NDebug);
596 			}else{
597 				/* look for floating point instructions to interpret */
598 				x = spllo();
599 				rv = fpiarm(ureg);
600 				splx(x);
601 				if(rv == 0){
602 					ldrexvalid = 0;
603 					snprint(buf, sizeof buf,
604 						"undefined instruction: pc %#lux\n",
605 						ureg->pc);
606 					postnote(up, 1, buf, NDebug);
607 				}
608 			}
609 		}else{
610 			if (ureg->pc & 3) {
611 				iprint("rounding fault pc %#lux down to word\n",
612 					ureg->pc);
613 				ureg->pc &= ~3;
614 			}
615 			iprint("undefined instruction: pc %#lux inst %#ux\n",
616 				ureg->pc, ((u32int*)ureg->pc)[-2]);
617 			panic("undefined instruction");
618 		}
619 		break;
620 	}
621 	splhi();
622 
623 	/* delaysched set because we held a lock or because our quantum ended */
624 	if(up && up->delaysched && clockintr){
625 		ldrexvalid = 0;
626 		sched();		/* can cause more traps */
627 		splhi();
628 	}
629 
630 	if(user){
631 		if(up->procctl || up->nnote)
632 			notify(ureg);
633 		kexit(ureg);
634 	}
635 }
636 
637 /*
638  * Fill in enough of Ureg to get a stack trace, and call a function.
639  * Used by debugging interface rdb.
640  */
641 void
callwithureg(void (* fn)(Ureg *))642 callwithureg(void (*fn)(Ureg*))
643 {
644 	Ureg ureg;
645 
646 	ureg.pc = getcallerpc(&fn);
647 	ureg.sp = PTR2UINT(&fn);
648 	fn(&ureg);
649 }
650 
651 static void
dumpstackwithureg(Ureg * ureg)652 dumpstackwithureg(Ureg *ureg)
653 {
654 	int x;
655 	uintptr l, v, i, estack;
656 	char *s;
657 
658 	dumpregs(ureg);
659 	if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
660 		iprint("dumpstack disabled\n");
661 		return;
662 	}
663 	iprint("dumpstack\n");
664 
665 	x = 0;
666 	x += iprint("ktrace /kernel/path %#.8lux %#.8lux %#.8lux # pc, sp, link\n",
667 		ureg->pc, ureg->sp, ureg->r14);
668 	delay(20);
669 	i = 0;
670 	if(up
671 	&& (uintptr)&l >= (uintptr)up->kstack
672 	&& (uintptr)&l <= (uintptr)up->kstack+KSTACK)
673 		estack = (uintptr)up->kstack+KSTACK;
674 	else if((uintptr)&l >= (uintptr)m->stack
675 	&& (uintptr)&l <= (uintptr)m+MACHSIZE)
676 		estack = (uintptr)m+MACHSIZE;
677 	else
678 		return;
679 	x += iprint("estackx %p\n", estack);
680 
681 	for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
682 		v = *(uintptr*)l;
683 		if((KTZERO < v && v < (uintptr)etext) || estack-l < 32){
684 			x += iprint("%.8p ", v);
685 			delay(20);
686 			i++;
687 		}
688 		if(i == 8){
689 			i = 0;
690 			x += iprint("\n");
691 			delay(20);
692 		}
693 	}
694 	if(i)
695 		iprint("\n");
696 }
697 
698 void
dumpstack(void)699 dumpstack(void)
700 {
701 	callwithureg(dumpstackwithureg);
702 }
703 
704 /*
705  * dump system control coprocessor registers
706  */
707 static void
dumpscr(void)708 dumpscr(void)
709 {
710 	iprint("0:\t%#8.8ux id\n", cpidget());
711 	iprint("\t%8.8#ux ct\n", cpctget());
712 	iprint("1:\t%#8.8ux control\n", controlget());
713 	iprint("2:\t%#8.8ux ttb\n", ttbget());
714 	iprint("3:\t%#8.8ux dac\n", dacget());
715 	iprint("4:\t(reserved)\n");
716 	iprint("5:\t%#8.8ux fsr\n", fsrget());
717 	iprint("6:\t%#8.8ux far\n", farget());
718 	iprint("7:\twrite-only cache\n");
719 	iprint("8:\twrite-only tlb\n");
720 	iprint("13:\t%#8.8ux pid\n", pidget());
721 	delay(10);
722 }
723 
724 /*
725  * dump general registers
726  */
727 static void
dumpgpr(Ureg * ureg)728 dumpgpr(Ureg* ureg)
729 {
730 	if(up != nil)
731 		iprint("cpu%d: registers for %s %lud\n",
732 			m->machno, up->text, up->pid);
733 	else
734 		iprint("cpu%d: registers for kernel\n", m->machno);
735 
736 	delay(20);
737 	iprint("%#8.8lux\tr0\n", ureg->r0);
738 	iprint("%#8.8lux\tr1\n", ureg->r1);
739 	iprint("%#8.8lux\tr2\n", ureg->r2);
740 	delay(20);
741 	iprint("%#8.8lux\tr3\n", ureg->r3);
742 	iprint("%#8.8lux\tr4\n", ureg->r4);
743 	iprint("%#8.8lux\tr5\n", ureg->r5);
744 	delay(20);
745 	iprint("%#8.8lux\tr6\n", ureg->r6);
746 	iprint("%#8.8lux\tr7\n", ureg->r7);
747 	iprint("%#8.8lux\tr8\n", ureg->r8);
748 	delay(20);
749 	iprint("%#8.8lux\tr9 (up)\n", ureg->r9);
750 	iprint("%#8.8lux\tr10 (m)\n", ureg->r10);
751 	iprint("%#8.8lux\tr11 (loader temporary)\n", ureg->r11);
752 	iprint("%#8.8lux\tr12 (SB)\n", ureg->r12);
753 	delay(20);
754 	iprint("%#8.8lux\tr13 (sp)\n", ureg->r13);
755 	iprint("%#8.8lux\tr14 (link)\n", ureg->r14);
756 	iprint("%#8.8lux\tr15 (pc)\n", ureg->pc);
757 	delay(20);
758 	iprint("%10.10lud\ttype\n", ureg->type);
759 	iprint("%#8.8lux\tpsr\n", ureg->psr);
760 	delay(20);
761 }
762 
763 void
dumpregs(Ureg * ureg)764 dumpregs(Ureg* ureg)
765 {
766 	dumpgpr(ureg);
767 	dumpscr();
768 }
769 
770 vlong
probeaddr(uintptr addr)771 probeaddr(uintptr addr)
772 {
773 	vlong v;
774 	static Lock fltlck;
775 
776 	ilock(&fltlck);
777 	trapped = 0;
778 	probing = 1;
779 	coherence();
780 
781 	v = *(ulong *)addr;	/* this may cause a fault */
782 	USED(probing);
783 	coherence();
784 
785 	probing = 0;
786 	coherence();
787 	if (trapped)
788 		v = -1;
789 	iunlock(&fltlck);
790 	return v;
791 }
792