svn commit: r200443 - in stable/8/sys: amd64/amd64 arm/arm i386/i386 ia64/ia64 mips/include mips/mips powerpc/aim powerpc/booke sparc64/include sparc64/sparc64 sun4v/sun4v sys

Konstantin Belousov kib at FreeBSD.org
Sat Dec 12 12:06:26 PST 2009


Author: kib
Date: Sat Dec 12 20:06:25 2009
New Revision: 200443
URL: http://svn.freebsd.org/changeset/base/200443

Log:
  MFC r199135:
  Extract the code that records syscall results in the frame into MD
  function cpu_set_syscall_retval().

Modified:
  stable/8/sys/amd64/amd64/trap.c
  stable/8/sys/amd64/amd64/vm_machdep.c
  stable/8/sys/arm/arm/trap.c
  stable/8/sys/arm/arm/vm_machdep.c
  stable/8/sys/i386/i386/trap.c
  stable/8/sys/i386/i386/vm_machdep.c
  stable/8/sys/ia64/ia64/trap.c
  stable/8/sys/ia64/ia64/vm_machdep.c
  stable/8/sys/mips/include/pcb.h
  stable/8/sys/mips/mips/trap.c
  stable/8/sys/mips/mips/vm_machdep.c
  stable/8/sys/powerpc/aim/trap.c
  stable/8/sys/powerpc/aim/vm_machdep.c
  stable/8/sys/powerpc/booke/trap.c
  stable/8/sys/powerpc/booke/vm_machdep.c
  stable/8/sys/sparc64/include/pcb.h
  stable/8/sys/sparc64/sparc64/trap.c
  stable/8/sys/sparc64/sparc64/vm_machdep.c
  stable/8/sys/sun4v/sun4v/trap.c
  stable/8/sys/sun4v/sun4v/vm_machdep.c
  stable/8/sys/sys/proc.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/amd64/amd64/trap.c
==============================================================================
--- stable/8/sys/amd64/amd64/trap.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/amd64/amd64/trap.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -1004,39 +1004,7 @@ syscall(struct trapframe *frame)
 #endif
 	}
 
-	switch (error) {
-	case 0:
-		frame->tf_rax = td->td_retval[0];
-		frame->tf_rdx = td->td_retval[1];
-		frame->tf_rflags &= ~PSL_C;
-		break;
-
-	case ERESTART:
-		/*
-		 * Reconstruct pc, we know that 'syscall' is 2 bytes.
-		 * We have to do a full context restore so that %r10
-		 * (which was holding the value of %rcx) is restored for
-		 * the next iteration.
-		 */
-		frame->tf_rip -= frame->tf_err;
-		frame->tf_r10 = frame->tf_rcx;
-		td->td_pcb->pcb_flags |= PCB_FULLCTX;
-		break;
-
-	case EJUSTRETURN:
-		break;
-
-	default:
- 		if (p->p_sysent->sv_errsize) {
- 			if (error >= p->p_sysent->sv_errsize)
-  				error = -1;	/* XXX */
-   			else
-  				error = p->p_sysent->sv_errtbl[error];
-		}
-		frame->tf_rax = error;
-		frame->tf_rflags |= PSL_C;
-		break;
-	}
+	cpu_set_syscall_retval(td, error);
 
 	/*
 	 * Traced syscall.

Modified: stable/8/sys/amd64/amd64/vm_machdep.c
==============================================================================
--- stable/8/sys/amd64/amd64/vm_machdep.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/amd64/amd64/vm_machdep.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -317,6 +317,45 @@ cpu_thread_free(struct thread *td)
 	cpu_thread_clean(td);
 }
 
+void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+
+	switch (error) {
+	case 0:
+		td->td_frame->tf_rax = td->td_retval[0];
+		td->td_frame->tf_rdx = td->td_retval[1];
+		td->td_frame->tf_rflags &= ~PSL_C;
+		break;
+
+	case ERESTART:
+		/*
+		 * Reconstruct pc, we know that 'syscall' is 2 bytes.
+		 * We have to do a full context restore so that %r10
+		 * (which was holding the value of %rcx) is restored
+		 * for the next iteration.
+		 */
+		td->td_frame->tf_rip -= td->td_frame->tf_err;
+		td->td_frame->tf_r10 = td->td_frame->tf_rcx;
+		td->td_pcb->pcb_flags |= PCB_FULLCTX;
+		break;
+
+	case EJUSTRETURN:
+		break;
+
+	default:
+		if (td->td_proc->p_sysent->sv_errsize) {
+			if (error >= td->td_proc->p_sysent->sv_errsize)
+				error = -1;	/* XXX */
+			else
+				error = td->td_proc->p_sysent->sv_errtbl[error];
+		}
+		td->td_frame->tf_rax = error;
+		td->td_frame->tf_rflags |= PSL_C;
+		break;
+	}
+}
+
 /*
  * Initialize machine state (pcb and trap frame) for a new thread about to
  * upcall. Put enough state in the new thread's PCB to get it to go back 

Modified: stable/8/sys/arm/arm/trap.c
==============================================================================
--- stable/8/sys/arm/arm/trap.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/arm/arm/trap.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -932,43 +932,8 @@ syscall(struct thread *td, trapframe_t *
 		KASSERT(td->td_ar == NULL, 
 		    ("returning from syscall with td_ar set!"));
 	}
-	switch (error) {
-	case 0: 
-#ifdef __ARMEB__
-		if ((insn & 0x000fffff) == SYS___syscall &&
-		    code != SYS_freebsd6_lseek && code != SYS_lseek) {
-			/*
-			 * 64-bit return, 32-bit syscall. Fixup byte order
-			 */ 
-			frame->tf_r0 = 0;
-			frame->tf_r1 = td->td_retval[0];
-		} else {
-			frame->tf_r0 = td->td_retval[0];
-			frame->tf_r1 = td->td_retval[1];
-		}
-#else
-		frame->tf_r0 = td->td_retval[0];
-	  	frame->tf_r1 = td->td_retval[1];
-#endif
-					      
-		frame->tf_spsr &= ~PSR_C_bit;   /* carry bit */
-		break;
-		
-	case ERESTART:
-		/*
-		 * Reconstruct the pc to point at the swi.
-		 */
-		frame->tf_pc -= INSN_SIZE;
-		break;
-	case EJUSTRETURN:                                       
-		/* nothing to do */  
-		break;
-	default:
 bad:
