summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2015-03-30 00:26:33 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2015-03-30 00:26:33 +0200
commite9e45e17eb015267aa9db69deecf26d07fa12011 (patch)
treed61ae4026b2809766abb649ec7bea128a7586e07
parent166afefab99ee1b83efd2b02cefae52f6584fd0c (diff)
sgi: preserve R27 in setregisters(), use setregisters() in noted()
GEVector() saves the exception return PC in Ureg.r27 which needs to be preserved. there should be no reason for the user to change the status register from noted() eigther, so we now just use setregisters() in noted() to restore previous general purpose registers. this means that CU1 will always be off after noted() because notify() has disabled the FPU on entry and set fpstatus to FPinactive if it was on. once user starts using FPU again, it will trap and restore fpu registers.
-rw-r--r--sys/src/9/sgi/trap.c31
1 files changed, 5 insertions, 26 deletions
diff --git a/sys/src/9/sgi/trap.c b/sys/src/9/sgi/trap.c
index d9a6ae204..4c59730f6 100644
--- a/sys/src/9/sgi/trap.c
+++ b/sys/src/9/sgi/trap.c
@@ -576,22 +576,6 @@ 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)))
- if((kstatus & INTMASK) != (ustatus & INTMASK))
- 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(); called from user's handler.
*/
void
@@ -613,20 +597,13 @@ noted(Ureg *kur, ulong arg0)
nur = up->ureg;
oureg = (ulong)nur;
- if((oureg & (BY2WD-1))
- || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
+ 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);
pexit("Suicide", 0);
}
- if(0 && !validstatus(kur->status, nur->status)) {
- qunlock(&up->debug);
- pprint("bad noted ureg status %#lux\n", nur->status);
- pexit("Suicide", 0);
- }
-
- memmove(kur, up->ureg, sizeof(Ureg));
+ setregisters(kur, (char*)kur, (char*)up->ureg, sizeof(Ureg));
switch(arg0) {
case NCONT:
case NRSTR: /* only used by APE */
@@ -873,10 +850,12 @@ userpc(void)
void
setregisters(Ureg *xp, char *pureg, char *uva, int n)
{
- ulong status;
+ ulong status, r27;
+ r27 = xp->r27; /* return PC for GEVector() */
status = xp->status;
memmove(pureg, uva, n);
+ xp->r27 = r27;
xp->status = status;
}