1d6dfd9efSDavid du Colombier #include "u.h"
2d6dfd9efSDavid du Colombier #include "../port/lib.h"
3d6dfd9efSDavid du Colombier #include "mem.h"
4d6dfd9efSDavid du Colombier #include "dat.h"
5d6dfd9efSDavid du Colombier #include "fns.h"
6d6dfd9efSDavid du Colombier #include "../port/error.h"
7d6dfd9efSDavid du Colombier #include "../port/systab.h"
8d6dfd9efSDavid du Colombier
9d6dfd9efSDavid du Colombier #include <tos.h>
10d6dfd9efSDavid du Colombier #include "ureg.h"
11d6dfd9efSDavid du Colombier
12d6dfd9efSDavid du Colombier typedef struct {
13d6dfd9efSDavid du Colombier uintptr pc;
14d6dfd9efSDavid du Colombier Ureg* arg0;
15d6dfd9efSDavid du Colombier char* arg1;
16d6dfd9efSDavid du Colombier char msg[ERRMAX];
17d6dfd9efSDavid du Colombier Ureg* old;
18d6dfd9efSDavid du Colombier Ureg ureg;
19d6dfd9efSDavid du Colombier } NFrame;
20d6dfd9efSDavid du Colombier
21d6dfd9efSDavid du Colombier /*
22d6dfd9efSDavid du Colombier * Return user to state before notify()
23d6dfd9efSDavid du Colombier */
24d6dfd9efSDavid du Colombier static void
noted(Ureg * cur,uintptr arg0)25d6dfd9efSDavid du Colombier noted(Ureg* cur, uintptr arg0)
26d6dfd9efSDavid du Colombier {
27d6dfd9efSDavid du Colombier Ureg *nur;
28d6dfd9efSDavid du Colombier NFrame *nf;
29d6dfd9efSDavid du Colombier
30d6dfd9efSDavid du Colombier qlock(&up->debug);
31d6dfd9efSDavid du Colombier if(arg0 != NRSTR && !up->notified){
32d6dfd9efSDavid du Colombier qunlock(&up->debug);
33d6dfd9efSDavid du Colombier pprint("call to noted() when not notified\n");
34d6dfd9efSDavid du Colombier pexit("Suicide", 0);
35d6dfd9efSDavid du Colombier }
36d6dfd9efSDavid du Colombier up->notified = 0;
37d6dfd9efSDavid du Colombier fpunoted();
38d6dfd9efSDavid du Colombier
39d6dfd9efSDavid du Colombier nf = up->ureg;
40d6dfd9efSDavid du Colombier
41d6dfd9efSDavid du Colombier /* sanity clause */
42d6dfd9efSDavid du Colombier if(!okaddr(PTR2UINT(nf), sizeof(NFrame), 0)){
43d6dfd9efSDavid du Colombier qunlock(&up->debug);
44d6dfd9efSDavid du Colombier pprint("bad ureg in noted %#p\n", nf);
45d6dfd9efSDavid du Colombier pexit("Suicide", 0);
46d6dfd9efSDavid du Colombier }
47d6dfd9efSDavid du Colombier
48d6dfd9efSDavid du Colombier /* don't let user change system status */
49d6dfd9efSDavid du Colombier nur = &nf->ureg;
50d6dfd9efSDavid du Colombier nur->status = cur->status;
51d6dfd9efSDavid du Colombier
52d6dfd9efSDavid du Colombier memmove(cur, nur, sizeof(Ureg));
53d6dfd9efSDavid du Colombier
54d6dfd9efSDavid du Colombier switch((int)arg0){
55d6dfd9efSDavid du Colombier case NCONT:
56d6dfd9efSDavid du Colombier case NRSTR:
57d6dfd9efSDavid du Colombier if(!okaddr(nur->pc, BY2SE, 0) || !okaddr(nur->usp, BY2SE, 0)){
58d6dfd9efSDavid du Colombier qunlock(&up->debug);
59d6dfd9efSDavid du Colombier pprint("suicide: trap in noted\n");
60d6dfd9efSDavid du Colombier pexit("Suicide", 0);
61d6dfd9efSDavid du Colombier }
62d6dfd9efSDavid du Colombier up->ureg = nf->old;
63d6dfd9efSDavid du Colombier qunlock(&up->debug);
64d6dfd9efSDavid du Colombier break;
65d6dfd9efSDavid du Colombier
66d6dfd9efSDavid du Colombier case NSAVE:
67d6dfd9efSDavid du Colombier if(!okaddr(nur->pc, BY2SE, 0) || !okaddr(nur->usp, BY2SE, 0)){
68d6dfd9efSDavid du Colombier qunlock(&up->debug);
69d6dfd9efSDavid du Colombier pprint("suicide: trap in noted\n");
70d6dfd9efSDavid du Colombier pexit("Suicide", 0);
71d6dfd9efSDavid du Colombier }
72d6dfd9efSDavid du Colombier qunlock(&up->debug);
73d6dfd9efSDavid du Colombier
74d6dfd9efSDavid du Colombier splhi();
75d6dfd9efSDavid du Colombier nf->arg1 = nf->msg;
76d6dfd9efSDavid du Colombier nf->arg0 = &nf->ureg;
77d6dfd9efSDavid du Colombier cur->r3 = PTR2UINT(nf->arg0);
78d6dfd9efSDavid du Colombier nf->pc = 0;
79d6dfd9efSDavid du Colombier cur->sp = PTR2UINT(nf);
80d6dfd9efSDavid du Colombier break;
81d6dfd9efSDavid du Colombier
82d6dfd9efSDavid du Colombier default:
83d6dfd9efSDavid du Colombier pprint("unknown noted arg %#p\n", arg0);
84d6dfd9efSDavid du Colombier up->lastnote.flag = NDebug;
85d6dfd9efSDavid du Colombier /* fall through */
86d6dfd9efSDavid du Colombier case NDFLT:
87d6dfd9efSDavid du Colombier if(up->lastnote.flag == NDebug){
88d6dfd9efSDavid du Colombier qunlock(&up->debug);
89d6dfd9efSDavid du Colombier pprint("suicide: %s\n", up->lastnote.msg);
90d6dfd9efSDavid du Colombier }
91d6dfd9efSDavid du Colombier else
92d6dfd9efSDavid du Colombier qunlock(&up->debug);
93d6dfd9efSDavid du Colombier pexit(up->lastnote.msg, up->lastnote.flag != NDebug);
94d6dfd9efSDavid du Colombier }
95d6dfd9efSDavid du Colombier }
96d6dfd9efSDavid du Colombier
97d6dfd9efSDavid du Colombier /*
98d6dfd9efSDavid du Colombier * Call user, if necessary, with note.
99d6dfd9efSDavid du Colombier * Pass user the Ureg struct and the note on his stack.
100d6dfd9efSDavid du Colombier */
101d6dfd9efSDavid du Colombier int
notify(Ureg * ureg)102d6dfd9efSDavid du Colombier notify(Ureg* ureg)
103d6dfd9efSDavid du Colombier {
104d6dfd9efSDavid du Colombier int l;
105d6dfd9efSDavid du Colombier Note *n;
106d6dfd9efSDavid du Colombier ulong s;
107d6dfd9efSDavid du Colombier uintptr sp;
108d6dfd9efSDavid du Colombier NFrame *nf;
109d6dfd9efSDavid du Colombier
110d6dfd9efSDavid du Colombier if(up->procctl)
111d6dfd9efSDavid du Colombier procctl(up);
112d6dfd9efSDavid du Colombier if(up->nnote == 0)
113d6dfd9efSDavid du Colombier return 0;
114d6dfd9efSDavid du Colombier
115d6dfd9efSDavid du Colombier fpunotify(ureg);
116d6dfd9efSDavid du Colombier
117d6dfd9efSDavid du Colombier s = spllo();
118d6dfd9efSDavid du Colombier qlock(&up->debug);
119d6dfd9efSDavid du Colombier up->notepending = 0;
120d6dfd9efSDavid du Colombier n = &up->note[0];
121d6dfd9efSDavid du Colombier if(strncmp(n->msg, "sys:", 4) == 0){
122d6dfd9efSDavid du Colombier l = strlen(n->msg);
123d6dfd9efSDavid du Colombier if(l > ERRMAX-15) /* " pc=0x12345678\0" */
124d6dfd9efSDavid du Colombier l = ERRMAX-15;
125d6dfd9efSDavid du Colombier sprint(n->msg+l, " pc=%#.8lux", ureg->pc);
126d6dfd9efSDavid du Colombier }
127d6dfd9efSDavid du Colombier
128d6dfd9efSDavid du Colombier if(n->flag!=NUser && (up->notified || up->notify==0)){
129d6dfd9efSDavid du Colombier if(n->flag == NDebug)
130d6dfd9efSDavid du Colombier pprint("suicide: %s\n", n->msg);
131d6dfd9efSDavid du Colombier qunlock(&up->debug);
132d6dfd9efSDavid du Colombier pexit(n->msg, n->flag!=NDebug);
133d6dfd9efSDavid du Colombier }
134d6dfd9efSDavid du Colombier
135d6dfd9efSDavid du Colombier if(up->notified) {
136d6dfd9efSDavid du Colombier qunlock(&up->debug);
137d6dfd9efSDavid du Colombier splhi();
138d6dfd9efSDavid du Colombier return 0;
139d6dfd9efSDavid du Colombier }
140d6dfd9efSDavid du Colombier
141d6dfd9efSDavid du Colombier if(up->notify == nil){
142d6dfd9efSDavid du Colombier qunlock(&up->debug);
143d6dfd9efSDavid du Colombier pexit(n->msg, n->flag!=NDebug);
144d6dfd9efSDavid du Colombier }
145d6dfd9efSDavid du Colombier if(!okaddr(PTR2UINT(up->notify), BY2WD, 0)){
146d6dfd9efSDavid du Colombier qunlock(&up->debug);
147d6dfd9efSDavid du Colombier pprint("suicide: notify function address %#p\n", up->notify);
148d6dfd9efSDavid du Colombier pexit("Suicide", 0);
149d6dfd9efSDavid du Colombier }
150d6dfd9efSDavid du Colombier
151d6dfd9efSDavid du Colombier sp = ureg->usp & ~(BY2V-1);
152d6dfd9efSDavid du Colombier sp -= (sizeof(NFrame)+BY2V-1) & ~(BY2V-1);
153d6dfd9efSDavid du Colombier
154d6dfd9efSDavid du Colombier if(!okaddr(sp, sizeof(NFrame), 1)){
155d6dfd9efSDavid du Colombier qunlock(&up->debug);
156d6dfd9efSDavid du Colombier pprint("suicide: notify stack address %#p\n", sp);
157d6dfd9efSDavid du Colombier pexit("Suicide", 0);
158d6dfd9efSDavid du Colombier }
159d6dfd9efSDavid du Colombier
160d6dfd9efSDavid du Colombier nf = UINT2PTR(sp);
161d6dfd9efSDavid du Colombier memmove(&nf->ureg, ureg, sizeof(Ureg));
162d6dfd9efSDavid du Colombier nf->old = up->ureg;
163d6dfd9efSDavid du Colombier up->ureg = nf;
164d6dfd9efSDavid du Colombier memmove(nf->msg, up->note[0].msg, ERRMAX);
165d6dfd9efSDavid du Colombier nf->arg1 = nf->msg;
166d6dfd9efSDavid du Colombier nf->arg0 = up->ureg;
167d6dfd9efSDavid du Colombier ureg->r3 = PTR2UINT(up->ureg);
168d6dfd9efSDavid du Colombier nf->pc = 0;
169d6dfd9efSDavid du Colombier
170d6dfd9efSDavid du Colombier ureg->usp = sp;
171d6dfd9efSDavid du Colombier ureg->pc = PTR2UINT(up->notify);
172d6dfd9efSDavid du Colombier up->notified = 1;
173d6dfd9efSDavid du Colombier up->nnote--;
174d6dfd9efSDavid du Colombier memmove(&up->lastnote, &up->note[0], sizeof(Note));
175d6dfd9efSDavid du Colombier memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
176d6dfd9efSDavid du Colombier
177d6dfd9efSDavid du Colombier qunlock(&up->debug);
178d6dfd9efSDavid du Colombier splx(s);
179d6dfd9efSDavid du Colombier return 1;
180d6dfd9efSDavid du Colombier }
181d6dfd9efSDavid du Colombier
182d6dfd9efSDavid du Colombier /*
183d6dfd9efSDavid du Colombier * system calls and 'orrible notes
184d6dfd9efSDavid du Colombier */
185d6dfd9efSDavid du Colombier
186d6dfd9efSDavid du Colombier /* TO DO: make this trap a separate asm entry point, as on some other RISC architectures */
187d6dfd9efSDavid du Colombier void
syscall(Ureg * ureg)188d6dfd9efSDavid du Colombier syscall(Ureg* ureg)
189d6dfd9efSDavid du Colombier {
190d6dfd9efSDavid du Colombier char *e;
191d6dfd9efSDavid du Colombier u32int s;
192d6dfd9efSDavid du Colombier uintptr sp;
193d6dfd9efSDavid du Colombier long ret;
194d6dfd9efSDavid du Colombier int i, scallnr;
195d6dfd9efSDavid du Colombier
196d6dfd9efSDavid du Colombier cycles(&up->kentry);
197d6dfd9efSDavid du Colombier
198d6dfd9efSDavid du Colombier m->syscall++;
199d6dfd9efSDavid du Colombier up->insyscall = 1;
200d6dfd9efSDavid du Colombier up->pc = ureg->pc;
201d6dfd9efSDavid du Colombier up->dbgreg = ureg;
202d6dfd9efSDavid du Colombier
203d6dfd9efSDavid du Colombier if(up->procctl == Proc_tracesyscall){
204d6dfd9efSDavid du Colombier up->procctl = Proc_stopme;
205d6dfd9efSDavid du Colombier procctl(up);
206d6dfd9efSDavid du Colombier }
207d6dfd9efSDavid du Colombier
208d6dfd9efSDavid du Colombier scallnr = ureg->r3;
209d6dfd9efSDavid du Colombier up->scallnr = scallnr;
210d6dfd9efSDavid du Colombier if(scallnr == RFORK)
211d6dfd9efSDavid du Colombier fpusysrfork(ureg);
212d6dfd9efSDavid du Colombier spllo();
213d6dfd9efSDavid du Colombier
214d6dfd9efSDavid du Colombier sp = ureg->sp;
215d6dfd9efSDavid du Colombier up->nerrlab = 0;
216d6dfd9efSDavid du Colombier ret = -1;
217d6dfd9efSDavid du Colombier if(!waserror()){
218d6dfd9efSDavid du Colombier if(scallnr >= nsyscall){
219d6dfd9efSDavid du Colombier pprint("bad sys call number %d pc %lux\n",
220d6dfd9efSDavid du Colombier scallnr, ureg->pc);
221d6dfd9efSDavid du Colombier postnote(up, 1, "sys: bad sys call", NDebug);
222d6dfd9efSDavid du Colombier error(Ebadarg);
223d6dfd9efSDavid du Colombier }
224d6dfd9efSDavid du Colombier
225d6dfd9efSDavid du Colombier if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD))
226d6dfd9efSDavid du Colombier validaddr(sp, sizeof(Sargs)+BY2WD, 0);
227d6dfd9efSDavid du Colombier
228d6dfd9efSDavid du Colombier up->s = *((Sargs*)(sp+BY2WD));
229d6dfd9efSDavid du Colombier up->psstate = sysctab[scallnr];
230d6dfd9efSDavid du Colombier
231d6dfd9efSDavid du Colombier ret = systab[scallnr](up->s.args);
232d6dfd9efSDavid du Colombier poperror();
233d6dfd9efSDavid du Colombier }else{
234d6dfd9efSDavid du Colombier /* failure: save the error buffer for errstr */
235d6dfd9efSDavid du Colombier e = up->syserrstr;
236d6dfd9efSDavid du Colombier up->syserrstr = up->errstr;
237d6dfd9efSDavid du Colombier up->errstr = e;
238d6dfd9efSDavid du Colombier }
239d6dfd9efSDavid du Colombier if(up->nerrlab){
240d6dfd9efSDavid du Colombier print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
241d6dfd9efSDavid du Colombier for(i = 0; i < NERR; i++)
242d6dfd9efSDavid du Colombier print("sp=%#p pc=%#p\n",
243d6dfd9efSDavid du Colombier up->errlab[i].sp, up->errlab[i].pc);
244d6dfd9efSDavid du Colombier panic("error stack");
245d6dfd9efSDavid du Colombier }
246d6dfd9efSDavid du Colombier
247d6dfd9efSDavid du Colombier /*
248d6dfd9efSDavid du Colombier * Put return value in frame.
249d6dfd9efSDavid du Colombier */
250d6dfd9efSDavid du Colombier ureg->r3 = ret;
251d6dfd9efSDavid du Colombier
252d6dfd9efSDavid du Colombier if(up->procctl == Proc_tracesyscall){
253d6dfd9efSDavid du Colombier up->procctl = Proc_stopme;
254d6dfd9efSDavid du Colombier s = splhi();
255d6dfd9efSDavid du Colombier procctl(up);
256d6dfd9efSDavid du Colombier splx(s);
257d6dfd9efSDavid du Colombier }
258d6dfd9efSDavid du Colombier
259d6dfd9efSDavid du Colombier up->insyscall = 0;
260d6dfd9efSDavid du Colombier up->psstate = 0;
261d6dfd9efSDavid du Colombier
262d6dfd9efSDavid du Colombier if(scallnr == NOTED)
263d6dfd9efSDavid du Colombier noted(ureg, *(uintptr*)(sp+BY2SE));
264d6dfd9efSDavid du Colombier
265d6dfd9efSDavid du Colombier splhi();
266d6dfd9efSDavid du Colombier if(scallnr != RFORK && (up->procctl || up->nnote))
267d6dfd9efSDavid du Colombier notify(ureg);
268d6dfd9efSDavid du Colombier
269d6dfd9efSDavid du Colombier /* if we delayed sched because we held a lock, sched now */
270d6dfd9efSDavid du Colombier if(up->delaysched){
271d6dfd9efSDavid du Colombier sched();
272d6dfd9efSDavid du Colombier splhi();
273d6dfd9efSDavid du Colombier }
274d6dfd9efSDavid du Colombier kexit(ureg);
275d6dfd9efSDavid du Colombier }
276d6dfd9efSDavid du Colombier
277d6dfd9efSDavid du Colombier /*
278*f80d550dSDavid du Colombier * called in syscallfmt.c, sysfile.c, sysproc.c
279d6dfd9efSDavid du Colombier */
280d6dfd9efSDavid du Colombier void
validalign(uintptr addr,unsigned align)281*f80d550dSDavid du Colombier validalign(uintptr addr, unsigned align)
282d6dfd9efSDavid du Colombier {
283*f80d550dSDavid du Colombier /*
284*f80d550dSDavid du Colombier * Plan 9 is a 32-bit O/S, and the hardware it runs on
285*f80d550dSDavid du Colombier * does not usually have instructions which move 64-bit
286*f80d550dSDavid du Colombier * quantities directly, synthesizing the operations
287*f80d550dSDavid du Colombier * with 32-bit move instructions. Therefore, the compiler
288*f80d550dSDavid du Colombier * (and hardware) usually only enforce 32-bit alignment,
289*f80d550dSDavid du Colombier * if at all.
290*f80d550dSDavid du Colombier *
291*f80d550dSDavid du Colombier * Take this out if the architecture warrants it.
292*f80d550dSDavid du Colombier */
293*f80d550dSDavid du Colombier if(align == sizeof(vlong))
294*f80d550dSDavid du Colombier align = sizeof(long);
295*f80d550dSDavid du Colombier
296*f80d550dSDavid du Colombier /*
297*f80d550dSDavid du Colombier * Check align is a power of 2, then addr alignment.
298*f80d550dSDavid du Colombier */
299*f80d550dSDavid du Colombier if((align != 0 && !(align & (align-1))) && !(addr & (align-1)))
300*f80d550dSDavid du Colombier return;
301*f80d550dSDavid du Colombier postnote(up, 1, "sys: odd address", NDebug);
302d6dfd9efSDavid du Colombier error(Ebadarg);
303*f80d550dSDavid du Colombier /*NOTREACHED*/
304d6dfd9efSDavid du Colombier }
305d6dfd9efSDavid du Colombier
306d6dfd9efSDavid du Colombier uintptr
sysexecstack(uintptr stack,int argc)307d6dfd9efSDavid du Colombier sysexecstack(uintptr stack, int argc)
308d6dfd9efSDavid du Colombier {
309d6dfd9efSDavid du Colombier /*
310d6dfd9efSDavid du Colombier * Given a current bottom-of-stack and a count
311d6dfd9efSDavid du Colombier * of pointer arguments to be pushed onto it followed
312d6dfd9efSDavid du Colombier * by an integer argument count, return a suitably
313d6dfd9efSDavid du Colombier * aligned new bottom-of-stack which will satisfy any
314d6dfd9efSDavid du Colombier * hardware stack-alignment contraints.
315d6dfd9efSDavid du Colombier * Rounding the stack down to be aligned with the
316d6dfd9efSDavid du Colombier * natural size of a pointer variable usually suffices,
317d6dfd9efSDavid du Colombier * but some architectures impose further restrictions,
318d6dfd9efSDavid du Colombier * e.g. 32-bit SPARC, where the stack must be 8-byte
319d6dfd9efSDavid du Colombier * aligned although pointers and integers are 32-bits.
320d6dfd9efSDavid du Colombier */
321d6dfd9efSDavid du Colombier USED(argc);
322d6dfd9efSDavid du Colombier
323d6dfd9efSDavid du Colombier return STACKALIGN(stack);
324d6dfd9efSDavid du Colombier }
325d6dfd9efSDavid du Colombier
326d6dfd9efSDavid du Colombier long
execregs(ulong entry,ulong ssize,ulong nargs)327d6dfd9efSDavid du Colombier execregs(ulong entry, ulong ssize, ulong nargs)
328d6dfd9efSDavid du Colombier {
329d6dfd9efSDavid du Colombier ulong *sp;
330d6dfd9efSDavid du Colombier Ureg *ureg;
331d6dfd9efSDavid du Colombier
332d6dfd9efSDavid du Colombier fpusysprocsetup(up); /* up is a guess */
333d6dfd9efSDavid du Colombier
334d6dfd9efSDavid du Colombier sp = (ulong*)(USTKTOP - ssize);
335d6dfd9efSDavid du Colombier *--sp = nargs;
336d6dfd9efSDavid du Colombier
337d6dfd9efSDavid du Colombier ureg = up->dbgreg;
338d6dfd9efSDavid du Colombier // memset(ureg, 0, 31*sizeof(ulong));
339d6dfd9efSDavid du Colombier ureg->usp = (ulong)sp;
340d6dfd9efSDavid du Colombier ureg->pc = entry;
341d6dfd9efSDavid du Colombier ureg->srr1 &= ~MSR_FP; /* disable floating point */
342d6dfd9efSDavid du Colombier
343d6dfd9efSDavid du Colombier /*
344d6dfd9efSDavid du Colombier * return the address of kernel/user shared data
345d6dfd9efSDavid du Colombier * (e.g. clock stuff)
346d6dfd9efSDavid du Colombier */
347d6dfd9efSDavid du Colombier return USTKTOP-sizeof(Tos);
348d6dfd9efSDavid du Colombier }
349d6dfd9efSDavid du Colombier
350d6dfd9efSDavid du Colombier void
sysprocsetup(Proc * p)351d6dfd9efSDavid du Colombier sysprocsetup(Proc* p)
352d6dfd9efSDavid du Colombier {
353d6dfd9efSDavid du Colombier fpusysprocsetup(p);
354d6dfd9efSDavid du Colombier }
355d6dfd9efSDavid du Colombier
356d6dfd9efSDavid du Colombier /*
357d6dfd9efSDavid du Colombier * Craft a return frame which will cause the child to pop out of
358d6dfd9efSDavid du Colombier * the scheduler in user mode with the return register zero. Set
359d6dfd9efSDavid du Colombier * pc to point to a l.s return function.
360d6dfd9efSDavid du Colombier */
361d6dfd9efSDavid du Colombier void
forkchild(Proc * p,Ureg * ureg)362d6dfd9efSDavid du Colombier forkchild(Proc *p, Ureg *ureg)
363d6dfd9efSDavid du Colombier {
364d6dfd9efSDavid du Colombier Ureg *cureg;
365d6dfd9efSDavid du Colombier
366d6dfd9efSDavid du Colombier //print("%lud setting up for forking child %lud\n", up->pid, p->pid);
367d6dfd9efSDavid du Colombier p->sched.sp = (ulong)p->kstack+KSTACK-(sizeof(Ureg)+2*BY2SE);
368d6dfd9efSDavid du Colombier p->sched.pc = (ulong)forkret;
369d6dfd9efSDavid du Colombier
370d6dfd9efSDavid du Colombier cureg = (Ureg*)(p->sched.sp+2*BY2SE);
371d6dfd9efSDavid du Colombier memmove(cureg, ureg, sizeof(Ureg));
372d6dfd9efSDavid du Colombier
373d6dfd9efSDavid du Colombier /* syscall returns 0 for child */
374d6dfd9efSDavid du Colombier cureg->r3 = 0;
375d6dfd9efSDavid du Colombier
376d6dfd9efSDavid du Colombier /* Things from bottom of syscall which were never executed */
377d6dfd9efSDavid du Colombier p->psstate = 0;
378d6dfd9efSDavid du Colombier p->insyscall = 0;
379d6dfd9efSDavid du Colombier
380d6dfd9efSDavid du Colombier fpusysrforkchild(p, cureg, up);
381d6dfd9efSDavid du Colombier }
382