-		frame->tf_r0 = error;
-		frame->tf_spsr |= PSR_C_bit;    /* carry bit */
-		break;
-	}
+	cpu_set_syscall_retval(td, error);
 
 	WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
 	    (code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");

Modified: stable/8/sys/arm/arm/vm_machdep.c
==============================================================================
--- stable/8/sys/arm/arm/vm_machdep.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/arm/arm/vm_machdep.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -51,6 +51,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/proc.h>
 #include <sys/socketvar.h>
 #include <sys/sf_buf.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
 #include <sys/unistd.h>
 #include <machine/cpu.h>
 #include <machine/pcb.h>
@@ -261,6 +263,57 @@ done:
 #endif
 }
 
+void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+	trapframe_t *frame;
+	int fixup;
+#ifdef __ARMEB__
+	uint32_t insn;
+#endif
+
+	frame = td->td_frame;
+	fixup = 0;
+
+#ifdef __ARMEB__
+	insn = *(u_int32_t *)(frame->tf_pc - INSN_SIZE);
+	if ((insn & 0x000fffff) == SYS___syscall) {
+		register_t *ap = &frame->tf_r0;
+		register_t code = ap[_QUAD_LOWWORD];
+		if (td->td_proc->p_sysent->sv_mask)
+			code &= td->td_proc->p_sysent->sv_mask;
+		fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek)
+		    ? 1 : 0;
+	}
+#endif
+
+	switch (error) {
+	case 0:
+		if (fixup) {
+			frame->tf_r0 = 0;
+			frame->tf_r1 = td->td_retval[0];
+		} else {
+			frame->tf_r0 = td->td_retval[0];
+			frame->tf_r1 = td->td_retval[1];
+		}
+		frame->tf_spsr &= ~PSR_C_bit;   /* carry bit */
+		break;
+	case ERESTART:
+		/*
+		 * Reconstruct the pc to point at the swi.
+		 */
+		frame->tf_pc -= INSN_SIZE;
+		break;
+	case EJUSTRETURN:
+		/* nothing to do */
+		break;
+	default:
+		frame->tf_r0 = error;
+		frame->tf_spsr |= PSR_C_bit;    /* carry bit */
+		break;
+	}
+}
+
 /*
  * Initialize machine state (pcb and trap frame) for a new thread about to
  * upcall. Put enough state in the new thread's PCB to get it to go back 

Modified: stable/8/sys/i386/i386/trap.c
==============================================================================
--- stable/8/sys/i386/i386/trap.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/i386/i386/trap.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -1093,35 +1093,7 @@ syscall(struct trapframe *frame)
 #endif
 	}
 
-	switch (error) {
-	case 0:
-		frame->tf_eax = td->td_retval[0];
-		frame->tf_edx = td->td_retval[1];
-		frame->tf_eflags &= ~PSL_C;
-		break;
-
-	case ERESTART:
-		/*
-		 * Reconstruct pc, assuming lcall $X,y is 7 bytes,
-		 * int 0x80 is 2 bytes. We saved this in tf_err.
-		 */
-		frame->tf_eip -= frame->tf_err;
-		break;
-
-	case EJUSTRETURN:
-		break;
-
-	default:
- 		if (p->p_sysent->sv_errsize) {
- 			if (error >= p->p_sysent->sv_errsize)
-  				error = -1;	/* XXX */
-   			else
-  				error = p->p_sysent->sv_errtbl[error];
-		}
-		frame->tf_eax = error;
-		frame->tf_eflags |= PSL_C;
-		break;
-	}
+	cpu_set_syscall_retval(td, error);
 
 	/*
 	 * Traced syscall.

Modified: stable/8/sys/i386/i386/vm_machdep.c
==============================================================================
--- stable/8/sys/i386/i386/vm_machdep.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/i386/i386/vm_machdep.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -381,6 +381,41 @@ cpu_thread_free(struct thread *td)
 	cpu_thread_clean(td);
 }
 
+void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+
+	switch (error) {
+	case 0:
+		td->td_frame->tf_eax = td->td_retval[0];
+		td->td_frame->tf_edx = td->td_retval[1];
+		td->td_frame->tf_eflags &= ~PSL_C;
+		break;
+
+	case ERESTART:
+		/*
+		 * Reconstruct pc, assuming lcall $X,y is 7 bytes, int
+		 * 0x80 is 2 bytes. We saved this in tf_err.
+		 */
+		td->td_frame->tf_eip -= td->td_frame->tf_err;
+		break;
+
+	case EJUSTRETURN:
+		break;
+
+	default:
+		if (td->td_proc->p_sysent->sv_errsize) {
+			if (error >= td->td_proc->p_sysent->sv_errsize)
+				error = -1;	/* XXX */
+			else
+				error = td->td_proc->p_sysent->sv_errtbl[error];
+		}
+		td->td_frame->tf_eax = error;
+		td->td_frame->tf_eflags |= PSL_C;
+		break;
+	}
+}
+
 /*
  * Initialize machine state (pcb and trap frame) for a new thread about to
  * upcall. Put enough state in the new thread's PCB to get it to go back 

Modified: stable/8/sys/ia64/ia64/trap.c
==============================================================================
--- stable/8/sys/ia64/ia64/trap.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/ia64/ia64/trap.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -976,26 +976,7 @@ syscall(struct trapframe *tf)
 	error = (*callp->sy_call)(td, args);
 	AUDIT_SYSCALL_EXIT(error, td);
 
-	if (error != EJUSTRETURN) {
-		/*
-		 * Save the "raw" error code in r10. We use this to handle
-		 * syscall restarts (see do_ast()).
-		 */
-		tf->tf_scratch.gr10 = error;
-		if (error == 0) {
-			tf->tf_scratch.gr8 = td->td_retval[0];
-			tf->tf_scratch.gr9 = td->td_retval[1];
-		} else if (error != ERESTART) {
-			if (error < p->p_sysent->sv_errsize)
-				error = p->p_sysent->sv_errtbl[error];
-			/*
-			 * Translated error codes are returned in r8. User
-			 * processes use the translated error code.
-			 */
-			tf->tf_scratch.gr8 = error;
-		}
-	}
-
+	cpu_set_syscall_retval(td, error);
 	td->td_syscalls++;
 
 	/*

Modified: stable/8/sys/ia64/ia64/vm_machdep.c
==============================================================================
--- stable/8/sys/ia64/ia64/vm_machdep.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/ia64/ia64/vm_machdep.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -73,6 +73,7 @@
 #include <sys/malloc.h>
 #include <sys/bio.h>
 #include <sys/buf.h>
+#include <sys/sysent.h>
 #include <sys/vnode.h>
 #include <sys/vmmeter.h>
 #include <sys/kernel.h>
@@ -140,6 +141,36 @@ cpu_thread_swapout(struct thread *td)
 }
 
 void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+	struct proc *p;
+	struct trapframe *tf;
+
+	if (error == EJUSTRETURN)
+		return;
+
+	tf = td->td_frame;
+
+	/*
+	 * Save the "raw" error code in r10. We use this to handle
+	 * syscall restarts (see do_ast()).
+	 */
+	tf->tf_scratch.gr10 = error;
+	if (error == 0) {
+		tf->tf_scratch.gr8 = td->td_retval[0];
+		tf->tf_scratch.gr9 = td->td_retval[1];
+	} else if (error != ERESTART) {
+		p = td->td_proc;
+		if (error < p->p_sysent->sv_errsize)
+			error = p->p_sysent->sv_errtbl[error];
+		/*
+		 * Translated error codes are returned in r8. User
+		 */
+		tf->tf_scratch.gr8 = error;
+	}
+}
+
+void
 cpu_set_upcall(struct thread *td, struct thread *td0)
 {
 	struct pcb *pcb;

Modified: stable/8/sys/mips/include/pcb.h
==============================================================================
--- stable/8/sys/mips/include/pcb.h	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/mips/include/pcb.h	Sat Dec 12 20:06:25 2009	(r200443)
@@ -52,6 +52,7 @@ struct pcb
 	struct trapframe pcb_regs;	/* saved CPU and registers */
 	label_t pcb_context;		/* kernel context for resume */
 	int	pcb_onfault;		/* for copyin/copyout faults */
+	register_t pcb_tpc;
 };
 
 /* these match the regnum's in regnum.h

Modified: stable/8/sys/mips/mips/trap.c
==============================================================================
--- stable/8/sys/mips/mips/trap.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/mips/mips/trap.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -644,7 +644,6 @@ dofault:
 			struct trapframe *locr0 = td->td_frame;
 			struct sysent *callp;
 			unsigned int code;
-			unsigned int tpc;
 			int nargs, nsaved;
 			register_t args[8];
 
@@ -660,7 +659,7 @@ dofault:
 				thread_user_enter(td);
 #endif
 			/* compute next PC after syscall instruction */
