Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"u.h"
2
#include	"../port/lib.h"
3
#include	"mem.h"
4
#include	"dat.h"
5
#include	"fns.h"
6
#include	"ureg.h"
7
#include	"../port/error.h"
8
#include	"tos.h"
9
#include	<trace.h>
10
 
11
static Lock vctllock;
12
Vctl *vctl[256];
13
 
14
int intrstack[5];
15
uvlong intrtime[5];
16
vlong lastoffset;
17
int inintr;
18
int nintr[10];
19
int nintro;
20
int dblintr[64];
21
ulong thisto[32];
22
ulong thistoo;
23
vlong vnot[64];
24
ulong vnon[64];
25
 
26
void
27
intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name)
28
{
29
	int vno;
30
	Vctl *v;
31
 
32
	if(f == nil){
33
		print("intrenable: nil handler for %d for %s\n",
34
			irq, name);
35
		return;
36
	}
37
 
38
	v = xalloc(sizeof(Vctl));
39
	v->isintr = 1;
40
	v->irq = irq;
41
	v->f = f;
42
	v->a = a;
43
	strncpy(v->name, name, KNAMELEN-1);
44
	v->name[KNAMELEN-1] = 0;
45
 
46
	ilock(&vctllock);
47
	vno = vectorenable(v);
48
	if(vno == -1){
49
		iunlock(&vctllock);
50
		print("intrenable: couldn't enable irq %d for %s\n",
51
			irq, v->name);
52
		xfree(v);
53
		return;
54
	}
55
	v->next = vctl[vno];
56
	vctl[vno] = v;
57
	iunlock(&vctllock);
58
}
59
 
60
void
61
intrdisable(int irq, void (*f)(Ureg *, void *), void *a, char *name)
62
{
63
	Vctl **pv, *v;
64
 
65
	ilock(&vctllock);
66
	pv = &vctl[irq];
67
	while (*pv && 
68
		  ((*pv)->irq != irq || (*pv)->f != f || (*pv)->a != a ||
69
		   strcmp((*pv)->name, name)))
70
		pv = &((*pv)->next);
71
 
72
	if(*pv == nil){
73
		print("intrdisable: irq %d not found\n", irq);
74
		iunlock(&vctllock);
75
		return;
76
	}
77
 
78
	v = *pv;
79
	*pv = (*pv)->next;	/* Link out the entry */
80
 
81
	if(vctl[irq] == nil)
82
		vectordisable(v);
83
	iunlock(&vctllock);
84
	xfree(v);
85
}
86
 
87
void	syscall(Ureg*);
88
void	noted(Ureg*, ulong);
89
static void _dumpstack(Ureg*);
90
 
91
char *excname[] =
92
{
93
	"reserved 0",
94
	"system reset",
95
	"machine check",
96
	"data access",
97
	"instruction access",
98
	"external interrupt",
99
	"alignment",
100
	"program exception",
101
	"floating-point unavailable",
102
	"decrementer",
103
	"reserved A",
104
	"reserved B",
105
	"system call",
106
	"trace trap",
107
	"floating point assist",
108
	"reserved F",
109
	"reserved 10",
110
	"data load translation miss",
111
	"data store translation miss",
112
	"instruction address breakpoint",
113
	"system management interrupt",
114
};
115
 
116
char *fpcause[] =
117
{
118
	"inexact operation",
119
	"division by zero",
120
	"underflow",
121
	"overflow",
122
	"invalid operation",
123
};
124
char	*fpexcname(Ureg*, ulong, char*);
125
#define FPEXPMASK	0xfff80300		/* Floating exception bits in fpscr */
126
 
127
 
