diff --git a/sys/arch/arm/arm32/syscall.c b/sys/arch/arm/arm/syscall.c similarity index 76% rename from sys/arch/arm/arm32/syscall.c rename to sys/arch/arm/arm/syscall.c index 41f55b4c0bf9..0dc9758de241 100644 --- a/sys/arch/arm/arm32/syscall.c +++ b/sys/arch/arm/arm/syscall.c @@ -1,4 +1,4 @@ -/* $NetBSD: syscall.c,v 1.3 2002/01/05 22:41:47 chris Exp $ */ +/* $NetBSD: syscall.c,v 1.1 2002/01/12 20:02:13 bjh21 Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -80,11 +80,15 @@ #include "opt_syscall_debug.h" #include + +__RCSID("$NetBSD: syscall.c,v 1.1 2002/01/12 20:02:13 bjh21 Exp $"); + +#include #include -#include -#include #include +#include #include +#include #include #ifdef KTRACE #include @@ -94,42 +98,50 @@ #include #include -#include #include -u_int arm700bugcount = 0; -void syscall __P((trapframe_t *, int)); +#ifdef arm26 +#include +#endif + +#ifdef CPU_ARM7 +struct evcnt arm700bugcount = + EVCNT_INITIALISER(EVCNT_TYPE_MISC, NULL, "cpu", "arm700swibug"); +#endif -/* - * syscall(frame): - * - * System call request from POSIX system call gate interface to kernel. - */ void -syscall(frame, code) - trapframe_t *frame; - int code; +syscall(trapframe_t *frame) { - caddr_t stackargs; const struct sysent *callp; struct proc *p; - int error; - u_int argsize; - int *args, copyargs[8], rval[2]; - int regparams; + u_int32_t insn; + int code, error; + u_int nap, nargs; + register_t *ap, *args, copyargs[8], rval[2]; /* * Enable interrupts if they were enabled before the exception. * Since all syscalls *should* come from user mode it will always * be safe to enable them, but check anyway. */ +#ifdef arm26 + if ((frame->tf_r15 & R15_IRQ_DISABLE) == 0) + int_on(); +#else if (!(frame->tf_spsr & I32_bit)) enable_interrupts(I32_bit); +#endif -#ifdef DEBUG - if ((GetCPSR() & PSR_MODE) != PSR_SVC32_MODE) - panic("syscall: not in SVC32 mode"); -#endif /* DEBUG */ +#ifdef arm26 + frame->tf_pc += INSN_SIZE; +#endif + + /* XXX fuword? */ +#ifdef __PROG32 + insn = *(u_int32_t *)(frame->tf_pc - INSN_SIZE); +#else + insn = *(u_int32_t *)((frame->tf_r15 & R15_PC) - INSN_SIZE); +#endif uvmexp.syscalls++; p = curproc; @@ -152,22 +164,22 @@ syscall(frame, code) * If the instruction that caused the exception is not a SWI * then we hit the bug. */ - if ((ReadWord(frame->tf_pc - INSN_SIZE) & 0x0f000000) != 0x0f000000) { + if ((insn & 0x0f000000) != 0x0f000000) { frame->tf_pc -= INSN_SIZE; - ++arm700bugcount; + /* + * Yuck. arm700bugcount should be per-CPU and + * attached at the same time as the CPU. + */ + if (!cold && arm700bugcount.ev_list.tqe_next == NULL) + evcnt_attach_static(&arm700bugcount); + ++arm700bugcount.ev_count; userret(p); return; } #endif /* CPU_ARM7 */ - /* - * Support for architecture dependant SWIs - */ - if (code & 0x00f00000) { - /* - * Support for the Architecture defined SWI's in case the - * processor does not support them. - */ + switch (insn & 0xf00000) { /* Which OS is the SWI from? */ + case 0xf00000: /* ARM-defined SWIs */ switch (code) { case 0x00f00000 : /* IMB */ case 0x00f00001 : /* IMB_range */ @@ -178,59 +190,61 @@ syscall(frame, code) break; default: /* Undefined so illegal instruction */ - trapsignal(p, SIGILL, ReadWord(frame->tf_pc - INSN_SIZE)); + trapsignal(p, SIGILL, insn); break; } + userret(p); + return; + case 0x000000: /* Old unofficial NetBSD range. */ + case 0xa00000: /* New official NetBSD range. */ + break; + default: + /* Undefined so illegal instruction */ + trapsignal(p, SIGILL, insn); userret(p); return; } - stackargs = (caddr_t)&frame->tf_r0; - regparams = 4 * sizeof(int); + code = insn & 0x000fffff; + + ap = &frame->tf_r0; + nap = 4; callp = p->p_emul->e_sysent; switch (code) { case SYS_syscall: - /* Don't have to look in user space, we have it in the trapframe */ -/* code = fuword(stackargs);*/ - code = ReadWord(stackargs); - stackargs += sizeof(int); - regparams -= sizeof(int); + code = *ap++; + nap--; break; - case SYS___syscall: - if (callp != sysent) +#if 0 + if (!(p->p_emul->e_flags & EMUL_HAS_SYS___syscall)) break; +#endif - /* Since this will be a register we look in the trapframe not user land */ -/* code = fuword(stackargs + _QUAD_LOWWORD * sizeof(int));*/ - code = ReadWord(stackargs + _QUAD_LOWWORD * sizeof(int)); - stackargs += sizeof(quad_t); - regparams -= sizeof(quad_t); - break; - - default: - /* do nothing by default */ + code = ap[_QUAD_LOWWORD]; + ap += 2; + nap -= 2; break; } code &= (SYS_NSYSENT - 1); callp += code; - argsize = callp->sy_argsize; - if (argsize <= regparams) - args = (int *)stackargs; + nargs = callp->sy_argsize / sizeof(register_t); + if (nargs <= nap) + args = ap; else { - args = copyargs; - bcopy(stackargs, (caddr_t)args, regparams); - error = copyin((caddr_t)frame->tf_usr_sp, - (caddr_t)args + regparams, argsize - regparams); + memcpy(copyargs, ap, nap * sizeof(register_t)); + error = copyin((void *)frame->tf_usr_sp, copyargs + nap, + (nargs - nap) * sizeof(register_t)); if (error) goto bad; + args = copyargs; } #ifdef SYSCALL_DEBUG - scdebug_call(p, code, callp->sy_narg, args); + scdebug_call(p, code, args); #endif #ifdef KTRACE if (KTRPOINT(p, KTR_SYSCALL)) @@ -245,7 +259,12 @@ syscall(frame, code) case 0: frame->tf_r0 = rval[0]; frame->tf_r1 = rval[1]; + +#ifdef __PROG32 frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ +#else + frame->tf_r15 &= ~R15_FLAG_C; /* carry bit */ +#endif break; case ERESTART: @@ -262,7 +281,11 @@ syscall(frame, code) default: bad: frame->tf_r0 = error; +#ifdef __PROG32 frame->tf_spsr |= PSR_C_bit; /* carry bit */ +#else + frame->tf_r15 |= R15_FLAG_C; /* carry bit */ +#endif break; } @@ -284,7 +307,11 @@ child_return(arg) struct trapframe *frame = p->p_addr->u_pcb.pcb_tf; frame->tf_r0 = 0; - frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ +#ifdef __PROG32 + frame->tf_spsr &= ~PSR_C_bit; /* carry bit */ +#else + frame->tf_r15 &= ~R15_FLAG_C; /* carry bit */ +#endif userret(p); #ifdef KTRACE diff --git a/sys/arch/arm/conf/files.arm b/sys/arch/arm/conf/files.arm index 3319f2a4d1f4..3de84adb7848 100644 --- a/sys/arch/arm/conf/files.arm +++ b/sys/arch/arm/conf/files.arm @@ -1,4 +1,4 @@ -# $NetBSD: files.arm,v 1.49 2002/01/07 21:15:50 bjh21 Exp $ +# $NetBSD: files.arm,v 1.50 2002/01/12 20:02:14 bjh21 Exp $ # temporary define to allow easy moving to ../arch/arm/arm32 defflag ARM32 @@ -70,6 +70,7 @@ file arch/arm/arm/process_machdep.c file arch/arm/arm/procfs_machdep.c procfs file arch/arm/arm/sig_machdep.c file arch/arm/arm/sigcode.S +file arch/arm/arm/syscall.c file arch/arm/arm/undefined.c # vectors.S gets included manually by Makefile.arm26, since it needs # to be at the start of the text segment on those machines. @@ -89,7 +90,6 @@ file arch/arm/arm32/pmap.c arm32 file arch/arm/arm32/setcpsr.S arm32 file arch/arm/arm32/setstack.S arm32 file arch/arm/arm32/stubs.c arm32 -file arch/arm/arm32/syscall.c arm32 file arch/arm/arm32/sys_machdep.c arm32 file arch/arm/arm32/vm_machdep.c arm32 diff --git a/sys/arch/arm26/arm26/except.c b/sys/arch/arm26/arm26/except.c index 59900ade26d3..3f7a0c8c8dbd 100644 --- a/sys/arch/arm26/arm26/except.c +++ b/sys/arch/arm26/arm26/except.c @@ -1,4 +1,4 @@ -/* $NetBSD: except.c,v 1.39 2001/12/21 22:56:17 bjh21 Exp $ */ +/* $NetBSD: except.c,v 1.40 2002/01/12 20:02:15 bjh21 Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 Ben Harris * All rights reserved. @@ -32,16 +32,14 @@ #include -__KERNEL_RCSID(0, "$NetBSD: except.c,v 1.39 2001/12/21 22:56:17 bjh21 Exp $"); +__KERNEL_RCSID(0, "$NetBSD: except.c,v 1.40 2002/01/12 20:02:15 bjh21 Exp $"); #include "opt_cputypes.h" #include "opt_ddb.h" #include "opt_ktrace.h" -#include "opt_syscall_debug.h" #include #include -#include #include #include #include @@ -103,155 +101,6 @@ swi_handler(struct trapframe *tf) (*(void (*)(struct trapframe *))(curproc->p_emul->e_syscall))(tf); } -void -syscall(struct trapframe *tf) -{ - struct proc *p; - vaddr_t pc; - int code, nargs, nregargs, nextreg, nstkargs; - const struct sysent *sy; - register_t args[8]; /* XXX just enough for mmap... */ - register_t rval[2], or15; - int error; - - /* Enable interrupts if they were enabled before the trap. */ - if ((tf->tf_r15 & R15_IRQ_DISABLE) == 0) - int_on(); - uvmexp.traps++; - uvmexp.syscalls++; - p = curproc; - if (p == NULL) - p = &proc0; - if ((tf->tf_r15 & R15_MODE) == R15_MODE_USR) - p->p_addr->u_pcb.pcb_tf = tf; - - if ((tf->tf_r15 & R15_MODE) != R15_MODE_USR) { -#ifdef DEBUG - printf("SWI:\n"); - printregs(tf); - printf("pc -> "); - disassemble(tf->tf_r15 & R15_PC); -#endif - panic("SWI in kernel mode"); - } - - pc = tf->tf_r15 & R15_PC; - -#ifdef DIAGNOSTIC - if ((*(u_int32_t *)pc & 0x0f000000) != 0x0f000000) { - disassemble(pc); - panic("SWI on non-SWI instruction"); - } -#endif - - /* Look up the system call and see if it's magic. */ - code = *(register_t *)pc & 0x00ffffff; - switch (code) { - case SYS_syscall: /* Indirect system call. First arg is new code */ - code = tf->tf_r0; - nregargs = 3; nextreg = 1; - break; - case SYS___syscall: /* As above, but quad_t arg */ - if (p->p_emul->e_sysent == sysent) { /* NetBSD emulation */ - code = tf->tf_r0; /* XXX assume little-endian */ - nregargs = 2; nextreg = 2; - break; - } - /* FALLTHROUGH */ - default: - nregargs = 4; nextreg = 0; - } - code &= (SYS_NSYSENT - 1); - sy = &p->p_emul->e_sysent[code]; - - nargs = sy->sy_argsize / sizeof(register_t); - nregargs = min(nregargs, nargs); - nstkargs = nargs - nregargs; - - if (nregargs > 0) - bcopy(&tf->tf_r0 + nextreg, args, - nregargs * sizeof(register_t)); - - if (nstkargs > 0) { - error = copyin((caddr_t)tf->tf_r13, args + nregargs, - nstkargs * sizeof(register_t)); - if (error) { -#ifdef SYSCALL_DEBUG - scdebug_call(p, code, (register_t *)args); -#endif - goto bad; - } - } - -#ifdef SYSCALL_DEBUG - scdebug_call(p, code, args); -#endif -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSCALL)) - ktrsyscall(p, code, nargs * sizeof(register_t), args); -#endif - - rval[0] = 0; - rval[1] = tf->tf_r1; - - /* Set return address */ - or15 = tf->tf_r15; - tf->tf_r15 += 4; - - error = sy->sy_call(p, args, rval); - - switch (error) { - case 0: - tf->tf_r0 = rval[0]; - tf->tf_r1 = rval[1]; - tf->tf_r15 &= ~R15_FLAG_C; - break; - case ERESTART: - tf->tf_r15 = or15; - break; - case EJUSTRETURN: - /* nothing to do */ - break; - default: - bad: - tf->tf_r0 = rval[0] = error; - tf->tf_r15 |= R15_FLAG_C; - break; - } -#ifdef SYSCALL_DEBUG - scdebug_ret(p, code, error, rval); -#endif - userret(p); -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) - ktrsysret(p, code, error, rval[0]); -#endif -} - -/* - * Return from fork(2) in the child. This is effectively the tail end of - * a normal successful syscall return. - */ -void -child_return(void *arg) -{ - struct proc *p = arg; - struct trapframe *tf; - - tf = p->p_addr->u_pcb.pcb_tf; - tf->tf_r0 = 0; - tf->tf_r15 &= ~R15_FLAG_C; - -#ifdef SYSCALL_DEBUG - scdebug_ret(p, SYS_fork /* XXX */, 0, &tf->tf_r0); -#endif - userret(p); -#ifdef KTRACE - if (KTRPOINT(p, KTR_SYSRET)) - ktrsysret(p, SYS_fork /* XXX */, 0, tf->tf_r0); -#endif -} - void prefetch_abort_handler(struct trapframe *tf) {