-			tpc = trapframe->pc;	/* Remember if restart */
+			td->td_pcb->pcb_tpc = trapframe->pc;	/* Remember if restart */
 			if (DELAYBRANCH(trapframe->cause)) {	/* Check BD bit */
 				locr0->pc = MipsEmulateBranch(locr0, trapframe->pc, 0,
 				    0);
@@ -761,44 +760,7 @@ dofault:
 			locr0 = td->td_frame;
 #endif
 			trapdebug_enter(locr0, -code);
-			switch (i) {
-			case 0:
-				if (quad_syscall && code != SYS_lseek) {
-					/*
-					 * System call invoked through the
-					 * SYS___syscall interface but the
-					 * return value is really just 32
-					 * bits.
-					 */
-					locr0->v0 = td->td_retval[0];
-					if (_QUAD_LOWWORD)
-						locr0->v1 = td->td_retval[0];
-					locr0->a3 = 0;
-				} else {
-					locr0->v0 = td->td_retval[0];
-					locr0->v1 = td->td_retval[1];
-					locr0->a3 = 0;
-				}
-				break;
-
-			case ERESTART:
-				locr0->pc = tpc;
-				break;
-
-			case EJUSTRETURN:
-				break;	/* nothing to do */
-
-			default:
-				if (quad_syscall && code != SYS_lseek) {
-					locr0->v0 = i;
-					if (_QUAD_LOWWORD)
-						locr0->v1 = i;
-					locr0->a3 = 1;
-				} else {
-					locr0->v0 = i;
-					locr0->a3 = 1;
-				}
-			}
+			cpu_set_syscall_retval(td, i);
 
 			/*
 			 * The sync'ing of I & D caches for SYS_ptrace() is

Modified: stable/8/sys/mips/mips/vm_machdep.c
==============================================================================
--- stable/8/sys/mips/mips/vm_machdep.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/mips/mips/vm_machdep.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/malloc.h>
 #include <sys/proc.h>
+#include <sys/syscall.h>
 #include <sys/buf.h>
 #include <sys/vnode.h>
 #include <sys/vmmeter.h>
@@ -256,6 +257,62 @@ cpu_thread_alloc(struct thread *td)
 	}
 }
 
+void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+	struct trapframe *locr0 = td->td_frame;
+	unsigned int code;
+	int quad_syscall;
+
+	code = locr0->v0;
+	quad_syscall = 0;
+	if (code == SYS_syscall)
+		code = locr0->a0;
+	else if (code == SYS___syscall) {
+		code = _QUAD_LOWWORD ? locr0->a1 : locr0->a0;
+		quad_syscall = 1;
+	}
+
+	switch (error) {
+	case 0:
+		if (quad_syscall && code != SYS_lseek) {
+			/*
+			 * System call invoked through the
+			 * SYS___syscall interface but the
+			 * return value is really just 32
+			 * bits.
+			 */
+			locr0->v0 = td->td_retval[0];
+			if (_QUAD_LOWWORD)
+				locr0->v1 = td->td_retval[0];
+			locr0->a3 = 0;
+		} else {
+			locr0->v0 = td->td_retval[0];
+			locr0->v1 = td->td_retval[1];
+			locr0->a3 = 0;
+		}
+		break;
+
+	case ERESTART:
+		locr0->pc = td->td_pcb->pcb_tpc;
+		break;
+
+	case EJUSTRETURN:
+		break;	/* nothing to do */
+
+	default:
+		if (quad_syscall && code != SYS_lseek) {
+			locr0->v0 = error;
+			if (_QUAD_LOWWORD)
+				locr0->v1 = error;
+			locr0->a3 = 1;
+		} else {
+			locr0->v0 = error;
+			locr0->a3 = 1;
+		}
+	}
+}
+
 /*
  * Initialize machine state (pcb and trap frame) for a new thread about to
  * upcall. Put enough state in the new thread's PCB to get it to go back

Modified: stable/8/sys/powerpc/aim/trap.c
==============================================================================
--- stable/8/sys/powerpc/aim/trap.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/powerpc/aim/trap.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -417,43 +417,8 @@ syscall(struct trapframe *frame)
 		CTR3(KTR_SYSC, "syscall: p=%s %s ret=%x", td->td_name,
 		     syscallnames[code], td->td_retval[0]);
 	}
-	switch (error) {
-	case 0:
-		if (frame->fixreg[0] == SYS___syscall &&
-		    code != SYS_freebsd6_lseek && code != SYS_lseek) {
-			/*
-			 * 64-bit return, 32-bit syscall. Fixup byte order
-			 */
-			frame->fixreg[FIRSTARG] = 0;
-			frame->fixreg[FIRSTARG + 1] = td->td_retval[0];
-		} else {
-			frame->fixreg[FIRSTARG] = td->td_retval[0];
-			frame->fixreg[FIRSTARG + 1] = td->td_retval[1];
-		}
-		/* XXX: Magic number */
-		frame->cr &= ~0x10000000;
-		break;
-	case ERESTART:
-		/*
-		 * Set user's pc back to redo the system call.
-		 */
-		frame->srr0 -= 4;
-		break;
-	case EJUSTRETURN:
-		/* nothing to do */
-		break;
-	default:
-		if (p->p_sysent->sv_errsize) {
-			if (error >= p->p_sysent->sv_errsize)
-				error = -1;	/* XXX */
-			else
-				error = p->p_sysent->sv_errtbl[error];
-		}
-		frame->fixreg[FIRSTARG] = error;
-		/* XXX: Magic number: Carry Flag Equivalent? */
-		frame->cr |= 0x10000000;
-		break;
-	}
+
+	cpu_set_syscall_retval(td, error);
 
 	/*
 	 * Check for misbehavior.

Modified: stable/8/sys/powerpc/aim/vm_machdep.c
==============================================================================
--- stable/8/sys/powerpc/aim/vm_machdep.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/powerpc/aim/vm_machdep.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -81,7 +81,9 @@
 #include <sys/kernel.h>
 #include <sys/mbuf.h>
 #include <sys/sf_buf.h>
+#include <sys/syscall.h>
 #include <sys/sysctl.h>
+#include <sys/sysent.h>
 #include <sys/unistd.h>
 
 #include <machine/cpu.h>
@@ -422,6 +424,59 @@ cpu_thread_swapout(struct thread *td)
 }
 
 void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+	struct proc *p;
+	struct trapframe *tf;
+	int fixup;
+
+	if (error == EJUSTRETURN)
+		return;
+
+	p = td->td_proc;
+	tf = td->td_frame;
+
+	if (tf->fixreg[0] == SYS___syscall) {
+		int code = tf->fixreg[FIRSTARG + 1];
+		if (p->p_sysent->sv_mask)
+			code &= p->p_sysent->sv_mask;
+		fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek) ?
+		    1 : 0;
+	} else
+		fixup = 0;
+
+	switch (error) {
+	case 0:
+		if (fixup) {
+			/*
+			 * 64-bit return, 32-bit syscall. Fixup byte order
+			 */
+			tf->fixreg[FIRSTARG] = 0;
+			tf->fixreg[FIRSTARG + 1] = td->td_retval[0];
+		} else {
+			tf->fixreg[FIRSTARG] = td->td_retval[0];
+			tf->fixreg[FIRSTARG + 1] = td->td_retval[1];
+		}
+		tf->cr &= ~0x10000000;		/* XXX: Magic number */
+		break;
+	case ERESTART:
+		/*
+		 * Set user's pc back to redo the system call.
+		 */
+		tf->srr0 -= 4;
+		break;
+	default:
+		if (p->p_sysent->sv_errsize) {
+			error = (error < p->p_sysent->sv_errsize) ?
+			    p->p_sysent->sv_errtbl[error] : -1;
+		}
+		tf->fixreg[FIRSTARG] = error;
+		tf->cr |= 0x10000000;		/* XXX: Magic number */
+		break;
+	}
+}
+
+void
 cpu_set_upcall(struct thread *td, struct thread *td0)
 {
 	struct pcb *pcb2;

Modified: stable/8/sys/powerpc/booke/trap.c
==============================================================================
--- stable/8/sys/powerpc/booke/trap.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/powerpc/booke/trap.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -417,42 +417,7 @@ syscall(struct trapframe *frame)
 		     syscallnames[code], td->td_retval[0]);
 	}
 