128
char *regname[]={
129
	"CAUSE",	"SRR1",
130
	"PC",		"GOK",
131
	"LR",		"CR",
132
	"XER",		"CTR",
133
	"R0",		"R1",
134
	"R2",		"R3",
135
	"R4",		"R5",
136
	"R6",		"R7",
137
	"R8",		"R9",
138
	"R10",		"R11",
139
	"R12",		"R13",
140
	"R14",		"R15",
141
	"R16",		"R17",
142
	"R18",		"R19",
143
	"R20",		"R21",
144
	"R22",		"R23",
145
	"R24",		"R25",
146
	"R26",		"R27",
147
	"R28",		"R29",
148
	"R30",		"R31",
149
	"DCMP",		"ICMP",
150
	"DMISS",	"IMISS",
151
	"HASH1",	"HASH2",
152
	"DAR",		"DSISR",
153
};
154
 
155
void
156
kexit(Ureg*)
157
{
158
	uvlong t;
159
	Tos *tos;
160
 
161
	/* precise time accounting, kernel exit */
162
	tos = (Tos*)(USTKTOP-sizeof(Tos));
163
	cycles(&t);
164
	tos->kcycles += t - up->kentry;
165
	tos->pcycles = up->pcycles;
166
	tos->pid = up->pid;
167
}
168
 
169
void
170
trap(Ureg *ureg)
171
{
172
	int ecode, user;
173
	char buf[ERRMAX], *s;
174
	extern FPsave initfp;
175
 
176
	ecode = (ureg->cause >> 8) & 0xff;
177
	user = (ureg->srr1 & MSR_PR) != 0;
178
	if(user){
179
		cycles(&up->kentry);
180
		up->dbgreg = ureg;
181
	}
182
	if(ureg->status & MSR_RI == 0)
183
		print("double fault?: ecode = %d\n", ecode);
184
 
185
	switch(ecode) {
186
	case CEI:
187
		m->intr++;
188
		intr(ureg);
189
		break;
190
	case CDEC:
191
		clockintr(ureg);
192
		break;
193
	case CDSI:
194
		m->pfault++;
195
		if (up == nil){
196
			dumpregs(ureg);
197
			panic("kernel fault");
198
		}
199
		up->mmureg = ureg;
200
		faultpower(ureg, ureg->dar, (ureg->dsisr & BIT(6)) == 0);
201
		break;
202
	case CISI:
203
		m->pfault++;
204
		if (up == nil){
205
			dumpregs(ureg);
206
			panic("kernel fault");
207
		}
208
		up->mmureg = ureg;
209
		faultpower(ureg, ureg->pc, 1);
210
		break;
211
	case CIMISS:	/* instruction miss */
212
		if (up == nil){
213
			dumpregs(ureg);
214
			panic("kernel fault");
215
		}
216
		up->mmureg = ureg;
217
		faultpower(ureg, ureg->imiss, 1);
218
		break;
219
	case CLMISS:	/* data load miss */
220
		if (up == nil){
221
			dumpregs(ureg);
222
			panic("kernel fault");
223
		}
224
		up->mmureg = ureg;
225
		faultpower(ureg, ureg->dmiss, 1);
226
		break;
227
	case CSMISS:	/* data store miss */
228
		if (up == nil){
229
			dumpregs(ureg);
230
			panic("kernel fault");
231
		}
232
		up->mmureg = ureg;
233
		faultpower(ureg, ureg->dmiss, 0);
234
		break;
235
 
236
	case CSYSCALL:
237
		if(!user)
238
			panic("syscall in kernel: srr1 0x%4.4luX\n", ureg->srr1);
239
		syscall(ureg);
240
		if (up->delaysched){
241
			sched();
242
			splhi();
243
		}
244
		kexit(ureg);
245
		return;		/* syscall() calls notify itself, don't do it again */
246
 
247
	case CFPU:
248
		if(!user || up == nil) {
249
			dumpregs(ureg);
250
			panic("floating point in kernel");
251
		}
252
		switch(up->fpstate){
253
		case FPinit:
254
			fprestore(&initfp);
255
			up->fpstate = FPactive;
256
			break;
257
		case FPinactive:
258
			fprestore(&up->fpsave);
259
			up->fpstate = FPactive;
260
			break;
261
		case FPactive:
262
			print("up->fpstate %d\n", up->fpstate);
263
			delay(100);
264
			dumpregs(ureg);
265
			delay(200);
266
			panic("fpstate");
267
			break;
268
		default:
269
			if(user){
270
				spllo();
271
				sprint(buf, "sys: floating point in note handler:");
272
				postnote(up, 1, buf, NDebug);
273
				break;
274
			}
275
			panic("kernel fpstate illegal");
276
		}
277
		ureg->srr1 |= MSR_FP;
278
		break;
279
	case CPROG:
280
		if(ureg->status & (1<<19))
281
			s = "floating point exception";
282
		else if(ureg->status & (1<<18))
283
			s = "illegal instruction";
284
		else if(ureg->status & (1<<17))
285
			s = "privileged instruction";
286
		else
287
			s = "undefined program exception";
288
		if(user){
289
			spllo();
290
			sprint(buf, "sys: trap: %s", s);
291
			postnote(up, 1, buf, NDebug);
292
			break;
293
		}
294
		dumpregs(ureg);
295
		panic(s);
296
		break;
297
	default:
298
		if(ecode < nelem(excname) && user){
299
			spllo();
300
			sprint(buf, "sys: trap: %s", excname[ecode]);
301
			postnote(up, 1, buf, NDebug);
302
			break;
303
		}
304
		dumpregs(ureg);
305
		if(ecode < nelem(excname))
306
			panic("%s", excname[ecode]);
307
		panic("unknown trap/intr: %d\n", ecode);
308
	}
309
 
310
	/* restoreureg must execute at high IPL */
311
	splhi();
312
 
313
	/* delaysched set because we held a lock or because our quantum ended */
314
	if(up && up->delaysched && ecode == CDEC){
315
		sched();
316
		splhi();
317
	}
318
 
319
	if(user) {
320
		if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
321
			postnote(up, 1, buf, NDebug);
322
		}
323
		notify(ureg);
324
		if(up->fpstate != FPactive)
325
			ureg->srr1 &= ~MSR_FP;
326
		kexit(ureg);
327
	}
