From c065eadb535347661079b93ef4b77739ec40a064 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Thu, 6 Feb 2014 22:43:33 +0100 Subject: [PATCH] pc64: fix note handling --- sys/src/9/kw/syscall.c | 2 +- sys/src/9/omap4/trap.c | 2 +- sys/src/9/pc/trap.c | 2 +- sys/src/9/pc64/fns.h | 1 + sys/src/9/pc64/l.s | 5 +++++ sys/src/9/pc64/trap.c | 17 ++++++++++++++--- 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; -- 2.44.0