-	switch (error) {
-	case 0:
-		if (frame->fixreg[0] == SYS___syscall && SYS_lseek) {
-			/*
-			 * 64-bit return, 32-bit syscall. Fixup byte order
-			 */
-			frame->fixreg[FIRSTARG] = 0;
-			frame->fixreg[FIRSTARG + 1] = td->td_retval[0];
-		} else {
-			frame->fixreg[FIRSTARG] = td->td_retval[0];
-			frame->fixreg[FIRSTARG + 1] = td->td_retval[1];
-		}
-		/* XXX: Magic number */
-		frame->cr &= ~0x10000000;
-		break;
-	case ERESTART:
-		/*
-		 * Set user's pc back to redo the system call.
-		 */
-		frame->srr0 -= 4;
-		break;
-	case EJUSTRETURN:
-		/* nothing to do */
-		break;
-	default:
-		if (p->p_sysent->sv_errsize) {
-			if (error >= p->p_sysent->sv_errsize)
-				error = -1;	/* XXX */
-			else
-				error = p->p_sysent->sv_errtbl[error];
-		}
-		frame->fixreg[FIRSTARG] = error;
-		/* XXX: Magic number: Carry Flag Equivalent? */
-		frame->cr |= 0x10000000;
-		break;
-	}
+	cpu_set_syscall_retval(td, error);
 
 	/*
 	 * Check for misbehavior.

Modified: stable/8/sys/powerpc/booke/vm_machdep.c
==============================================================================
--- stable/8/sys/powerpc/booke/vm_machdep.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/powerpc/booke/vm_machdep.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -113,7 +113,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/mbuf.h>
 #include <sys/sf_buf.h>
+#include <sys/syscall.h>
 #include <sys/sysctl.h>
+#include <sys/sysent.h>
 #include <sys/unistd.h>
 
 #include <machine/clock.h>
@@ -423,6 +425,59 @@ cpu_thread_swapout(struct thread *td)
 }
 
 void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+	struct proc *p;
+	struct trapframe *tf;
+	int fixup;
+
+	p = td->td_proc;
+	tf = td->td_frame;
+
+	if (tf->fixreg[0] == SYS___syscall) {
+		int code = tf->fixreg[FIRSTARG + 1];
+		if (p->p_sysent->sv_mask)
+			code &= p->p_sysent->sv_mask;
+		fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek) ?
+		    1 : 0;
+	} else
+		fixup = 0;
+
+	switch (error) {
+	case 0:
+		if (fixup) {
+			/*
+			 * 64-bit return, 32-bit syscall. Fixup byte order
+			 */
+			tf->fixreg[FIRSTARG] = 0;
+			tf->fixreg[FIRSTARG + 1] = td->td_retval[0];
+		} else {
+			tf->fixreg[FIRSTARG] = td->td_retval[0];
+			tf->fixreg[FIRSTARG + 1] = td->td_retval[1];
+		}
+		tf->cr &= ~0x10000000;		/* XXX: Magic number */
+		break;
+	case ERESTART:
+		/*
+		 * Set user's pc back to redo the system call.
+		 */
+		tf->srr0 -= 4;
+		break;
+	case EJUSTRETURN:
+		/* nothing to do */
+		break;
+	default:
+		if (p->p_sysent->sv_errsize) {
+			error = (error < p->p_sysent->sv_errsize) ?
+			    p->p_sysent->sv_errtbl[error] : -1;
+		}
+		tf->fixreg[FIRSTARG] = error;
+		tf->cr |= 0x10000000;		/* XXX: Magic number */
+		break;
+	}
+}
+
+void
 cpu_set_upcall(struct thread *td, struct thread *td0)
 {
 	struct pcb *pcb2;

Modified: stable/8/sys/sparc64/include/pcb.h
==============================================================================
--- stable/8/sys/sparc64/include/pcb.h	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/sparc64/include/pcb.h	Sat Dec 12 20:06:25 2009	(r200443)
@@ -49,7 +49,8 @@ struct pcb {
 	uint64_t pcb_nsaved;
 	uint64_t pcb_pc;
 	uint64_t pcb_sp;
-	uint64_t pcb_pad[4];
+	uint64_t pcb_tpc;
+	uint64_t pcb_pad[3];
 } __aligned(64);
 
 #ifdef _KERNEL

Modified: stable/8/sys/sparc64/sparc64/trap.c
==============================================================================
--- stable/8/sys/sparc64/sparc64/trap.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/sparc64/sparc64/trap.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -538,7 +538,6 @@ syscall(struct trapframe *tf)
 	register_t *argp;
 	struct proc *p;
 	u_long code;
-	u_long tpc;
 	int reg;
 	int regcnt;
 	int narg;
@@ -562,7 +561,7 @@ syscall(struct trapframe *tf)
 	 * For syscalls, we don't want to retry the faulting instruction
 	 * (usually), instead we need to advance one instruction.
 	 */
-	tpc = tf->tf_tpc;
+	td->td_pcb->pcb_tpc = tf->tf_tpc;
 	TF_DONE(tf);
 
 	reg = 0;
@@ -626,39 +625,7 @@ syscall(struct trapframe *tf)
 		    td->td_retval[1]);
 	}
 