328
}
329
 
330
void
331
faultpower(Ureg *ureg, ulong addr, int read)
332
{
333
	int user, insyscall, n;
334
	char buf[ERRMAX];
335
 
336
	user = (ureg->srr1 & MSR_PR) != 0;
337
	insyscall = up->insyscall;
338
	up->insyscall = 1;
339
	n = fault(addr, read);
340
	if(n < 0){
341
		if(!user){
342
			dumpregs(ureg);
343
			panic("fault: 0x%lux", addr);
344
		}
345
		sprint(buf, "sys: trap: fault %s addr=0x%lux", read? "read" : "write", addr);
346
		postnote(up, 1, buf, NDebug);
347
	}
348
	up->insyscall = insyscall;
349
}
350
 
351
void
352
sethvec(int v, void (*r)(void))
353
{
354
	ulong *vp, pa, o;
355
 
356
	vp = KADDR(v);
357
	vp[0] = 0x7c1043a6;			/* MOVW R0, SPR(SPRG0) */
358
	vp[1] = 0x7c0802a6;			/* MOVW LR, R0 */
359
	vp[2] = 0x7c1243a6;			/* MOVW R0, SPR(SPRG2) */
360
	pa = PADDR(r);
361
	o = pa >> 25;
362
	if(o != 0 && o != 0x7F){
363
		/* a branch too far */
364
		vp[3] = (15<<26)|(pa>>16);	/* MOVW $r&~0xFFFF, R0 */
365
		vp[4] = (24<<26)|(pa&0xFFFF);	/* OR $r&0xFFFF, R0 */
366
		vp[5] = 0x7c0803a6;		/* MOVW	R0, LR */
367
		vp[6] = 0x4e800021;		/* BL (LR) */
368
	}else
369
		vp[3] = (18<<26)|(pa&0x3FFFFFC)|3;	/* bla */
370
}
371
 
