Module Name: src
Committed By: matt
Date: Fri Aug 21 17:46:23 UTC 2009
Modified Files:
src/sys/arch/mips/mips [matt-nb5-mips64]: syscall.c
Log Message:
New simplier implentation that handles all 4 ABIs: O32/N32/O64/N64.
To generate a diff of this commit:
cvs rdiff -u -r1.37.12.1 -r1.37.12.2 src/sys/arch/mips/mips/syscall.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/mips/mips/syscall.c
diff -u src/sys/arch/mips/mips/syscall.c:1.37.12.1 src/sys/arch/mips/mips/syscall.c:1.37.12.2
--- src/sys/arch/mips/mips/syscall.c:1.37.12.1 Thu Aug 20 04:22:54 2009
+++ src/sys/arch/mips/mips/syscall.c Fri Aug 21 17:46:23 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: syscall.c,v 1.37.12.1 2009/08/20 04:22:54 uebayasi Exp $ */
+/* $NetBSD: syscall.c,v 1.37.12.2 2009/08/21 17:46:23 matt Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -107,7 +107,7 @@
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
-__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.37.12.1 2009/08/20 04:22:54 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.37.12.2 2009/08/21 17:46:23 matt Exp $");
#if defined(_KERNEL_OPT)
#include "opt_sa.h"
@@ -140,21 +140,16 @@
#endif
void EMULNAME(syscall_intern)(struct proc *);
-void EMULNAME(syscall_plain)(struct lwp *, u_int, u_int, u_int);
-void EMULNAME(syscall_fancy)(struct lwp *, u_int, u_int, u_int);
+static void EMULNAME(syscall)(struct lwp *, uint32_t, uint32_t, vaddr_t);
-vaddr_t MachEmulateBranch(struct frame *, vaddr_t, u_int, int);
+register_t MachEmulateBranch(struct frame *, register_t, u_int, int);
#define DELAYBRANCH(x) ((int)(x)<0)
void
EMULNAME(syscall_intern)(struct proc *p)
{
-
- if (trace_is_enabled(p))
- p->p_md.md_syscall = EMULNAME(syscall_fancy);
- else
- p->p_md.md_syscall = EMULNAME(syscall_plain);
+ p->p_md.md_syscall = EMULNAME(syscall);
}
/*
@@ -164,25 +159,35 @@
* in v0, and the arguments in the registers (as normal). They return
* an error flag in a3 (if a3 != 0 on return, the syscall had an error),
* and the return value (if any) in v0 and possibly v1.
- *
- * XXX Needs to be heavily rototilled for N32 or LP64 support.
*/
void
-EMULNAME(syscall_plain)(struct lwp *l, u_int status, u_int cause, u_int opc)
+EMULNAME(syscall)(struct lwp *l, u_int status, u_int cause, vaddr_t opc)
{
struct proc *p = l->l_proc;
- struct frame *frame = (struct frame *)l->l_md.md_regs;
- register_t *args, copyargs[8];
- register_t *rval = NULL; /* XXX gcc */
-#if _MIPS_BSD_API == _MIPS_BSD_API_LP32_64CLEAN
- register_t copyrval[2];
-#endif
- mips_reg_t ov0;
- size_t nsaved, nargs;
+ struct frame *frame = l->l_md.md_regs;
+ mips_reg_t *fargs = &frame->f_regs[_R_A0];
+ void *args = NULL;
+ void *rval = NULL; /* XXX gcc */
+#if !defined(__mips_o32)
+ register32_t copy32args[2+SYS_MAXSYSARGS];
+ register_t copy32rval[2];
+#endif
+ register_t copyargs[2+SYS_MAXSYSARGS];
+ mips_reg_t saved_v0;
+ vaddr_t usp;
+ size_t nargs;
const struct sysent *callp;
- int error;
- u_int code;
+ int code, error;
+#if defined(__mips_o32)
+ const int abi = _MIPS_BSD_API_O32;
+ KASSERTMSG(p->p_md.md_abi != abi, ("pid %d(%p): md_abi(%d) != abi(%d)", p->p_pid, p, p->p_md.md_abi, abi));
+ size_t nregs = 4;
+#else
+ const int abi = p->p_md.md_abi;
+ size_t nregs = _MIPS_SIM_NEWABI_P(abi) ? 8 : 4;
+ size_t i;
+#endif
LWP_CACHE_CREDS(l, p);
@@ -191,10 +196,10 @@
if (DELAYBRANCH(cause))
frame->f_regs[_R_PC] = MachEmulateBranch(frame, opc, 0, 0);
else
- frame->f_regs[_R_PC] = opc + sizeof(int);
+ frame->f_regs[_R_PC] = opc + sizeof(uint32_t);
callp = p->p_emul->e_sysent;
- ov0 = code = frame->f_regs[_R_V0] - SYSCALL_SHIFT;
+ saved_v0 = code = frame->f_regs[_R_V0] - SYSCALL_SHIFT;
#ifdef KERN_SA
if (__predict_false((l->l_savp)
@@ -202,255 +207,110 @@
l->l_savp->savp_pflags &= ~SAVP_FLAG_DELIVERING;
#endif
- switch (code) {
- case SYS_syscall:
- case SYS___syscall:
- args = copyargs;
- if (code == SYS_syscall) {
- /*
- * Code is first argument, followed by actual args.
- */
- code = frame->f_regs[_R_A0] - SYSCALL_SHIFT;
- args[0] = frame->f_regs[_R_A1];
- args[1] = frame->f_regs[_R_A2];
- args[2] = frame->f_regs[_R_A3];
- nsaved = 3;
- } else {
- /*
- * Like syscall, but code is a quad, so as to maintain
- * quad alignment for the rest of the arguments.
- */
- code = frame->f_regs[_R_A0 + _QUAD_LOWWORD]
- - SYSCALL_SHIFT;
- args[0] = frame->f_regs[_R_A2];
- args[1] = frame->f_regs[_R_A3];
- nsaved = 2;
- }
-
- if (code >= p->p_emul->e_nsysent)
- callp += p->p_emul->e_nosys;
- else
- callp += code;
- nargs = callp->sy_argsize / sizeof(register_t);
-
- if (nargs > nsaved) {
- error = copyin(
- ((register_t *)(vaddr_t)frame->f_regs[_R_SP] + 4),
- (args + nsaved),
- (nargs - nsaved) * sizeof(register_t));
- if (error)
- goto bad;
- }
- break;
-
- default:
- if (code >= p->p_emul->e_nsysent)
- callp += p->p_emul->e_nosys;
- else
- callp += code;
- nargs = callp->sy_narg;
-
- if (nargs < 5) {
-#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32
- args = (register_t *)&frame->f_regs[_R_A0];
-#elif _MIPS_BSD_API == _MIPS_BSD_API_LP32_64CLEAN
- args = copyargs;
- args[0] = frame->f_regs[_R_A0];
- args[1] = frame->f_regs[_R_A1];
- args[2] = frame->f_regs[_R_A2];
- args[3] = frame->f_regs[_R_A3];
-#else
- panic("syscall not implemented for current MIPS ABI\n");
-#endif
- } else {
- args = copyargs;
- error = copyin(
- ((register_t *)(vaddr_t)frame->f_regs[_R_SP] + 4),
- (©args[4]),
- (nargs - 4) * sizeof(register_t));
- if (error)
- goto bad;
- args[0] = frame->f_regs[_R_A0];
- args[1] = frame->f_regs[_R_A1];
- args[2] = frame->f_regs[_R_A2];
- args[3] = frame->f_regs[_R_A3];
- }
- break;
+ if (code == SYS_syscall
+ || (code == SYS___syscall && abi != _MIPS_BSD_API_O32)) {
+ /*
+ * Code is first argument, followed by actual args.
+ */
+ code = *fargs++ - SYSCALL_SHIFT;
+ nregs--;
+ } else if (code == SYS___syscall) {
+ /*
+ * Like syscall, but code is a quad, so as to maintain
+ * quad alignment for the rest of the arguments.
+ */
+ code = fargs[_QUAD_LOWWORD] - SYSCALL_SHIFT;
+ fargs += 2;
+ nregs -= 2;
}
-#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32
- rval = (register_t *)&frame->f_regs[_R_V0];
- rval[0] = 0;
- /* rval[1] already has V1 */
-#elif _MIPS_BSD_API == _MIPS_BSD_API_LP32_64CLEAN
- rval = copyrval;
- rval[0] = 0;
- rval[1] = frame->f_regs[_R_V1];
-#endif
-
- error = sy_call(callp, l, args, rval);
-
- switch (error) {
- case 0:
-#if _MIPS_BSD_API == _MIPS_BSD_API_LP32_64CLEAN
- frame->f_regs[_R_V0] = rval[0];
- frame->f_regs[_R_V1] = rval[1];
-#endif
- frame->f_regs[_R_A3] = 0;
- break;
- case ERESTART:
- frame->f_regs[_R_V0] = ov0; /* restore syscall code */
- frame->f_regs[_R_PC] = opc;
- break;
- case EJUSTRETURN:
- break; /* nothing to do */
- default:
- bad:
- if (p->p_emul->e_errno)
- error = p->p_emul->e_errno[error];
- frame->f_regs[_R_V0] = error;
- frame->f_regs[_R_A3] = 1;
- break;
- }
-
- userret(l);
-}
-
-void
-EMULNAME(syscall_fancy)(struct lwp *l, u_int status, u_int cause, u_int opc)
-{
- struct proc *p = l->l_proc;
- struct frame *frame = (struct frame *)l->l_md.md_regs;
- register_t *args, copyargs[8];
- register_t *rval = NULL; /* XXX gcc */
-#if _MIPS_BSD_API == _MIPS_BSD_API_LP32_64CLEAN
- register_t copyrval[2];
-#endif
- mips_reg_t ov0;
- size_t nsaved, nargs;
- const struct sysent *callp;
- int error;
- u_int code;
-
- LWP_CACHE_CREDS(l, p);
-
- uvmexp.syscalls++;
-
- if (DELAYBRANCH(cause))
- frame->f_regs[_R_PC] = MachEmulateBranch(frame, opc, 0, 0);
+ if (code >= p->p_emul->e_nsysent)
+ callp += p->p_emul->e_nosys;
else
- frame->f_regs[_R_PC] = opc + sizeof(int);
-
- callp = p->p_emul->e_sysent;
- ov0 = code = frame->f_regs[_R_V0] - SYSCALL_SHIFT;
+ callp += code;
-#ifdef KERN_SA
- if (__predict_false((l->l_savp)
- && (l->l_savp->savp_pflags & SAVP_FLAG_DELIVERING)))
- l->l_savp->savp_pflags &= ~SAVP_FLAG_DELIVERING;
+#if !defined(__mips_o32)
+ if (abi != _MIPS_BSD_API_O32) {
#endif
-
- switch (code) {
- case SYS_syscall:
- case SYS___syscall:
- args = copyargs;
- if (code == SYS_syscall) {
+ CTASSERT(sizeof(copyargs[0]) == sizeof(fargs[0]));
+ nargs = callp->sy_argsize / sizeof(copyargs[0]);
+ rval = &frame->f_regs[_R_V0];
+ frame->f_regs[_R_V0] = 0;
+ /* rval[1] already is V1 */
+ if (nargs <= nregs) {
/*
- * Code is first argument, followed by actual args.
+ * Just use the frame for the source of arguments
*/
- code = frame->f_regs[_R_A0] - SYSCALL_SHIFT;
- args[0] = frame->f_regs[_R_A1];
- args[1] = frame->f_regs[_R_A2];
- args[2] = frame->f_regs[_R_A3];
- nsaved = 3;
+ args = fargs;
} else {
+ const size_t nsaved = _MIPS_SIM_NEWABI_P(abi) ? 0 : 4;
+ args = copyargs;
/*
- * Like syscall, but code is a quad, so as to maintain
- * quad alignment for the rest of the arguments.
+ * Copy the arguments passed via register from the * trap frame to our argument array
*/
- code = frame->f_regs[_R_A0 + _QUAD_LOWWORD]
- - SYSCALL_SHIFT;
- args[0] = frame->f_regs[_R_A2];
- args[1] = frame->f_regs[_R_A3];
- nsaved = 2;
- }
-
- if (code >= p->p_emul->e_nsysent)
- callp += p->p_emul->e_nosys;
- else
- callp += code;
- nargs = callp->sy_argsize / sizeof(register_t);
-
- if (nargs > nsaved) {
- error = copyin(
- ((register_t *)(vaddr_t)frame->f_regs[_R_SP] + 4),
- (args + nsaved),
- (nargs - nsaved) * sizeof(register_t));
+ memcpy(copyargs, fargs, nregs * sizeof(register_t));
+ /*
+ * Start copying args skipping the register slots
+ * slots on the stack.
+ */
+ usp = frame->f_regs[_R_SP] + nsaved*sizeof(register_t);
+ error = copyin((register_t *)usp, ©args[nregs],
+ (nargs - nregs) * sizeof(copyargs[0]));
if (error)
goto bad;
}
- break;
-
- default:
- if (code >= p->p_emul->e_nsysent)
- callp += p->p_emul->e_nosys;
- else
- callp += code;
- nargs = callp->sy_narg;
-
- if (nargs < 5) {
-#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32
- args = (register_t *)&frame->f_regs[_R_A0];
-#elif _MIPS_BSD_API == _MIPS_BSD_API_LP32_64CLEAN
- args = copyargs;
- args[0] = frame->f_regs[_R_A0];
- args[1] = frame->f_regs[_R_A1];
- args[2] = frame->f_regs[_R_A2];
- args[3] = frame->f_regs[_R_A3];
-#else
- panic("syscall not implemented for current MIPS ABI\n");
-#endif
- } else {
- args = copyargs;
- error = copyin(
- ((register_t *)(vaddr_t)frame->f_regs[_R_SP] + 4),
- (©args[4]),
- (nargs - 4) * sizeof(register_t));
+#if !defined(__mips_o32)
+ } else {
+ /*
+ * All arguments are 32bits wide and 64bit arguments use
+ * two 32bit registers or stack slots.
+ */
+ nargs = callp->sy_argsize / sizeof(copy32args[0]);
+ rval = copy32rval;
+ args = copy32args;
+ copy32rval[0] = 0;
+ copy32rval[1] = frame->f_regs[_R_V1];
+ CTASSERT(sizeof(copy32args[0]) != sizeof(fargs[0]));
+ /*
+ * Copy the register passed arguments from the trapframe to
+ * the set of 32bit copies.
+ */
+ for (i = 0; i < 4 && i < nargs; i++)
+ copy32args[i] = fargs[i];
+ if (nargs > nregs) {
+ /*
+ * Copy the remainder of the arguments from the stack
+ * after skipped the slots for the 4 register passed
+ * arguments.
+ */
+ usp = frame->f_regs[_R_SP] + 4*sizeof(register32_t);
+ error = copyin((register32_t *)usp, ©32args[nregs],
+ (nargs - nregs) * sizeof(copy32args[0]));
if (error)
goto bad;
- args[0] = frame->f_regs[_R_A0];
- args[1] = frame->f_regs[_R_A1];
- args[2] = frame->f_regs[_R_A2];
- args[3] = frame->f_regs[_R_A3];
}
- break;
}
+#endif
- if ((error = trace_enter(code, args, callp->sy_narg)) != 0)
+ if (__predict_false(p->p_trace_enabled)
+ && (error = trace_enter(code, args, nargs)) != 0)
goto out;
-#if !defined(_MIPS_BSD_API) || _MIPS_BSD_API == _MIPS_BSD_API_LP32
- rval = (register_t *)&frame->f_regs[_R_V0];
- rval[0] = 0;
- /* rval[1] already has V1 */
-#elif _MIPS_BSD_API == _MIPS_BSD_API_LP32_64CLEAN
- rval = copyrval;
- rval[0] = 0;
- rval[1] = frame->f_regs[_R_V1];
-#endif
+ error = (*callp->sy_call)(l, args, rval);
- error = sy_call(callp, l, args, rval);
-out:
+ out:
switch (error) {
case 0:
-#if _MIPS_BSD_API == _MIPS_BSD_API_LP32_64CLEAN
- frame->f_regs[_R_V0] = rval[0];
- frame->f_regs[_R_V1] = rval[1];
+#if !defined(__mips_o32)
+ if (abi == _MIPS_BSD_API_O32) {
+ frame->f_regs[_R_V0] = copy32rval[0];
+ frame->f_regs[_R_V1] = copy32rval[1];
+ }
#endif
frame->f_regs[_R_A3] = 0;
break;
case ERESTART:
- frame->f_regs[_R_V0] = ov0; /* restore syscall code */
+ frame->f_regs[_R_V0] = saved_v0; /* restore syscall code */
frame->f_regs[_R_PC] = opc;
break;
case EJUSTRETURN:
@@ -464,7 +324,8 @@
break;
}
- trace_exit(code, rval, error);
+ if (__predict_false(p->p_trace_enabled))
+ trace_exit(code, &frame->f_regs[_R_V0], error);
userret(l);
}