xref: /plan9/sys/src/9/omap/trap.c (revision 9b7bf7df4595c26f1e9b67beb0c6e44c9876fb05)
18e32b400SDavid du Colombier /*
28e32b400SDavid du Colombier  * omap3530 traps, exceptions, interrupts, system calls.
38e32b400SDavid du Colombier  */
48e32b400SDavid du Colombier #include "u.h"
58e32b400SDavid du Colombier #include "../port/lib.h"
68e32b400SDavid du Colombier #include "mem.h"
78e32b400SDavid du Colombier #include "dat.h"
88e32b400SDavid du Colombier #include "fns.h"
98e32b400SDavid du Colombier #include "../port/error.h"
108e32b400SDavid du Colombier 
118e32b400SDavid du Colombier #include "ureg.h"
128e32b400SDavid du Colombier #include "arm.h"
138e32b400SDavid du Colombier 
148e32b400SDavid du Colombier enum {
158e32b400SDavid du Colombier 	Nirqs = 96,
168e32b400SDavid du Colombier 	Nvec = 8,		/* # of vectors at start of lexception.s */
178e32b400SDavid du Colombier 	Bi2long = BI2BY * sizeof(long),
188e32b400SDavid du Colombier };
198e32b400SDavid du Colombier 
208e32b400SDavid du Colombier extern int notify(Ureg*);
218e32b400SDavid du Colombier 
228e32b400SDavid du Colombier extern int ldrexvalid;
238e32b400SDavid du Colombier 
248e32b400SDavid du Colombier /* omap35x intc (aka mpu_intc) */
258e32b400SDavid du Colombier typedef struct Intrregs Intrregs;
268e32b400SDavid du Colombier struct Intrregs {
278e32b400SDavid du Colombier 	/*
288e32b400SDavid du Colombier 	 * the manual inserts "INTCPS_" before each register name;
298e32b400SDavid du Colombier 	 * we'll just assume the prefix.
308e32b400SDavid du Colombier 	 */
318e32b400SDavid du Colombier 	uchar	_pad0[4*4];
328e32b400SDavid du Colombier 	ulong	sysconfig;
338e32b400SDavid du Colombier 	ulong	sysstatus;		/* ro */
348e32b400SDavid du Colombier 	uchar	_pad1[0x40 - 0x18];
358e32b400SDavid du Colombier 	ulong	sir_irq;		/* ro */
368e32b400SDavid du Colombier 	ulong	sir_fiq;		/* ro */
378e32b400SDavid du Colombier 	ulong	control;
388e32b400SDavid du Colombier 	ulong	protection;
398e32b400SDavid du Colombier 	ulong	idle;
408e32b400SDavid du Colombier 	uchar	_pad2[0x60 - 0x54];
418e32b400SDavid du Colombier 	ulong	irq_priority;
428e32b400SDavid du Colombier 	ulong	fiq_priority;
438e32b400SDavid du Colombier 	ulong	threshold;
448e32b400SDavid du Colombier 	uchar	_pad3[0x80 - 0x6c];
458e32b400SDavid du Colombier 	struct Bits {			/* bitmaps */
468e32b400SDavid du Colombier 		ulong	itr;		/* ro: pending intrs (no mask) */
478e32b400SDavid du Colombier 		ulong	mir;		/* interrupt mask: 1 means masked */
488e32b400SDavid du Colombier 		ulong	mir_clear;	/* wo: 1 sets the bit */
498e32b400SDavid du Colombier 		ulong	mir_set;	/* wo: 1 clears the bit */
508e32b400SDavid du Colombier 		ulong	isr_set;	/* software interrupts */
518e32b400SDavid du Colombier 		ulong	isr_clear;	/* wo */
528e32b400SDavid du Colombier 		ulong	pending_irq;	/* ro */
538e32b400SDavid du Colombier 		ulong	pending_fiq;	/* ro */
548e32b400SDavid du Colombier 	} bits[3];			/* 3*32 = 96 (Nirqs) */
558e32b400SDavid du Colombier 	ulong	ilr[Nirqs];
568e32b400SDavid du Colombier };
578e32b400SDavid du Colombier 
588e32b400SDavid du Colombier enum {
598e32b400SDavid du Colombier 	/* sysconfig bits */
608e32b400SDavid du Colombier 	Softreset	= 1<<1,
618e32b400SDavid du Colombier 
628e32b400SDavid du Colombier 	/* sysstatus bits */
638e32b400SDavid du Colombier 	Resetdone	= 1<<0,
648e32b400SDavid du Colombier 
658e32b400SDavid du Colombier 	/* sir_irq/fiq bits */
668e32b400SDavid du Colombier 	Activeirq	= MASK(7),
678e32b400SDavid du Colombier 
688e32b400SDavid du Colombier 	/* control bits */
698e32b400SDavid du Colombier 	Newirqagr	= 1<<0,
708e32b400SDavid du Colombier 
718e32b400SDavid du Colombier 	/* protection bits */
728e32b400SDavid du Colombier 	Protection	= 1<<0,
738e32b400SDavid du Colombier 
748e32b400SDavid du Colombier 	/* irq/fiq_priority bits */
758e32b400SDavid du Colombier 	Irqpriority	= MASK(6),
768e32b400SDavid du Colombier 
778e32b400SDavid du Colombier 	/* threshold bits */
788e32b400SDavid du Colombier 	Prioritythreshold = MASK(8),
798e32b400SDavid du Colombier 
808e32b400SDavid du Colombier 	/* ilr bits */
818e32b400SDavid du Colombier 	Priority	= MASK(8) - MASK(2),
828e32b400SDavid du Colombier };
838e32b400SDavid du Colombier 
848e32b400SDavid du Colombier typedef struct Vctl Vctl;
858e32b400SDavid du Colombier typedef struct Vctl {
868e32b400SDavid du Colombier 	Vctl*	next;		/* handlers on this vector */
878e32b400SDavid du Colombier 	char	*name;		/* of driver, xallocated */
888e32b400SDavid du Colombier 	void	(*f)(Ureg*, void*);	/* handler to call */
898e32b400SDavid du Colombier 	void*	a;		/* argument to call it with */
908e32b400SDavid du Colombier } Vctl;
918e32b400SDavid du Colombier 
928e32b400SDavid du Colombier static Lock vctllock;
938e32b400SDavid du Colombier static Vctl* vctl[Nirqs];
948e32b400SDavid du Colombier 
958e32b400SDavid du Colombier /*
968e32b400SDavid du Colombier  *   Layout at virtual address 0.
978e32b400SDavid du Colombier  */
988e32b400SDavid du Colombier typedef struct Vpage0 {
998e32b400SDavid du Colombier 	void	(*vectors[Nvec])(void);
1008e32b400SDavid du Colombier 	u32int	vtable[Nvec];
1018e32b400SDavid du Colombier } Vpage0;
1028e32b400SDavid du Colombier static Vpage0 *vpage0;
1038e32b400SDavid du Colombier 
1048e32b400SDavid du Colombier uvlong ninterrupt;
1058e32b400SDavid du Colombier uvlong ninterruptticks;
1068e32b400SDavid du Colombier int irqtooearly = 1;
1078e32b400SDavid du Colombier 
1088e32b400SDavid du Colombier static volatile int probing, trapped;
1098e32b400SDavid du Colombier 
1108e32b400SDavid du Colombier static int
irqinuse(uint irq)1118e32b400SDavid du Colombier irqinuse(uint irq)
1128e32b400SDavid du Colombier {
1138e32b400SDavid du Colombier 	Intrregs *ip = (Intrregs *)PHYSINTC;
1148e32b400SDavid du Colombier 
1158e32b400SDavid du Colombier 	/*
1168e32b400SDavid du Colombier 	 * mir registers are odd: a 0 bit means intr unmasked (i.e.,
1178e32b400SDavid du Colombier 	 * we've unmasked it because it's in use).
1188e32b400SDavid du Colombier 	 */
1198e32b400SDavid du Colombier 	return (ip->bits[irq / Bi2long].mir & (1 << (irq % Bi2long))) == 0;
1208e32b400SDavid du Colombier }
1218e32b400SDavid du Colombier 
1228e32b400SDavid du Colombier static void
intcmask(uint irq)1238e32b400SDavid du Colombier intcmask(uint irq)
1248e32b400SDavid du Colombier {
1258e32b400SDavid du Colombier 	Intrregs *ip = (Intrregs *)PHYSINTC;
1268e32b400SDavid du Colombier 
1278e32b400SDavid du Colombier 	ip->bits[irq / Bi2long].mir_set = 1 << (irq % Bi2long);
1288e32b400SDavid du Colombier 	coherence();
1298e32b400SDavid du Colombier }
1308e32b400SDavid du Colombier 
1318e32b400SDavid du Colombier static void
intcunmask(uint irq)1328e32b400SDavid du Colombier intcunmask(uint irq)
1338e32b400SDavid du Colombier {
1348e32b400SDavid du Colombier 	Intrregs *ip = (Intrregs *)PHYSINTC;
1358e32b400SDavid du Colombier 
1368e32b400SDavid du Colombier 	ip->bits[irq / Bi2long].mir_clear = 1 << (irq % Bi2long);
1378e32b400SDavid du Colombier 	coherence();
1388e32b400SDavid du Colombier }
1398e32b400SDavid du Colombier 
1408e32b400SDavid du Colombier static void
intcmaskall(void)1418e32b400SDavid du Colombier intcmaskall(void)
1428e32b400SDavid du Colombier {
1438e32b400SDavid du Colombier 	int i;
1448e32b400SDavid du Colombier 	Intrregs *ip = (Intrregs *)PHYSINTC;
1458e32b400SDavid du Colombier 
1468e32b400SDavid du Colombier 	for (i = 0; i < 3; i++)
1478e32b400SDavid du Colombier 		ip->bits[i].mir_set = ~0;
1488e32b400SDavid du Colombier 	coherence();
1498e32b400SDavid du Colombier }
1508e32b400SDavid du Colombier 
1518e32b400SDavid du Colombier static void
intcunmaskall(void)1528e32b400SDavid du Colombier intcunmaskall(void)
1538e32b400SDavid du Colombier {
1548e32b400SDavid du Colombier 	int i;
1558e32b400SDavid du Colombier 	Intrregs *ip = (Intrregs *)PHYSINTC;
1568e32b400SDavid du Colombier 
1578e32b400SDavid du Colombier 	for (i = 0; i < 3; i++)
1588e32b400SDavid du Colombier 		ip->bits[i].mir_clear = ~0;
1598e32b400SDavid du Colombier 	coherence();
1608e32b400SDavid du Colombier }
1618e32b400SDavid du Colombier 
1628e32b400SDavid du Colombier static void
intcinvertall(void)1638e32b400SDavid du Colombier intcinvertall(void)
1648e32b400SDavid du Colombier {
1658e32b400SDavid du Colombier 	int i, s;
1668e32b400SDavid du Colombier 	ulong bits;
1678e32b400SDavid du Colombier 	Intrregs *ip = (Intrregs *)PHYSINTC;
1688e32b400SDavid du Colombier 
1698e32b400SDavid du Colombier 	s = splhi();
1708e32b400SDavid du Colombier 	for (i = 0; i < 3; i++) {
1718e32b400SDavid du Colombier 		bits = ip->bits[i].mir;
1728e32b400SDavid du Colombier 		ip->bits[i].mir_set = ~0;	/* mask all */
1738e32b400SDavid du Colombier 		coherence();
1748e32b400SDavid du Colombier 		/* clearing enables only those intrs. that were disabled */
1758e32b400SDavid du Colombier 		ip->bits[i].mir_clear = bits;
1768e32b400SDavid du Colombier 	}
1778e32b400SDavid du Colombier 	coherence();
1788e32b400SDavid du Colombier 	splx(s);
1798e32b400SDavid du Colombier }
1808e32b400SDavid du Colombier 
1818e32b400SDavid du Colombier static void
intrsave(ulong buf[3])1828e32b400SDavid du Colombier intrsave(ulong buf[3])
1838e32b400SDavid du Colombier {
1848e32b400SDavid du Colombier 	int i;
1858e32b400SDavid du Colombier 	Intrregs *ip = (Intrregs *)PHYSINTC;
1868e32b400SDavid du Colombier 
1878e32b400SDavid du Colombier 	for (i = 0; i < nelem(buf); i++)
1888e32b400SDavid du Colombier 		buf[i] = ip->bits[i].mir;
1898e32b400SDavid du Colombier 	coherence();
1908e32b400SDavid du Colombier }
1918e32b400SDavid du Colombier 
1928e32b400SDavid du Colombier static void
intrrestore(ulong buf[3])1938e32b400SDavid du Colombier intrrestore(ulong buf[3])
1948e32b400SDavid du Colombier {
1958e32b400SDavid du Colombier 	int i, s;
1968e32b400SDavid du Colombier 	Intrregs *ip = (Intrregs *)PHYSINTC;
1978e32b400SDavid du Colombier 
1988e32b400SDavid du Colombier 	s = splhi();
1998e32b400SDavid du Colombier 	for (i = 0; i < nelem(buf); i++) {
2008e32b400SDavid du Colombier 		ip->bits[i].mir_clear = ~0;	/* unmask all */
2018e32b400SDavid du Colombier 		coherence();
2028e32b400SDavid du Colombier 		ip->bits[i].mir_set = buf[i];	/* mask previously disabled */
2038e32b400SDavid du Colombier 	}
2048e32b400SDavid du Colombier 	coherence();
2058e32b400SDavid du Colombier 	splx(s);
2068e32b400SDavid du Colombier }
2078e32b400SDavid du Colombier 
2088e32b400SDavid du Colombier /*
2098e32b400SDavid du Colombier  *  set up for exceptions
2108e32b400SDavid du Colombier  */
2118e32b400SDavid du Colombier void
trapinit(void)2128e32b400SDavid du Colombier trapinit(void)
2138e32b400SDavid du Colombier {
2148e32b400SDavid du Colombier 	int i;
2158e32b400SDavid du Colombier 	Intrregs *ip = (Intrregs *)PHYSINTC;
2168e32b400SDavid du Colombier 
2178e32b400SDavid du Colombier 	/* set up the exception vectors */
2188e32b400SDavid du Colombier 	vpage0 = (Vpage0*)HVECTORS;
2198e32b400SDavid du Colombier 	memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
2208e32b400SDavid du Colombier 	memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
2218e32b400SDavid du Colombier 	cacheuwbinv();
2228e32b400SDavid du Colombier 	l2cacheuwbinv();
2238e32b400SDavid du Colombier 
2248e32b400SDavid du Colombier 	/* set up the stacks for the interrupt modes */
2258e32b400SDavid du Colombier 	setr13(PsrMfiq, m->sfiq);
2268e32b400SDavid du Colombier 	setr13(PsrMirq, m->sirq);
2278e32b400SDavid du Colombier 	setr13(PsrMabt, m->sabt);
2288e32b400SDavid du Colombier 	setr13(PsrMund, m->sund);
2298e32b400SDavid du Colombier #ifdef HIGH_SECURITY
2308e32b400SDavid du Colombier 	setr13(PsrMmon, m->smon);
2318e32b400SDavid du Colombier #endif
2328e32b400SDavid du Colombier 	setr13(PsrMsys, m->ssys);
2338e32b400SDavid du Colombier 
2348e32b400SDavid du Colombier 	intcmaskall();
2358e32b400SDavid du Colombier 	ip->control = 0;
2368e32b400SDavid du Colombier 	ip->threshold = Prioritythreshold;	/* disable threshold */
2378e32b400SDavid du Colombier 	for (i = 0; i < Nirqs; i++)
2388e32b400SDavid du Colombier 		ip->ilr[i] = 0<<2 | 0;	/* all intrs pri 0 & to irq, not fiq */
2398e32b400SDavid du Colombier 	irqtooearly = 0;
2408e32b400SDavid du Colombier 	coherence();
2418e32b400SDavid du Colombier }
2428e32b400SDavid du Colombier 
2438e32b400SDavid du Colombier void
intrsoff(void)2448e32b400SDavid du Colombier intrsoff(void)
2458e32b400SDavid du Colombier {
2468e32b400SDavid du Colombier 	Intrregs *ip = (Intrregs *)PHYSINTC;
2478e32b400SDavid du Colombier 
2488e32b400SDavid du Colombier 	intcmaskall();
2498e32b400SDavid du Colombier 	ip->control = Newirqagr;	/* dismiss interrupt */
2508e32b400SDavid du Colombier 	coherence();
2518e32b400SDavid du Colombier }
2528e32b400SDavid du Colombier 
2538e32b400SDavid du Colombier /*
2548e32b400SDavid du Colombier  *  enable an irq interrupt
2558e32b400SDavid du Colombier  */
2568e32b400SDavid du Colombier int
irqenable(int irq,void (* f)(Ureg *,void *),void * a,char * name)2578e32b400SDavid du Colombier irqenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
2588e32b400SDavid du Colombier {
2598e32b400SDavid du Colombier 	Vctl *v;
2608e32b400SDavid du Colombier 
2618e32b400SDavid du Colombier 	if(irq >= nelem(vctl) || irq < 0)
2628e32b400SDavid du Colombier 		panic("irqenable irq %d", irq);
2638e32b400SDavid du Colombier 
2648e32b400SDavid du Colombier 	if (irqtooearly) {
2658e32b400SDavid du Colombier 		iprint("irqenable for %d %s called too early\n", irq, name);
2668e32b400SDavid du Colombier 		return -1;
2678e32b400SDavid du Colombier 	}
2688e32b400SDavid du Colombier 	if(irqinuse(irq))
2698e32b400SDavid du Colombier 		print("irqenable: %s: irq %d already in use, chaining\n",
2708e32b400SDavid du Colombier 			name, irq);
2718e32b400SDavid du Colombier 	v = malloc(sizeof(Vctl));
2728e32b400SDavid du Colombier 	if (v == nil)
2738e32b400SDavid du Colombier 		panic("irqenable: malloc Vctl");
2748e32b400SDavid du Colombier 	v->f = f;
2758e32b400SDavid du Colombier 	v->a = a;
2768e32b400SDavid du Colombier 	v->name = malloc(strlen(name)+1);
2778e32b400SDavid du Colombier 	if (v->name == nil)
2788e32b400SDavid du Colombier 		panic("irqenable: malloc name");
2798e32b400SDavid du Colombier 	strcpy(v->name, name);
2808e32b400SDavid du Colombier 
2818e32b400SDavid du Colombier 	lock(&vctllock);
2828e32b400SDavid du Colombier 	v->next = vctl[irq];
2838e32b400SDavid du Colombier 	vctl[irq] = v;
2848e32b400SDavid du Colombier 
2858e32b400SDavid du Colombier 	intcunmask(irq);
2868e32b400SDavid du Colombier 	unlock(&vctllock);
2878e32b400SDavid du Colombier 	return 0;
2888e32b400SDavid du Colombier }
2898e32b400SDavid du Colombier 
2908e32b400SDavid du Colombier /*
2918e32b400SDavid du Colombier  *  disable an irq interrupt
2928e32b400SDavid du Colombier  */
2938e32b400SDavid du Colombier int
irqdisable(int irq,void (* f)(Ureg *,void *),void * a,char * name)2948e32b400SDavid du Colombier irqdisable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
2958e32b400SDavid du Colombier {
2968e32b400SDavid du Colombier 	Vctl **vp, *v;
2978e32b400SDavid du Colombier 
2988e32b400SDavid du Colombier 	if(irq >= nelem(vctl) || irq < 0)
2998e32b400SDavid du Colombier 		panic("irqdisable irq %d", irq);
3008e32b400SDavid du Colombier 
3018e32b400SDavid du Colombier 	lock(&vctllock);
3028e32b400SDavid du Colombier 	for(vp = &vctl[irq]; v = *vp; vp = &v->next)
3038e32b400SDavid du Colombier 		if (v->f == f && v->a == a && strcmp(v->name, name) == 0){
3048e32b400SDavid du Colombier 			print("irqdisable: remove %s\n", name);
3058e32b400SDavid du Colombier 			*vp = v->next;
3068e32b400SDavid du Colombier 			free(v);
3078e32b400SDavid du Colombier 			break;
3088e32b400SDavid du Colombier 		}
3098e32b400SDavid du Colombier 
3108e32b400SDavid du Colombier 	if(v == nil)
3118e32b400SDavid du Colombier 		print("irqdisable: irq %d, name %s not enabled\n", irq, name);
3128e32b400SDavid du Colombier 	if(vctl[irq] == nil){
3138e32b400SDavid du Colombier 		print("irqdisable: clear icmr bit %d\n", irq);
3148e32b400SDavid du Colombier 		intcmask(irq);
3158e32b400SDavid du Colombier 	}
3168e32b400SDavid du Colombier 	unlock(&vctllock);
3178e32b400SDavid du Colombier 
3188e32b400SDavid du Colombier 	return 0;
3198e32b400SDavid du Colombier }
3208e32b400SDavid du Colombier 
3218e32b400SDavid du Colombier /*
3228e32b400SDavid du Colombier  *  called by trap to handle access faults
3238e32b400SDavid du Colombier  */
3248e32b400SDavid du Colombier static void
faultarm(Ureg * ureg,uintptr va,int user,int read)3258e32b400SDavid du Colombier faultarm(Ureg *ureg, uintptr va, int user, int read)
3268e32b400SDavid du Colombier {
3278e32b400SDavid du Colombier 	int n, insyscall;
3288e32b400SDavid du Colombier 	char buf[ERRMAX];
3298e32b400SDavid du Colombier 
3308e32b400SDavid du Colombier 	if(up == nil) {
3318e32b400SDavid du Colombier 		dumpregs(ureg);
3328e32b400SDavid du Colombier 		panic("fault: nil up in faultarm, accessing %#p", va);
3338e32b400SDavid du Colombier 	}
3348e32b400SDavid du Colombier 	insyscall = up->insyscall;
3358e32b400SDavid du Colombier 	up->insyscall = 1;
3368e32b400SDavid du Colombier 	n = fault(va, read);
3378e32b400SDavid du Colombier 	if(n < 0){
3388e32b400SDavid du Colombier 		if(!user){
3398e32b400SDavid du Colombier 			dumpregs(ureg);
3408e32b400SDavid du Colombier 			panic("fault: kernel accessing %#p", va);
3418e32b400SDavid du Colombier 		}
3428e32b400SDavid du Colombier 		/* don't dump registers; programs suicide all the time */
3438e32b400SDavid du Colombier 		snprint(buf, sizeof buf, "sys: trap: fault %s va=%#p",
3448e32b400SDavid du Colombier 			read? "read": "write", va);
3458e32b400SDavid du Colombier 		postnote(up, 1, buf, NDebug);
3468e32b400SDavid du Colombier 	}
3478e32b400SDavid du Colombier 	up->insyscall = insyscall;
3488e32b400SDavid du Colombier }
3498e32b400SDavid du Colombier 
3508e32b400SDavid du Colombier /*
3518e32b400SDavid du Colombier  *  called by trap to handle interrupts.
3528e32b400SDavid du Colombier  *  returns true iff a clock interrupt, thus maybe reschedule.
3538e32b400SDavid du Colombier  */
3548e32b400SDavid du Colombier static int
irq(Ureg * ureg)3558e32b400SDavid du Colombier irq(Ureg* ureg)
3568e32b400SDavid du Colombier {
3578e32b400SDavid du Colombier 	int clockintr;
3588e32b400SDavid du Colombier 	uint irqno, handled, t, ticks = perfticks();
3598e32b400SDavid du Colombier 	Intrregs *ip = (Intrregs *)PHYSINTC;
3608e32b400SDavid du Colombier 	Vctl *v;
3618e32b400SDavid du Colombier 	static int nesting, lastirq = -1;
3628e32b400SDavid du Colombier 
3638e32b400SDavid du Colombier 	handled = 0;
3648e32b400SDavid du Colombier 	irqno = ip->sir_irq & Activeirq;
3658e32b400SDavid du Colombier 
3668e32b400SDavid du Colombier 	if (irqno >= 37 && irqno <= 47)		/* this is a clock intr? */
3678e32b400SDavid du Colombier 		m->inclockintr++;		/* yes, count nesting */
3688e32b400SDavid du Colombier 	lastirq = irqno;
3698e32b400SDavid du Colombier 
3708e32b400SDavid du Colombier 	if (irqno >= nelem(vctl)) {
3718e32b400SDavid du Colombier 		iprint("trap: irq %d >= # vectors (%d)\n", irqno, nelem(vctl));
3728e32b400SDavid du Colombier 		ip->control = Newirqagr;	/* dismiss interrupt */
3738e32b400SDavid du Colombier 		return 0;
3748e32b400SDavid du Colombier 	}
3758e32b400SDavid du Colombier 
3768e32b400SDavid du Colombier 	++nesting;
3778e32b400SDavid du Colombier 	for(v = vctl[irqno]; v != nil; v = v->next)
3788e32b400SDavid du Colombier 		if (v->f) {
3798e32b400SDavid du Colombier 			if (islo())
3808e32b400SDavid du Colombier 				panic("trap: pl0 before trap handler for %s",
3818e32b400SDavid du Colombier 					v->name);
3828e32b400SDavid du Colombier 			v->f(ureg, v->a);
3838e32b400SDavid du Colombier 			if (islo())
3848e32b400SDavid du Colombier 				panic("trap: %s lowered pl", v->name);
3858e32b400SDavid du Colombier //			splhi();		/* in case v->f lowered pl */
3868e32b400SDavid du Colombier 			handled++;
3878e32b400SDavid du Colombier 		}
3888bfb44c2SDavid du Colombier 	if(!handled) {
389436938c0SDavid du Colombier 		iprint("unexpected interrupt: irq %d", irqno);
390436938c0SDavid du Colombier 		switch (irqno) {
391436938c0SDavid du Colombier 		case 56:
392436938c0SDavid du Colombier 		case 57:
393436938c0SDavid du Colombier 			iprint(" (I⁲C)");
394436938c0SDavid du Colombier 			break;
395436938c0SDavid du Colombier 		case 83:
396436938c0SDavid du Colombier 		case 86:
397436938c0SDavid du Colombier 		case 94:
398436938c0SDavid du Colombier 			iprint(" (MMC)");
399436938c0SDavid du Colombier 			break;
400436938c0SDavid du Colombier 		}
401436938c0SDavid du Colombier 
4028bfb44c2SDavid du Colombier 		if(irqno < nelem(vctl)) {
4038bfb44c2SDavid du Colombier 			intcmask(irqno);
404436938c0SDavid du Colombier 			iprint(", now masked");
4058bfb44c2SDavid du Colombier 		}
406436938c0SDavid du Colombier 		iprint("\n");
4078bfb44c2SDavid du Colombier 	}
4088e32b400SDavid du Colombier 	t = perfticks();
4098e32b400SDavid du Colombier 	ninterrupt++;
4108e32b400SDavid du Colombier 	if(t < ticks)
4118e32b400SDavid du Colombier 		ninterruptticks += ticks-t;
4128e32b400SDavid du Colombier 	else
4138e32b400SDavid du Colombier 		ninterruptticks += t-ticks;
4148e32b400SDavid du Colombier 	ip->control = Newirqagr;	/* dismiss interrupt */
4158e32b400SDavid du Colombier 	coherence();
4168e32b400SDavid du Colombier 
4178e32b400SDavid du Colombier 	--nesting;
4188e32b400SDavid du Colombier 	clockintr = m->inclockintr == 1;
4198e32b400SDavid du Colombier 	if (irqno >= 37 && irqno <= 47)
4208e32b400SDavid du Colombier 		m->inclockintr--;
4218e32b400SDavid du Colombier 	return clockintr;
4228e32b400SDavid du Colombier }
4238e32b400SDavid du Colombier 
4248e32b400SDavid du Colombier /*
4258e32b400SDavid du Colombier  *  returns 1 if the instruction writes memory, 0 otherwise
4268e32b400SDavid du Colombier  */
4278e32b400SDavid du Colombier int
writetomem(ulong inst)4288e32b400SDavid du Colombier writetomem(ulong inst)
4298e32b400SDavid du Colombier {
4308e32b400SDavid du Colombier 	/* swap always write memory */
4318e32b400SDavid du Colombier 	if((inst & 0x0FC00000) == 0x01000000)
4328e32b400SDavid du Colombier 		return 1;
4338e32b400SDavid du Colombier 
4348e32b400SDavid du Colombier 	/* loads and stores are distinguished by bit 20 */
4358e32b400SDavid du Colombier 	if(inst & (1<<20))
4368e32b400SDavid du Colombier 		return 0;
4378e32b400SDavid du Colombier 
4388e32b400SDavid du Colombier 	return 1;
4398e32b400SDavid du Colombier }
4408e32b400SDavid du Colombier 
441b3b810bfSDavid du Colombier void	prgpmcerrs(void);
442b3b810bfSDavid du Colombier 
4438e32b400SDavid du Colombier /*
4448e32b400SDavid du Colombier  *  here on all exceptions other than syscall (SWI)
4458e32b400SDavid du Colombier  */
4468e32b400SDavid du Colombier void
trap(Ureg * ureg)4478e32b400SDavid du Colombier trap(Ureg *ureg)
4488e32b400SDavid du Colombier {
4498e32b400SDavid du Colombier 	int clockintr, user, x, rv, rem;
4508e32b400SDavid du Colombier 	ulong inst, fsr;
4518e32b400SDavid du Colombier 	uintptr va;
4528e32b400SDavid du Colombier 	char buf[ERRMAX];
4538e32b400SDavid du Colombier 
4548e32b400SDavid du Colombier 	splhi();			/* paranoia */
4558e32b400SDavid du Colombier 	if(up != nil)
4568e32b400SDavid du Colombier 		rem = ((char*)ureg)-up->kstack;
4578e32b400SDavid du Colombier 	else
4588e32b400SDavid du Colombier 		rem = ((char*)ureg)-((char*)m+sizeof(Mach));
4598e32b400SDavid du Colombier 	if(rem < 1024) {
4608e32b400SDavid du Colombier 		iprint("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux\n",
4618e32b400SDavid du Colombier 			rem, up, ureg, ureg->pc);
4628e32b400SDavid du Colombier 		delay(1000);
4638e32b400SDavid du Colombier 		dumpstack();
4648e32b400SDavid du Colombier 		panic("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux",
4658e32b400SDavid du Colombier 			rem, up, ureg, ureg->pc);
4668e32b400SDavid du Colombier 	}
4678e32b400SDavid du Colombier 
4688e32b400SDavid du Colombier 	user = (ureg->psr & PsrMask) == PsrMusr;
4698e32b400SDavid du Colombier 	if(user){
4708e32b400SDavid du Colombier 		up->dbgreg = ureg;
4718e32b400SDavid du Colombier 		cycles(&up->kentry);
4728e32b400SDavid du Colombier 	}
4738e32b400SDavid du Colombier 
4748e32b400SDavid du Colombier 	/*
4758e32b400SDavid du Colombier 	 * All interrupts/exceptions should be resumed at ureg->pc-4,
4768e32b400SDavid du Colombier 	 * except for Data Abort which resumes at ureg->pc-8.
4778e32b400SDavid du Colombier 	 */
4788e32b400SDavid du Colombier 	if(ureg->type == (PsrMabt+1))
4798e32b400SDavid du Colombier 		ureg->pc -= 8;
4808e32b400SDavid du Colombier 	else
4818e32b400SDavid du Colombier 		ureg->pc -= 4;
4828e32b400SDavid du Colombier 
4838e32b400SDavid du Colombier 	clockintr = 0;		/* if set, may call sched() before return */
4848e32b400SDavid du Colombier 	switch(ureg->type){
4858e32b400SDavid du Colombier 	default:
4868e32b400SDavid du Colombier 		panic("unknown trap; type %#lux, psr mode %#lux", ureg->type,
4878e32b400SDavid du Colombier 			ureg->psr & PsrMask);
4888e32b400SDavid du Colombier 		break;
4898e32b400SDavid du Colombier 	case PsrMirq:
4908e32b400SDavid du Colombier 		ldrexvalid = 0;
4918e32b400SDavid du Colombier 		clockintr = irq(ureg);
492634d7e5aSDavid du Colombier 		m->intr++;
4938e32b400SDavid du Colombier 		break;
4948e32b400SDavid du Colombier 	case PsrMabt:			/* prefetch fault */
4958e32b400SDavid du Colombier 		ldrexvalid = 0;
496*9b7bf7dfSDavid du Colombier 		x = ifsrget();
497*9b7bf7dfSDavid du Colombier 		fsr = (x>>7) & 0x8 | x & 0x7;
498*9b7bf7dfSDavid du Colombier 		switch(fsr){
499*9b7bf7dfSDavid du Colombier 		case 0x02:		/* instruction debug event (BKPT) */
500*9b7bf7dfSDavid du Colombier 			if(user){
501*9b7bf7dfSDavid du Colombier 				snprint(buf, sizeof buf, "sys: breakpoint");
502*9b7bf7dfSDavid du Colombier 				postnote(up, 1, buf, NDebug);
503*9b7bf7dfSDavid du Colombier 			}else{
504*9b7bf7dfSDavid du Colombier 				iprint("kernel bkpt: pc %#lux inst %#ux\n",
505*9b7bf7dfSDavid du Colombier 					ureg->pc, *(u32int*)ureg->pc);
506*9b7bf7dfSDavid du Colombier 				panic("kernel bkpt");
507*9b7bf7dfSDavid du Colombier 			}
508*9b7bf7dfSDavid du Colombier 			break;
509*9b7bf7dfSDavid du Colombier 		default:
5108e32b400SDavid du Colombier 			faultarm(ureg, ureg->pc, user, 1);
5118e32b400SDavid du Colombier 			break;
512*9b7bf7dfSDavid du Colombier 		}
513*9b7bf7dfSDavid du Colombier 		break;
5148e32b400SDavid du Colombier 	case PsrMabt+1:			/* data fault */
5158e32b400SDavid du Colombier 		ldrexvalid = 0;
5168e32b400SDavid du Colombier 		va = farget();
5178e32b400SDavid du Colombier 		inst = *(ulong*)(ureg->pc);
518b3b810bfSDavid du Colombier 		/* bits 12 and 10 have to be concatenated with status */
519b3b810bfSDavid du Colombier 		x = fsrget();
520b3b810bfSDavid du Colombier 		fsr = (x>>7) & 0x20 | (x>>6) & 0x10 | x & 0xf;
5218e32b400SDavid du Colombier 		if (probing && !user) {
5228e32b400SDavid du Colombier 			if (trapped++ > 0)
5238e32b400SDavid du Colombier 				panic("trap: recursive probe %#lux", va);
5248e32b400SDavid du Colombier 			ureg->pc += 4;	/* continue at next instruction */
5258e32b400SDavid du Colombier 			break;
5268e32b400SDavid du Colombier 		}
5278e32b400SDavid du Colombier 		switch(fsr){
528b3b810bfSDavid du Colombier 		default:
529b3b810bfSDavid du Colombier 		case 0xa:		/* ? was under external abort */
530b3b810bfSDavid du Colombier 			panic("unknown data fault, 6b fsr %#lux", fsr);
531b3b810bfSDavid du Colombier 			break;
5328e32b400SDavid du Colombier 		case 0x0:
5338e32b400SDavid du Colombier 			panic("vector exception at %#lux", ureg->pc);
5348e32b400SDavid du Colombier 			break;
535b3b810bfSDavid du Colombier 		case 0x1:		/* alignment fault */
536b3b810bfSDavid du Colombier 		case 0x3:		/* access flag fault (section) */
5378e32b400SDavid du Colombier 			if(user){
5388e32b400SDavid du Colombier 				snprint(buf, sizeof buf,
5398e32b400SDavid du Colombier 					"sys: alignment: pc %#lux va %#p\n",
5408e32b400SDavid du Colombier 					ureg->pc, va);
5418e32b400SDavid du Colombier 				postnote(up, 1, buf, NDebug);
5428e32b400SDavid du Colombier 			} else
5438e32b400SDavid du Colombier 				panic("kernel alignment: pc %#lux va %#p", ureg->pc, va);
5448e32b400SDavid du Colombier 			break;
5458e32b400SDavid du Colombier 		case 0x2:
5468e32b400SDavid du Colombier 			panic("terminal exception at %#lux", ureg->pc);
5478e32b400SDavid du Colombier 			break;
548b3b810bfSDavid du Colombier 		case 0x4:		/* icache maint fault */
549b3b810bfSDavid du Colombier 		case 0x6:		/* access flag fault (page) */
550b3b810bfSDavid du Colombier 		case 0x8:		/* precise external abort, non-xlat'n */
551b3b810bfSDavid du Colombier 		case 0x28:
552b3b810bfSDavid du Colombier 		case 0xc:		/* l1 translation, precise ext. abort */
553b3b810bfSDavid du Colombier 		case 0x2c:
554b3b810bfSDavid du Colombier 		case 0xe:		/* l2 translation, precise ext. abort */
555b3b810bfSDavid du Colombier 		case 0x2e:
556b3b810bfSDavid du Colombier 		case 0x16:		/* imprecise ext. abort, non-xlt'n */
557b3b810bfSDavid du Colombier 		case 0x36:
5588e32b400SDavid du Colombier 			panic("external abort %#lux pc %#lux addr %#p",
5598e32b400SDavid du Colombier 				fsr, ureg->pc, va);
5608e32b400SDavid du Colombier 			break;
561b3b810bfSDavid du Colombier 		case 0x1c:		/* l1 translation, precise parity err */
562b3b810bfSDavid du Colombier 		case 0x1e:		/* l2 translation, precise parity err */
563b3b810bfSDavid du Colombier 		case 0x18:		/* imprecise parity or ecc err */
564b3b810bfSDavid du Colombier 			panic("translation parity error %#lux pc %#lux addr %#p",
565b3b810bfSDavid du Colombier 				fsr, ureg->pc, va);
566b3b810bfSDavid du Colombier 			break;
5678e32b400SDavid du Colombier 		case 0x5:		/* translation fault, no section entry */
5688e32b400SDavid du Colombier 		case 0x7:		/* translation fault, no page entry */
5698e32b400SDavid du Colombier 			faultarm(ureg, va, user, !writetomem(inst));
5708e32b400SDavid du Colombier 			break;
5718e32b400SDavid du Colombier 		case 0x9:
5728e32b400SDavid du Colombier 		case 0xb:
5738e32b400SDavid du Colombier 			/* domain fault, accessing something we shouldn't */
5748e32b400SDavid du Colombier 			if(user){
5758e32b400SDavid du Colombier 				snprint(buf, sizeof buf,
5768e32b400SDavid du Colombier 					"sys: access violation: pc %#lux va %#p\n",
5778e32b400SDavid du Colombier 					ureg->pc, va);
5788e32b400SDavid du Colombier 				postnote(up, 1, buf, NDebug);
5798e32b400SDavid du Colombier 			} else
5808e32b400SDavid du Colombier 				panic("kernel access violation: pc %#lux va %#p",
5818e32b400SDavid du Colombier 					ureg->pc, va);
5828e32b400SDavid du Colombier 			break;
5838e32b400SDavid du Colombier 		case 0xd:
5848e32b400SDavid du Colombier 		case 0xf:
5858e32b400SDavid du Colombier 			/* permission error, copy on write or real permission error */
5868e32b400SDavid du Colombier 			faultarm(ureg, va, user, !writetomem(inst));
5878e32b400SDavid du Colombier 			break;
5888e32b400SDavid du Colombier 		}
5898e32b400SDavid du Colombier 		break;
5908e32b400SDavid du Colombier 	case PsrMund:			/* undefined instruction */
5918e32b400SDavid du Colombier 		if(user){
592a4b9e815SDavid du Colombier 			if(seg(up, ureg->pc, 0) != nil &&
593a4b9e815SDavid du Colombier 			   *(u32int*)ureg->pc == 0xD1200070){
594a4b9e815SDavid du Colombier 				snprint(buf, sizeof buf, "sys: breakpoint");
595a4b9e815SDavid du Colombier 				postnote(up, 1, buf, NDebug);
596a4b9e815SDavid du Colombier 			}else{
5978e32b400SDavid du Colombier 				/* look for floating point instructions to interpret */
5988e32b400SDavid du Colombier 				x = spllo();
5998e32b400SDavid du Colombier 				rv = fpiarm(ureg);
6008e32b400SDavid du Colombier 				splx(x);
6018e32b400SDavid du Colombier 				if(rv == 0){
6028e32b400SDavid du Colombier 					ldrexvalid = 0;
6038e32b400SDavid du Colombier 					snprint(buf, sizeof buf,
6048e32b400SDavid du Colombier 						"undefined instruction: pc %#lux\n",
6058e32b400SDavid du Colombier 						ureg->pc);
6068e32b400SDavid du Colombier 					postnote(up, 1, buf, NDebug);
6078e32b400SDavid du Colombier 				}
608a4b9e815SDavid du Colombier 			}
6098e32b400SDavid du Colombier 		}else{
6108e32b400SDavid du Colombier 			if (ureg->pc & 3) {
6118e32b400SDavid du Colombier 				iprint("rounding fault pc %#lux down to word\n",
6128e32b400SDavid du Colombier 					ureg->pc);
6138e32b400SDavid du Colombier 				ureg->pc &= ~3;
6148e32b400SDavid du Colombier 			}
6158e32b400SDavid du Colombier 			iprint("undefined instruction: pc %#lux inst %#ux\n",
6168e32b400SDavid du Colombier 				ureg->pc, ((u32int*)ureg->pc)[-2]);
6178e32b400SDavid du Colombier 			panic("undefined instruction");
6188e32b400SDavid du Colombier 		}
6198e32b400SDavid du Colombier 		break;
6208e32b400SDavid du Colombier 	}
6218e32b400SDavid du Colombier 	splhi();
6228e32b400SDavid du Colombier 
6238e32b400SDavid du Colombier 	/* delaysched set because we held a lock or because our quantum ended */
6248e32b400SDavid du Colombier 	if(up && up->delaysched && clockintr){
6258e32b400SDavid du Colombier 		ldrexvalid = 0;
6268e32b400SDavid du Colombier 		sched();		/* can cause more traps */
6278e32b400SDavid du Colombier 		splhi();
6288e32b400SDavid du Colombier 	}
6298e32b400SDavid du Colombier 
6308e32b400SDavid du Colombier 	if(user){
6318e32b400SDavid du Colombier 		if(up->procctl || up->nnote)
6328e32b400SDavid du Colombier 			notify(ureg);
6338e32b400SDavid du Colombier 		kexit(ureg);
6348e32b400SDavid du Colombier 	}
6358e32b400SDavid du Colombier }
6368e32b400SDavid du Colombier 
6378e32b400SDavid du Colombier /*
6388e32b400SDavid du Colombier  * Fill in enough of Ureg to get a stack trace, and call a function.
6398e32b400SDavid du Colombier  * Used by debugging interface rdb.
6408e32b400SDavid du Colombier  */
6418e32b400SDavid du Colombier void
callwithureg(void (* fn)(Ureg *))6428e32b400SDavid du Colombier callwithureg(void (*fn)(Ureg*))
6438e32b400SDavid du Colombier {
6448e32b400SDavid du Colombier 	Ureg ureg;
6458e32b400SDavid du Colombier 
6468e32b400SDavid du Colombier 	ureg.pc = getcallerpc(&fn);
6478e32b400SDavid du Colombier 	ureg.sp = PTR2UINT(&fn);
6488e32b400SDavid du Colombier 	fn(&ureg);
6498e32b400SDavid du Colombier }
6508e32b400SDavid du Colombier 
6518e32b400SDavid du Colombier static void
dumpstackwithureg(Ureg * ureg)6528e32b400SDavid du Colombier dumpstackwithureg(Ureg *ureg)
6538e32b400SDavid du Colombier {
6548e32b400SDavid du Colombier 	int x;
6558e32b400SDavid du Colombier 	uintptr l, v, i, estack;
6568e32b400SDavid du Colombier 	char *s;
6578e32b400SDavid du Colombier 
6588e32b400SDavid du Colombier 	dumpregs(ureg);
6598e32b400SDavid du Colombier 	if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
6608e32b400SDavid du Colombier 		iprint("dumpstack disabled\n");
6618e32b400SDavid du Colombier 		return;
6628e32b400SDavid du Colombier 	}
6638e32b400SDavid du Colombier 	iprint("dumpstack\n");
6648e32b400SDavid du Colombier 
6658e32b400SDavid du Colombier 	x = 0;
6668e32b400SDavid du Colombier 	x += iprint("ktrace /kernel/path %#.8lux %#.8lux %#.8lux # pc, sp, link\n",
6678e32b400SDavid du Colombier 		ureg->pc, ureg->sp, ureg->r14);
6688e32b400SDavid du Colombier 	delay(20);
6698e32b400SDavid du Colombier 	i = 0;
6708e32b400SDavid du Colombier 	if(up
6718e32b400SDavid du Colombier 	&& (uintptr)&l >= (uintptr)up->kstack
6728e32b400SDavid du Colombier 	&& (uintptr)&l <= (uintptr)up->kstack+KSTACK)
6738e32b400SDavid du Colombier 		estack = (uintptr)up->kstack+KSTACK;
6748e32b400SDavid du Colombier 	else if((uintptr)&l >= (uintptr)m->stack
6758e32b400SDavid du Colombier 	&& (uintptr)&l <= (uintptr)m+MACHSIZE)
6768e32b400SDavid du Colombier 		estack = (uintptr)m+MACHSIZE;
6778e32b400SDavid du Colombier 	else
6788e32b400SDavid du Colombier 		return;
6798e32b400SDavid du Colombier 	x += iprint("estackx %p\n", estack);
6808e32b400SDavid du Colombier 
6818e32b400SDavid du Colombier 	for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
6828e32b400SDavid du Colombier 		v = *(uintptr*)l;
6838e32b400SDavid du Colombier 		if((KTZERO < v && v < (uintptr)etext) || estack-l < 32){
6848e32b400SDavid du Colombier 			x += iprint("%.8p ", v);
6858e32b400SDavid du Colombier 			delay(20);
6868e32b400SDavid du Colombier 			i++;
6878e32b400SDavid du Colombier 		}
6888e32b400SDavid du Colombier 		if(i == 8){
6898e32b400SDavid du Colombier 			i = 0;
6908e32b400SDavid du Colombier 			x += iprint("\n");
6918e32b400SDavid du Colombier 			delay(20);
6928e32b400SDavid du Colombier 		}
6938e32b400SDavid du Colombier 	}
6948e32b400SDavid du Colombier 	if(i)
6958e32b400SDavid du Colombier 		iprint("\n");
6968e32b400SDavid du Colombier }
6978e32b400SDavid du Colombier 
6988e32b400SDavid du Colombier void
dumpstack(void)6998e32b400SDavid du Colombier dumpstack(void)
7008e32b400SDavid du Colombier {
7018e32b400SDavid du Colombier 	callwithureg(dumpstackwithureg);
7028e32b400SDavid du Colombier }
7038e32b400SDavid du Colombier 
7048e32b400SDavid du Colombier /*
7058e32b400SDavid du Colombier  * dump system control coprocessor registers
7068e32b400SDavid du Colombier  */
7078e32b400SDavid du Colombier static void
dumpscr(void)7088e32b400SDavid du Colombier dumpscr(void)
7098e32b400SDavid du Colombier {
7108e32b400SDavid du Colombier 	iprint("0:\t%#8.8ux id\n", cpidget());
7118e32b400SDavid du Colombier 	iprint("\t%8.8#ux ct\n", cpctget());
7128e32b400SDavid du Colombier 	iprint("1:\t%#8.8ux control\n", controlget());
7138e32b400SDavid du Colombier 	iprint("2:\t%#8.8ux ttb\n", ttbget());
7148e32b400SDavid du Colombier 	iprint("3:\t%#8.8ux dac\n", dacget());
7158e32b400SDavid du Colombier 	iprint("4:\t(reserved)\n");
7168e32b400SDavid du Colombier 	iprint("5:\t%#8.8ux fsr\n", fsrget());
7178e32b400SDavid du Colombier 	iprint("6:\t%#8.8ux far\n", farget());
7188e32b400SDavid du Colombier 	iprint("7:\twrite-only cache\n");
7198e32b400SDavid du Colombier 	iprint("8:\twrite-only tlb\n");
7208e32b400SDavid du Colombier 	iprint("13:\t%#8.8ux pid\n", pidget());
7218e32b400SDavid du Colombier 	delay(10);
7228e32b400SDavid du Colombier }
7238e32b400SDavid du Colombier 
7248e32b400SDavid du Colombier /*
7258e32b400SDavid du Colombier  * dump general registers
7268e32b400SDavid du Colombier  */
7278e32b400SDavid du Colombier static void
dumpgpr(Ureg * ureg)7288e32b400SDavid du Colombier dumpgpr(Ureg* ureg)
7298e32b400SDavid du Colombier {
7308e32b400SDavid du Colombier 	if(up != nil)
7318e32b400SDavid du Colombier 		iprint("cpu%d: registers for %s %lud\n",
7328e32b400SDavid du Colombier 			m->machno, up->text, up->pid);
7338e32b400SDavid du Colombier 	else
7348e32b400SDavid du Colombier 		iprint("cpu%d: registers for kernel\n", m->machno);
7358e32b400SDavid du Colombier 
7368e32b400SDavid du Colombier 	delay(20);
7378e32b400SDavid du Colombier 	iprint("%#8.8lux\tr0\n", ureg->r0);
7388e32b400SDavid du Colombier 	iprint("%#8.8lux\tr1\n", ureg->r1);
7398e32b400SDavid du Colombier 	iprint("%#8.8lux\tr2\n", ureg->r2);
7408e32b400SDavid du Colombier 	delay(20);
7418e32b400SDavid du Colombier 	iprint("%#8.8lux\tr3\n", ureg->r3);
7428e32b400SDavid du Colombier 	iprint("%#8.8lux\tr4\n", ureg->r4);
7438e32b400SDavid du Colombier 	iprint("%#8.8lux\tr5\n", ureg->r5);
7448e32b400SDavid du Colombier 	delay(20);
7458e32b400SDavid du Colombier 	iprint("%#8.8lux\tr6\n", ureg->r6);
7468e32b400SDavid du Colombier 	iprint("%#8.8lux\tr7\n", ureg->r7);
7478e32b400SDavid du Colombier 	iprint("%#8.8lux\tr8\n", ureg->r8);
7488e32b400SDavid du Colombier 	delay(20);
7498e32b400SDavid du Colombier 	iprint("%#8.8lux\tr9 (up)\n", ureg->r9);
7508e32b400SDavid du Colombier 	iprint("%#8.8lux\tr10 (m)\n", ureg->r10);
7518e32b400SDavid du Colombier 	iprint("%#8.8lux\tr11 (loader temporary)\n", ureg->r11);
7528e32b400SDavid du Colombier 	iprint("%#8.8lux\tr12 (SB)\n", ureg->r12);
7538e32b400SDavid du Colombier 	delay(20);
7548e32b400SDavid du Colombier 	iprint("%#8.8lux\tr13 (sp)\n", ureg->r13);
7558e32b400SDavid du Colombier 	iprint("%#8.8lux\tr14 (link)\n", ureg->r14);
7568e32b400SDavid du Colombier 	iprint("%#8.8lux\tr15 (pc)\n", ureg->pc);
7578e32b400SDavid du Colombier 	delay(20);
7588e32b400SDavid du Colombier 	iprint("%10.10lud\ttype\n", ureg->type);
7598e32b400SDavid du Colombier 	iprint("%#8.8lux\tpsr\n", ureg->psr);
7608e32b400SDavid du Colombier 	delay(20);
7618e32b400SDavid du Colombier }
7628e32b400SDavid du Colombier 
7638e32b400SDavid du Colombier void
dumpregs(Ureg * ureg)7648e32b400SDavid du Colombier dumpregs(Ureg* ureg)
7658e32b400SDavid du Colombier {
7668e32b400SDavid du Colombier 	dumpgpr(ureg);
7678e32b400SDavid du Colombier 	dumpscr();
7688e32b400SDavid du Colombier }
7698e32b400SDavid du Colombier 
7708e32b400SDavid du Colombier vlong
probeaddr(uintptr addr)7718e32b400SDavid du Colombier probeaddr(uintptr addr)
7728e32b400SDavid du Colombier {
7738e32b400SDavid du Colombier 	vlong v;
7748e32b400SDavid du Colombier 	static Lock fltlck;
7758e32b400SDavid du Colombier 
7768e32b400SDavid du Colombier 	ilock(&fltlck);
7778e32b400SDavid du Colombier 	trapped = 0;
7788e32b400SDavid du Colombier 	probing = 1;
7798e32b400SDavid du Colombier 	coherence();
7808e32b400SDavid du Colombier 
7818e32b400SDavid du Colombier 	v = *(ulong *)addr;	/* this may cause a fault */
7828e32b400SDavid du Colombier 	USED(probing);
7838e32b400SDavid du Colombier 	coherence();
7848e32b400SDavid du Colombier 
7858e32b400SDavid du Colombier 	probing = 0;
7868e32b400SDavid du Colombier 	coherence();
7878e32b400SDavid du Colombier 	if (trapped)
7888e32b400SDavid du Colombier 		v = -1;
7898e32b400SDavid du Colombier 	iunlock(&fltlck);
7908e32b400SDavid du Colombier 	return v;
7918e32b400SDavid du Colombier }
792