Since no system call takes more than 6 arguments, and no more than one
authormiod <miod@openbsd.org>
Thu, 11 Jan 2024 19:16:26 +0000 (19:16 +0000)
committermiod <miod@openbsd.org>
Thu, 11 Jan 2024 19:16:26 +0000 (19:16 +0000)
off_t argument, there is no need to process more than 6 arguments on
64-bit platforms and 8 on 32-bit platforms.

Make the syscall argument gathering code simpler by removing never-used code
to fetch more arguments from the stack, and local argument arrays when pointing
to the trap frame does the job.

ok guenther@ jsing@

sys/arch/alpha/alpha/trap.c
sys/arch/amd64/amd64/trap.c
sys/arch/arm64/arm64/syscall.c
sys/arch/m88k/m88k/trap.c
sys/arch/mips64/mips64/trap.c
sys/arch/powerpc/powerpc/trap.c
sys/arch/powerpc64/powerpc64/syscall.c
sys/arch/riscv64/riscv64/syscall.c
sys/arch/sparc64/sparc64/trap.c

index c5d57de..899b3ed 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.110 2023/12/13 15:57:22 miod Exp $ */
+/* $OpenBSD: trap.c,v 1.111 2024/01/11 19:16:26 miod Exp $ */
 /* $NetBSD: trap.c,v 1.52 2000/05/24 16:48:33 thorpej Exp $ */
 
 /*-
@@ -501,10 +501,10 @@ syscall(u_int64_t code, struct trapframe *framep)
 {
        const struct sysent *callp = sysent;
        struct proc *p;
-       int error;
+       int error = ENOSYS;
        u_int64_t opc;
        u_long rval[2];
-       u_long args[10];                                        /* XXX */
+       u_long args[6];
        u_int nargs;
 
        atomic_add_int(&uvmexp.syscalls, 1);
@@ -513,18 +513,13 @@ syscall(u_int64_t code, struct trapframe *framep)
        framep->tf_regs[FRAME_SP] = alpha_pal_rdusp();
        opc = framep->tf_regs[FRAME_PC] - 4;
 