372
void
373
setmvec(int v, void (*r)(void), void (*t)(void))
374
{
375
	ulong *vp, pa, o, n;
376
 
377
	vp = KADDR(v);
378
	n = 0;
379
	vp[n++] = 0x7c1043a6;			/* MOVW R0, SPR(SPRG0) */
380
	vp[n++] = 0x7c0802a6;			/* MOVW LR, R0 */
381
	vp[n++] = 0x7c1243a6;			/* MOVW R0, SPR(SPRG2) */
382
	pa = PADDR(r);
383
	o = pa >> 25;
384
	if(o != 0 && o != 0x7F){
385
		/* a branch too far */
386
		vp[n++] = (15<<26)|(pa>>16);	/* MOVW $r&~0xFFFF, R0 */
387
		vp[n++] = (24<<26)|(pa&0xFFFF);	/* OR $r&0xFFFF, R0 */
388
		vp[n++] = 0x7c0803a6;		/* MOVW	R0, LR */
389
		vp[n++] = 0x4e800021;		/* BL (LR) */
390
	}else
391
		vp[n++] = (18<<26)|(pa&0x3FFFFFC)|3;	/* bla */
392
	pa = PADDR(t);
393
	o = pa >> 25;
394
	if(o != 0 && o != 0x7F){
395
		/* a branch too far */
396
		vp[n++] = (15<<26)|(pa>>16);	/* MOVW $r&~0xFFFF, R0 */
397
		vp[n++] = (24<<26)|(pa&0xFFFF);	/* OR $r&0xFFFF, R0 */
398
		vp[n++] = 0x7c0803a6;		/* MOVW	R0, LR */
399
		vp[n] = 0x4e800021;		/* BL (LR) */
400
	}else
401
		vp[n] = (18<<26)|(pa&0x3FFFFFC)|3;	/* bla */
402
}
403
 
404
 
405
void
406
intr(Ureg *ureg)
407
{
408
	int vno, pvno, i;
409
	Vctl *ctl, *v;
410
	void (*pt)(Proc*, int, vlong);
411
	uvlong tt, x;
412
 
413
	cycles(&tt);
414
	pt = proctrace;
415
	pvno = -1;
416
	for(i = 0; i < 64; i++){
417
		vno = intvec();
418
		if(vno == 0)
419
			break;
420
		cycles(&x);
421
		vnot[vno] -= x;
422
		if(vno == pvno)
423
			dblintr[vno]++;
424
		pvno = vno;
425
		if(pt && up && up->trace)
426
			pt(up, (vno << 16) | SInts, 0);
427
 
428
		if(vno > nelem(vctl) || (ctl = vctl[vno]) == 0) {
429
			iprint("spurious intr %d\n", vno);
430
			return;
431
		}
432
 
433
		for(v = ctl; v != nil; v = v->next)
434
			if(v->f)
435
				v->f(ureg, v->a);
436
 
437
		intend(vno);	/* reenable the interrupt */
438
 
439
		if(pt && up && up->trace)
440
			pt(up, (vno << 16) | SInte, 0);
441
		cycles(&x);
442
		vnot[vno] += x;
443
		vnon[vno]++;
444
	}
445
	if(i < nelem(nintr))
446
		nintr[i]++;
447
	else
448
		nintro++;
449
	cycles(&x);
450
	tt = x - tt;
451
	i = tt / 3600;	 /* 100 microseconds units */
452
	if(i < nelem(thisto))
453
		thisto[i]++;
454
	else
455
		thistoo++;
456
 
457
	if(up)
458
		preempted();
459
}
460
 