-	/*
-	 * MP SAFE (we may or may not have the MP lock at this point)
-	 */
-	switch (error) {
-	case 0:
-		tf->tf_out[0] = td->td_retval[0];
-		tf->tf_out[1] = td->td_retval[1];
-		tf->tf_tstate &= ~TSTATE_XCC_C;
-		break;
-
-	case ERESTART:
-		/*
-		 * Undo the tpc advancement we have done above, we want to
-		 * reexecute the system call.
-		 */
-		tf->tf_tpc = tpc;
-		tf->tf_tnpc -= 4;
-		break;
-
-	case EJUSTRETURN:
-		break;
-
-	default:
-		if (p->p_sysent->sv_errsize) {
-			if (error >= p->p_sysent->sv_errsize)
-				error = -1;	/* XXX */
-			else
-				error = p->p_sysent->sv_errtbl[error];
-		}
-		tf->tf_out[0] = error;
-		tf->tf_tstate |= TSTATE_XCC_C;
-		break;
-	}
+	cpu_set_syscall_retval(td, error);
 
 	/*
 	 * Check for misbehavior.

Modified: stable/8/sys/sparc64/sparc64/vm_machdep.c
==============================================================================
--- stable/8/sys/sparc64/sparc64/vm_machdep.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/sparc64/sparc64/vm_machdep.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/mbuf.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
+#include <sys/sysent.h>
 #include <sys/sf_buf.h>
 #include <sys/sched.h>
 #include <sys/sysctl.h>
@@ -166,6 +167,42 @@ cpu_thread_swapout(struct thread *td)
 }
 
 void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+
+	switch (error) {
+	case 0:
+		td->td_frame->tf_out[0] = td->td_retval[0];
+		td->td_frame->tf_out[1] = td->td_retval[1];
+		td->td_frame->tf_tstate &= ~TSTATE_XCC_C;
+		break;
+
+	case ERESTART:
+		/*
+		 * Undo the tpc advancement we have done on syscall
+		 * enter, we want to reexecute the system call.
+		 */
+		td->td_frame->tf_tpc = td->td_pcb->pcb_tpc;
+		td->td_frame->tf_tnpc -= 4;
+		break;
+
+	case EJUSTRETURN:
+		break;
+
+	default:
+		if (td->td_proc->p_sysent->sv_errsize) {
+			if (error >= td->td_proc->p_sysent->sv_errsize)
+				error = -1;	/* XXX */
+			else
+				error = td->td_proc->p_sysent->sv_errtbl[error];
+		}
+		td->td_frame->tf_out[0] = error;
+		td->td_frame->tf_tstate |= TSTATE_XCC_C;
+		break;
+	}
+}
+
+void
 cpu_set_upcall(struct thread *td, struct thread *td0)
 {
 	struct trapframe *tf;

Modified: stable/8/sys/sun4v/sun4v/trap.c
==============================================================================
--- stable/8/sys/sun4v/sun4v/trap.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/sun4v/sun4v/trap.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -81,6 +81,7 @@
 #include <machine/cpu.h>
 #include <machine/frame.h>
 #include <machine/intr_machdep.h>
+#include <machine/pcb.h>
 #include <machine/smp.h>
 #include <machine/trap.h>
 #include <machine/tstate.h>
@@ -582,7 +583,6 @@ syscall(struct trapframe *tf)
 	register_t *argp;
 	struct proc *p;
 	u_long code;
-	u_long tpc;
 	int reg;
 	int regcnt;
 	int narg;
@@ -606,7 +606,7 @@ syscall(struct trapframe *tf)
 	 * For syscalls, we don't want to retry the faulting instruction
 	 * (usually), instead we need to advance one instruction.
 	 */
-	tpc = tf->tf_tpc;
+	td->td_pcb->pcb_tpc = tf->tf_tpc;
 	TF_DONE(tf);
 
 	reg = 0;
@@ -673,40 +673,8 @@ syscall(struct trapframe *tf)
 		    error, syscallnames[code], td->td_retval[0],
 		    td->td_retval[1]);
 	}
