summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2002-09-10 22:43:50 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2002-09-10 22:43:50 +0000
commitc8869f6570b73a73d8ac94a11ae4dc1fd8fc3742 (patch)
treeb1101e62589dbd28c582f4d485a12618b28c7725 /sys
parentcc58655fc1916c594234ef0b59340ebfe3aee32e (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.S31
-rw-r--r--sys/arch/hppa/hppa/trap.c121
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
}