13de6a9c0SDavid du Colombier /* we use l1 and l2 cache ops to help stability. */
23de6a9c0SDavid du Colombier
33de6a9c0SDavid du Colombier #include "u.h"
43de6a9c0SDavid du Colombier #include "../port/lib.h"
53de6a9c0SDavid du Colombier #include "mem.h"
63de6a9c0SDavid du Colombier #include "dat.h"
73de6a9c0SDavid du Colombier #include "fns.h"
83de6a9c0SDavid du Colombier #include "../port/error.h"
93de6a9c0SDavid du Colombier #include "../port/systab.h"
103de6a9c0SDavid du Colombier
113de6a9c0SDavid du Colombier #include <tos.h>
123de6a9c0SDavid du Colombier #include "ureg.h"
133de6a9c0SDavid du Colombier
143de6a9c0SDavid du Colombier #include "arm.h"
153de6a9c0SDavid du Colombier
163de6a9c0SDavid du Colombier enum {
173de6a9c0SDavid du Colombier Psrsysbits = PsrMask | PsrDfiq | PsrDirq | PsrDasabt | PsrMbz,
183de6a9c0SDavid du Colombier };
193de6a9c0SDavid du Colombier
203de6a9c0SDavid du Colombier typedef struct {
213de6a9c0SDavid du Colombier uintptr ip;
223de6a9c0SDavid du Colombier Ureg* arg0;
233de6a9c0SDavid du Colombier char* arg1;
243de6a9c0SDavid du Colombier char msg[ERRMAX];
253de6a9c0SDavid du Colombier Ureg* old;
263de6a9c0SDavid du Colombier Ureg ureg;
273de6a9c0SDavid du Colombier } NFrame;
283de6a9c0SDavid du Colombier
293de6a9c0SDavid du Colombier /*
303de6a9c0SDavid du Colombier * Return user to state before notify()
313de6a9c0SDavid du Colombier */
323de6a9c0SDavid du Colombier static void
noted(Ureg * cur,uintptr arg0)333de6a9c0SDavid du Colombier noted(Ureg* cur, uintptr arg0)
343de6a9c0SDavid du Colombier {
353de6a9c0SDavid du Colombier NFrame *nf;
363de6a9c0SDavid du Colombier Ureg *nur;
373de6a9c0SDavid du Colombier
383de6a9c0SDavid du Colombier qlock(&up->debug);
393de6a9c0SDavid du Colombier if(arg0 != NRSTR && !up->notified){
403de6a9c0SDavid du Colombier qunlock(&up->debug);
413de6a9c0SDavid du Colombier pprint("call to noted() when not notified\n");
423de6a9c0SDavid du Colombier pexit("Suicide", 0);
433de6a9c0SDavid du Colombier }
443de6a9c0SDavid du Colombier up->notified = 0;
453de6a9c0SDavid du Colombier fpunoted();
463de6a9c0SDavid du Colombier
473de6a9c0SDavid du Colombier nf = up->ureg;
483de6a9c0SDavid du Colombier
493de6a9c0SDavid du Colombier /* sanity clause */
503de6a9c0SDavid du Colombier if(!okaddr(PTR2UINT(nf), sizeof(NFrame), 0)){
513de6a9c0SDavid du Colombier qunlock(&up->debug);
523de6a9c0SDavid du Colombier pprint("bad ureg in noted %#p\n", nf);
533de6a9c0SDavid du Colombier pexit("Suicide", 0);
543de6a9c0SDavid du Colombier }
553de6a9c0SDavid du Colombier
563de6a9c0SDavid du Colombier /* don't let user change system flags */
573de6a9c0SDavid du Colombier nur = &nf->ureg;
583de6a9c0SDavid du Colombier nur->psr &= Psrsysbits;
593de6a9c0SDavid du Colombier nur->psr |= cur->psr & ~Psrsysbits;
603de6a9c0SDavid du Colombier
613de6a9c0SDavid du Colombier memmove(cur, nur, sizeof(Ureg));
623de6a9c0SDavid du Colombier
633de6a9c0SDavid du Colombier switch((int)arg0){
643de6a9c0SDavid du Colombier case NCONT:
653de6a9c0SDavid du Colombier case NRSTR:
663de6a9c0SDavid du Colombier if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->sp, BY2WD, 0)){
673de6a9c0SDavid du Colombier qunlock(&up->debug);
683de6a9c0SDavid du Colombier pprint("suicide: trap in noted\n");
693de6a9c0SDavid du Colombier pexit("Suicide", 0);
703de6a9c0SDavid du Colombier }
713de6a9c0SDavid du Colombier up->ureg = nf->old;
723de6a9c0SDavid du Colombier qunlock(&up->debug);
733de6a9c0SDavid du Colombier break;
743de6a9c0SDavid du Colombier case NSAVE:
753de6a9c0SDavid du Colombier if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->sp, BY2WD, 0)){
763de6a9c0SDavid du Colombier qunlock(&up->debug);
773de6a9c0SDavid du Colombier pprint("suicide: trap in noted\n");
783de6a9c0SDavid du Colombier pexit("Suicide", 0);
793de6a9c0SDavid du Colombier }
803de6a9c0SDavid du Colombier qunlock(&up->debug);
813de6a9c0SDavid du Colombier
823de6a9c0SDavid du Colombier splhi();
83*39120342SDavid du Colombier nf->arg1 = nf->msg; /* arg 1 is string */
84*39120342SDavid du Colombier nf->arg0 = &nf->ureg; /* arg 0 XX(FP) is ureg* */
853de6a9c0SDavid du Colombier nf->ip = 0;
863de6a9c0SDavid du Colombier cur->sp = PTR2UINT(nf);
87*39120342SDavid du Colombier cur->r0 = PTR2UINT(nf->arg0); /* arg 0 in reg is ureg* */
883de6a9c0SDavid du Colombier break;
893de6a9c0SDavid du Colombier default:
903de6a9c0SDavid du Colombier pprint("unknown noted arg %#p\n", arg0);
913de6a9c0SDavid du Colombier up->lastnote.flag = NDebug;
923de6a9c0SDavid du Colombier /*FALLTHROUGH*/
933de6a9c0SDavid du Colombier case NDFLT:
943de6a9c0SDavid du Colombier if(up->lastnote.flag == NDebug){
953de6a9c0SDavid du Colombier qunlock(&up->debug);
963de6a9c0SDavid du Colombier pprint("suicide: %s\n", up->lastnote.msg);
973de6a9c0SDavid du Colombier }
983de6a9c0SDavid du Colombier else
993de6a9c0SDavid du Colombier qunlock(&up->debug);
1003de6a9c0SDavid du Colombier pexit(up->lastnote.msg, up->lastnote.flag != NDebug);
1013de6a9c0SDavid du Colombier }
1023de6a9c0SDavid du Colombier }
1033de6a9c0SDavid du Colombier
1043de6a9c0SDavid du Colombier /*
1053de6a9c0SDavid du Colombier * Call user, if necessary, with note.
1063de6a9c0SDavid du Colombier * Pass user the Ureg struct and the note on his stack.
1073de6a9c0SDavid du Colombier */
1083de6a9c0SDavid du Colombier int
notify(Ureg * ureg)1093de6a9c0SDavid du Colombier notify(Ureg* ureg)
1103de6a9c0SDavid du Colombier {
1113de6a9c0SDavid du Colombier int l;
1123de6a9c0SDavid du Colombier Note *n;
1133de6a9c0SDavid du Colombier u32int s;
1143de6a9c0SDavid du Colombier uintptr sp;
1153de6a9c0SDavid du Colombier NFrame *nf;
1163de6a9c0SDavid du Colombier
1173de6a9c0SDavid du Colombier if(up->procctl)
1183de6a9c0SDavid du Colombier procctl(up);
1193de6a9c0SDavid du Colombier if(up->nnote == 0)
1203de6a9c0SDavid du Colombier return 0;
1213de6a9c0SDavid du Colombier
1223de6a9c0SDavid du Colombier fpunotify(ureg);
1233de6a9c0SDavid du Colombier
1243de6a9c0SDavid du Colombier s = spllo();
1253de6a9c0SDavid du Colombier qlock(&up->debug);
1263de6a9c0SDavid du Colombier
1273de6a9c0SDavid du Colombier up->notepending = 0;
1283de6a9c0SDavid du Colombier n = &up->note[0];
1293de6a9c0SDavid du Colombier if(strncmp(n->msg, "sys:", 4) == 0){
1303de6a9c0SDavid du Colombier l = strlen(n->msg);
1313de6a9c0SDavid du Colombier if(l > ERRMAX-23) /* " pc=0x0123456789abcdef\0" */
1323de6a9c0SDavid du Colombier l = ERRMAX-23;
1333de6a9c0SDavid du Colombier snprint(n->msg + l, sizeof n->msg - l, " pc=%#lux", ureg->pc);
1343de6a9c0SDavid du Colombier }
1353de6a9c0SDavid du Colombier
1363de6a9c0SDavid du Colombier if(n->flag != NUser && (up->notified || up->notify == 0)){
1373de6a9c0SDavid du Colombier if(n->flag == NDebug)
1383de6a9c0SDavid du Colombier pprint("suicide: %s\n", n->msg);
1393de6a9c0SDavid du Colombier qunlock(&up->debug);
1403de6a9c0SDavid du Colombier pexit(n->msg, n->flag != NDebug);
1413de6a9c0SDavid du Colombier }
1423de6a9c0SDavid du Colombier
1433de6a9c0SDavid du Colombier if(up->notified){
1443de6a9c0SDavid du Colombier qunlock(&up->debug);
1453de6a9c0SDavid du Colombier splhi();
1463de6a9c0SDavid du Colombier return 0;
1473de6a9c0SDavid du Colombier }
1483de6a9c0SDavid du Colombier
1493de6a9c0SDavid du Colombier if(up->notify == nil){
1503de6a9c0SDavid du Colombier qunlock(&up->debug);
1513de6a9c0SDavid du Colombier pexit(n->msg, n->flag != NDebug);
1523de6a9c0SDavid du Colombier }
1533de6a9c0SDavid du Colombier if(!okaddr(PTR2UINT(up->notify), 1, 0)){
1543de6a9c0SDavid du Colombier pprint("suicide: notify function address %#p\n", up->notify);
1553de6a9c0SDavid du Colombier qunlock(&up->debug);
1563de6a9c0SDavid du Colombier pexit("Suicide", 0);
1573de6a9c0SDavid du Colombier }
1583de6a9c0SDavid du Colombier
1593de6a9c0SDavid du Colombier sp = ureg->sp - sizeof(NFrame);
1603de6a9c0SDavid du Colombier if(!okaddr(sp, sizeof(NFrame), 1)){
1613de6a9c0SDavid du Colombier qunlock(&up->debug);
1623de6a9c0SDavid du Colombier pprint("suicide: notify stack address %#p\n", sp);
1633de6a9c0SDavid du Colombier pexit("Suicide", 0);
1643de6a9c0SDavid du Colombier }
1653de6a9c0SDavid du Colombier
1663de6a9c0SDavid du Colombier nf = UINT2PTR(sp);
1673de6a9c0SDavid du Colombier memmove(&nf->ureg, ureg, sizeof(Ureg));
1683de6a9c0SDavid du Colombier nf->old = up->ureg;
1693de6a9c0SDavid du Colombier up->ureg = nf;
1703de6a9c0SDavid du Colombier memmove(nf->msg, up->note[0].msg, ERRMAX);
171*39120342SDavid du Colombier nf->arg1 = nf->msg; /* arg 1 is string */
172*39120342SDavid du Colombier nf->arg0 = &nf->ureg; /* arg 0 XX(FP) is ureg* */
173*39120342SDavid du Colombier ureg->r0 = PTR2UINT(nf->arg0); /* arg 0 in r0 is ureg* */
1743de6a9c0SDavid du Colombier nf->ip = 0;
1753de6a9c0SDavid du Colombier
1763de6a9c0SDavid du Colombier ureg->sp = sp;
1773de6a9c0SDavid du Colombier ureg->pc = PTR2UINT(up->notify);
1783de6a9c0SDavid du Colombier
1793de6a9c0SDavid du Colombier up->notified = 1;
1803de6a9c0SDavid du Colombier up->nnote--;
1813de6a9c0SDavid du Colombier memmove(&up->lastnote, &up->note[0], sizeof(Note));
1823de6a9c0SDavid du Colombier memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
1833de6a9c0SDavid du Colombier
1843de6a9c0SDavid du Colombier qunlock(&up->debug);
1853de6a9c0SDavid du Colombier splx(s);
1863de6a9c0SDavid du Colombier
1873de6a9c0SDavid du Colombier l1cache->wb(); /* is this needed? */
1883de6a9c0SDavid du Colombier return 1;
1893de6a9c0SDavid du Colombier }
1903de6a9c0SDavid du Colombier
1913de6a9c0SDavid du Colombier void
syscall(Ureg * ureg)1923de6a9c0SDavid du Colombier syscall(Ureg* ureg)
1933de6a9c0SDavid du Colombier {
1943de6a9c0SDavid du Colombier char *e;
1953de6a9c0SDavid du Colombier u32int s;
1963de6a9c0SDavid du Colombier ulong sp;
1973de6a9c0SDavid du Colombier long ret;
1983de6a9c0SDavid du Colombier int i, scallnr;
1993de6a9c0SDavid du Colombier vlong startns, stopns;
2003de6a9c0SDavid du Colombier
2013de6a9c0SDavid du Colombier if(!userureg(ureg))
2023de6a9c0SDavid du Colombier panic("syscall: from kernel: pc %#lux r14 %#lux psr %#lux",
2033de6a9c0SDavid du Colombier ureg->pc, ureg->r14, ureg->psr);
2043de6a9c0SDavid du Colombier
2053de6a9c0SDavid du Colombier cycles(&up->kentry);
2063de6a9c0SDavid du Colombier
2073de6a9c0SDavid du Colombier m->syscall++;
2083de6a9c0SDavid du Colombier up->insyscall = 1;
2093de6a9c0SDavid du Colombier up->pc = ureg->pc;
2103de6a9c0SDavid du Colombier up->dbgreg = ureg;
2113de6a9c0SDavid du Colombier
2123de6a9c0SDavid du Colombier scallnr = ureg->r0;
2133de6a9c0SDavid du Colombier up->scallnr = scallnr;
2143de6a9c0SDavid du Colombier if(scallnr == RFORK)
2153de6a9c0SDavid du Colombier fpusysrfork(ureg);
2163de6a9c0SDavid du Colombier spllo();
2173de6a9c0SDavid du Colombier sp = ureg->sp;
2183de6a9c0SDavid du Colombier
2193de6a9c0SDavid du Colombier if(up->procctl == Proc_tracesyscall){
2203de6a9c0SDavid du Colombier /*
2213de6a9c0SDavid du Colombier * Redundant validaddr. Do we care?
2223de6a9c0SDavid du Colombier * Tracing syscalls is not exactly a fast path...
2233de6a9c0SDavid du Colombier * Beware, validaddr currently does a pexit rather
2243de6a9c0SDavid du Colombier * than an error if there's a problem; that might
2253de6a9c0SDavid du Colombier * change in the future.
2263de6a9c0SDavid du Colombier */
2273de6a9c0SDavid du Colombier if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD))
2283de6a9c0SDavid du Colombier validaddr(sp, sizeof(Sargs)+BY2WD, 0);
2293de6a9c0SDavid du Colombier
2303de6a9c0SDavid du Colombier syscallfmt(scallnr, ureg->pc, (va_list)(sp+BY2WD));
2313de6a9c0SDavid du Colombier up->procctl = Proc_stopme;
2323de6a9c0SDavid du Colombier procctl(up);
2333de6a9c0SDavid du Colombier if (up->syscalltrace)
2343de6a9c0SDavid du Colombier free(up->syscalltrace);
2353de6a9c0SDavid du Colombier up->syscalltrace = nil;
2363de6a9c0SDavid du Colombier }
2373de6a9c0SDavid du Colombier
2383de6a9c0SDavid du Colombier up->nerrlab = 0;
2393de6a9c0SDavid du Colombier ret = -1;
2403de6a9c0SDavid du Colombier startns = todget(nil);
2413de6a9c0SDavid du Colombier
2423de6a9c0SDavid du Colombier l1cache->wb(); /* system is more stable with this */
2433de6a9c0SDavid du Colombier if(!waserror()){
2443de6a9c0SDavid du Colombier if(scallnr >= nsyscall){
2453de6a9c0SDavid du Colombier pprint("bad sys call number %d pc %#lux\n",
2463de6a9c0SDavid du Colombier scallnr, ureg->pc);
2473de6a9c0SDavid du Colombier postnote(up, 1, "sys: bad sys call", NDebug);
2483de6a9c0SDavid du Colombier error(Ebadarg);
2493de6a9c0SDavid du Colombier }
2503de6a9c0SDavid du Colombier
2513de6a9c0SDavid du Colombier if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD))
2523de6a9c0SDavid du Colombier validaddr(sp, sizeof(Sargs)+BY2WD, 0);
2533de6a9c0SDavid du Colombier
2543de6a9c0SDavid du Colombier up->s = *((Sargs*)(sp+BY2WD));
2553de6a9c0SDavid du Colombier up->psstate = sysctab[scallnr];
2563de6a9c0SDavid du Colombier
2573de6a9c0SDavid du Colombier /* iprint("%s: syscall %s\n", up->text, sysctab[scallnr]?sysctab[scallnr]:"huh?"); */
2583de6a9c0SDavid du Colombier
2593de6a9c0SDavid du Colombier ret = systab[scallnr](up->s.args);
2603de6a9c0SDavid du Colombier poperror();
2613de6a9c0SDavid du Colombier }else{
2623de6a9c0SDavid du Colombier /* failure: save the error buffer for errstr */
2633de6a9c0SDavid du Colombier e = up->syserrstr;
2643de6a9c0SDavid du Colombier up->syserrstr = up->errstr;
2653de6a9c0SDavid du Colombier up->errstr = e;
2663de6a9c0SDavid du Colombier }
2673de6a9c0SDavid du Colombier if(up->nerrlab){
2683de6a9c0SDavid du Colombier print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
2693de6a9c0SDavid du Colombier for(i = 0; i < NERR; i++)
2703de6a9c0SDavid du Colombier print("sp=%#p pc=%#p\n",
2713de6a9c0SDavid du Colombier up->errlab[i].sp, up->errlab[i].pc);
2723de6a9c0SDavid du Colombier panic("error stack");
2733de6a9c0SDavid du Colombier }
2743de6a9c0SDavid du Colombier
2753de6a9c0SDavid du Colombier /*
2763de6a9c0SDavid du Colombier * Put return value in frame. On the x86 the syscall is
2773de6a9c0SDavid du Colombier * just another trap and the return value from syscall is
2783de6a9c0SDavid du Colombier * ignored. On other machines the return value is put into
2793de6a9c0SDavid du Colombier * the results register by caller of syscall.
2803de6a9c0SDavid du Colombier */
2813de6a9c0SDavid du Colombier ureg->r0 = ret;
2823de6a9c0SDavid du Colombier
2833de6a9c0SDavid du Colombier if(up->procctl == Proc_tracesyscall){
2843de6a9c0SDavid du Colombier stopns = todget(nil);
2853de6a9c0SDavid du Colombier up->procctl = Proc_stopme;
2863de6a9c0SDavid du Colombier sysretfmt(scallnr, (va_list)(sp+BY2WD), ret, startns, stopns);
2873de6a9c0SDavid du Colombier s = splhi();
2883de6a9c0SDavid du Colombier procctl(up);
2893de6a9c0SDavid du Colombier splx(s);
2903de6a9c0SDavid du Colombier if(up->syscalltrace)
2913de6a9c0SDavid du Colombier free(up->syscalltrace);
2923de6a9c0SDavid du Colombier up->syscalltrace = nil;
2933de6a9c0SDavid du Colombier }
2943de6a9c0SDavid du Colombier
2953de6a9c0SDavid du Colombier up->insyscall = 0;
2963de6a9c0SDavid du Colombier up->psstate = 0;
2973de6a9c0SDavid du Colombier
2983de6a9c0SDavid du Colombier if(scallnr == NOTED)
2993de6a9c0SDavid du Colombier noted(ureg, *(ulong*)(sp+BY2WD));
3003de6a9c0SDavid du Colombier
3013de6a9c0SDavid du Colombier splhi();
3023de6a9c0SDavid du Colombier if(scallnr != RFORK && (up->procctl || up->nnote))
3033de6a9c0SDavid du Colombier notify(ureg);
3043de6a9c0SDavid du Colombier
3053de6a9c0SDavid du Colombier l1cache->wb(); /* system is more stable with this */
3063de6a9c0SDavid du Colombier
3073de6a9c0SDavid du Colombier /* if we delayed sched because we held a lock, sched now */
3083de6a9c0SDavid du Colombier if(up->delaysched){
3093de6a9c0SDavid du Colombier sched();
3103de6a9c0SDavid du Colombier splhi();
3113de6a9c0SDavid du Colombier }
3123de6a9c0SDavid du Colombier kexit(ureg);
3133de6a9c0SDavid du Colombier }
3143de6a9c0SDavid du Colombier
3153de6a9c0SDavid du Colombier long
execregs(ulong entry,ulong ssize,ulong nargs)3163de6a9c0SDavid du Colombier execregs(ulong entry, ulong ssize, ulong nargs)
3173de6a9c0SDavid du Colombier {
3183de6a9c0SDavid du Colombier ulong *sp;
3193de6a9c0SDavid du Colombier Ureg *ureg;
3203de6a9c0SDavid du Colombier
3213de6a9c0SDavid du Colombier sp = (ulong*)(USTKTOP - ssize);
3223de6a9c0SDavid du Colombier *--sp = nargs;
3233de6a9c0SDavid du Colombier
3243de6a9c0SDavid du Colombier ureg = up->dbgreg;
3253de6a9c0SDavid du Colombier // memset(ureg, 0, 15*sizeof(ulong));
3263de6a9c0SDavid du Colombier ureg->r13 = (ulong)sp;
3273de6a9c0SDavid du Colombier ureg->pc = entry;
3283de6a9c0SDavid du Colombier //print("%lud: EXECREGS pc %#ux sp %#ux nargs %ld\n", up->pid, ureg->pc, ureg->r13, nargs);
3293de6a9c0SDavid du Colombier allcache->wbse(ureg, sizeof *ureg); /* is this needed? */
3303de6a9c0SDavid du Colombier
3313de6a9c0SDavid du Colombier /*
3323de6a9c0SDavid du Colombier * return the address of kernel/user shared data
3333de6a9c0SDavid du Colombier * (e.g. clock stuff)
3343de6a9c0SDavid du Colombier */
3353de6a9c0SDavid du Colombier return USTKTOP-sizeof(Tos);
3363de6a9c0SDavid du Colombier }
3373de6a9c0SDavid du Colombier
3383de6a9c0SDavid du Colombier void
sysprocsetup(Proc * p)3393de6a9c0SDavid du Colombier sysprocsetup(Proc* p)
3403de6a9c0SDavid du Colombier {
3413de6a9c0SDavid du Colombier fpusysprocsetup(p);
3423de6a9c0SDavid du Colombier }
3433de6a9c0SDavid du Colombier
3443de6a9c0SDavid du Colombier /*
3453de6a9c0SDavid du Colombier * Craft a return frame which will cause the child to pop out of
3463de6a9c0SDavid du Colombier * the scheduler in user mode with the return register zero. Set
3473de6a9c0SDavid du Colombier * pc to point to a l.s return function.
3483de6a9c0SDavid du Colombier */
3493de6a9c0SDavid du Colombier void
forkchild(Proc * p,Ureg * ureg)3503de6a9c0SDavid du Colombier forkchild(Proc *p, Ureg *ureg)
3513de6a9c0SDavid du Colombier {
3523de6a9c0SDavid du Colombier Ureg *cureg;
3533de6a9c0SDavid du Colombier
3543de6a9c0SDavid du Colombier p->sched.sp = (ulong)p->kstack+KSTACK-sizeof(Ureg);
3553de6a9c0SDavid du Colombier p->sched.pc = (ulong)forkret;
3563de6a9c0SDavid du Colombier
3573de6a9c0SDavid du Colombier cureg = (Ureg*)(p->sched.sp);
3583de6a9c0SDavid du Colombier memmove(cureg, ureg, sizeof(Ureg));
3593de6a9c0SDavid du Colombier
3603de6a9c0SDavid du Colombier /* syscall returns 0 for child */
3613de6a9c0SDavid du Colombier cureg->r0 = 0;
3623de6a9c0SDavid du Colombier
3633de6a9c0SDavid du Colombier /* Things from bottom of syscall which were never executed */
3643de6a9c0SDavid du Colombier p->psstate = 0;
3653de6a9c0SDavid du Colombier p->insyscall = 0;
3663de6a9c0SDavid du Colombier
3673de6a9c0SDavid du Colombier fpusysrforkchild(p, cureg, up);
3683de6a9c0SDavid du Colombier }
369