461
char*
462
fpexcname(Ureg *ur, ulong fpscr, char *buf)
463
{
464
	int i;
465
	char *s;
466
	ulong fppc;
467
 
468
	fppc = ur->pc;
469
	s = 0;
470
	fpscr >>= 3;		/* trap enable bits */
471
	fpscr &= (fpscr>>22);	/* anded with exceptions */
472
	for(i=0; i<5; i++)
473
		if(fpscr & (1<<i))
474
			s = fpcause[i];
475
	if(s == 0)
476
		return "no floating point exception";
477
	sprint(buf, "%s fppc=0x%lux", s, fppc);
478
	return buf;
479
}
480
 
481
/*
482
 * Fill in enough of Ureg to get a stack trace, and call a function.
483
 * Used by debugging interface rdb.
484
 */
485
 
486
static void
487
getpcsp(ulong *pc, ulong *sp)
488
{
489
	*pc = getcallerpc(&pc);
490
	*sp = (ulong)&pc-4;
491
}
492
 
493
void
494
callwithureg(void (*fn)(Ureg*))
495
{
496
	Ureg ureg;
497
 
498
	getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
499
	ureg.lr = getcallerpc(&fn);
500
	fn(&ureg);
501
}
502
 
503
static void
504
_dumpstack(Ureg *ureg)
505
{
506
	ulong l, sl, el, v;
507
	int i;
508
 
509
	l = (ulong)&l;
510
	if(up == 0){
511
		el = (ulong)m+BY2PG;
512
		sl = el-KSTACK;
513
	}
514
	else{
515
		sl = (ulong)up->kstack;
516
		el = sl + KSTACK;
517
	}
518
	if(l > el || l < sl){
519
		el = (ulong)m+BY2PG;
520
		sl = el-KSTACK;
521
	}
522
	if(l > el || l < sl)
523
		return;
524
	print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->lr);
525
	i = 0;
526
	for(; l < el; l += 4){
527
		v = *(ulong*)l;
528
		if(KTZERO < v && v < (ulong)etext){
529
			print("%.8lux=%.8lux ", l, v);
530
			if(i++ == 4){
531
				print("\n");
532
				i = 0;
533
			}
534
		}
535
	}
536
}
537
 
538
void
539
dumpstack(void)
540
{
541
	callwithureg(_dumpstack);
542
}
543
 
544
void
545
dumpregs(Ureg *ur)
546
{
547
	int i;
548
	ulong *l;
549
 
550
	if(up) {
551
		print("registers for %s %ld\n", up->text, up->pid);
552
		if(ur->srr1 & MSR_PR == 0)
553
		if(ur->usp < (ulong)up->kstack || ur->usp > (ulong)up->kstack+KSTACK)
554
			print("invalid stack ptr\n");
555
	}
556
	else
557
		print("registers for kernel\n");
558
 
559
	for(i=0; i<16; i+=2)
560
		print("sr[%x]\t0x%.8lux\tsr[%x]\t0x%.8lux\n", i, getsr(i<<28), i+1, getsr((i+1)<<28));
561
	l = &ur->cause;
562
	for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2)
563
		print("%s\t0x%.8lux\t%s\t0x%.8lux\n", regname[i], l[0], regname[i+1], l[1]);
564
	delay(500);
565
}
566
 
567
static void
568
linkproc(void)
569
{
570
	spllo();
571
	(*up->kpfun)(up->kparg);
572
	pexit("", 0);
573
}
574
 
575
void
576
kprocchild(Proc *p, void (*func)(void*), void *arg)
577
{
578
	p->sched.pc = (ulong)linkproc;
579
	p->sched.sp = (ulong)p->kstack+KSTACK;
580
 
581
	p->kpfun = func;
582
	p->kparg = arg;
583
}
584
 
585
/*
586
 * called in syscallfmt.c, sysfile.c, sysproc.c
587
 */
