summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2014-02-06 22:43:33 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2014-02-06 22:43:33 +0100
commitc065eadb535347661079b93ef4b77739ec40a064 (patch)
tree353ab14f113b852603af16f6a2450d2c00e9fe0a
parentbfbc5ab1970bbf9307e03a42e69b0d55eb92f2ef (diff)
pc64: fix note handling
-rw-r--r--sys/src/9/kw/syscall.c2
-rw-r--r--sys/src/9/omap4/trap.c2
-rw-r--r--sys/src/9/pc/trap.c2
-rw-r--r--sys/src/9/pc64/fns.h1
-rw-r--r--sys/src/9/pc64/l.s5
-rw-r--r--sys/src/9/pc64/trap.c17
6 files changed, 23 insertions, 6 deletions
diff --git a/sys/src/9/kw/syscall.c b/sys/src/9/kw/syscall.c
index fc148dee9..8ef7a0edf 100644
--- a/sys/src/9/kw/syscall.c
+++ b/sys/src/9/kw/syscall.c
@@ -261,7 +261,7 @@ syscall(Ureg* ureg)
up->psstate = 0;
if(scallnr == NOTED)
- noted(ureg, up->s.args[0]);
+ noted(ureg, *((ulong*)up->s.args));
splhi();
if(scallnr != RFORK && (up->procctl || up->nnote))
diff --git a/sys/src/9/omap4/trap.c b/sys/src/9/omap4/trap.c
index 26de7ac8d..50450855a 100644
--- a/sys/src/9/omap4/trap.c
+++ b/sys/src/9/omap4/trap.c
@@ -370,7 +370,7 @@ syscall(Ureg *ureg)
up->psstate = nil;
if(scall == NOTED)
- noted(ureg, up->s.args[0]);
+ noted(ureg, *((ulong*)up->s.args));
if(scall != RFORK && (up->procctl || up->nnote)){
splhi();
notify(ureg);
diff --git a/sys/src/9/pc/trap.c b/sys/src/9/pc/trap.c
index cf85bcad6..fbc6aef2c 100644
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -799,7 +799,7 @@ syscall(Ureg* ureg)
up->psstate = 0;
if(scallnr == NOTED)
- noted(ureg, up->s.args[0]);
+ noted(ureg, *((ulong*)up->s.args));
if(scallnr!=RFORK && (up->procctl || up->nnote)){
splhi();
diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h
index 5586d1aa5..47c3acf7a 100644
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -104,6 +104,7 @@ uintptr *mmuwalk(uintptr*, uintptr, int, int);
int mtrr(uvlong, uvlong, char *);
void mtrrclock(void);
int mtrrprint(char *, long);
+void noteret(void);
uchar nvramread(int);
void nvramwrite(int, uchar);
void outb(int, int);
diff --git a/sys/src/9/pc64/l.s b/sys/src/9/pc64/l.s
index e1eb310b1..e0038a1d6 100644
--- a/sys/src/9/pc64/l.s
+++ b/sys/src/9/pc64/l.s
@@ -737,6 +737,10 @@ TEXT forkret(SB), 1, $-4
BYTE $0x48; SYSRET /* SYSRETQ */
+TEXT noteret(SB), 1, $-4
+ CLI
+ JMP _intrestore
+
/*
* Interrupt/exception handling.
*/
@@ -786,6 +790,7 @@ _intrnested:
PUSHQ SP
CALL trap(SB)
+_intrestore:
POPQ AX
POPQ AX
diff --git a/sys/src/9/pc64/trap.c b/sys/src/9/pc64/trap.c
index a83fe2f3f..41a8c4978 100644
--- a/sys/src/9/pc64/trap.c
+++ b/sys/src/9/pc64/trap.c
@@ -758,8 +758,19 @@ syscall(Ureg* ureg)
up->insyscall = 0;
up->psstate = 0;
- if(scallnr == NOTED)
- noted(ureg, up->s.args[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()
+ */
+ ((void**)&ureg)[-1] = (void*)noteret;
+ }
if(scallnr!=RFORK && (up->procctl || up->nnote)){
splhi();
@@ -904,7 +915,7 @@ if(0) print("%s %lud: noted %#p %#p\n",
pprint("suicide: trap in noted\n");
pexit("Suicide", 0);
}
- up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
+ up->ureg = (Ureg*)(*(uintptr*)(oureg-BY2WD));
qunlock(&up->debug);
break;