diff options
-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 } |