diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 2002-09-10 22:43:50 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 2002-09-10 22:43:50 +0000 |
commit | c8869f6570b73a73d8ac94a11ae4dc1fd8fc3742 (patch) | |
tree | b1101e62589dbd28c582f4d485a12618b28c7725 /sys | |
parent | cc58655fc1916c594234ef0b59340ebfe3aee32e (diff) |
copy syscall args in the syscall() based on the
amount given in the sysent.
deal w/ the words swappage phenomena due to reverse
long word storage on the stack and that being
reverse copied by words yielding long word being word swapped.
do it only for syscall(2) and __syscall(2) since that's how those
w/ long word args syscalls get used (for proper alignment).
discussed and ideas from: deraadt@, drahn@ and fredette@
note: this might be a good point for a regress.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/hppa/hppa/locore.S | 31 | ||||
-rw-r--r-- | sys/arch/hppa/hppa/trap.c | 121 |
2 files changed, 94 insertions, 58 deletions
diff --git a/sys/arch/hppa/hppa/locore.S b/sys/arch/hppa/hppa/locore.S index d407bc5abcc..d723aaf9021 100644 --- a/sys/arch/hppa/hppa/locore.S +++ b/sys/arch/hppa/hppa/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.85 2002/09/10 21:20:23 mickey Exp $ */ +/* $OpenBSD: locore.S,v 1.86 2002/09/10 22:43:49 mickey Exp $ */ /* * Copyright (c) 1998-2002 Michael Shalayeff @@ -573,7 +573,6 @@ $syscall stw t4, TF_R19 -TRAPFRAME_SIZEOF(sr1, t3) /* t4 for vfork() */ stw t1, TF_R22 -TRAPFRAME_SIZEOF(sr1, t3) /* syscall # */ stw sp, TF_R30 -TRAPFRAME_SIZEOF(sr1, t3) /* user stack */ - copy sp, t4 ldo HPPA_FRAME_SIZE+HPPA_FRAME_MAXARGS(t3), sp ldil L%kpsw, t1 ldw R%kpsw(sr1, t1), t1 @@ -623,34 +622,6 @@ $syscall stw r0, HPPA_FRAME_CRP(sr1, sp) /* - * Copy Arguments - * unfortunately mmap() under bsd requires 7 words; - * linux is confined to 5, and hpux to 6. - * assuming the `long' syscall it gives us the maximum - * 9 words, which very much overkill for an average of 3. - * we keep it at 10, since bundling will keep it - * at the same speed as 9 anyway. - * - * TODO: setup the onfault handler - */ - stw arg0, 1*4(sr1, t3) /* XXX can use ,bc */ - stw arg1, 2*4(sr1, t3) - stw arg2, 3*4(sr1, t3) - stw arg3, 4*4(sr1, t3) - ldw HPPA_FRAME_ARG( 4)(sr2, t4), arg0 - ldw HPPA_FRAME_ARG( 5)(sr2, t4), arg1 - ldw HPPA_FRAME_ARG( 6)(sr2, t4), arg2 - ldw HPPA_FRAME_ARG( 7)(sr2, t4), arg3 - stw arg0, 5*4(sr1, t3) - stw arg1, 6*4(sr1, t3) - stw arg2, 7*4(sr1, t3) - stw arg3, 8*4(sr1, t3) - ldw HPPA_FRAME_ARG( 8)(sr2, t4), arg0 - ldw HPPA_FRAME_ARG( 9)(sr2, t4), arg1 - stw arg0, 9*4(sr1, t3) - stw arg1,10*4(sr1, t3) - - /* * Save the rest of the CPU context */ mfsp sr0, arg0 /* use ,bc */ diff --git a/sys/arch/hppa/hppa/trap.c b/sys/arch/hppa/hppa/trap.c index e51c21c8817..340abbff9bc 100644 --- a/sys/arch/hppa/hppa/trap.c +++ b/sys/arch/hppa/hppa/trap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trap.c,v 1.46 2002/08/13 07:00:50 mickey Exp $ */ +/* $OpenBSD: trap.c,v 1.47 2002/09/10 22:43:49 mickey Exp $ */ /* * Copyright (c) 1998-2001 Michael Shalayeff @@ -91,7 +91,7 @@ int trap_types = sizeof(trap_type)/sizeof(trap_type[0]); int want_resched, astpending; -void syscall(struct trapframe *frame, int *args); +void syscall(struct trapframe *frame); static __inline void userret (struct proc *p, register_t pc, u_quad_t oticks) @@ -354,6 +354,10 @@ trap(type, frame) trapsignal(p, SIGSEGV, vftype, SEGV_MAPERR, sv); } else { if (p && p->p_addr->u_pcb.pcb_onfault) { +#if 0 +if (kdb_trap (type, va, frame)) + return; +#endif pcbp = &p->p_addr->u_pcb; frame->tf_iioq_tail = 4 + (frame->tf_iioq_head = @@ -361,15 +365,16 @@ trap(type, frame) #ifdef DDB frame->tf_iir = 0; #endif - break; - } + } else { #if 0 if (kdb_trap (type, va, frame)) return; #else - panic("trap: uvm_fault(%p, %x, %d, %d): %d", - map, va, 0, vftype, ret); + panic("trap: " + "uvm_fault(%p, %x, %d, %d): %d", + map, va, 0, vftype, ret); #endif + } } } break; @@ -449,50 +454,107 @@ child_return(arg) #endif } + /* * call actual syscall routine - * from the low-level syscall handler: - * - all HPPA_FRAME_NARGS syscall's arguments supposed to be copied onto - * our stack, this wins compared to copyin just needed amount anyway - * - register args are copied onto stack too */ void -syscall(frame, args) +syscall(frame) struct trapframe *frame; - int *args; { - register struct proc *p; + register struct proc *p = curproc; register const struct sysent *callp; - int nsys, code, argsize, error; - int rval[2]; + int nsys, code, argsize, argoff, oerror, error; + int args[8], rval[2]; uvmexp.syscalls++; if (!USERMODE(frame->tf_iioq_head)) panic("syscall"); - p = curproc; p->p_md.md_regs = frame; nsys = p->p_emul->e_nsysent; callp = p->p_emul->e_sysent; - code = frame->tf_t1; - switch (code) { + + argoff = 4; + switch (code = frame->tf_t1) { case SYS_syscall: - code = *args; - args += 1; + code = frame->tf_arg0; + args[0] = frame->tf_arg1; + args[1] = frame->tf_arg2; + args[2] = frame->tf_arg3; + argoff = 3; break; case SYS___syscall: if (callp != sysent) break; - code = *args; - args += 2; + /* + * this works, because quads get magically swapped + * due to the args being layed backwards on the stack + * and then copied in words + */ + code = frame->tf_arg0; + args[0] = frame->tf_arg2; + args[1] = frame->tf_arg3; + argoff = 2; + break; + default: + args[0] = frame->tf_arg0; + args[1] = frame->tf_arg1; + args[2] = frame->tf_arg2; + args[3] = frame->tf_arg3; + break; } if (code < 0 || code >= nsys) callp += p->p_emul->e_nosys; /* bad syscall # */ else callp += code; - argsize = callp->sy_argsize; + + oerror = error = 0; + if ((argsize = callp->sy_argsize)) { + int i; + + for (i = 0, argsize -= argoff * 4; + argsize > 0; i++, argsize -= 4) { + error = copyin((void *)(frame->tf_sp + + HPPA_FRAME_ARG(i + 4)), args + i + argoff, 4); + + if (error) + break; + } + + /* + * coming from syscall() or __syscall we must be + * having one of those w/ a 64 bit arguments, + * which needs a word swap due to the order + * of the arguments on the stack. + * this assumes that none of 'em are called + * by their normal syscall number, maybe a regress + * test should be used, to whatch the behaviour. + */ + if (!error && argoff < 4) { + int t; + + i = 0; + switch (code) { + case SYS_lseek: + case SYS_truncate: + case SYS_ftruncate: i = 2; break; + case SYS_preadv: + case SYS_pwritev: + case SYS_pread: + case SYS_pwrite: i = 4; break; + case SYS_mmap: i = 6; break; + } + + if (i) { + t = args[i]; + args[i] = args[i + 1]; + args[i + 1] = t; + } + } + } #ifdef SYSCALL_DEBUG scdebug_call(p, code, args); @@ -501,15 +563,17 @@ syscall(frame, args) if (KTRPOINT(p, KTR_SYSCALL)) ktrsyscall(p, code, argsize, args); #endif + if (error) + goto bad; rval[0] = 0; - rval[1] = 0; + rval[1] = frame->tf_ret1; #if NSYSTRACE > 0 if (ISSET(p->p_flag, P_SYSTRACE)) - error = systrace_redirect(code, p, args, rval); + oerror = error = systrace_redirect(code, p, args, rval); else #endif - error = (*callp->sy_call)(p, args, rval); + oerror = error = (*callp->sy_call)(p, args, rval); switch (error) { case 0: p = curproc; /* changes on exec() */ @@ -526,17 +590,18 @@ syscall(frame, args) p = curproc; break; default: + bad: if (p->p_emul->e_errno) error = p->p_emul->e_errno[error]; frame->tf_t1 = error; break; } #ifdef SYSCALL_DEBUG - scdebug_ret(p, code, error, rval); + scdebug_ret(p, code, oerror, rval); #endif userret(p, frame->tf_iioq_head, 0); #ifdef KTRACE if (KTRPOINT(p, KTR_SYSRET)) - ktrsysret(p, code, error, rval[0]); + ktrsysret(p, code, oerror, rval[0]); #endif } |