588
void
589
validalign(uintptr addr, unsigned align)
590
{
591
	/*
592
	 * Plan 9 is a 32-bit O/S, and the hardware it runs on
593
	 * does not usually have instructions which move 64-bit
594
	 * quantities directly, synthesizing the operations
595
	 * with 32-bit move instructions. Therefore, the compiler
596
	 * (and hardware) usually only enforce 32-bit alignment,
597
	 * if at all.
598
	 *
599
	 * Take this out if the architecture warrants it.
600
	 */
601
	if(align == sizeof(vlong))
602
		align = sizeof(long);
603
 
604
	/*
605
	 * Check align is a power of 2, then addr alignment.
606
	 */
607
	if((align != 0 && !(align & (align-1))) && !(addr & (align-1)))
608
		return;
609
	postnote(up, 1, "sys: odd address", NDebug);
610
	error(Ebadarg);
611
	/*NOTREACHED*/
612
}
613
 
614
long
615
execregs(ulong entry, ulong ssize, ulong nargs)
616
{
617
	ulong *sp;
618
	Ureg *ureg;
619
 
620
	sp = (ulong*)(USTKTOP - ssize);
621
	*--sp = nargs;
622
 
623
	ureg = up->dbgreg;
624
	ureg->usp = (ulong)sp;
625
	ureg->pc = entry;
626
	ureg->srr1 &= ~MSR_FP;		/* disable floating point */
627
	up->fpstate = FPinit;
628
	return USTKTOP-sizeof(Tos);		/* address of kernel/user shared data */
629
}
630
 
631
void
632
forkchild(Proc *p, Ureg *ur)
633
{
634
	Ureg *cur;
635
 
636
	p->sched.sp = (ulong)p->kstack+KSTACK-UREGSIZE;
637
	p->sched.pc = (ulong)forkret;
638
 
639
	cur = (Ureg*)(p->sched.sp+2*BY2WD);
640
	memmove(cur, ur, sizeof(Ureg));
641
	cur->r3 = 0;
642
 
643
	/* Things from bottom of syscall we never got to execute */
644
	p->psstate = 0;
645
	p->insyscall = 0;
646
}
647
 
648
ulong
649
userpc(void)
650
{
651
	Ureg *ureg;
652
 
653
	ureg = (Ureg*)up->dbgreg;
654
	return ureg->pc;
655
}
656
 
657
 
658
/* This routine must save the values of registers the user is not 
659
 * permitted to write from devproc and then restore the saved values 
660
 * before returning
661
 */
662
void
663
setregisters(Ureg *xp, char *pureg, char *uva, int n)
664
{
665
	ulong status;
666
 
667
	status = xp->status;
668
	memmove(pureg, uva, n);
669
	xp->status = status;
670
}
671
 
672
/* Give enough context in the ureg to produce a kernel stack for
673
 * a sleeping process
674
 */
675
void
676
setkernur(Ureg* ureg, Proc* p)
677
{
678
	ureg->pc = p->sched.pc;
679
	ureg->sp = p->sched.sp+4;
680
}
681
 
682
ulong
683
dbgpc(Proc *p)
684
{
685
	Ureg *ureg;
686
 
687
	ureg = p->dbgreg;
688
	if(ureg == 0)
689
		return 0;
690
 
691
	return ureg->pc;
692
}
693
 
694
/*
695
 *  system calls
696
 */
697
#include "../port/systab.h"
698
 
699
/* TODO: make this trap a separate asm entry point, like on other RISC architectures */
700
void
701
syscall(Ureg* ureg)
702
{
703
	int i;
704
	char *e;
705
	long	ret;
706
	ulong sp, scallnr;
707
 
708
	m->syscall++;
709
	up->insyscall = 1;
710
	up->pc = ureg->pc;
711
	up->dbgreg = ureg;
712
 
713
	if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
714
		print("fpstate check, entry syscall\n");
715
		delay(200);
716
		dumpregs(ureg);
717
		print("fpstate check, entry syscall\n");
718
	}
719
 
720
	scallnr = ureg->r3;
721
	up->scallnr = ureg->r3;
