ref: a691c9111a69257e206ce895d35396d0f6225929
dir: /trap.c/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "../port/systab.h"
#include <tos.h>
#include "ureg.h"
int (*buserror)(Ureg*);
/* SPSR bits user can modify */
#define USPSRMASK (0xFULL<<28)
void
trapinit(void)
{
}
static char *traps[64] = {
[0x00] "sys: trap: unknown",
[0x01] "sys: trap: WFI or WFE instruction execution",
[0x0E] "sys: trap: illegal execution state",
[0x18] "sys: trap: illegal MSR/MRS access",
[0x22] "sys: trap: misaligned pc",
[0x26] "sys: trap: stack pointer misaligned",
[0x30] "sys: breakpoint",
[0x32] "sys: software step",
[0x34] "sys: watchpoint",
[0x3C] "sys: breakpoint",
};
void
trap(Ureg *ureg)
{
}
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();
up->nerrlab = 0;
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);
startns = todget(nil);
}
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){
stopns = todget(nil);
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()
*/
returnto(noteret);
splhi();
up->fpstate &= ~FPillegal;
}
else
splhi();
if(scallnr != RFORK && (up->procctl || up->nnote))
notify(ureg);
if(up->delaysched){
sched();
splhi();
}
kexit(ureg);
fpukexit(ureg, nil);
}
int
notify(Ureg *ureg)
{
uintptr sp;
char *msg;
if(up->procctl)
procctl();
if(up->nnote == 0)
return 0;
spllo();
qlock(&up->debug);
msg = popnote(ureg);
if(msg == nil){
qunlock(&up->debug);
splhi();
return 0;
}
sp = ureg->sp;
sp -= 256; /* debugging: preserve context causing problem */
sp -= sizeof(Ureg);
sp = STACKALIGN(sp);
if(!okaddr((uintptr)up->notify, 1, 0)
|| !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)
|| ((uintptr) up->notify & 3) != 0
|| (sp & 7) != 0){
qunlock(&up->debug);
pprint("suicide: bad address in notify: handler=%#p sp=%#p\n",
up->notify, sp);
pexit("Suicide", 0);
}
memmove((Ureg*)sp, ureg, sizeof(Ureg));
*(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
up->ureg = (void*)sp;
sp -= BY2WD+ERRMAX;
memmove((char*)sp, msg, ERRMAX);
sp -= 3*BY2WD;
*(uintptr*)(sp+2*BY2WD) = sp+3*BY2WD;
*(uintptr*)(sp+1*BY2WD) = (uintptr)up->ureg;
ureg->r0 = (uintptr) up->ureg;
ureg->sp = sp;
ureg->pc = (uintptr) up->notify;
ureg->cause = 0;
qunlock(&up->debug);
splhi();
fpuprocsave(up);
up->fpstate |= FPillegal;
return 1;
}
void
noted(Ureg *ureg, ulong arg0)
{
}
static void
faultnote(Ureg *ureg, char *access, uintptr addr)
{
}
int
userureg(Ureg* ureg)
{
return 0;
}
uintptr
userpc(void)
{
Ureg *ur = up->dbgreg;
return ur->pc;
}
uintptr
dbgpc(Proc *)
{
Ureg *ur = up->dbgreg;
if(ur == nil)
return 0;
return ur->pc;
}
void
procfork(Proc *p)
{
fpuprocfork(p);
p->tpidr = up->tpidr;
}
void
procsetup(Proc *p)
{
}
void
procsave(Proc *p)
{
}
void
procrestore(Proc *p)
{
}
void
kprocchild(Proc *p, void (*entry)(void))
{
}
void
forkchild(Proc *p, Ureg *ureg)
{
}
uintptr
execregs(uintptr entry, ulong ssize, ulong nargs)
{
return 0;
}
void
evenaddr(uintptr addr)
{
}
void
callwithureg(void (*f) (Ureg *))
{
}
void
setkernur(Ureg *ureg, Proc *p)
{
}
void
setupwatchpts(Proc*, Watchpt*, int)
{
}
void
setregisters(Ureg* ureg, char* pureg, char* uva, int n)
{
}
static void
dumpstackwithureg(Ureg *ureg)
{
}
void
dumpstack(void)
{
callwithureg(dumpstackwithureg);
}
void
dumpregs(Ureg *ureg)
{
}