From 82f13a2768c269a4d86d3b7e9122e229737a9574 Mon Sep 17 00:00:00 2001 From: miod Date: Thu, 11 Jan 2024 19:16:26 +0000 Subject: [PATCH] Since no system call takes more than 6 arguments, and no more than one 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 | 19 ++++------ sys/arch/amd64/amd64/trap.c | 45 ++++++++-------------- sys/arch/arm64/arm64/syscall.c | 24 +++--------- sys/arch/m88k/m88k/trap.c | 52 ++++++-------------------- sys/arch/mips64/mips64/trap.c | 26 ++++--------- sys/arch/powerpc/powerpc/trap.c | 34 ++++++----------- sys/arch/powerpc64/powerpc64/syscall.c | 30 ++++----------- sys/arch/riscv64/riscv64/syscall.c | 30 ++++----------- sys/arch/sparc64/sparc64/trap.c | 36 ++++-------------- 9 files changed, 81 insertions(+), 215 deletions(-) diff --git a/sys/arch/alpha/alpha/trap.c b/sys/arch/alpha/alpha/trap.c index c5d57de02ab..899b3edccf2 100644 --- a/sys/arch/alpha/alpha/trap.c +++ b/sys/arch/alpha/alpha/trap.c @@ -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: diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c index bccc016f790..d64f7c1af08 100644 --- a/sys/arch/amd64/amd64/trap.c +++ b/sys/arch/amd64/amd64/trap.c @@ -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; diff --git a/sys/arch/arm64/arm64/syscall.c b/sys/arch/arm64/arm64/syscall.c index 675423d1cc2..21a77a019a6 100644 --- a/sys/arch/arm64/arm64/syscall.c +++ b/sys/arch/arm64/arm64/syscall.c @@ -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 * @@ -26,16 +26,14 @@ #include -#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; diff --git a/sys/arch/m88k/m88k/trap.c b/sys/arch/m88k/m88k/trap.c index bc99e8cd15b..7b8211e8525 100644 --- a/sys/arch/m88k/m88k/trap.c +++ b/sys/arch/m88k/m88k/trap.c @@ -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]; diff --git a/sys/arch/mips64/mips64/trap.c b/sys/arch/mips64/mips64/trap.c index 5fa9c7ef830..c4751488c23 100644 --- a/sys/arch/mips64/mips64/trap.c +++ b/sys/arch/mips64/mips64/trap.c @@ -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: diff --git a/sys/arch/powerpc/powerpc/trap.c b/sys/arch/powerpc/powerpc/trap.c index 80931f9b0ff..85b0747b347 100644 --- a/sys/arch/powerpc/powerpc/trap.c +++ b/sys/arch/powerpc/powerpc/trap.c @@ -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]; diff --git a/sys/arch/powerpc64/powerpc64/syscall.c b/sys/arch/powerpc64/powerpc64/syscall.c index 3d60de8616a..b7681f0489f 100644 --- a/sys/arch/powerpc64/powerpc64/syscall.c +++ b/sys/arch/powerpc64/powerpc64/syscall.c @@ -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 @@ -24,35 +24,21 @@ #include #include -#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; diff --git a/sys/arch/riscv64/riscv64/syscall.c b/sys/arch/riscv64/riscv64/syscall.c index 2c02730664d..2a4e604c9f4 100644 --- a/sys/arch/riscv64/riscv64/syscall.c +++ b/sys/arch/riscv64/riscv64/syscall.c @@ -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 @@ -27,8 +27,6 @@ #include -#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; diff --git a/sys/arch/sparc64/sparc64/trap.c b/sys/arch/sparc64/sparc64/trap.c index deb4c527191..a2116f085a9 100644 --- a/sys/arch/sparc64/sparc64/trap.c +++ b/sys/arch/sparc64/sparc64/trap.c @@ -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 ). - */ - 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 ), 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; -- 2.20.1