722
	if(scallnr == RFORK && up->fpstate == FPactive){
723
		fpsave(&up->fpsave);
724
		up->fpstate = FPinactive;
725
	}
726
	spllo();
727
 
728
	sp = ureg->usp;
729
	up->nerrlab = 0;
730
	ret = -1;
731
	if(!waserror()){
732
		if(scallnr >= nsyscall || systab[scallnr] == nil){
733
			pprint("bad sys call number %ld pc %lux\n", scallnr, ureg->pc);
734
			postnote(up, 1, "sys: bad sys call", NDebug);
735
			error(Ebadarg);
736
		}
737
 
738
		if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
739
			validaddr(sp, sizeof(Sargs)+BY2WD, 0);
740
 
741
		up->s = *((Sargs*)(sp+BY2WD));
742
		up->psstate = sysctab[scallnr];
743
 
744
		ret = systab[scallnr](up->s.args);
745
		poperror();
746
	}else{
747
		/* failure: save the error buffer for errstr */
748
		e = up->syserrstr;
749
		up->syserrstr = up->errstr;
750
		up->errstr = e;
751
	}
752
	if(up->nerrlab){
753
		print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
754
		print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr);
755
		for(i = 0; i < NERR; i++)
756
			print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
757
		panic("error stack");
758
	}
759
 
760
	up->insyscall = 0;
761
	up->psstate = 0;
762
 
763
	/*
764
	 *  Put return value in frame.  On the x86 the syscall is
765
	 *  just another trap and the return value from syscall is
766
	 *  ignored.  On other machines the return value is put into
767
	 *  the results register by caller of syscall.
768
	 */
769
	ureg->r3 = ret;
770
 
771
	if(scallnr == NOTED)
772
		noted(ureg, *(ulong*)(sp+BY2WD));
773
 
774
	/* restoreureg must execute at high IPL */
775
	splhi();
776
	if(scallnr!=RFORK)
777
		notify(ureg);
778
 
779
	if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
780
		print("fpstate check, exit syscall nr %lud, pid %lud\n", scallnr, up->pid);
781
		dumpregs(ureg);
782
	}
783
	if(up->fpstate != FPactive)
784
		ureg->srr1 &= ~MSR_FP;
785
}
786
 
787
/*
788
 *  Call user, if necessary, with note.
789
 *  Pass user the Ureg struct and the note on his stack.
790
 */
791
int
792
notify(Ureg* ur)
793
{
794
	int l;
795
	ulong s, sp;
796
	Note *n;
797
 
798
	if(up->procctl)
799
		procctl(up);
800
	if(up->nnote == 0)
801
		return 0;
802
 
803
	s = spllo();
804
	qlock(&up->debug);
805
	up->notepending = 0;
806
	n = &up->note[0];
807
	if(strncmp(n->msg, "sys:", 4) == 0){
808
		l = strlen(n->msg);
809
		if(l > ERRMAX-15)	/* " pc=0x12345678\0" */
810
			l = ERRMAX-15;
811
		sprint(n->msg+l, " pc=0x%.8lux", ur->pc);
812
	}
813
 
814
	if(n->flag!=NUser && (up->notified || up->notify==0)){
815
		if(n->flag == NDebug)
816
			pprint("suicide: %s\n", n->msg);
817
		qunlock(&up->debug);
818
		pexit(n->msg, n->flag!=NDebug);
819
	}
820
 
821
	if(up->notified) {
822
		qunlock(&up->debug);
823
		splhi();
824
		return 0;
825
	}
826
 
827
	if(!up->notify) {
828
		qunlock(&up->debug);
829
		pexit(n->msg, n->flag!=NDebug);
830
	}
831
 
832
	if(up->fpstate == FPactive){
833
		fpsave(&up->fpsave);
834
		up->fpstate = FPinactive;
835
	}
836
	up->fpstate |= FPillegal;
837
 
838
	sp = ur->usp & ~(BY2V-1);
839
	sp -= sizeof(Ureg);
840
 
841
	if(!okaddr((ulong)up->notify, BY2WD, 0) ||
842
	   !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)) {
843
		pprint("suicide: bad address or sp in notify\n");
844
		qunlock(&up->debug);
845
		pexit("Suicide", 0);
846
	}