-       // XXX out of range stays on syscall0, which we assume is enosys
-       if (code > 0 && code < SYS_MAXSYSCALL)
-               callp += code;
+       if (code <= 0 || code >= SYS_MAXSYSCALL)
+               goto bad;
+
+       callp += code;
 
        nargs = callp->sy_narg;
        switch (nargs) {
-       default:
-               if (nargs > 10)         /* XXX */
-                       panic("syscall: too many args (%d)", nargs);
-               if ((error = copyin((caddr_t)(framep->tf_regs[FRAME_SP]), &args[6],
-                   (nargs - 6) * sizeof(u_long))))
-                       goto bad;
        case 6:
                args[5] = framep->tf_regs[FRAME_A5];
        case 5:
index bccc016..d64f7c1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: trap.c,v 1.102 2023/12/12 15:30:55 deraadt Exp $      */
+/*     $OpenBSD: trap.c,v 1.103 2024/01/11 19:16:26 miod Exp $ */
 /*     $NetBSD: trap.c,v 1.2 2003/05/04 23:51:56 fvdl Exp $    */
 
 /*-
@@ -550,12 +550,10 @@ ast(struct trapframe *frame)
 void
 syscall(struct trapframe *frame)
 {
-       caddr_t params;
        const struct sysent *callp;
        struct proc *p;
        int error = ENOSYS;
-       size_t argsize, argoff;
-       register_t code, args[9], rval[2], *argp;
+       register_t code, args[6], rval[2], *argp;
 
        verify_smap(__func__);
        uvmexp.syscalls++;
@@ -568,36 +566,23 @@ syscall(struct trapframe *frame)
 
        code = frame->tf_rax;
        argp = &args[0];
-       argoff = 0;
 
        if (code <= 0 || code >= SYS_MAXSYSCALL)
                goto bad;
        callp = sysent + code;
-       argsize = (callp->sy_argsize >> 3) + argoff;
-       if (argsize) {
-               switch (MIN(argsize, 6)) {
-               case 6:
-                       args[5] = frame->tf_r9;
-               case 5:
-                       args[4] = frame->tf_r8;
-               case 4:
-                       args[3] = frame->tf_r10;
-               case 3:
-                       args[2] = frame->tf_rdx;
-               case 2:
-                       args[1] = frame->tf_rsi;
-               case 1:
-                       args[0] = frame->tf_rdi;
-                       break;
-               default:
-                       panic("impossible syscall argsize");
-               }
-               if (argsize > 6) {
-                       argsize -= 6;
-                       params = (caddr_t)frame->tf_rsp + sizeof(register_t);
-                       if ((error = copyin(params, &args[6], argsize << 3)))
-                               goto bad;
-               }
+       switch (callp->sy_narg) {
+       case 6:
+               args[5] = frame->tf_r9;
+       case 5:
+               args[4] = frame->tf_r8;
+       case 4:
+               args[3] = frame->tf_r10;
+       case 3:
+               args[2] = frame->tf_rdx;
+       case 2:
+               args[1] = frame->tf_rsi;
+       case 1:
+               args[0] = frame->tf_rdi;
        }
 
        rval[0] = 0;
index 675423d..21a77a0 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.c,v 1.17 2023/12/13 15:57:22 miod Exp $ */
+/* $OpenBSD: syscall.c,v 1.18 2024/01/11 19:16:26 miod Exp $ */
 /*
  * Copyright (c) 2015 Dale Rahn <drahn@dalerahn.com>
  *
 
 #include <uvm/uvm_extern.h>
 
-#define MAXARGS 8
-
 void
 svc_handler(trapframe_t *frame)
 {
        struct proc *p = curproc;
        const struct sysent *callp;
        int code, error = ENOSYS;
-       u_int nap = 8, nargs;
-       register_t *ap, *args, copyargs[MAXARGS], rval[2];
+       u_int nargs;
+       register_t *args, rval[2];
 
        uvmexp.syscalls++;
 
@@ -47,24 +45,12 @@ svc_handler(trapframe_t *frame)
        frame->tf_elr += 8;
 
        code = frame->tf_x[8];
-
-       ap = &frame->tf_x[0];
-
        if (code <= 0 || code >= SYS_MAXSYSCALL)
                goto bad;
 
        callp = sysent + code;
-       nargs = callp->sy_argsize / sizeof(register_t);
-       if (nargs <= nap) {
-               args = ap;
-       } else {
-               KASSERT(nargs <= MAXARGS);
-               memcpy(copyargs, ap, nap * sizeof(register_t));
-               if ((error = copyin((void *)frame->tf_sp, copyargs + nap,
-                   (nargs - nap) * sizeof(register_t))))
-                       goto bad;
-               args = copyargs;
-       }
+       nargs = callp->sy_narg;
+       args = &frame->tf_x[0];
 
        rval[0] = 0;
        rval[1] = 0;
index bc99e8c..7b8211e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: trap.c,v 1.131 2023/12/15 15:20:16 miod Exp $ */
+/*     $OpenBSD: trap.c,v 1.132 2024/01/11 19:16:26 miod Exp $ */
 /*
  * Copyright (c) 2004, Miodrag Vallat.
  * Copyright (c) 1998 Steve Murphree, Jr.
@@ -1152,39 +1152,24 @@ error_fatal(struct trapframe *frame)
 void
 m88100_syscall(register_t code, struct trapframe *tf)
 {
-       int i, nap;
        const struct sysent *callp = sysent;
        struct proc *p = curproc;
        int error;
-       register_t args[8] __aligned(8);
+       register_t *args;
        register_t rval[2] __aligned(8);
-       register_t *ap;
 
        uvmexp.syscalls++;
 
        p->p_md.md_tf = tf;
 
-       /*
-        * For 88k, all the arguments are passed in the registers (r2-r9),
-        * and further arguments (if any) on stack.
-        */
-       ap = &tf->tf_r[2];
-       nap = 8; /* r2-r9 */
-
        // XXX out of range stays on syscall0, which we assume is enosys
        if (code > 0 && code < SYS_MAXSYSCALL)
                callp += code;
 
-       i = callp->sy_argsize / sizeof(register_t);
-       if (i > sizeof(args) / sizeof(register_t))
-               panic("syscall nargs");
-       if (i > nap) {
-               bcopy((caddr_t)ap, (caddr_t)args, nap * sizeof(register_t));
-               if ((error = copyin((caddr_t)tf->tf_r[31], args + nap,
-                   (i - nap) * sizeof(register_t))))
-                       goto bad;
-       } else
-               bcopy((caddr_t)ap, (caddr_t)args, i * sizeof(register_t));
+       /*
+        * For 88k, all the arguments are passed in the registers (r2-r9).
+        */
+       args = &tf->tf_r[2];
 
        rval[0] = 0;
        rval[1] = tf->tf_r[3];
@@ -1254,39 +1239,24 @@ m88100_syscall(register_t code, struct trapframe *tf)
 void
 m88110_syscall(register_t code, struct trapframe *tf)
 {
-       int i, nap;
        const struct sysent *callp = sysent;
        struct proc *p = curproc;
        int error;
-       register_t args[8] __aligned(8);
        register_t rval[2] __aligned(8);
-       register_t *ap;
+       register_t *args;
 
        uvmexp.syscalls++;
 
        p->p_md.md_tf = tf;
 
-       /*
-        * For 88k, all the arguments are passed in the registers (r2-r9),
-        * and further arguments (if any) on stack.
-        */
-       ap = &tf->tf_r[2];
-       nap = 8;        /* r2-r9 */
-
        // XXX out of range stays on syscall0, which we assume is enosys
        if (code > 0 && code < SYS_MAXSYSCALL)
                callp += code;
 
-       i = callp->sy_argsize / sizeof(register_t);
-       if (i > sizeof(args) / sizeof(register_t))
-               panic("syscall nargs");
-       if (i > nap) {
-               bcopy((caddr_t)ap, (caddr_t)args, nap * sizeof(register_t));
-               if ((error = copyin((caddr_t)tf->tf_r[31], args + nap,
-                   (i - nap) * sizeof(register_t))))
-                       goto bad;
-       } else
-               bcopy((caddr_t)ap, (caddr_t)args, i * sizeof(register_t));
+       /*
+        * For 88k, all the arguments are passed in the registers (r2-r9).
+        */
+       ap = &tf->tf_r[2];
 
        rval[0] = 0;
        rval[1] = tf->tf_r[3];
index 5fa9c7e..c475148 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: trap.c,v 1.170 2023/12/13 15:57:22 miod Exp $ */
+/*     $OpenBSD: trap.c,v 1.171 2024/01/11 19:16:26 miod Exp $ */
 
 /*
  * Copyright (c) 1988 University of Utah.
@@ -400,11 +400,8 @@ fault_common_no_miss:
                unsigned int code;
                register_t tpc;
                uint32_t branch = 0;
-               int error, numarg;
-               struct args {
-                       register_t i[8];
-               } args;
-               register_t rval[2];
+               int error;
+               register_t *args, rval[2];
 
                atomic_inc_int(&uvmexp.syscalls);
 
@@ -428,17 +425,10 @@ fault_common_no_miss:
                if (code > 0 && code < SYS_MAXSYSCALL)
                        callp += code;
 
-               numarg = callp->sy_narg;
-               args.i[0] = locr0->a0;
-               args.i[1] = locr0->a1;
-               args.i[2] = locr0->a2;
-               args.i[3] = locr0->a3;
-               if (numarg > 4) {
-                       args.i[4] = locr0->a4;
-                       args.i[5] = locr0->a5;
-                       args.i[6] = locr0->a6;
-                       args.i[7] = locr0->a7;
-               }
+               /*
+                * This relies upon a0-a5 being contiguous in struct trapframe.
+                */
+               args = &locr0->a0;
 
                rval[0] = 0;
                rval[1] = 0;
@@ -448,7 +438,7 @@ fault_common_no_miss:
                    TRAPSIZE : trppos[ci->ci_cpuid]) - 1].code = code;
 #endif
 