-	
-	/*
-	 * MP SAFE (we may or may not have the MP lock at this point)
-	 */
-	switch (error) {
-	case 0:
-		tf->tf_out[0] = td->td_retval[0];
-		tf->tf_out[1] = td->td_retval[1];
-		tf->tf_tstate &= ~TSTATE_XCC_C;
-		break;
 
-	case ERESTART:
-		/*
-		 * Undo the tpc advancement we have done above, we want to
-		 * reexecute the system call.
-		 */
-		tf->tf_tpc = tpc;
-		tf->tf_tnpc -= 4;
-		break;
-
-	case EJUSTRETURN:
-		break;
-
-	default:
- 		if (p->p_sysent->sv_errsize) {
- 			if (error >= p->p_sysent->sv_errsize)
-  				error = -1;	/* XXX */
-   			else
-  				error = p->p_sysent->sv_errtbl[error];
-		}
-		tf->tf_out[0] = error;
-		tf->tf_tstate |= TSTATE_XCC_C;
-		break;
-	}
+	cpu_set_syscall_retval(td, error);
 
 	/*
 	 * Handle reschedule and other end-of-syscall issues

Modified: stable/8/sys/sun4v/sun4v/vm_machdep.c
==============================================================================
--- stable/8/sys/sun4v/sun4v/vm_machdep.c	Sat Dec 12 18:18:46 2009	(r200442)
+++ stable/8/sys/sun4v/sun4v/vm_machdep.c	Sat Dec 12 20:06:25 2009	(r200443)
@@ -57,6 +57,7 @@
 #include <sys/mutex.h>
 #include <sys/sf_buf.h>
 #include <sys/sysctl.h>
+#include <sys/sysent.h>
 #include <sys/unistd.h>
 #include <sys/vmmeter.h>
 
@@ -142,6 +143,42 @@ cpu_thread_swapout(struct thread *td)
 }
 
 void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+
+	switch (error) {
+	case 0:
+		td->td_frame->tf_out[0] = td->td_retval[0];
+		td->td_frame->tf_out[1] = td->td_retval[1];
+		td->td_frame->tf_tstate &= ~TSTATE_XCC_C;
+		break;
+
+	case ERESTART:
+		/*
+		 * Undo the tpc advancement we have done on syscall
+		 * enter, we want to reexecute the system call.
+		 */
+		td->td_frame->tf_tpc = td->td_pcb->pcb_tpc;
+		td->td_frame->tf_tnpc -= 4;
+		break;
+
+	case EJUSTRETURN:
+		break;
+
+	default:
+		if (td->td_proc->p_sysent->sv_errsize) {
+			if (error >= td->td_proc->p_sysent->sv_errsize)
+				error = -1;	/* XXX */
+			else
+				error = td->td_proc->p_sysent->sv_errtbl[error];
+		}
+		td->td_frame->tf_out[0] = error;
+		td->td_frame->tf_tstate |= TSTATE_XCC_C;
+		break;
+	}
+}
+
+void
 cpu_set_upcall(struct thread *td, struct thread *td0)
 {
 	struct trapframe *tf;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-stable-8 mailing list