847
 
848
	memmove((Ureg*)sp, ur, sizeof(Ureg));
849
	*(Ureg**)(sp-BY2WD) = up->ureg;	/* word under Ureg is old up->ureg */
850
	up->ureg = (void*)sp;
851
	sp -= BY2WD+ERRMAX;
852
	memmove((char*)sp, up->note[0].msg, ERRMAX);
853
	sp -= 3*BY2WD;
854
	*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;	/* arg 2 is string */
855
	ur->r1 = (long)up->ureg;		/* arg 1 is ureg* */
856
	((ulong*)sp)[1] = (ulong)up->ureg;	/* arg 1 0(FP) is ureg* */
857
	((ulong*)sp)[0] = 0;			/* arg 0 is pc */
858
	ur->usp = sp;
859
	ur->pc = (ulong)up->notify;
860
	up->notified = 1;
861
	up->nnote--;
862
	memmove(&up->lastnote, &up->note[0], sizeof(Note));
863
	memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
864
 
865
	qunlock(&up->debug);
866
	splx(s);
867
	return 1;
868
}
869
 
870
 
871
/*
872
 *   Return user to state before notify()
873
 */
874
void
875
noted(Ureg* ureg, ulong arg0)
876
{
877
	Ureg *nureg;
878
	ulong oureg, sp;
879
 
880
	qlock(&up->debug);
881
	if(arg0!=NRSTR && !up->notified) {
882
		qunlock(&up->debug);
883
		pprint("call to noted() when not notified\n");
884
		pexit("Suicide", 0);
885
	}
886
	up->notified = 0;
887
 
888
	nureg = up->ureg;	/* pointer to user returned Ureg struct */
889
 
890
	/* sanity clause */
891
	oureg = (ulong)nureg;
892
	if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
893
		pprint("bad ureg in noted or call to noted when not notified\n");
894
		qunlock(&up->debug);
895
		pexit("Suicide", 0);
896
	}
897
 
898
	memmove(ureg, nureg, sizeof(Ureg));
899
 
900
	switch(arg0){
901
	case NCONT:
902
	case NRSTR:
903
		if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){
904
			pprint("suicide: trap in noted\n");
905
			qunlock(&up->debug);
906
			pexit("Suicide", 0);
907
		}
908
		up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
909
		qunlock(&up->debug);
910
		break;
911
 
912
	case NSAVE:
913
		if(!okaddr(nureg->pc, BY2WD, 0)
914
		|| !okaddr(nureg->usp, BY2WD, 0)){
915
			pprint("suicide: trap in noted\n");
916
			qunlock(&up->debug);
917
			pexit("Suicide", 0);
918
		}
919
		qunlock(&up->debug);
920
		sp = oureg-4*BY2WD-ERRMAX;
921
		splhi();
922
		ureg->sp = sp;
923
		((ulong*)sp)[1] = oureg;	/* arg 1 0(FP) is ureg* */
924
		((ulong*)sp)[0] = 0;		/* arg 0 is pc */
925
		break;
926
 
927
	default:
928
		pprint("unknown noted arg 0x%lux\n", arg0);
929
		up->lastnote.flag = NDebug;
930
		/* fall through */
931
 
932
	case NDFLT:
933
		if(up->lastnote.flag == NDebug)
934
			pprint("suicide: %s\n", up->lastnote.msg);
935
		qunlock(&up->debug);
936
		pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
937
	}
938
	up->fpstate &= ~FPillegal;
939
	if (up->fpstate == FPactive)
940
		ureg->srr1 |= MSR_FP;
941
	else
942
		ureg->srr1 &= ~MSR_FP;
943
}