xref: /plan9-contrib/sys/src/9k/k10/syscall.c (revision d2e450be46c1f486e7113435d56267330fd9a676)
19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier 
79ef1f84bSDavid du Colombier #include "../port/error.h"
89ef1f84bSDavid du Colombier 
99ef1f84bSDavid du Colombier #include "/sys/src/libc/9syscall/sys.h"
109ef1f84bSDavid du Colombier 
119ef1f84bSDavid du Colombier #include <tos.h>
12d46407a3SDavid du Colombier #include <ptrace.h>
139ef1f84bSDavid du Colombier 
149ef1f84bSDavid du Colombier #include "amd64.h"
159ef1f84bSDavid du Colombier #include "ureg.h"
169ef1f84bSDavid du Colombier 
179ef1f84bSDavid du Colombier typedef struct {
189ef1f84bSDavid du Colombier 	uintptr	ip;
199ef1f84bSDavid du Colombier 	Ureg*	arg0;
209ef1f84bSDavid du Colombier 	char*	arg1;
219ef1f84bSDavid du Colombier 	char	msg[ERRMAX];
229ef1f84bSDavid du Colombier 	Ureg*	old;
239ef1f84bSDavid du Colombier 	Ureg	ureg;
249ef1f84bSDavid du Colombier } NFrame;
259ef1f84bSDavid du Colombier 
269ef1f84bSDavid du Colombier /*
279ef1f84bSDavid du Colombier  *   Return user to state before notify()
289ef1f84bSDavid du Colombier  */
299ef1f84bSDavid du Colombier static void
noted(Ureg * cur,uintptr arg0)309ef1f84bSDavid du Colombier noted(Ureg* cur, uintptr arg0)
319ef1f84bSDavid du Colombier {
329ef1f84bSDavid du Colombier 	NFrame *nf;
339ef1f84bSDavid du Colombier 	Note note;
349ef1f84bSDavid du Colombier 	Ureg *nur;
359ef1f84bSDavid du Colombier 
369ef1f84bSDavid du Colombier 	qlock(&up->debug);
379ef1f84bSDavid du Colombier 	if(arg0 != NRSTR && !up->notified){
389ef1f84bSDavid du Colombier 		qunlock(&up->debug);
399ef1f84bSDavid du Colombier 		pprint("suicide: call to noted when not notified\n");
409ef1f84bSDavid du Colombier 		pexit("Suicide", 0);
419ef1f84bSDavid du Colombier 	}
429ef1f84bSDavid du Colombier 	up->notified = 0;
439ef1f84bSDavid du Colombier 	fpunoted();
449ef1f84bSDavid du Colombier 
459ef1f84bSDavid du Colombier 	nf = up->ureg;
469ef1f84bSDavid du Colombier 
479ef1f84bSDavid du Colombier 	/* sanity clause */
489ef1f84bSDavid du Colombier 	if(!okaddr(PTR2UINT(nf), sizeof(NFrame), 0)){
499ef1f84bSDavid du Colombier 		qunlock(&up->debug);
509ef1f84bSDavid du Colombier 		pprint("suicide: bad ureg %#p in noted\n", nf);
519ef1f84bSDavid du Colombier 		pexit("Suicide", 0);
529ef1f84bSDavid du Colombier 	}
539ef1f84bSDavid du Colombier 
549ef1f84bSDavid du Colombier 	/*
559ef1f84bSDavid du Colombier 	 * Check the segment selectors are all valid.
569ef1f84bSDavid du Colombier 	 */
579ef1f84bSDavid du Colombier 	nur = &nf->ureg;
58*d2e450beSDavid du Colombier #ifdef notdef
599ef1f84bSDavid du Colombier 	if(nur->cs != SSEL(SiUCS, SsRPL3) || nur->ss != SSEL(SiUDS, SsRPL3)
609ef1f84bSDavid du Colombier 	|| nur->ds != SSEL(SiUDS, SsRPL3) || nur->es != SSEL(SiUDS, SsRPL3)
619ef1f84bSDavid du Colombier 	|| nur->fs != SSEL(SiUDS, SsRPL3) || nur->gs != SSEL(SiUDS, SsRPL3)){
629ef1f84bSDavid du Colombier 		qunlock(&up->debug);
639ef1f84bSDavid du Colombier 		pprint("suicide: bad segment selector in noted\n");
649ef1f84bSDavid du Colombier 		pexit("Suicide", 0);
659ef1f84bSDavid du Colombier 	}
66*d2e450beSDavid du Colombier #endif /* notdef */
679ef1f84bSDavid du Colombier 
689ef1f84bSDavid du Colombier 	/* don't let user change system flags */
699ef1f84bSDavid du Colombier 	nur->flags &= (Of|Df|Sf|Zf|Af|Pf|Cf);
709ef1f84bSDavid du Colombier 	nur->flags |= cur->flags & ~(Of|Df|Sf|Zf|Af|Pf|Cf);
719ef1f84bSDavid du Colombier 
729ef1f84bSDavid du Colombier 	memmove(cur, nur, sizeof(Ureg));
739ef1f84bSDavid du Colombier 
749ef1f84bSDavid du Colombier 	switch((int)arg0){
759ef1f84bSDavid du Colombier 	case NCONT:
769ef1f84bSDavid du Colombier 	case NRSTR:
779ef1f84bSDavid du Colombier 		if(!okaddr(nur->ip, BY2SE, 0) || !okaddr(nur->sp, BY2SE, 0)){
789ef1f84bSDavid du Colombier 			qunlock(&up->debug);
799ef1f84bSDavid du Colombier 			pprint("suicide: trap in noted pc=%#p sp=%#p\n",
809ef1f84bSDavid du Colombier 				nur->ip, nur->sp);
819ef1f84bSDavid du Colombier 			pexit("Suicide", 0);
829ef1f84bSDavid du Colombier 		}
839ef1f84bSDavid du Colombier 		up->ureg = nf->old;
849ef1f84bSDavid du Colombier 		qunlock(&up->debug);
859ef1f84bSDavid du Colombier 		break;
869ef1f84bSDavid du Colombier 	case NSAVE:
879ef1f84bSDavid du Colombier 		if(!okaddr(nur->ip, BY2SE, 0) || !okaddr(nur->sp, BY2SE, 0)){
889ef1f84bSDavid du Colombier 			qunlock(&up->debug);
899ef1f84bSDavid du Colombier 			pprint("suicide: trap in noted pc=%#p sp=%#p\n",
909ef1f84bSDavid du Colombier 				nur->ip, nur->sp);
919ef1f84bSDavid du Colombier 			pexit("Suicide", 0);
929ef1f84bSDavid du Colombier 		}
939ef1f84bSDavid du Colombier 		qunlock(&up->debug);
949ef1f84bSDavid du Colombier 
959ef1f84bSDavid du Colombier 		splhi();
969ef1f84bSDavid du Colombier 		nf->arg1 = nf->msg;
979ef1f84bSDavid du Colombier 		nf->arg0 = &nf->ureg;
989ef1f84bSDavid du Colombier 		cur->bp = PTR2UINT(nf->arg0);
999ef1f84bSDavid du Colombier 		nf->ip = 0;
1009ef1f84bSDavid du Colombier 		cur->sp = PTR2UINT(nf);
1019ef1f84bSDavid du Colombier 		break;
1029ef1f84bSDavid du Colombier 	default:
1039ef1f84bSDavid du Colombier 		memmove(&note, &up->lastnote, sizeof(Note));
1049ef1f84bSDavid du Colombier 		qunlock(&up->debug);
1059ef1f84bSDavid du Colombier 		pprint("suicide: bad arg %#p in noted: %s\n", arg0, note.msg);
1069ef1f84bSDavid du Colombier 		pexit(note.msg, 0);
1079ef1f84bSDavid du Colombier 		break;
1089ef1f84bSDavid du Colombier 	case NDFLT:
1099ef1f84bSDavid du Colombier 		memmove(&note, &up->lastnote, sizeof(Note));
1109ef1f84bSDavid du Colombier 		qunlock(&up->debug);
1119ef1f84bSDavid du Colombier 		if(note.flag == NDebug)
1129ef1f84bSDavid du Colombier 			pprint("suicide: %s\n", note.msg);
1139ef1f84bSDavid du Colombier 		pexit(note.msg, note.flag != NDebug);
1149ef1f84bSDavid du Colombier 		break;
1159ef1f84bSDavid du Colombier 	}
1169ef1f84bSDavid du Colombier }
1179ef1f84bSDavid du Colombier 
1189ef1f84bSDavid du Colombier /*
1199ef1f84bSDavid du Colombier  *  Call user, if necessary, with note.
1209ef1f84bSDavid du Colombier  *  Pass user the Ureg struct and the note on his stack.
1219ef1f84bSDavid du Colombier  */
1229ef1f84bSDavid du Colombier int
notify(Ureg * ureg)1239ef1f84bSDavid du Colombier notify(Ureg* ureg)
1249ef1f84bSDavid du Colombier {
1259ef1f84bSDavid du Colombier 	int l;
1269ef1f84bSDavid du Colombier 	Mreg s;
1279ef1f84bSDavid du Colombier 	Note note;
1289ef1f84bSDavid du Colombier 	uintptr sp;
1299ef1f84bSDavid du Colombier 	NFrame *nf;
1309ef1f84bSDavid du Colombier 
1319ef1f84bSDavid du Colombier 	if(up->procctl)
1329ef1f84bSDavid du Colombier 		procctl(up);
1339ef1f84bSDavid du Colombier 	if(up->nnote == 0)
1349ef1f84bSDavid du Colombier 		return 0;
1359ef1f84bSDavid du Colombier 
1369ef1f84bSDavid du Colombier 	fpunotify(ureg);
1379ef1f84bSDavid du Colombier 
1389ef1f84bSDavid du Colombier 	s = spllo();
1399ef1f84bSDavid du Colombier 	qlock(&up->debug);
1409ef1f84bSDavid du Colombier 
1419ef1f84bSDavid du Colombier 	up->notepending = 0;
1429ef1f84bSDavid du Colombier 	memmove(&note, &up->note[0], sizeof(Note));
1439ef1f84bSDavid du Colombier 	if(strncmp(note.msg, "sys:", 4) == 0){
1449ef1f84bSDavid du Colombier 		l = strlen(note.msg);
1459ef1f84bSDavid du Colombier 		if(l > ERRMAX-sizeof(" pc=0x0123456789abcdef"))
1469ef1f84bSDavid du Colombier 			l = ERRMAX-sizeof(" pc=0x0123456789abcdef");
1479ef1f84bSDavid du Colombier 		sprint(note.msg+l, " pc=%#p", ureg->ip);
1489ef1f84bSDavid du Colombier 	}
1499ef1f84bSDavid du Colombier 
1509ef1f84bSDavid du Colombier 	if(note.flag != NUser && (up->notified || up->notify == nil)){
1519ef1f84bSDavid du Colombier 		qunlock(&up->debug);
1529ef1f84bSDavid du Colombier 		if(note.flag == NDebug)
1539ef1f84bSDavid du Colombier 			pprint("suicide: %s\n", note.msg);
1549ef1f84bSDavid du Colombier 		pexit(note.msg, note.flag != NDebug);
1559ef1f84bSDavid du Colombier 	}
1569ef1f84bSDavid du Colombier 
1579ef1f84bSDavid du Colombier 	if(up->notified){
1589ef1f84bSDavid du Colombier 		qunlock(&up->debug);
1599ef1f84bSDavid du Colombier 		splhi();
1609ef1f84bSDavid du Colombier 		return 0;
1619ef1f84bSDavid du Colombier 	}
1629ef1f84bSDavid du Colombier 
1639ef1f84bSDavid du Colombier 	if(up->notify == nil){
1649ef1f84bSDavid du Colombier 		qunlock(&up->debug);
1659ef1f84bSDavid du Colombier 		pexit(note.msg, note.flag != NDebug);
1669ef1f84bSDavid du Colombier 	}
1679ef1f84bSDavid du Colombier 	if(!okaddr(PTR2UINT(up->notify), sizeof(ureg->ip), 0)){
1689ef1f84bSDavid du Colombier 		qunlock(&up->debug);
1699ef1f84bSDavid du Colombier 		pprint("suicide: bad function address %#p in notify\n",
1709ef1f84bSDavid du Colombier 			up->notify);
1719ef1f84bSDavid du Colombier 		pexit("Suicide", 0);
1729ef1f84bSDavid du Colombier 	}
1739ef1f84bSDavid du Colombier 
1749ef1f84bSDavid du Colombier 	sp = ureg->sp - sizeof(NFrame);
1759ef1f84bSDavid du Colombier 	if(!okaddr(sp, sizeof(NFrame), 1)){
1769ef1f84bSDavid du Colombier 		qunlock(&up->debug);
1779ef1f84bSDavid du Colombier 		pprint("suicide: bad stack address %#p in notify\n", sp);
1789ef1f84bSDavid du Colombier 		pexit("Suicide", 0);
1799ef1f84bSDavid du Colombier 	}
1809ef1f84bSDavid du Colombier 
1819ef1f84bSDavid du Colombier 	nf = UINT2PTR(sp);
1829ef1f84bSDavid du Colombier 	memmove(&nf->ureg, ureg, sizeof(Ureg));
1839ef1f84bSDavid du Colombier 	nf->old = up->ureg;
1849ef1f84bSDavid du Colombier 	up->ureg = nf;
1859ef1f84bSDavid du Colombier 	memmove(nf->msg, note.msg, ERRMAX);
1869ef1f84bSDavid du Colombier 	nf->arg1 = nf->msg;
1879ef1f84bSDavid du Colombier 	nf->arg0 = &nf->ureg;
1889ef1f84bSDavid du Colombier 	ureg->bp = PTR2UINT(nf->arg0);
1899ef1f84bSDavid du Colombier 	nf->ip = 0;
1909ef1f84bSDavid du Colombier 
1919ef1f84bSDavid du Colombier 	ureg->sp = sp;
1929ef1f84bSDavid du Colombier 	ureg->ip = PTR2UINT(up->notify);
1939ef1f84bSDavid du Colombier 	up->notified = 1;
1949ef1f84bSDavid du Colombier 	up->nnote--;
1959ef1f84bSDavid du Colombier 	memmove(&up->lastnote, &note, sizeof(Note));
1969ef1f84bSDavid du Colombier 	memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
1979ef1f84bSDavid du Colombier 
1989ef1f84bSDavid du Colombier 	qunlock(&up->debug);
1999ef1f84bSDavid du Colombier 	splx(s);
2009ef1f84bSDavid du Colombier 
2019ef1f84bSDavid du Colombier 	return 1;
2029ef1f84bSDavid du Colombier }
2039ef1f84bSDavid du Colombier 
2049ef1f84bSDavid du Colombier void
syscall(int scallnr,Ureg * ureg)2059ef1f84bSDavid du Colombier syscall(int scallnr, Ureg* ureg)
2069ef1f84bSDavid du Colombier {
2079ef1f84bSDavid du Colombier 	char *e;
2089ef1f84bSDavid du Colombier 	uintptr	sp;
2099ef1f84bSDavid du Colombier 	int i, s;
2109ef1f84bSDavid du Colombier 	vlong startns, stopns;
2119ef1f84bSDavid du Colombier 	Ar0 ar0;
2129ef1f84bSDavid du Colombier 	static Ar0 zar0;
213d46407a3SDavid du Colombier 	void (*pt)(Proc*, int, vlong, vlong);
2149ef1f84bSDavid du Colombier 
2159ef1f84bSDavid du Colombier 	if(!userureg(ureg))
2169ef1f84bSDavid du Colombier 		panic("syscall: cs %#llux\n", ureg->cs);
2179ef1f84bSDavid du Colombier 
2189ef1f84bSDavid du Colombier 	cycles(&up->kentry);
2199ef1f84bSDavid du Colombier 
2209ef1f84bSDavid du Colombier 	m->syscall++;
2219ef1f84bSDavid du Colombier 	up->insyscall = 1;
2229ef1f84bSDavid du Colombier 	up->pc = ureg->ip;
2239ef1f84bSDavid du Colombier 	sp = ureg->sp;
2249ef1f84bSDavid du Colombier 	up->scallnr = scallnr;
2259ef1f84bSDavid du Colombier 	up->dbgreg = ureg;
2269ef1f84bSDavid du Colombier 	startns = 0;
2279ef1f84bSDavid du Colombier 
228d46407a3SDavid du Colombier 	if(up->trace && (pt = proctrace) != nil)
229d46407a3SDavid du Colombier 		pt(up, STrap, todget(nil), STrapSC|scallnr);
230d46407a3SDavid du Colombier 
2319ef1f84bSDavid du Colombier 	if(up->procctl == Proc_tracesyscall){
2329ef1f84bSDavid du Colombier 		/*
2339ef1f84bSDavid du Colombier 		 * Redundant validaddr.  Do we care?
2349ef1f84bSDavid du Colombier 		 * Tracing syscalls is not exactly a fast path...
2359ef1f84bSDavid du Colombier 		 * Beware, validaddr currently does a pexit rather
2369ef1f84bSDavid du Colombier 		 * than an error if there's a problem; that might
2379ef1f84bSDavid du Colombier 		 * change in the future.
2389ef1f84bSDavid du Colombier 		 */
2399ef1f84bSDavid du Colombier 		if(sp < (USTKTOP-PGSZ) || sp > (USTKTOP-sizeof(up->arg)-BY2V))
2409ef1f84bSDavid du Colombier 			validaddr((void *)sp, sizeof(up->arg)+BY2V, 0);
2419ef1f84bSDavid du Colombier 
2429ef1f84bSDavid du Colombier 		syscallfmt(scallnr, (va_list)(sp+BY2V));
2439ef1f84bSDavid du Colombier 		up->procctl = Proc_stopme;
2449ef1f84bSDavid du Colombier 		procctl(up);
2459ef1f84bSDavid du Colombier 		if(up->syscalltrace)
2469ef1f84bSDavid du Colombier 			free(up->syscalltrace);
2479ef1f84bSDavid du Colombier 		up->syscalltrace = nil;
2489ef1f84bSDavid du Colombier 		startns = todget(nil);
2499ef1f84bSDavid du Colombier 	}
2509ef1f84bSDavid du Colombier 
2519ef1f84bSDavid du Colombier 	if(scallnr == RFORK)
2529ef1f84bSDavid du Colombier 		fpusysrfork(ureg);
2539ef1f84bSDavid du Colombier 	spllo();
2549ef1f84bSDavid du Colombier 
2559ef1f84bSDavid du Colombier 	up->nerrlab = 0;
2569ef1f84bSDavid du Colombier 	ar0 = zar0;
2579ef1f84bSDavid du Colombier 	if(!waserror()){
2589ef1f84bSDavid du Colombier 		if(scallnr >= nsyscall || systab[scallnr].f == nil){
2599ef1f84bSDavid du Colombier 			pprint("bad sys call number %d pc %#llux\n",
2609ef1f84bSDavid du Colombier 				scallnr, ureg->ip);
2619ef1f84bSDavid du Colombier 			postnote(up, 1, "sys: bad sys call", NDebug);
2629ef1f84bSDavid du Colombier 			error(Ebadarg);
2639ef1f84bSDavid du Colombier 		}
2649ef1f84bSDavid du Colombier 
2659ef1f84bSDavid du Colombier 		if(sp < (USTKTOP-PGSZ) || sp > (USTKTOP-sizeof(up->arg)-BY2SE))
2669ef1f84bSDavid du Colombier 			validaddr(UINT2PTR(sp), sizeof(up->arg)+BY2SE, 0);
2679ef1f84bSDavid du Colombier 
2689ef1f84bSDavid du Colombier 		memmove(up->arg, UINT2PTR(sp+BY2SE), sizeof(up->arg));
2699ef1f84bSDavid du Colombier 		up->psstate = systab[scallnr].n;
2709ef1f84bSDavid du Colombier 
2719ef1f84bSDavid du Colombier 		systab[scallnr].f(&ar0, (va_list)up->arg);
2729ef1f84bSDavid du Colombier 		poperror();
2739ef1f84bSDavid du Colombier 	}
2749ef1f84bSDavid du Colombier 	else{
2759ef1f84bSDavid du Colombier 		/* failure: save the error buffer for errstr */
2769ef1f84bSDavid du Colombier 		e = up->syserrstr;
2779ef1f84bSDavid du Colombier 		up->syserrstr = up->errstr;
2789ef1f84bSDavid du Colombier 		up->errstr = e;
2799ef1f84bSDavid du Colombier 		if(DBGFLG && up->pid == 1)
2809ef1f84bSDavid du Colombier 			iprint("%s: syscall %s error %s\n",
2819ef1f84bSDavid du Colombier 				up->text, systab[scallnr].n, up->syserrstr);
2829ef1f84bSDavid du Colombier 		ar0 = systab[scallnr].r;
2839ef1f84bSDavid du Colombier 	}
2849ef1f84bSDavid du Colombier 	if(up->nerrlab){
2859ef1f84bSDavid du Colombier 		print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
2869ef1f84bSDavid du Colombier 		for(i = 0; i < NERR; i++)
2879ef1f84bSDavid du Colombier 			print("sp=%#p pc=%#p\n",
2889ef1f84bSDavid du Colombier 				up->errlab[i].sp, up->errlab[i].pc);
2899ef1f84bSDavid du Colombier 		panic("error stack");
2909ef1f84bSDavid du Colombier 	}
2919ef1f84bSDavid du Colombier 
2929ef1f84bSDavid du Colombier 	/*
2939ef1f84bSDavid du Colombier 	 * Put return value in frame.
2949ef1f84bSDavid du Colombier 	 * Which element of Ar0 to use is based on specific
2952f4a50f4SDavid du Colombier 	 * knowledge of the architecture.
2969ef1f84bSDavid du Colombier 	 */
2979ef1f84bSDavid du Colombier 	ureg->ax = ar0.p;
2989ef1f84bSDavid du Colombier 
2999ef1f84bSDavid du Colombier 	if(up->procctl == Proc_tracesyscall){
3009ef1f84bSDavid du Colombier 		stopns = todget(nil);
3019ef1f84bSDavid du Colombier 		up->procctl = Proc_stopme;
3029ef1f84bSDavid du Colombier 		sysretfmt(scallnr, (va_list)(sp+BY2V), &ar0, startns, stopns);
3039ef1f84bSDavid du Colombier 		s = splhi();
3049ef1f84bSDavid du Colombier 		procctl(up);
3059ef1f84bSDavid du Colombier 		splx(s);
3069ef1f84bSDavid du Colombier 		if(up->syscalltrace)
3079ef1f84bSDavid du Colombier 			free(up->syscalltrace);
3089ef1f84bSDavid du Colombier 		up->syscalltrace = nil;
3099ef1f84bSDavid du Colombier 	}
3109ef1f84bSDavid du Colombier 
3119ef1f84bSDavid du Colombier 	up->insyscall = 0;
3129ef1f84bSDavid du Colombier 	up->psstate = 0;
3139ef1f84bSDavid du Colombier 
3149ef1f84bSDavid du Colombier 	if(scallnr == NOTED)
3159ef1f84bSDavid du Colombier 		noted(ureg, *(uintptr*)(sp+BY2SE));
3169ef1f84bSDavid du Colombier 
3179ef1f84bSDavid du Colombier 	splhi();
3185891e653SDavid du Colombier 	if(scallnr != RFORK && scallnr != NSEC && (up->procctl || up->nnote))
3199ef1f84bSDavid du Colombier 		notify(ureg);
3209ef1f84bSDavid du Colombier 
3219ef1f84bSDavid du Colombier 	/* if we delayed sched because we held a lock, sched now */
3229ef1f84bSDavid du Colombier 	if(up->delaysched){
3239ef1f84bSDavid du Colombier 		sched();
3249ef1f84bSDavid du Colombier 		splhi();
3259ef1f84bSDavid du Colombier 	}
3269ef1f84bSDavid du Colombier 	kexit(ureg);
3279ef1f84bSDavid du Colombier }
3289ef1f84bSDavid du Colombier 
3299ef1f84bSDavid du Colombier uintptr
sysexecstack(uintptr stack,int argc)3309ef1f84bSDavid du Colombier sysexecstack(uintptr stack, int argc)
3319ef1f84bSDavid du Colombier {
3329ef1f84bSDavid du Colombier 	/*
3339ef1f84bSDavid du Colombier 	 * Given a current bottom-of-stack and a count
3349ef1f84bSDavid du Colombier 	 * of pointer arguments to be pushed onto it followed
3359ef1f84bSDavid du Colombier 	 * by an integer argument count, return a suitably
3369ef1f84bSDavid du Colombier 	 * aligned new bottom-of-stack which will satisfy any
3379ef1f84bSDavid du Colombier 	 * hardware stack-alignment contraints.
3389ef1f84bSDavid du Colombier 	 * Rounding the stack down to be aligned with the
3399ef1f84bSDavid du Colombier 	 * natural size of a pointer variable usually suffices,
3409ef1f84bSDavid du Colombier 	 * but some architectures impose further restrictions,
3419ef1f84bSDavid du Colombier 	 * e.g. 32-bit SPARC, where the stack must be 8-byte
3429ef1f84bSDavid du Colombier 	 * aligned although pointers and integers are 32-bits.
3439ef1f84bSDavid du Colombier 	 */
3449ef1f84bSDavid du Colombier 	USED(argc);
3459ef1f84bSDavid du Colombier 
3469ef1f84bSDavid du Colombier 	return STACKALIGN(stack);
3479ef1f84bSDavid du Colombier }
3489ef1f84bSDavid du Colombier 
3499ef1f84bSDavid du Colombier void*
sysexecregs(uintptr entry,ulong ssize,ulong nargs)3509ef1f84bSDavid du Colombier sysexecregs(uintptr entry, ulong ssize, ulong nargs)
3519ef1f84bSDavid du Colombier {
3529ef1f84bSDavid du Colombier 	uintptr *sp;
3539ef1f84bSDavid du Colombier 	Ureg *ureg;
3549ef1f84bSDavid du Colombier 
3559ef1f84bSDavid du Colombier 	sp = (uintptr*)(USTKTOP - ssize);
3569ef1f84bSDavid du Colombier 	*--sp = nargs;
3579ef1f84bSDavid du Colombier 
3589ef1f84bSDavid du Colombier 	ureg = up->dbgreg;
3599ef1f84bSDavid du Colombier 	ureg->sp = PTR2UINT(sp);
3609ef1f84bSDavid du Colombier 	ureg->ip = entry;
3619ef1f84bSDavid du Colombier 	ureg->type = 64;			/* fiction for acid */
3629ef1f84bSDavid du Colombier 
3639ef1f84bSDavid du Colombier 	/*
3649ef1f84bSDavid du Colombier 	 * return the address of kernel/user shared data
3659ef1f84bSDavid du Colombier 	 * (e.g. clock stuff)
3669ef1f84bSDavid du Colombier 	 */
3679ef1f84bSDavid du Colombier 	return UINT2PTR(USTKTOP-sizeof(Tos));
3689ef1f84bSDavid du Colombier }
3699ef1f84bSDavid du Colombier 
3709ef1f84bSDavid du Colombier void
sysprocsetup(Proc * p)3719ef1f84bSDavid du Colombier sysprocsetup(Proc* p)
3729ef1f84bSDavid du Colombier {
3739ef1f84bSDavid du Colombier 	fpusysprocsetup(p);
3749ef1f84bSDavid du Colombier }
3759ef1f84bSDavid du Colombier 
3769ef1f84bSDavid du Colombier void
sysrforkchild(Proc * child,Proc * parent)3779ef1f84bSDavid du Colombier sysrforkchild(Proc* child, Proc* parent)
3789ef1f84bSDavid du Colombier {
3799ef1f84bSDavid du Colombier 	Ureg *cureg;
3809ef1f84bSDavid du Colombier 
3819ef1f84bSDavid du Colombier 	/*
3829ef1f84bSDavid du Colombier 	 * Add 3*BY2SE to the stack to account for
3839ef1f84bSDavid du Colombier 	 *  - the return PC
3849ef1f84bSDavid du Colombier 	 *  - trap's arguments (syscallnr, ureg)
3859ef1f84bSDavid du Colombier 	 */
3869ef1f84bSDavid du Colombier 	child->sched.sp = PTR2UINT(child->kstack+KSTACK-(sizeof(Ureg)+3*BY2SE));
3879ef1f84bSDavid du Colombier 	child->sched.pc = PTR2UINT(sysrforkret);
3889ef1f84bSDavid du Colombier 
3899ef1f84bSDavid du Colombier 	cureg = (Ureg*)(child->sched.sp+3*BY2SE);
3909ef1f84bSDavid du Colombier 	memmove(cureg, parent->dbgreg, sizeof(Ureg));
3919ef1f84bSDavid du Colombier 
3929ef1f84bSDavid du Colombier 	/* Things from bottom of syscall which were never executed */
3939ef1f84bSDavid du Colombier 	child->psstate = 0;
3949ef1f84bSDavid du Colombier 	child->insyscall = 0;
3959ef1f84bSDavid du Colombier 
3969ef1f84bSDavid du Colombier 	fpusysrforkchild(child, parent);
3979ef1f84bSDavid du Colombier }
398