summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
}