-               error = mi_syscall(p, code, callp, args.i, rval);
+               error = mi_syscall(p, code, callp, args, rval);
 
                switch (error) {
                case 0:
index 80931f9..85b0747 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: trap.c,v 1.133 2023/12/13 15:57:22 miod Exp $ */
+/*     $OpenBSD: trap.c,v 1.134 2024/01/11 19:16:27 miod Exp $ */
 /*     $NetBSD: trap.c,v 1.3 1996/10/13 03:31:37 christos Exp $        */
 
 /*
@@ -61,10 +61,8 @@ static int fix_unaligned(struct proc *p, struct trapframe *frame);
 int badaddr(char *addr, u_int32_t len);
 void trap(struct trapframe *frame);
 
-/* These definitions should probably be somewhere else                         XXX */
-#define        FIRSTARG        3               /* first argument is in reg 3 */
-#define        NARGREG         8               /* 8 args are in registers */
-#define        MOREARGS(sp)    ((caddr_t)((int)(sp) + 8)) /* more args go here */
+/* XXX This definition should probably be somewhere else */
+#define        FIRSTARG        3               /* first syscall argument is in reg 3 */
 
 #ifdef ALTIVEC
 static int altivec_assist(struct proc *p, vaddr_t);
@@ -240,10 +238,8 @@ trap(struct trapframe *frame)
        vaddr_t va;
        int access_type;
        const struct sysent *callp = sysent;
-       size_t argsize;
        register_t code, error;
-       register_t *params, rval[2], args[10];
-       int n;
+       register_t *params, rval[2];
 
        if (frame->srr1 & PSL_PR) {
                type |= EXC_USER;
@@ -360,24 +356,16 @@ trap(struct trapframe *frame)
        case EXC_SC|EXC_USER:
                uvmexp.syscalls++;
 
-               params = frame->fixreg + FIRSTARG;
-
                code = frame->fixreg[0];
-               // XXX out of range stays on syscall0, which we assume is enosys
-               if (code > 0 && code < SYS_MAXSYSCALL)
-                       callp += code;
-
-               argsize = callp->sy_argsize;
-               n = NARGREG - (params - (frame->fixreg + FIRSTARG));
-               if (argsize > n * sizeof(register_t)) {
-                       bcopy(params, args, n * sizeof(register_t));
-
-                       if ((error = copyin(MOREARGS(frame->fixreg[1]),
-                          args + n, argsize - n * sizeof(register_t))))
-                               goto bad;
-                       params = args;
+               if (code <= 0 || code >= SYS_MAXSYSCALL) {
+                       error = ENOSYS;
+                       goto bad;
                }
 
+               callp += code;
+
+               params = frame->fixreg + FIRSTARG;
+
                rval[0] = 0;
                rval[1] = frame->fixreg[FIRSTARG + 1];
 
index 3d60de8..b7681f0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscall.c,v 1.13 2023/12/13 15:57:22 miod Exp $       */
+/*     $OpenBSD: syscall.c,v 1.14 2024/01/11 19:16:27 miod Exp $       */
 
 /*
  * Copyright (c) 2015 Dale Rahn <drahn@dalerahn.com>
 #include <sys/syscall.h>
 #include <sys/syscall_mi.h>
 
-#define MAXARGS 8
-
 void
 syscall(struct trapframe *frame)
 {
        struct proc *p = curproc;
        const struct sysent *callp = sysent;
-       int code, error;
-       int nap = 8, nargs;
-       register_t *ap, *args, copyargs[MAXARGS], rval[2];
-
-       ap = &frame->fixreg[3];
+       int code, error = ENOSYS;
+       register_t *args, rval[2];
 
        code = frame->fixreg[0];
-       // XXX out of range stays on syscall0, which we assume is enosys
-       if (code > 0 && code < SYS_MAXSYSCALL)
-               callp += code;
+       if (code <= 0 || code >= SYS_MAXSYSCALL)
+               goto bad;
 
-       nargs = callp->sy_argsize / sizeof(register_t);
-       if (nargs <= nap) {
-               args = ap;
-       } else {
-               KASSERT(nargs <= MAXARGS);
-               memcpy(copyargs, ap, nap * sizeof(register_t));
-               if ((error = copyin((register_t *)frame->fixreg[1] + 8,
-                   copyargs + nap, (nargs - nap) * sizeof(register_t))))
-                       goto bad;
-               args = copyargs;
-       }
+       callp += code;
+
+       args = &frame->fixreg[3];
 
        rval[0] = 0;
        rval[1] = 0;
index 2c02730..2a4e604 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: syscall.c,v 1.18 2023/12/13 15:57:22 miod Exp $       */
+/*     $OpenBSD: syscall.c,v 1.19 2024/01/11 19:16:27 miod Exp $       */
 
 /*
  * Copyright (c) 2020 Brian Bamsch <bbamsch@google.com>
@@ -27,8 +27,6 @@
 
 #include <machine/syscall.h>
 
-#define MAXARGS 8
-
 static __inline struct trapframe *
 process_frame(struct proc *p)
 {
@@ -40,30 +38,18 @@ svc_handler(trapframe_t *frame)
 {
        struct proc *p = curproc;
        const struct sysent *callp = sysent;
-       int code, error;
-       u_int nap = 8, nargs;
-       register_t *ap, *args, copyargs[MAXARGS], rval[2];
+       int code, error = ENOSYS;
+       register_t *args, rval[2];
 
        uvmexp.syscalls++;
 
-       ap = &frame->tf_a[0];
        code = frame->tf_t[0];
+       if (code <= 0 || code >= SYS_MAXSYSCALL)
+               goto bad;
 
-       // XXX out of range stays on syscall0, which we assume is enosys
-       if (code > 0 && code < SYS_MAXSYSCALL)
-               callp += code;
-
-       nargs = callp->sy_argsize / sizeof(register_t);
-       if (nargs <= nap) {
-               args = ap;
-       } else {
-               KASSERT(nargs <= MAXARGS);
-               memcpy(copyargs, ap, nap * sizeof(register_t));
-               if ((error = copyin((void *)frame->tf_sp, copyargs + nap,
-                   (nargs - nap) * sizeof(register_t))))
-                       goto bad;
-               args = copyargs;
-       }
+       callp += code;
+
+       args = &frame->tf_a[0];
 
        rval[0] = 0;
        rval[1] = 0;
index deb4c52..a2116f0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: trap.c,v 1.118 2023/12/13 15:57:22 miod Exp $ */
+/*     $OpenBSD: trap.c,v 1.119 2024/01/11 19:16:27 miod Exp $ */
 /*     $NetBSD: trap.c,v 1.73 2001/08/09 01:03:01 eeh Exp $ */
 
 /*
@@ -1105,14 +1105,11 @@ out:
 void
 syscall(struct trapframe *tf, register_t code, register_t pc)
 {
-       int i, nap;
-       int64_t *ap;
        const struct sysent *callp;
        struct proc *p = curproc;
        int error = ENOSYS, new;
-       register_t args[8];
        register_t rval[2];
-       register_t *argp;
+       register_t *args;
 
        if ((tf->tf_out[6] & 1) == 0)
                sigexit(p, SIGILL);
@@ -1130,34 +1127,17 @@ syscall(struct trapframe *tf, register_t code, register_t pc)
        new = code & SYSCALL_G2RFLAG;
        code &= ~SYSCALL_G2RFLAG;
 
-       /*
-        * The first six system call arguments are in the six %o registers.
-        * Any arguments beyond that are in the `argument extension' area
-        * of the user's stack frame (see <machine/frame.h>).
-        */
-       ap = &tf->tf_out[0];
-       nap = 6;
-
        if (code <= 0 || code >= SYS_MAXSYSCALL)
                goto bad;
        callp = sysent + code;
-       i = callp->sy_narg; /* Why divide? */
-       if (i > nap) {  /* usually false */
-               if (i > 8)
-                       panic("syscall nargs");
-               /* Read the whole block in */
-               if ((error = copyin((caddr_t)tf->tf_out[6]
-                   + BIAS + offsetof(struct frame, fr_argx),
-                   &args[nap], (i - nap) * sizeof(register_t))))
-                       goto bad;
-               i = nap;
-       }
+
        /*
-        * It should be faster to do <= 6 longword copies than
-        * to call bcopy
+        * The first six system call arguments are in the six %o registers.
+        * Any arguments beyond that are in the `argument extension' area
+        * of the user's stack frame (see <machine/frame.h>), but no system
+        * call currently uses more than six arguments.
         */
-       for (argp = args; i--;)
-               *argp++ = *ap++;
+       args = (register_t *)&tf->tf_out[0];
 
        rval[0] = 0;
        rval[1] = 0;