M carrera/dat.h => carrera/dat.h +1 -1
@@ 79,7 79,7 @@ struct PMMU
*/
struct Notsave
{
- ulong svstatus;
+ ulong UNUSED;
};
#include "../port/portdat.h"
M carrera/mem.h => carrera/mem.h +4 -1
@@ 66,7 66,10 @@
#define ERL 0x00000004
#define KSUPER 0x00000008
#define KUSER 0x00000010
+#define KSU 0x00000018
#define UX 0x00000020
+#define SX 0x00000040
+#define KX 0x00000080
#define INTMASK 0x0000ff00
#define INTR0 0x00000100
#define INTR1 0x00000200
@@ 93,7 96,7 @@
* Magic registers
*/
#define USER 24 /* R24 is up-> */
-#define MACH 25 /* R25 is m-> */
+#define MACH 25 /* R25 is m-> */
/*
* Fundamental addresses
M carrera/trap.c => carrera/trap.c +59 -11
@@ 7,7 7,7 @@
#include "io.h"
#include "../port/error.h"
-void noted(Ureg**, ulong);
+void noted(Ureg*, Ureg**, ulong);
void rfnote(Ureg**);
void kernfault(Ureg*, int);
@@ 527,20 527,20 @@ notify(Ureg *ur)
qunlock(&up->debug);
pexit(n->msg, n->flag!=NDebug);
}
- up->svstatus = ur->status;
sp = ur->usp & ~(BY2V-1);
sp -= sizeof(Ureg);
if(!okaddr((ulong)up->notify, BY2WD, 0) ||
- !okaddr(sp-ERRLEN-3*BY2WD, sizeof(Ureg)+ERRLEN-3*BY2WD, 1)) {
+ !okaddr(sp-ERRLEN-4*BY2WD, sizeof(Ureg)+ERRLEN-4*BY2WD, 1)) {
pprint("suicide: bad address or sp in notify\n");
qunlock(&up->debug);
pexit("Suicide", 0);
}
- up->ureg = (void*)sp;
memmove((Ureg*)sp, ur, sizeof(Ureg));
- sp -= ERRLEN;
+ *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
+ up->ureg = (void*)sp;
+ sp -= BY2WD+ERRLEN;
memmove((char*)sp, up->note[0].msg, ERRLEN);
sp -= 3*BY2WD;
*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */
@@ 563,15 563,31 @@ notify(Ureg *ur)
}
/*
+ * Check that status is OK to return from note.
+ */
+int
+validstatus(ulong kstatus, ulong ustatus)
+{
+ if((kstatus & (INTMASK|KX|SX|UX)) != (ustatus & (INTMASK|KX|SX|UX)))
+ return 0;
+ if((ustatus&(KSU|ERL|EXL|IE)) != (KUSER|EXL|IE))
+ return 0;
+ if(ustatus & (0xFFFF0000&~CU1)) /* no CU3, CU2, CU0, RP, FR, RE, DS */
+ return 0;
+ return 1;
+}
+
+/*
* Return user to state before notify()
*/
void
-noted(Ureg **urp, ulong arg0)
+noted(Ureg *kur, Ureg **urp, ulong arg0)
{
Ureg *nur;
+ ulong oureg, sp;
qlock(&up->debug);
- if(!up->notified) {
+ if(arg0!=NRSTR && !up->notified) {
qunlock(&up->debug);
pprint("call to noted() when not notified\n");
pexit("Suicide", 0);
@@ 579,22 595,54 @@ noted(Ureg **urp, ulong arg0)
up->notified = 0;
nur = up->ureg;
- if(nur->status!=up->svstatus) {
+ if(!validstatus(kur->status, nur->status)) {
qunlock(&up->debug);
pprint("bad noted ureg status %lux\n", nur->status);
pexit("Suicide", 0);
}
+ oureg = (ulong)up->ureg;
+ if(oureg){
+ if(oureg>=USTKTOP || oureg<USTKTOP-USTKSIZE
+ || (oureg & (BY2V-1))
+ || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
+ pprint("suicide: bad up->ureg in noted\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+ }
+
memmove(*urp, up->ureg, sizeof(Ureg));
switch(arg0) {
case NCONT:
- if(!okaddr(nur->pc, 1, 0) || !okaddr(nur->usp, BY2WD, 0)){
+ case NRSTR:
+ if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
+ pprint("suicide: trap in noted\n");
+ qunlock(&up->debug);
+ pexit("Suicide", 0);
+ }
+ up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
+ qunlock(&up->debug);
+ splhi();
+ rfnote(urp);
+ break;
+
+ case NSAVE:
+ if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
pprint("suicide: trap in noted\n");
qunlock(&up->debug);
pexit("Suicide", 0);
}
qunlock(&up->debug);
+ sp = oureg-4*BY2WD-ERRLEN;
splhi();
+ (*urp)->sp = sp;
+ ((ulong*)sp)[1] = (ulong)up->ureg; /* arg 1 0(FP) is ureg* */
+ ((ulong*)sp)[0] = 0; /* arg 0 is pc */
+ (*urp)->r1 = oureg; /* arg 1 is ureg* */
+ (*urp)->hr1 = 0;
+ if(oureg < 0)
+ (*urp)->hr1 = ~0;
rfnote(urp);
break;
@@ 672,8 720,8 @@ error:
up->nerrlab = 0;
up->psstate = 0;
up->insyscall = 0;
- if(up->scallnr == NOTED) /* ugly hack */
- noted(&aur, *(ulong*)(sp+BY2WD)); /* doesn't return */
+ if(up->scallnr == NOTED) /* ugly hack */
+ noted(ur, &aur, *(ulong*)(sp+BY2WD)); /* doesn't return */
splhi();
if(up->scallnr!=RFORK && (up->procctl || up->nnote)){
M pc/devastar.c => pc/devastar.c +1 -1
@@ 418,7 418,7 @@ astarreset(void)
a->mem = getisa(a->mem, Pagesize, Pagesize);
if(a->mem == 0)
panic("astarreset: %lux", a->mem);
- a->mem & ~KZERO;
+ a->mem &= ~KZERO;
if(astarsetup(a) < 0){
xfree(a);
M pc/trap.c => pc/trap.c +1 -0
@@ 472,6 472,7 @@ syscall(Ureg *ur, void *arg)
if(up->scallnr!=RFORK && (up->procctl || up->nnote))
notify(ur);
+
}
/*
M port/lib.h => port/lib.h +2 -0
@@ 93,6 93,8 @@ extern char end[];
#define NCONT 0 /* continue after note */
#define NDFLT 1 /* terminate after note */
+#define NSAVE 2 /* clear note but hold state */
+#define NRSTR 3 /* restore saved state */
typedef struct Qid Qid;
typedef struct Dir Dir;
M port/proc.c => port/proc.c +1 -0
@@ 313,6 313,7 @@ newproc(void)
p->mp = 0;
p->movetime = 0;
p->wired = 0;
+ p->ureg = 0;
memset(p->seg, 0, sizeof p->seg);
p->pid = incref(&pidalloc);
p->noteid = incref(¬eidalloc);
M port/sysproc.c => port/sysproc.c +4 -7
@@ 92,7 92,7 @@ sysrfork(ulong *arg)
p->notified = 0;
p->lastnote = up->lastnote;
p->notify = up->notify;
- p->ureg = 0;
+ p->ureg = up->ureg;
p->dbgreg = 0;
/* Make a new set of memory segments */
@@ 126,10 126,8 @@ sysrfork(ulong *arg)
incref(p->pgrp);
}
- if(flag & RFREND) {
- closergrp(up->rgrp);
- up->rgrp = newrgrp();
- }
+ if(flag & RFREND)
+ p->rgrp = newrgrp();
else {
incref(up->rgrp);
p->rgrp = up->rgrp;
@@ 549,8 547,7 @@ sysnotify(ulong *arg)
long
sysnoted(ulong *arg)
{
- USED(arg);
- if(up->notified == 0)
+ if(arg[0]!=NRSTR && !up->notified)
error(Egreg);
return 0;
}