Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
699
dumpstack(void)
700
{
701
	callwithureg(dumpstackwithureg);
702
}
703
 
704
/*
705
 * dump system control coprocessor registers
706
 */
707
static 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
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
764
dumpregs(Ureg* ureg)
765
{
766
	dumpgpr(ureg);
767
	dumpscr();
768
}
769
 
770
vlong
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
}