ref: 6253af7a5ce9ed1f223769b1d690b9f6beca6850
parent: ba59008e1da6bdf87648f9cc44aac83095c49600
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Apr 15 20:26:01 EDT 2025
kernel: refactor syscall and note handling The differences between the syscall handlers are just the scallnr register, return register and the address where we fetch the stack arguments. So provide a dosyscall() function where we pass the syscall number, the Sargs* pointer and a uintptr* for the return value. The sysnoted() call is a bit special, as it needs all the registers to be restoed. For this dosyscall() returns a integer status. When 1, full register restore is needed. Also, it was determined that the Sargs* pointer needs to be alignment checked (now using evenaddr()). Now all kernels support ratrace syscall tracing.
--- a/sys/src/9/arm64/fns.h
+++ b/sys/src/9/arm64/fns.h
@@ -110,7 +110,6 @@
extern void procrestore(Proc *);
extern void trap(Ureg*);
extern void syscall(Ureg*);
-extern void noted(Ureg*, ulong);
extern void faultarm64(Ureg*);
extern void dumpstack(void);
extern void dumpregs(Ureg*);
--- a/sys/src/9/arm64/trap.c
+++ b/sys/src/9/arm64/trap.c
@@ -4,7 +4,6 @@
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
-#include "../port/systab.h"
#include <tos.h>
#include "ureg.h"
@@ -187,87 +186,17 @@
void
syscall(Ureg *ureg)
{
- vlong startns, stopns;
- uintptr sp, ret;
ulong scallnr;
- int i, s;
- char *e;
if(!kenter(ureg))
panic("syscall from kernel");
fpukenter(ureg);
- m->syscall++;
- up->insyscall = 1;
- up->pc = ureg->pc;
-
- sp = ureg->sp;
- up->scallnr = scallnr = ureg->r0;
- spllo();
-
- startns = 0;
- ret = -1;
- if(!waserror()){
- if(sp < USTKTOP - BY2PG || sp > USTKTOP - sizeof(Sargs) - BY2WD){
- validaddr(sp, sizeof(Sargs)+BY2WD, 0);
- evenaddr(sp);
- }
- up->s = *((Sargs*) (sp + BY2WD));
-
- if(up->procctl == Proc_tracesyscall){
- syscallfmt(scallnr, ureg->pc, (va_list) up->s.args);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- todget(nil, &startns);
- }
-
- if(scallnr >= nsyscall || systab[scallnr] == nil){
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
- up->psstate = sysctab[scallnr];
- ret = systab[scallnr]((va_list)up->s.args);
- poperror();
- }else{
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
- }
- if(up->nerrlab){
- print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
- for(i = 0; i < NERR; i++)
- print("sp=%#p pc=%#p\n", up->errlab[i].sp, up->errlab[i].pc);
- panic("error stack");
- }
- ureg->r0 = ret;
- if(up->procctl == Proc_tracesyscall){
- todget(nil, &stopns);
- sysretfmt(scallnr, (va_list) up->s.args, ret, startns, stopns);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- }
- up->insyscall = 0;
- up->psstate = 0;
-
- if(scallnr == NOTED){
- noted(ureg, *((ulong*) up->s.args));
- /*
- * normally, syscall() returns to forkret()
- * not restoring general registers when going
- * to userspace. to completely restore the
- * interrupted context, we have to return thru
- * noteret(). we override return pc to jump to
- * to it when returning form syscall()
- */
+ scallnr = ureg->r0;
+ if(dosyscall(scallnr, (Sargs*)(ureg->sp+BY2WD), &ureg->r0))
returnto(noteret);
- }
- splhi();
- if(scallnr != RFORK && (up->procctl || up->nnote))
+ if(up->procctl || up->nnote)
notify(ureg);
if(up->delaysched)
@@ -333,7 +262,7 @@
}
void
-noted(Ureg *ureg, ulong arg0)
+noted(Ureg *ureg, int arg0)
{
Ureg *nureg;
uintptr oureg, sp;
--- a/sys/src/9/bcm64/fns.h
+++ b/sys/src/9/bcm64/fns.h
@@ -109,7 +109,6 @@
extern void procrestore(Proc *);
extern void trap(Ureg*);
extern void syscall(Ureg*);
-extern void noted(Ureg*, ulong);
extern void faultarm64(Ureg*);
extern void dumpstack(void);
extern void dumpregs(Ureg*);
--- a/sys/src/9/cycv/fns.h
+++ b/sys/src/9/cycv/fns.h
@@ -44,7 +44,6 @@
void setasid(ulong);
void flushtlb(void);
void touser(void *);
-void noted(Ureg *, ulong);
void l1switch(L1 *, int);
void intrenable(int, void (*)(Ureg *, void *), void *, int, char *);
void intrinit(void);
--- a/sys/src/9/cycv/trap.c
+++ b/sys/src/9/cycv/trap.c
@@ -195,83 +195,16 @@
}
}
-#include "../port/systab.h"
-
void
syscall(Ureg *ureg)
{
- char *e;
- uintptr sp;
- long ret;
- int i, s;
ulong scallnr;
- vlong startns, stopns;
if(!kenter(ureg))
panic("syscall: pc=%#.8lux", ureg->pc);
-
- m->syscall++;
- up->insyscall = 1;
- up->pc = ureg->pc;
-
- sp = ureg->sp;
- up->scallnr = scallnr = ureg->r0;
-
- spllo();
-
- ret = -1;
- if(!waserror()){
- if(sp < USTKTOP - BY2PG || sp > USTKTOP - sizeof(Sargs) - BY2WD){
- validaddr(sp, sizeof(Sargs)+BY2WD, 0);
- evenaddr(sp);
- }
- up->s = *((Sargs*) (sp + BY2WD));
-
- if(up->procctl == Proc_tracesyscall){
- syscallfmt(scallnr, ureg->pc, (va_list) up->s.args);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- todget(nil, &startns);
- }
-
- if(scallnr >= nsyscall || systab[scallnr] == nil){
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
- up->psstate = sysctab[scallnr];
- ret = systab[scallnr]((va_list)up->s.args);
- poperror();
- }else{
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
- }
- if(up->nerrlab){
- print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
- for(i = 0; i < NERR; i++)
- print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
- panic("error stack");
- }
-
- ureg->r0 = ret;
- if(up->procctl == Proc_tracesyscall){
- todget(nil, &stopns);
- sysretfmt(scallnr, (va_list) up->s.args, ret, startns, stopns);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- }
-
- up->insyscall = 0;
- up->psstate = 0;
- if(scallnr == NOTED)
- noted(ureg, *((ulong *) up->s.args));
-
- splhi();
- if(scallnr != RFORK && (up->procctl || up->nnote))
+ scallnr = ureg->r0;
+ dosyscall(scallnr, (Sargs*)(ureg->sp + BY2WD), &ureg->r0);
+ if(up->procctl || up->nnote)
notify(ureg);
if(up->delaysched)
sched();
@@ -353,7 +286,7 @@
}
void
-noted(Ureg *ureg, ulong arg0)
+noted(Ureg *ureg, int arg0)
{
Ureg *nureg;
ulong oureg, sp;
--- a/sys/src/9/imx8/fns.h
+++ b/sys/src/9/imx8/fns.h
@@ -112,7 +112,6 @@
extern void procrestore(Proc *);
extern void trap(Ureg*);
extern void syscall(Ureg*);
-extern void noted(Ureg*, ulong);
extern void faultarm64(Ureg*);
extern void dumpstack(void);
extern void dumpregs(Ureg*);
--- a/sys/src/9/lx2k/fns.h
+++ b/sys/src/9/lx2k/fns.h
@@ -112,7 +112,6 @@
extern void procrestore(Proc *);
extern void trap(Ureg*);
extern void syscall(Ureg*);
-extern void noted(Ureg*, ulong);
extern void faultarm64(Ureg*);
extern void dumpstack(void);
extern void dumpregs(Ureg*);
--- a/sys/src/9/mt7688/fns.h
+++ b/sys/src/9/mt7688/fns.h
@@ -85,8 +85,6 @@
ulong getconfig7(void);
ulong gethwreg3(void);
void plan9iniinit(void);
-void noted(Ureg*, ulong);
-int notify(Ureg*);
void intrinit(void);
int i8250console(void);
void setconfenv(void);
--- a/sys/src/9/mt7688/syscall.c
+++ b/sys/src/9/mt7688/syscall.c
@@ -4,7 +4,6 @@
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
-#include "../port/systab.h"
#include "tos.h"
#include "ureg.h"
@@ -11,111 +10,27 @@
FPsave initfp;
-
/*
* called directly from assembler, not via trap()
*/
void
-syscall(Ureg* ureg)
+syscall(Ureg *ur)
{
- char *e;
- u32int s;
- ulong sp;
- long ret;
- int i;
- vlong startns, stopns;
ulong scallnr;
- if(!kenter(ureg))
+ if(!kenter(ur))
panic("syscall from kernel");
-
- m->syscall++;
- up->insyscall = 1;
- up->pc = ureg->pc;
-
- scallnr = ureg->r1;
- up->scallnr = ureg->r1;
- spllo();
- sp = ureg->sp;
-
- up->nerrlab = 0;
- ret = -1;
-
- if(!waserror()){
- if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)))
- validaddr(sp, sizeof(Sargs), 0);
-
- up->s = *((Sargs*)(sp)); /* spim's libc is different to mips ... */
-
- if(up->procctl == Proc_tracesyscall){
- syscallfmt(scallnr, ureg->pc, (va_list)up->s.args);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- todget(nil, &startns);
- }
-
- if(scallnr >= nsyscall || systab[scallnr] == nil){
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
- up->psstate = sysctab[scallnr];
- ret = systab[scallnr]((va_list)up->s.args);
- poperror();
- }else{
- /* failure: save the error buffer for errstr */
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
-// iprint("[%lud %s] syscall %lud: %s\n",up->pid, up->text, scallnr, up->errstr);
- }
-
- if(up->nerrlab){
- iprint("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
- for(i = 0; i < NERR; i++)
- iprint("sp=%#p pc=%#p\n",
- up->errlab[i].sp, up->errlab[i].pc);
- panic("error stack");
- }
-
- /*
- * Put return value in frame. On the x86 the syscall is
- * just another trap and the return value from syscall is
- * ignored. On other machines the return value is put into
- * the results register by caller of syscall.
- */
- ureg->pc += 4;
- ureg->r1 = ret;
-
- if(up->procctl == Proc_tracesyscall){
- todget(nil, &stopns);
- sysretfmt(scallnr, (va_list)up->s.args, ret, startns, stopns);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- }
-
- up->insyscall = 0;
- up->psstate = 0;
-
- if(scallnr == NOTED)
- noted(ureg, *((ulong*)up->s.args));
-
- splhi();
- if(scallnr != RFORK && (up->procctl || up->nnote))
- notify(ureg);
-
+ scallnr = ur->r1;
+ if(dosyscall(scallnr, (Sargs*)ur->sp, &ur->r1) == 0)
+ ur->pc += 4;
+ if(up->procctl || up->nnote)
+ notify(ur);
/* if we delayed sched because we held a lock, sched now */
if(up->delaysched)
sched();
-
- kexit(ureg);
-
+ kexit(ur);
/* restore EXL in status */
setstatus(getstatus() | EXL);
-
}
void
@@ -131,7 +46,7 @@
}
FPsave*
-notefpsave(Proc *p)
+notefpsave(Proc*)
{
return nil;
}
@@ -195,7 +110,7 @@
* Return user to state before notify(); called from user's handler.
*/
void
-noted(Ureg *kur, ulong arg0)
+noted(Ureg *kur, int arg0)
{
Ureg *nur;
ulong oureg, sp;
@@ -214,8 +129,8 @@
oureg = (ulong)nur;
if((oureg & (BY2WD-1)) || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
- pprint("bad up->ureg in noted or call to noted() when not notified\n");
qunlock(&up->debug);
+ pprint("bad up->ureg in noted or call to noted() when not notified\n");
pexit("Suicide", 0);
}
@@ -225,8 +140,8 @@
case NCONT:
case NRSTR: /* only used by APE */
if(!okaddr(kur->pc, BY2WD, 0) || !okaddr(kur->usp, BY2WD, 0)){
- pprint("suicide: trap in noted\n");
qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
pexit("Suicide", 0);
}
up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
@@ -238,8 +153,8 @@
kur->r1 = oureg; /* arg 1 is ureg* */
kur->usp = sp;
if(!okaddr(kur->pc, BY2WD, 0) || !okaddr(kur->usp, 4*BY2WD, 1)){
- pprint("suicide: trap in noted\n");
qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
pexit("Suicide", 0);
}
qunlock(&up->debug);
@@ -248,14 +163,13 @@
break;
default:
- pprint("unknown noted arg %#lux\n", arg0);
up->lastnote->flag = NDebug;
/* fall through */
case NDFLT:
+ qunlock(&up->debug);
if(up->lastnote->flag == NDebug)
pprint("suicide: %s\n", up->lastnote->msg);
- qunlock(&up->debug);
pexit(up->lastnote->msg, up->lastnote->flag!=NDebug);
}
}
--- a/sys/src/9/mt7688/trap.c
+++ b/sys/src/9/mt7688/trap.c
@@ -14,7 +14,6 @@
int intr(Ureg*);
void kernfault(Ureg*, int);
-void noted(Ureg*, ulong);
void rfnote(Ureg**);
char *excname[] =
--- a/sys/src/9/mtx/trap.c
+++ b/sys/src/9/mtx/trap.c
@@ -5,6 +5,7 @@
#include "fns.h"
#include "ureg.h"
#include "io.h"
+#include "../port/pci.h"
#include "tos.h"
#include "../port/error.h"
@@ -145,7 +146,6 @@
}
void syscall(Ureg*);
-void noted(Ureg*, ulong);
static void _dumpstack(Ureg*);
char *excname[] =
@@ -374,10 +374,8 @@
mpiceoi(0);
}
- if(vno > nelem(vctl) || (ctl = vctl[vno]) == 0) {
+ if(vno > nelem(vctl) || (ctl = vctl[vno]) == 0)
panic("spurious intr %d", vno);
- return;
- }
if(ctl->isr)
ctl->isr(vno);
@@ -590,73 +588,34 @@
/*
* system calls
*/
-#include "../port/systab.h"
/* TODO: make this trap a separate asm entry point, like on other RISC architectures */
void
syscall(Ureg* ureg)
{
- int i;
- char *e;
- long ret;
- ulong sp, scallnr;
+ ulong scallnr;
- m->syscall++;
- up->insyscall = 1;
- up->pc = ureg->pc;
-
- scallnr = ureg->r3;
- up->scallnr = ureg->r3;
- spllo();
-
- sp = ureg->usp;
- ret = -1;
- if(!waserror()){
- if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
- validaddr(sp, sizeof(Sargs)+BY2WD, 0);
-
- up->s = *((Sargs*)(sp+BY2WD));
-
- if(scallnr >= nsyscall || systab[scallnr] == nil){
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
- up->psstate = sysctab[scallnr];
- ret = systab[scallnr](up->s.args);
- poperror();
- }else{
- /* failure: save the error buffer for errstr */
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
+ if(!kenter(ureg))
+ panic("syscall from kernel");
+ if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
+ print("fpstate check, entry syscall\n");
+ delay(200);
+ dumpregs(ureg);
+ print("fpstate check, entry syscall\n");
}
- if(up->nerrlab){
- print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
- print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr);
- for(i = 0; i < NERR; i++)
- print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
- panic("error stack");
- }
-
- up->insyscall = 0;
- up->psstate = 0;
-
- /*
- * Put return value in frame. On the x86 the syscall is
- * just another trap and the return value from syscall is
- * ignored. On other machines the return value is put into
- * the results register by caller of syscall.
- */
- ureg->r3 = ret;
-
- if(scallnr == NOTED)
- noted(ureg, *(ulong*)(sp+BY2WD));
-
- /* restoreureg must execute at high IPL */
- splhi();
- if(scallnr!=RFORK)
+ scallnr = ureg->r3;
+ dosyscall(scallnr, (Sargs*)(ureg->usp+BY2WD), &ureg->r3);
+ if(up->procctl || up->nnote)
notify(ureg);
- if(up->fpstate == FPinactive)
+ /* if we delayed sched because we held a lock, sched now */
+ if(up->delaysched)
+ sched();
+ kexit(ureg);
+ if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
+ print("fpstate check, exit syscall nr %lud, pid %lud\n", scallnr, up->pid);
+ dumpregs(ureg);
+ }
+ if(up->fpstate != FPactive)
ureg->srr1 &= ~MSR_FP;
}
@@ -716,7 +675,7 @@
* Return user to state before notify()
*/
void
-noted(Ureg* ureg, ulong arg0)
+noted(Ureg* ureg, int arg0)
{
Ureg *nureg;
ulong oureg, sp;
--- a/sys/src/9/omap/syscall.c
+++ b/sys/src/9/omap/syscall.c
@@ -4,7 +4,6 @@
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
-#include "../port/systab.h"
#include <tos.h>
#include "ureg.h"
@@ -23,8 +22,8 @@
/*
* Return user to state before notify()
*/
-static void
-noted(Ureg* cur, uintptr arg0)
+void
+noted(Ureg* cur, int arg0)
{
NFrame *nf;
@@ -147,88 +146,15 @@
void
syscall(Ureg* ureg)
{
- char *e;
- u32int s;
- ulong sp;
- long ret;
- int i, scallnr;
- vlong startns, stopns;
+ ulong scallnr;
if(!kenter(ureg))
panic("syscall: from kernel: pc %#lux r14 %#lux psr %#lux",
ureg->pc, ureg->r14, ureg->psr);
-
- m->syscall++;
- up->insyscall = 1;
- up->pc = ureg->pc;
-
scallnr = ureg->r0;
- up->scallnr = scallnr;
- spllo();
- sp = ureg->sp;
-
- up->nerrlab = 0;
- ret = -1;
- if(!waserror()){
- if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD))
- validaddr(sp, sizeof(Sargs)+BY2WD, 0);
- up->s = *((Sargs*)(sp+BY2WD));
- if(up->procctl == Proc_tracesyscall){
- syscallfmt(scallnr, ureg->pc, (va_list)up->s.args);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- todget(nil, &startns);
- }
- if(scallnr >= nsyscall || systab[scallnr] == nil){
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
- up->psstate = sysctab[scallnr];
- ret = systab[scallnr]((va_list)up->s.args);
- poperror();
- }else{
- /* failure: save the error buffer for errstr */
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
- }
- if(up->nerrlab){
- print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab);
- for(i = 0; i < NERR; i++)
- print("sp=%#p pc=%#p\n",
- up->errlab[i].sp, up->errlab[i].pc);
- panic("error stack");
- }
-
- /*
- * Put return value in frame. On the x86 the syscall is
- * just another trap and the return value from syscall is
- * ignored. On other machines the return value is put into
- * the results register by caller of syscall.
- */
- ureg->r0 = ret;
-
- if(up->procctl == Proc_tracesyscall){
- todget(nil, &stopns);
- sysretfmt(scallnr, (va_list)up->s.args, ret, startns, stopns);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- }
-
- up->insyscall = 0;
- up->psstate = 0;
-
- if(scallnr == NOTED)
- noted(ureg, *((ulong*)up->s.args));
-
- splhi();
- if(scallnr != RFORK && (up->procctl || up->nnote))
+ dosyscall(scallnr, (Sargs*)(ureg->sp + BY2WD), &ureg->r0);
+ if(up->procctl || up->nnote)
notify(ureg);
-
/* if we delayed sched because we held a lock, sched now */
if(up->delaysched)
sched();
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -12,8 +12,6 @@
extern int irqhandled(Ureg*, int);
extern void irqinit(void);
-void noted(Ureg*, ulong);
-
static void debugexc(Ureg*, void*);
static void debugbpt(Ureg*, void*);
static void fault386(Ureg*, void*);
@@ -450,100 +448,18 @@
}
/*
- * system calls
- */
-#include "../port/systab.h"
-
-/*
* Syscall is called directly from assembler without going through trap().
*/
void
syscall(Ureg* ureg)
{
- char *e;
- ulong sp;
- long ret;
- int i, s;
ulong scallnr;
- vlong startns, stopns;
if(!kenter(ureg))
panic("syscall: cs 0x%4.4luX", ureg->cs);
-
- m->syscall++;
- up->insyscall = 1;
- up->pc = ureg->pc;
-
- sp = ureg->usp;
scallnr = ureg->ax;
- up->scallnr = scallnr;
-
- spllo();
-
- ret = -1;
- if(!waserror()){
- if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
- validaddr(sp, sizeof(Sargs)+BY2WD, 0);
-
- up->s = *((Sargs*)(sp+BY2WD));
-
- if(up->procctl == Proc_tracesyscall){
- syscallfmt(scallnr, ureg->pc, (va_list)up->s.args);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- todget(nil, &startns);
- }
-
- if(scallnr >= nsyscall || systab[scallnr] == nil){
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
- up->psstate = sysctab[scallnr];
- ret = systab[scallnr]((va_list)up->s.args);
- poperror();
- }else{
- /* failure: save the error buffer for errstr */
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
- if(0 && up->pid == 1)
- print("syscall %lud error %s\n", scallnr, up->syserrstr);
- }
- if(up->nerrlab){
- print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
- for(i = 0; i < NERR; i++)
- print("sp=%lux pc=%lux\n",
- up->errlab[i].sp, up->errlab[i].pc);
- panic("error stack");
- }
-
- /*
- * Put return value in frame. On the x86 the syscall is
- * just another trap and the return value from syscall is
- * ignored. On other machines the return value is put into
- * the results register by caller of syscall.
- */
- ureg->ax = ret;
-
- if(up->procctl == Proc_tracesyscall){
- todget(nil, &stopns);
- sysretfmt(scallnr, (va_list)up->s.args, ret, startns, stopns);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- }
-
- up->insyscall = 0;
- up->psstate = 0;
-
- if(scallnr == NOTED)
- noted(ureg, *((ulong*)up->s.args));
-
- splhi();
- if(scallnr!=RFORK && (up->procctl || up->nnote))
+ dosyscall(scallnr, (Sargs*)(ureg->sp + BY2WD), &ureg->ax);
+ if(up->procctl || up->nnote)
notify(ureg);
/* if we delayed sched because we held a lock, sched now */
if(up->delaysched)
@@ -612,7 +528,7 @@
* Return user to state before notify()
*/
void
-noted(Ureg* ureg, ulong arg0)
+noted(Ureg* ureg, int arg0)
{
Ureg *nureg;
ulong oureg, sp;
--- a/sys/src/9/pc64/trap.c
+++ b/sys/src/9/pc64/trap.c
@@ -12,8 +12,6 @@
extern int irqhandled(Ureg*, int);
extern void irqinit(void);
-void noted(Ureg*, ulong);
-
static void debugexc(Ureg*, void*);
static void debugbpt(Ureg*, void*);
static void faultamd64(Ureg*, void*);
@@ -427,118 +425,24 @@
}
/*
- * system calls
- */
-#include "../port/systab.h"
-
-/*
* Syscall is called directly from assembler without going through trap().
*/
void
syscall(Ureg* ureg)
{
- char *e;
- uintptr sp;
- long long ret;
- int i, s;
ulong scallnr;
- vlong startns, stopns;
if(!kenter(ureg))
panic("syscall: cs 0x%4.4lluX", ureg->cs);
fpukenter(ureg);
-
- m->syscall++;
- up->insyscall = 1;
-
- up->pc = ureg->pc;
- sp = ureg->sp;
scallnr = ureg->bp; /* RARG */
- up->scallnr = scallnr;
- spllo();
-
- ret = -1;
- startns = 0;
- if(!waserror()){
- if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
- validaddr(sp, sizeof(Sargs)+BY2WD, 0);
-
- up->s = *((Sargs*)(sp+BY2WD));
- if(0){
- syscallfmt(scallnr, ureg->pc, (va_list)up->s.args);
- print("syscall: %s\n", up->syscalltrace);
- }
-
- if(up->procctl == Proc_tracesyscall){
- syscallfmt(scallnr, ureg->pc, (va_list)up->s.args);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- todget(nil, &startns);
- }
- if(scallnr >= nsyscall || systab[scallnr] == nil){
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
- up->psstate = sysctab[scallnr];
- ret = systab[scallnr]((va_list)up->s.args);
- poperror();
- }else{
- /* failure: save the error buffer for errstr */
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
- if(0 && up->pid == 1)
- print("syscall %lud error %s\n", scallnr, up->syserrstr);
- }
- if(up->nerrlab){
- print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
- for(i = 0; i < NERR; i++)
- print("sp=%#p pc=%#p\n",
- up->errlab[i].sp, up->errlab[i].pc);
- panic("error stack");
- }
- ureg->ax = ret;
-
- if(0){
- print("syscallret: %lud %s %s ret=%lld\n",
- up->pid, up->text, sysctab[scallnr], ret);
- }
-
- if(up->procctl == Proc_tracesyscall){
- todget(nil, &stopns);
- sysretfmt(scallnr, (va_list)up->s.args, ret, startns, stopns);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- }
-
- if(scallnr == NOTED){
- /*
- * normally, syscall() returns to forkret()
- * not restoring general registers when going
- * to userspace. to completely restore the
- * interrupted context, we have to return thru
- * noteret(). we override return pc to jump to
- * to it when returning form syscall()
- */
- ((void**)&ureg)[-1] = (void*)noteret;
- noted(ureg, *((ulong*)up->s.args));
- }
-
- splhi();
- if(scallnr != RFORK && (up->procctl || up->nnote) && notify(ureg))
+ if(dosyscall(scallnr, (Sargs*)(ureg->sp+BY2WD), &ureg->ax))
((void**)&ureg)[-1] = (void*)noteret; /* loads RARG */
-
- up->insyscall = 0;
- up->psstate = nil;
-
+ if((up->procctl || up->nnote) && notify(ureg))
+ ((void**)&ureg)[-1] = (void*)noteret; /* loads RARG */
/* if we delayed sched because we held a lock, sched now */
if(up->delaysched)
sched();
-
kexit(ureg);
fpukexit(ureg);
}
@@ -606,7 +510,7 @@
* Return user to state before notify()
*/
void
-noted(Ureg* ureg, ulong arg0)
+noted(Ureg* ureg, int arg0)
{
Ureg *nureg;
uintptr oureg, sp;
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -726,7 +726,6 @@
int noswap; /* process is not swappable */
int hang; /* hang at next exec for debug */
int procctl; /* Control for /proc debugging */
- uintptr pc; /* DEBUG only */
Lock rlock; /* sync sleep/wakeup with procinterrupt */
Rendez *r; /* rendezvous point slept on */
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -80,6 +80,7 @@
Walkqid* devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*);
int devwstat(Chan*, uchar*, int);
Dir* dirchanstat(Chan *);
+int dosyscall(ulong, Sargs*, uintptr*);
void drawactive(int);
void drawcmap(void);
void dtracytick(Ureg*);
@@ -221,6 +222,7 @@
Proc* newproc(void);
_Noreturn void nexterror(void);
int notify(Ureg*);
+void noted(Ureg*, int);
FPsave* notefpsave(Proc*);
ulong nkpages(Confmem*);
uvlong ns2fastticks(uvlong);
--- a/sys/src/9/port/portmkfile
+++ b/sys/src/9/port/portmkfile
@@ -112,8 +112,8 @@
random.$O: /sys/include/libsec.h
wifi.$O: /sys/include/libsec.h
devaoe.$O sdaoe.$O: /sys/include/fis.h
-sysproc.$O: /sys/include/a.out.h
-syscallfmt.$O: /sys/src/libc/9syscall/sys.h
+sysproc.$O: /sys/include/a.out.h ../port/systab.h
+sysproc.$O syscallfmt.$O: /sys/src/libc/9syscall/sys.h
devusb.$O usbxhci.$O usbxhcipci.$O: ../port/usb.h
usbxhci.$O usbxhcipci.$O: ../port/usbxhci.h
devether.$O: ../ip/ip.h ../ip/ipv6.h
--- a/sys/src/9/port/sysproc.c
+++ b/sys/src/9/port/sysproc.c
@@ -782,8 +782,12 @@
uintptr
sysnoted(va_list list)
{
- if(va_arg(list, int) != NRSTR && !up->notified)
+ int arg;
+
+ arg = va_arg(list, int);
+ if(arg != NRSTR && !up->notified)
error(Egreg);
+ noted(up->dbgreg, arg);
return 0;
}
@@ -1264,5 +1268,77 @@
evenaddr((uintptr)v);
validaddr((uintptr)v, sizeof(vlong), 1);
*v = todget(nil, nil);
+ return 0;
+}
+
+#include "../port/systab.h"
+
+int
+dosyscall(ulong scallnr, Sargs *args, uintptr *retp)
+{
+ vlong startns, stopns;
+ uintptr ret;
+ int s;
+
+ m->syscall++;
+
+ up->insyscall = 1;
+ s = spllo();
+
+ if(!waserror()){
+ evenaddr((uintptr)args);
+ validaddr((uintptr)args, sizeof(Sargs), 0);
+
+ up->s = *args;
+ up->scallnr = scallnr;
+
+ if(up->procctl == Proc_tracesyscall){
+ syscallfmt(scallnr, userpc(), (va_list)up->s.args);
+ splhi();
+ up->procctl = Proc_stopme;
+ procctl();
+ spllo();
+ todget(nil, &startns);
+ }
+ if(scallnr >= nsyscall || systab[scallnr] == nil){
+ postnote(up, 1, "sys: bad sys call", NDebug);
+ error(Ebadarg);
+ }
+ up->psstate = sysctab[scallnr];
+ ret = systab[scallnr]((va_list)up->s.args);
+ poperror();
+ if(scallnr == NOTED){
+ /* special case: noted() changes the ureg, return without setting *retp */
+ splx(s);
+ up->insyscall = 0;
+ up->psstate = nil;
+ return 1;
+ }
+ }else{
+ /* failure: save the error buffer for errstr */
+ char *e = up->syserrstr;
+ up->syserrstr = up->errstr;
+ up->errstr = e;
+ ret = -1;
+ }
+ if(up->nerrlab){
+ int i;
+
+ print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
+ for(i = 0; i < NERR; i++)
+ print("sp=%#p pc=%#p\n", up->errlab[i].sp, up->errlab[i].pc);
+ panic("error stack");
+ }
+ *retp = ret;
+ if(up->procctl == Proc_tracesyscall){
+ todget(nil, &stopns);
+ sysretfmt(scallnr, (va_list)up->s.args, ret, startns, stopns);
+ splhi();
+ up->procctl = Proc_stopme;
+ procctl();
+ }
+ splx(s);
+ up->insyscall = 0;
+ up->psstate = nil;
return 0;
}
--- a/sys/src/9/ppc/dat.h
+++ b/sys/src/9/ppc/dat.h
@@ -75,7 +75,7 @@
FPactive = 1,
FPinactive = 2,
/* Bit that's or-ed in during note handling (FP is illegal in note handlers) */
- FPillegal = 0x100,
+ FPnotify = 0x100,
};
struct Confmem
--- a/sys/src/9/ppc/main.c
+++ b/sys/src/9/ppc/main.c
@@ -189,12 +189,12 @@
}
void
-procfork(Proc *p)
+procfork(Proc*)
{
}
void
-procrestore(Proc *p)
+procrestore(Proc*)
{
}
--- a/sys/src/9/ppc/trap.c
+++ b/sys/src/9/ppc/trap.c
@@ -73,7 +73,6 @@
}
void syscall(Ureg*);
-void noted(Ureg*, ulong);
static void _dumpstack(Ureg*);
char *excname[] =
@@ -148,9 +147,9 @@
extern FPsave initfp;
user = kenter(ureg);
+ ecode = (ureg->cause >> 8) & 0xff;
if((ureg->status & MSR_RI) == 0)
print("double fault?: ecode = %d\n", ecode);
- ecode = (ureg->cause >> 8) & 0xff;
switch(ecode) {
case CEI:
m->intr++;
@@ -565,21 +564,15 @@
/*
* system calls
*/
-#include "../port/systab.h"
/* TODO: make this trap a separate asm entry point, like on other RISC architectures */
void
syscall(Ureg* ureg)
{
- int i;
- char *e;
- long ret;
- ulong sp, scallnr;
+ ulong scallnr;
- m->syscall++;
- up->insyscall = 1;
- up->pc = ureg->pc;
-
+ if(!kenter(ureg))
+ panic("syscall from kernel");
if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
print("fpstate check, entry syscall\n");
delay(200);
@@ -586,58 +579,14 @@
dumpregs(ureg);
print("fpstate check, entry syscall\n");
}
-
scallnr = ureg->r3;
- up->scallnr = ureg->r3;
- spllo();
-
- sp = ureg->usp;
- ret = -1;
- if(!waserror()){
- if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
- validaddr(sp, sizeof(Sargs)+BY2WD, 0);
-
- up->s = *((Sargs*)(sp+BY2WD));
- if(scallnr >= nsyscall || systab[scallnr] == nil){
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
- up->psstate = sysctab[scallnr];
- ret = systab[scallnr]((va_list)up->s.args);
- poperror();
- }else{
- /* failure: save the error buffer for errstr */
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
- }
- if(up->nerrlab){
- print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
- print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr);
- for(i = 0; i < NERR; i++)
- print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
- panic("error stack");
- }
-
- up->insyscall = 0;
- up->psstate = 0;
-
- /*
- * Put return value in frame. On the x86 the syscall is
- * just another trap and the return value from syscall is
- * ignored. On other machines the return value is put into
- * the results register by caller of syscall.
- */
- ureg->r3 = ret;
-
- if(scallnr == NOTED)
- noted(ureg, *(ulong*)(sp+BY2WD));
-
- /* restoreureg must execute at high IPL */
- splhi();
- if(scallnr!=RFORK)
+ dosyscall(scallnr, (Sargs*)(ureg->usp+BY2WD), &ureg->r3);
+ if(up->procctl || up->nnote)
notify(ureg);
-
+ /* if we delayed sched because we held a lock, sched now */
+ if(up->delaysched)
+ sched();
+ kexit(ureg);
if (up->fpstate == FPactive && (ureg->srr1 & MSR_FP) == 0){
print("fpstate check, exit syscall nr %lud, pid %lud\n", scallnr, up->pid);
dumpregs(ureg);
@@ -665,7 +614,7 @@
fpsave(up->fpsave);
up->fpstate = FPinactive;
}
- up->fpstate |= FPillegal;
+ up->fpstate |= FPnotify;
s = spllo();
qlock(&up->debug);
@@ -708,7 +657,7 @@
* Return user to state before notify()
*/
void
-noted(Ureg* ureg, ulong arg0)
+noted(Ureg* ureg, int arg0)
{
Ureg *nureg;
ulong oureg, sp;
@@ -770,7 +719,7 @@
pprint("suicide: %s\n", up->lastnote->msg);
pexit(up->lastnote->msg, up->lastnote->flag!=NDebug);
}
- up->fpstate &= ~FPillegal;
+ up->fpstate &= ~FPnotify;
if (up->fpstate == FPactive)
ureg->srr1 |= MSR_FP;
else
--- a/sys/src/9/sgi/trap.c
+++ b/sys/src/9/sgi/trap.c
@@ -21,7 +21,6 @@
int intr(Ureg*);
void kernfault(Ureg*, int);
-void noted(Ureg*, ulong);
void rfnote(Ureg**);
char *excname[] =
@@ -523,7 +522,7 @@
* Return user to state before notify(); called from user's handler.
*/
void
-noted(Ureg *kur, ulong arg0)
+noted(Ureg *kur, int arg0)
{
Ureg *nur;
ulong oureg, sp;
@@ -543,8 +542,8 @@
nur = up->ureg;
oureg = (ulong)nur;
if((oureg & (BY2WD-1)) || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
- pprint("bad up->ureg in noted or call to noted() when not notified\n");
qunlock(&up->debug);
+ pprint("bad up->ureg in noted or call to noted() when not notified\n");
pexit("Suicide", 0);
}
@@ -554,8 +553,8 @@
case NCONT:
case NRSTR: /* only used by APE */
if(!okaddr(kur->pc, BY2WD, 0) || !okaddr(kur->usp, BY2WD, 0)){
- pprint("suicide: trap in noted\n");
qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
pexit("Suicide", 0);
}
up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
@@ -564,20 +563,19 @@
case NSAVE: /* only used by APE */
sp = oureg-4*BY2WD-ERRMAX;
- kur->r1 = oureg; /* arg 1 is ureg* */
- kur->usp = sp;
- if(!okaddr(kur->pc, BY2WD, 0) || !okaddr(kur->usp, 4*BY2WD, 1)){
- pprint("suicide: trap in noted\n");
+ if(!okaddr(kur->pc, BY2WD, 0) || !okaddr(sp, 4*BY2WD, 1)){
qunlock(&up->debug);
+ pprint("suicide: trap in noted\n");
pexit("Suicide", 0);
}
qunlock(&up->debug);
+ kur->r1 = oureg; /* arg 1 is ureg* */
+ kur->usp = sp;
((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
((ulong*)sp)[0] = 0; /* arg 0 is pc */
break;
default:
- pprint("unknown noted arg %#lux\n", arg0);
up->lastnote->flag = NDebug;
/* fall through */
@@ -589,52 +587,6 @@
}
}
-#include "../port/systab.h"
-
-static void
-sctracesetup(ulong scallnr, ulong sp, uintptr pc, vlong *startnsp)
-{
- if(up->procctl == Proc_tracesyscall){
- /*
- * Redundant validaddr. Do we care?
- * Tracing syscalls is not exactly a fast path...
- * Beware, validaddr currently does a pexit rather
- * than an error if there's a problem; that might
- * change in the future.
- */
- if(sp < (USTKTOP-BY2PG) || sp > (USTKTOP-sizeof(Sargs)-BY2WD))
- validaddr(sp, sizeof(Sargs)+BY2WD, 0);
-
- syscallfmt(scallnr, pc, (va_list)(sp+BY2WD));
- up->procctl = Proc_stopme;
- procctl();
- if(up->syscalltrace)
- free(up->syscalltrace);
- up->syscalltrace = nil;
- todget(nil, startnsp);
- }
-}
-
-static void
-sctracefinish(ulong scallnr, ulong sp, int ret, vlong startns)
-{
- vlong stopns;
- int s;
-
- if(up->procctl == Proc_tracesyscall){
- todget(nil, &stopns);
- up->procctl = Proc_stopme;
- sysretfmt(scallnr, (va_list)(sp+BY2WD), ret,
- startns, stopns);
- s = splhi();
- procctl();
- splx(s);
- if(up->syscalltrace)
- free(up->syscalltrace);
- up->syscalltrace = nil;
- }
-}
-
/*
* called directly from assembler, not via trap()
*/
@@ -641,75 +593,15 @@
void
syscall(Ureg *ur)
{
- int i;
- volatile long ret;
- ulong sp, scallnr;
- vlong startns;
- char *e;
+ ulong scallnr;
if(!kenter(ur))
panic("syscall from kernel");
-
- m->syscall++;
- up->insyscall = 1;
- up->pc = ur->pc;
ur->cause = 16<<2; /* for debugging: system call is undef 16 */
-
scallnr = ur->r1;
- up->scallnr = ur->r1;
- sp = ur->sp;
- sctracesetup(scallnr, sp, ur->pc, &startns);
-
- /* no fpu, so no fp state to save */
- spllo();
-
- ret = -1;
- if(!waserror()) {
- if(sp & (BY2WD-1)){
- postnote(up, 1, "sys: odd stack", NDebug);
- error(Ebadarg);
- }
-
- if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
- validaddr(sp, sizeof(Sargs)+BY2WD, 0);
-
- up->s = *((Sargs*)(sp+BY2WD));
- if(scallnr >= nsyscall || systab[scallnr] == nil){
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
- up->psstate = sysctab[scallnr];
-
- ret = systab[scallnr]((va_list)up->s.args);
- poperror();
- }else{
- /* failure: save the error buffer for errstr */
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
- if(0 && up->pid == 1)
- print("[%lud %s] syscall %lud: %s\n",
- up->pid, up->text, scallnr, up->errstr);
- }
- if(up->nerrlab){
- print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
- for(i = 0; i < NERR; i++)
- print("sp=%#lux pc=%#lux\n",
- up->errlab[i].sp, up->errlab[i].pc);
- panic("error stack");
- }
- sctracefinish(scallnr, sp, ret, startns);
-
- ur->pc += 4;
- ur->r1 = ret;
-
- up->psstate = 0;
- up->insyscall = 0;
-
- if(scallnr == NOTED) /* ugly hack */
- noted(ur, *(ulong*)(sp+BY2WD)); /* may return */
- splhi();
- if(scallnr!=RFORK && (up->procctl || up->nnote))
+ if(dosyscall(scallnr, (Sargs*)(ur->sp+BY2WD), &ur->r1) == 0)
+ ur->pc += 4;
+ if(up->procctl || up->nnote)
notify(ur);
/* if we delayed sched because we held a lock, sched now */
if(up->delaysched)
--- a/sys/src/9/xen/mkfile
+++ b/sys/src/9/xen/mkfile
@@ -33,6 +33,7 @@
qlock.$O\
rebootcmd.$O\
segment.$O\
+ syscallfmt.$O\
sysfile.$O\
sysproc.$O\
taslock.$O\
--- a/sys/src/9/xen/trap.c
+++ b/sys/src/9/xen/trap.c
@@ -25,8 +25,6 @@
SPL3 = 3,
EvDisable = 4,
};
-
-void noted(Ureg*, ulong);
extern void irqinit(void);
extern int irqhandled(Ureg*, int);
@@ -361,105 +359,22 @@
}
/*
- * system calls
- */
-#include "../port/systab.h"
-
-/*
* Syscall is called directly from assembler without going through trap().
*/
void
syscall(Ureg* ureg)
{
- char *e;
- ulong sp;
- long ret;
- int i, s;
ulong scallnr;
- SYSCALLLOG(dprint("%d: syscall ...#%ld(%s)\n",
- up->pid, ureg->ax, sysctab[ureg->ax]);)
-
if(!kenter(ureg))
- panic("syscall: cs 0x%4.4luX\n", ureg->cs);
-
- m->syscall++;
- up->insyscall = 1;
- up->pc = ureg->pc;
-
- if(up->procctl == Proc_tracesyscall){
- up->procctl = Proc_stopme;
- procctl();
- }
-
+ panic("syscall: cs 0x%4.4luX", ureg->cs);
scallnr = ureg->ax;
- up->scallnr = scallnr;
- if(scallnr == RFORK && up->fpstate == FPactive){
- fpsave(up->fpsave);
- up->fpstate = FPinactive;
- }
- spllo();
-
- sp = ureg->usp;
- ret = -1;
- if(!waserror()){
- if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD))
- validaddr(sp, sizeof(Sargs)+BY2WD, 0);
-
- up->s = *((Sargs*)(sp+BY2WD));
-
- if(scallnr >= nsyscall || systab[scallnr] == nil){
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
- up->psstate = sysctab[scallnr];
- ret = systab[scallnr]((va_list)up->s.args);
- poperror();
- }else{
- /* failure: save the error buffer for errstr */
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
- if(0 && up->pid == 1)
- print("syscall %lud error %s\n", scallnr, up->syserrstr);
- }
- if(up->nerrlab){
- print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
- for(i = 0; i < NERR; i++)
- print("sp=%lux pc=%lux\n",
- up->errlab[i].sp, up->errlab[i].pc);
- panic("error stack");
- }
-
- SYSCALLLOG(dprint("%d: Syscall %d returns %d, ureg %p\n", up->pid, scallnr, ret, ureg);)
- /*
- * Put return value in frame. On the x86 the syscall is
- * just another trap and the return value from syscall is
- * ignored. On other machines the return value is put into
- * the results register by caller of syscall.
- */
- ureg->ax = ret;
-
- if(up->procctl == Proc_tracesyscall){
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- }
-
- up->insyscall = 0;
- up->psstate = 0;
- INTRLOG(dprint("cleared insyscall\n");)
- if(scallnr == NOTED)
- noted(ureg, *(ulong*)(sp+BY2WD));
-
- splhi();
- if(scallnr!=RFORK && (up->procctl || up->nnote))
+ dosyscall(scallnr, (Sargs*)(ureg->sp + BY2WD), &ureg->ax);
+ if(up->procctl || up->nnote)
notify(ureg);
/* if we delayed sched because we held a lock, sched now */
if(up->delaysched)
sched();
- INTRLOG(dprint("before kexit\n");)
kexit(ureg);
}
@@ -519,7 +434,7 @@
* Return user to state before notify()
*/
void
-noted(Ureg* ureg, ulong arg0)
+noted(Ureg* ureg, int arg0)
{
Ureg *nureg;
ulong oureg, sp;
@@ -541,8 +456,8 @@
/* sanity clause */
oureg = (ulong)nureg;
if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
- pprint("bad ureg in noted or call to noted when not notified\n");
qunlock(&up->debug);
+ pprint("bad ureg in noted or call to noted when not notified\n");
pexit("Suicide", 0);
}
@@ -561,8 +476,8 @@
pprint("ds is %#lux, wanted %#ux\n", nureg->ds, UDSEL);
pprint("es is %#lux, fs is %#lux, gs %#lux, wanted %#ux\n",
ureg->es, ureg->fs, ureg->gs, UDSEL);
- pprint("ss is %#lux, wanted %#ux\n", nureg->ss, UDSEL);
qunlock(&up->debug);
+ pprint("ss is %#lux, wanted %#ux\n", nureg->ss, UDSEL);
pexit("Suicide", 0);
}
@@ -582,19 +497,18 @@
case NSAVE:
sp = oureg-4*BY2WD-ERRMAX;
- ureg->usp = sp;
- if(!okaddr(ureg->pc, 1, 0) || !okaddr(ureg->usp, 4*BY2WD, 1)){
+ if(!okaddr(ureg->pc, 1, 0) || !okaddr(sp, 4*BY2WD, 1)){
qunlock(&up->debug);
pprint("suicide: trap in noted\n");
pexit("Suicide", 0);
}
qunlock(&up->debug);
+ ureg->usp = sp;
((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
((ulong*)sp)[0] = 0; /* arg 0 is pc */
break;
default:
- pprint("unknown noted arg 0x%lux\n", arg0);
up->lastnote->flag = NDebug;
/* fall through */
--- a/sys/src/9/zynq/fns.h
+++ b/sys/src/9/zynq/fns.h
@@ -45,7 +45,6 @@
void setasid(ulong);
void flushtlb(void);
void touser(void *);
-void noted(Ureg *, ulong);
void l1switch(L1 *, int);
void intrenable(int, void (*)(Ureg *, void *), void *, int, char *);
void intrinit(void);
--- a/sys/src/9/zynq/trap.c
+++ b/sys/src/9/zynq/trap.c
@@ -214,82 +214,16 @@
}
}
-#include "../port/systab.h"
-
void
syscall(Ureg *ureg)
{
- char *e;
- uintptr sp;
- long ret;
- int i, s;
ulong scallnr;
- vlong startns, stopns;
if(!kenter(ureg))
panic("syscall: pc=%#.8lux", ureg->pc);
-
- m->syscall++;
- up->insyscall = 1;
- up->pc = ureg->pc;
-
- sp = ureg->sp;
- up->scallnr = scallnr = ureg->r0;
-
- spllo();
-
- ret = -1;
- if(!waserror()){
- if(sp < USTKTOP - BY2PG || sp > USTKTOP - sizeof(Sargs) - BY2WD){
- validaddr(sp, sizeof(Sargs)+BY2WD, 0);
- evenaddr(sp);
- }
- up->s = *((Sargs*) (sp + BY2WD));
-
- if(up->procctl == Proc_tracesyscall){
- syscallfmt(scallnr, ureg->pc, (va_list) up->s.args);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- todget(nil, &startns);
- }
- if(scallnr >= nsyscall || systab[scallnr] == nil){
- postnote(up, 1, "sys: bad sys call", NDebug);
- error(Ebadarg);
- }
- up->psstate = sysctab[scallnr];
- ret = systab[scallnr]((va_list)up->s.args);
- poperror();
- }else{
- e = up->syserrstr;
- up->syserrstr = up->errstr;
- up->errstr = e;
- }
- if(up->nerrlab){
- print("bad errstack [%lud]: %d extra\n", scallnr, up->nerrlab);
- for(i = 0; i < NERR; i++)
- print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc);
- panic("error stack");
- }
-
- ureg->r0 = ret;
- if(up->procctl == Proc_tracesyscall){
- todget(nil, &stopns);
- sysretfmt(scallnr, (va_list) up->s.args, ret, startns, stopns);
- s = splhi();
- up->procctl = Proc_stopme;
- procctl();
- splx(s);
- }
-
- up->insyscall = 0;
- up->psstate = 0;
- if(scallnr == NOTED)
- noted(ureg, *((ulong *) up->s.args));
-
- splhi();
- if(scallnr != RFORK && (up->procctl || up->nnote))
+ scallnr = ureg->r0;
+ dosyscall(scallnr, (Sargs*)(ureg->sp + BY2WD), &ureg->r0);
+ if(up->procctl || up->nnote)
notify(ureg);
if(up->delaysched)
sched();
@@ -391,7 +325,7 @@
}
void
-noted(Ureg *ureg, ulong arg0)
+noted(Ureg *ureg, int arg0)
{
Ureg *nureg;
ulong oureg, sp;
@@ -432,15 +366,14 @@
case NSAVE:
sp = oureg - 4 * BY2WD - ERRMAX;
- ureg->sp = sp;
- ureg->r0 = (uintptr) oureg;
- if(!okaddr(ureg->pc, BY2WD, 0) || !okaddr(ureg->sp, 4 * BY2WD, 1) ||
- (ureg->pc & 3) != 0 || (ureg->sp & 3) != 0){
+ if(!okaddr(ureg->pc, BY2WD, 0) || !okaddr(sp, 4 * BY2WD, 1) || (ureg->pc & 3) != 0 || (sp & 3) != 0){
qunlock(&up->debug);
pprint("suicide: trap in noted\n");
pexit("Suicide", 0);
}
qunlock(&up->debug);
+ ureg->sp = sp;
+ ureg->r0 = (uintptr) oureg;
((ulong *) sp)[1] = oureg;
((ulong *) sp)[0] = 0;
break;
--
⑨