shithub: riscv

Download patch

ref: c065eadb535347661079b93ef4b77739ec40a064
parent: bfbc5ab1970bbf9307e03a42e69b0d55eb92f2ef
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Thu Feb 6 17:43:33 EST 2014

pc64: fix note handling

--- a/sys/src/9/kw/syscall.c
+++ b/sys/src/9/kw/syscall.c
@@ -261,7 +261,7 @@
 	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))
--- a/sys/src/9/omap4/trap.c
+++ b/sys/src/9/omap4/trap.c
@@ -370,7 +370,7 @@
 	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);
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -799,7 +799,7 @@
 	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();
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -104,6 +104,7 @@
 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);
--- a/sys/src/9/pc64/l.s
+++ b/sys/src/9/pc64/l.s
@@ -737,6 +737,10 @@
 
 	BYTE $0x48; SYSRET			/* SYSRETQ */
 
+TEXT noteret(SB), 1, $-4
+	CLI
+	JMP _intrestore
+
 /*
  * Interrupt/exception handling.
  */
@@ -786,6 +790,7 @@
 	PUSHQ	SP
 	CALL	trap(SB)
 
+_intrestore:
 	POPQ	AX
 
 	POPQ	AX
--- a/sys/src/9/pc64/trap.c
+++ b/sys/src/9/pc64/trap.c
@@ -758,9 +758,20 @@
 	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();
 		notify(ureg);
@@ -904,7 +915,7 @@
 			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;