diff options
-rw-r--r-- | sys/arch/hppa/hppa/hpux_machdep.c | 151 | ||||
-rw-r--r-- | sys/arch/hppa/hppa/locore.S | 21 | ||||
-rw-r--r-- | sys/arch/hppa/hppa/machdep.c | 159 | ||||
-rw-r--r-- | sys/arch/hppa/include/hpux_machdep.h | 82 | ||||
-rw-r--r-- | sys/arch/hppa/include/pcb.h | 15 |
5 files changed, 414 insertions, 14 deletions
diff --git a/sys/arch/hppa/hppa/hpux_machdep.c b/sys/arch/hppa/hppa/hpux_machdep.c new file mode 100644 index 00000000000..6bd71ad4589 --- /dev/null +++ b/sys/arch/hppa/hppa/hpux_machdep.c @@ -0,0 +1,151 @@ +/* $OpenBSD: hpux_machdep.c,v 1.1 2005/03/26 20:04:37 mickey Exp $ */ + +/* + * Copyright (c) 2004 Michael Shalayeff + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/exec.h> +#include <sys/signalvar.h> + +#include <compat/hpux/hpux.h> +#include <compat/hpux/hpux_sig.h> +#include <compat/hpux/hpux_util.h> +#include <compat/hpux/hpux_syscallargs.h> + +#include <machine/cpufunc.h> +#include <machine/frame.h> + +int +hpux_cpu_sysconf_arch(void) +{ + extern int cpu_model_hpux; /* machdep.c */ + + return cpu_model_hpux; +} + +int +hpux_sys_getcontext(struct proc *p, void *v, register_t *retval) +{ + struct hpux_sys_getcontext_args *uap = v; + int len = SCARG(uap, len); + + if (len <= 0) + return (EINVAL); + + if (len > 4) + len = 4; + + if (!copyout("FPU", SCARG(uap, buf), len)) + *retval = len; + + return (0); +} + +void +hpux_setregs(struct proc *p, struct exec_package *pack, u_long stack, + register_t *retval) +{ + extern int cpu_model_hpux; /* machdep.c */ + extern paddr_t fpu_curpcb; /* from locore.S */ + extern u_int fpu_version; /* from machdep.c */ + struct ps_strings arginfo; /* XXX copy back in from the stack */ + struct hpux_keybits { + int kb_cpuver; + int kb_fpustat; + int kb_nbits; + int kb_bits[2]; + } hpux_keybits; + struct trapframe *tf = p->p_md.md_regs; + struct pcb *pcb = &p->p_addr->u_pcb; + register_t zero; + + if (copyin((char *)PS_STRINGS, &arginfo, sizeof(arginfo))) + sigexit(p, SIGILL); + + stack = (stack + 0x1f) & ~0x1f; + hpux_keybits.kb_cpuver = cpu_model_hpux; + hpux_keybits.kb_fpustat = fpu_version; + hpux_keybits.kb_nbits = 1; + hpux_keybits.kb_bits[0] = 0; /* TODO report half-word insns */ + hpux_keybits.kb_bits[1] = -1; + if (copyout(&hpux_keybits, (void *)stack, sizeof(hpux_keybits))) + sigexit(p, SIGILL); + + tf->tf_flags = TFF_SYS|TFF_LAST; + tf->tf_iioq_tail = 4 + + (tf->tf_iioq_head = pack->ep_entry | HPPA_PC_PRIV_USER); + tf->tf_rp = 0; + tf->tf_arg0 = (register_t)arginfo.ps_nargvstr; + tf->tf_arg1 = (register_t)arginfo.ps_argvstr; + tf->tf_arg2 = (register_t)arginfo.ps_envstr; + tf->tf_arg3 = stack; /* keybits */ + stack += sizeof(hpux_keybits); + + /* setup terminal stack frame */ + stack = (stack + 0x1f) & ~0x1f; + tf->tf_r3 = stack; + tf->tf_sp = stack += HPPA_FRAME_SIZE; + zero = 0; + copyout(&zero, (caddr_t)(stack - HPPA_FRAME_SIZE), sizeof(register_t)); + copyout(&zero, (caddr_t)(stack + HPPA_FRAME_CRP), sizeof(register_t)); + + /* reset any of the pending FPU exceptions */ + pcb->pcb_fpregs[0] = ((u_int64_t)HPPA_FPU_INIT) << 32; + pcb->pcb_fpregs[1] = 0; + pcb->pcb_fpregs[2] = 0; + pcb->pcb_fpregs[3] = 0; + fdcache(HPPA_SID_KERNEL, (vaddr_t)pcb->pcb_fpregs, 8 * 4); + if (tf->tf_cr30 == fpu_curpcb) { + fpu_curpcb = 0; + /* force an fpu ctxsw, we won't be hugged by the cpu_switch */ + mtctl(0, CR_CCR); + } + retval[1] = 0; +} + +int +hpux_sigsetreturn(struct proc *p, void *v, register_t *retval) +{ + struct hpux_sigsetreturn_args /* { + syscallarg(caddr_t) addr; + syscallarg(int) cookie; + syscallarg(int) len; + } */ *uap = v; + struct pcb *pcb = &p->p_addr->u_pcb; + + /* XXX should fail on second call? */ + + pcb->pcb_sigreturn = SCARG(uap, addr); + pcb->pcb_srcookie = SCARG(uap, cookie); + pcb->pcb_sclen = SCARG(uap, len); + +printf("hpux_sigsetreturn(%p, %x, %d)\n", SCARG(uap, addr), SCARG(uap, cookie), SCARG(uap, len)); + + retval[0] = 0; + return (0); +} diff --git a/sys/arch/hppa/hppa/locore.S b/sys/arch/hppa/hppa/locore.S index 7e40e593286..2a9b661ca49 100644 --- a/sys/arch/hppa/hppa/locore.S +++ b/sys/arch/hppa/hppa/locore.S @@ -1,4 +1,4 @@ -/* $OpenBSD: locore.S,v 1.146 2005/03/16 13:20:43 mickey Exp $ */ +/* $OpenBSD: locore.S,v 1.147 2005/03/26 20:04:37 mickey Exp $ */ /* * Copyright (c) 1998-2004 Michael Shalayeff @@ -1095,7 +1095,7 @@ $fpusw_emu nop $fpusw_set - /* enable coprocessor */ + /* enable coprocessor XXX */ depi 3, 25, 2, r1 mtctl r1, ccr @@ -3105,6 +3105,21 @@ sigcode_call ALTENTRY(esigcode) EXIT(sigcode) +#ifdef COMPAT_HPUX +ENTRY(hpux_sigcode,0) + bb,>=,n arg3, 30, hpux_sigcode_call + dep r0, 31, 2, arg3 + ldw 4(arg3), r19 + ldw 0(arg3), arg3 +hpux_sigcode_call + .call + ble 0(sr0, arg3) + nop /* rp has already been set */ +ALTENTRY(hpux_esigcode) +EXIT(hpux_sigcode) +#endif /* COMPAT_HPUX */ + + #ifdef COMPAT_LINUX ENTRY(linux_sigcode,0) @@ -3112,7 +3127,7 @@ ENTRY(linux_sigcode,0) bv 0(rp) nop ALTENTRY(linux_esigcode) -EXIT(linix_sigcode) +EXIT(linux_sigcode) #endif /* COMPAT_LINUX */ .end diff --git a/sys/arch/hppa/hppa/machdep.c b/sys/arch/hppa/hppa/machdep.c index 835c90dfd56..6bbe931bb47 100644 --- a/sys/arch/hppa/hppa/machdep.c +++ b/sys/arch/hppa/hppa/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.141 2005/02/24 17:20:53 mickey Exp $ */ +/* $OpenBSD: machdep.c,v 1.142 2005/03/26 20:04:37 mickey Exp $ */ /* * Copyright (c) 1999-2003 Michael Shalayeff @@ -70,6 +70,10 @@ #ifdef COMPAT_HPUX #include <compat/hpux/hpux.h> +#include <compat/hpux/hpux_sig.h> +#include <compat/hpux/hpux_util.h> +#include <compat/hpux/hpux_syscallargs.h> +#include <machine/hpux_machdep.h> #endif #ifdef DDB @@ -1269,7 +1273,7 @@ sendsig(catcher, sig, mask, code, type, val) struct sigacts *psp = p->p_sigacts; struct sigcontext ksc; siginfo_t ksi; - register_t scp, sip, zero; + register_t scp, sip; int sss; #ifdef DEBUG @@ -1307,7 +1311,7 @@ sendsig(catcher, sig, mask, code, type, val) #ifdef DEBUG if ((tf->tf_iioq_head & ~PAGE_MASK) == SYSCALLGATE) - printf("sendsig: interrupted syscall at 0x%x:0x%x, flags %b\n", + printf("sendsig: interrupted syscall at 0x%x:0x%x flags %b\n", tf->tf_iioq_head, tf->tf_iioq_tail, tf->tf_ipsw, PSL_BITS); #endif @@ -1377,14 +1381,14 @@ sendsig(catcher, sig, mask, code, type, val) sigexit(p, SIGILL); } - zero = 0; - if (copyout(&zero, (caddr_t)scp + sss - HPPA_FRAME_SIZE, + if (copyout(&tf->tf_r3, (caddr_t)(tf->tf_sp - HPPA_FRAME_SIZE), sizeof(register_t))) sigexit(p, SIGILL); + tf->tf_r3 = tf->tf_sp - HPPA_FRAME_SIZE; #ifdef DEBUG if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) - printf("sendsig(%d): pc 0x%x, catcher 0x%x\n", p->p_pid, + printf("sendsig(%d): pc 0x%x catcher 0x%x\n", p->p_pid, tf->tf_iioq_head, tf->tf_arg3); #endif } @@ -1477,6 +1481,149 @@ sys_sigreturn(p, v, retval) return (EJUSTRETURN); } +#ifdef COMPAT_HPUX +void +hpux_sendsig(sig_t catcher, int sig, int mask, u_long code, int type, + union sigval val) +{ + extern paddr_t fpu_curpcb; /* from locore.S */ + extern u_int fpu_enable; + struct proc *p = curproc; + struct pcb *pcb = &p->p_addr->u_pcb; + struct trapframe *tf = p->p_md.md_regs; + struct sigacts *psp = p->p_sigacts; + struct hpux_sigcontext hsc; + int sss; + register_t scp; + +#ifdef DEBUG + if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) + printf("hpux_sendsig: %s[%d] sig %d catcher %p\n", + p->p_comm, p->p_pid, sig, catcher); +#endif + /* flush the FPU ctx first */ + if (tf->tf_cr30 == fpu_curpcb) { + mtctl(fpu_enable, CR_CCR); + fpu_save(fpu_curpcb); + fpu_curpcb = 0; + mtctl(0, CR_CCR); + } + + bzero(&hsc, sizeof hsc); + hsc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; + hsc.sc_omask = mask; + /* sc_scact ??? */ + + hsc.sc_ret0 = tf->tf_ret0; + hsc.sc_ret1 = tf->tf_ret1; + + hsc.sc_frame[0] = hsc.sc_args[0] = sig; + hsc.sc_frame[1] = hsc.sc_args[1] = NULL; + hsc.sc_frame[2] = hsc.sc_args[2] = scp; + + /* + * Allocate space for the signal handler context. + */ + if ((psp->ps_flags & SAS_ALTSTACK) && !hsc.sc_onstack && + (psp->ps_sigonstack & sigmask(sig))) { + scp = (register_t)psp->ps_sigstk.ss_sp; + psp->ps_sigstk.ss_flags |= SS_ONSTACK; + } else + scp = (tf->tf_sp + 63) & ~63; + + sss = (sizeof(hsc) + 63) & ~63; + + if (tf->tf_flags & TFF_SYS) { + hsc.sc_tfflags = HPUX_TFF_SYSCALL; + hsc.sc_syscall = tf->tf_t1; + } else if (tf->tf_flags & TFF_INTR) + hsc.sc_tfflags = HPUX_TFF_INTR; + else + hsc.sc_tfflags = HPUX_TFF_TRAP; + + hsc.sc_regs[0] = tf->tf_r1; + hsc.sc_regs[1] = tf->tf_rp; + hsc.sc_regs[2] = tf->tf_r3; + hsc.sc_regs[3] = tf->tf_r4; + hsc.sc_regs[4] = tf->tf_r5; + hsc.sc_regs[5] = tf->tf_r6; + hsc.sc_regs[6] = tf->tf_r7; + hsc.sc_regs[7] = tf->tf_r8; + hsc.sc_regs[8] = tf->tf_r9; + hsc.sc_regs[9] = tf->tf_r10; + hsc.sc_regs[10] = tf->tf_r11; + hsc.sc_regs[11] = tf->tf_r12; + hsc.sc_regs[12] = tf->tf_r13; + hsc.sc_regs[13] = tf->tf_r14; + hsc.sc_regs[14] = tf->tf_r15; + hsc.sc_regs[15] = tf->tf_r16; + hsc.sc_regs[16] = tf->tf_r17; + hsc.sc_regs[17] = tf->tf_r18; + hsc.sc_regs[18] = tf->tf_t4; + hsc.sc_regs[19] = tf->tf_t3; + hsc.sc_regs[20] = tf->tf_t2; + hsc.sc_regs[21] = tf->tf_t1; + hsc.sc_regs[22] = tf->tf_arg3; + hsc.sc_regs[23] = tf->tf_arg2; + hsc.sc_regs[24] = tf->tf_arg1; + hsc.sc_regs[25] = tf->tf_arg0; + hsc.sc_regs[26] = tf->tf_dp; + hsc.sc_regs[27] = tf->tf_ret0; + hsc.sc_regs[28] = tf->tf_ret1; + hsc.sc_regs[29] = tf->tf_sp; + hsc.sc_regs[30] = tf->tf_r31; + hsc.sc_regs[31] = tf->tf_sar; + hsc.sc_regs[32] = tf->tf_iioq_head; + hsc.sc_regs[33] = tf->tf_iisq_head; + hsc.sc_regs[34] = tf->tf_iioq_tail; + hsc.sc_regs[35] = tf->tf_iisq_tail; + hsc.sc_regs[35] = tf->tf_eiem; + hsc.sc_regs[36] = tf->tf_iir; + hsc.sc_regs[37] = tf->tf_isr; + hsc.sc_regs[38] = tf->tf_ior; + hsc.sc_regs[39] = tf->tf_ipsw; + hsc.sc_regs[40] = 0; + hsc.sc_regs[41] = tf->tf_sr4; + hsc.sc_regs[42] = tf->tf_sr0; + hsc.sc_regs[43] = tf->tf_sr1; + hsc.sc_regs[44] = tf->tf_sr2; + hsc.sc_regs[45] = tf->tf_sr3; + hsc.sc_regs[46] = tf->tf_sr5; + hsc.sc_regs[47] = tf->tf_sr6; + hsc.sc_regs[48] = tf->tf_sr7; + hsc.sc_regs[49] = tf->tf_rctr; + hsc.sc_regs[50] = tf->tf_pidr1; + hsc.sc_regs[51] = tf->tf_pidr2; + hsc.sc_regs[52] = tf->tf_ccr; + hsc.sc_regs[53] = tf->tf_pidr3; + hsc.sc_regs[54] = tf->tf_pidr4; + /* hsc.sc_regs[55] = tf->tf_cr24; */ + hsc.sc_regs[56] = tf->tf_vtop; + /* hsc.sc_regs[57] = tf->tf_cr26; */ + /* hsc.sc_regs[58] = tf->tf_cr27; */ + hsc.sc_regs[59] = 0; + hsc.sc_regs[60] = 0; + bcopy(p->p_addr->u_pcb.pcb_fpregs, hsc.sc_fpregs, + sizeof(hsc.sc_fpregs)); + + tf->tf_rp = (register_t)pcb->pcb_sigreturn; + tf->tf_arg3 = (register_t)catcher; + tf->tf_sp = scp + sss; + tf->tf_ipsw &= ~(PSL_N|PSL_B); + tf->tf_iioq_head = HPPA_PC_PRIV_USER | p->p_sigcode; + tf->tf_iioq_tail = tf->tf_iioq_head + 4; + + if (copyout(&hsc, (void *)scp, sizeof(hsc))) + sigexit(p, SIGILL); + +#ifdef DEBUG + if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid)) + printf("sendsig(%d): pc 0x%x rp 0x%x\n", p->p_pid, + tf->tf_iioq_head, tf->tf_rp); +#endif +} +#endif + /* * machine dependent system variables. */ diff --git a/sys/arch/hppa/include/hpux_machdep.h b/sys/arch/hppa/include/hpux_machdep.h new file mode 100644 index 00000000000..4e16c537f06 --- /dev/null +++ b/sys/arch/hppa/include/hpux_machdep.h @@ -0,0 +1,82 @@ +/* $OpenBSD: hpux_machdep.h,v 1.1 2005/03/26 20:04:37 mickey Exp $ */ + +/* + * Copyright (c) 2004 Michael Shalayeff + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _HPPA_HPUX_MACHDEP_H_ +#define _HPPA_HPUX_MACHDEP_H_ + +struct hpux_sigcontext { + int sc_syscall; + int sc_onstack; + int sc_omask; + char sc_scact; /* action to take on return from a syscall */ + char sc_eosys; + u_short sc_err; + register_t sc_ret0; + register_t sc_ret1; + register_t sc_args[4]; /* args for the handler */ + + /* HP/UX trapframe kinda thing */ + int sc_tfflags; + register_t sc_regs[62]; + int sc_pad; + int sc_fpregs[64]; + int sc_resv[32]; + +#if 0 + int sc_spare[8]; + u_int sc_flags; + u_int sc_ctxptr; + hpux_sigset_t sc_sigmask; + hpux_stack_t sc_stack; + hpux_siginfo_t sc_si; +#endif + + /* call frame follows */ + register_t sc_frame[4+8]; +}; + +#define HPUX_SIGCONTEXT_GETCTX 0x01 /* created by getcontext() */ + +/* trapframe flags */ +#define HPUX_TFF_TRAP 0x0001 +#define HPUX_TFF_SYSCALL 0x0002 +#define HPUX_TFF_INTR 0x0004 +#define HPUX_TFF_ARGSVALID 0x0010 +#define HPUX_TFF_WIDEREGS 0x0040 + +int hpux_cpu_makecmds(struct proc *p, struct exec_package *epp); +int hpux_cpu_vmcmd(struct proc *p, struct exec_vmcmd *ev); +int hpux_cpu_sysconf_arch(void); +int hpux_sys_getcontext(struct proc *p, void *v, register_t *retval); +int hpux_to_bsd_uoff(int *off, int *isps, struct proc *p); +void hpux_setregs(struct proc *p, struct exec_package *pack, + u_long stack, register_t *retval); +void hpux_sendsig(sig_t catcher, int sig, int mask, u_long code, + int type, union sigval val); + +#endif /* _HPPA_HPUX_MACHDEP_H_ */ diff --git a/sys/arch/hppa/include/pcb.h b/sys/arch/hppa/include/pcb.h index 16da7dd0053..612c4231586 100644 --- a/sys/arch/hppa/include/pcb.h +++ b/sys/arch/hppa/include/pcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pcb.h,v 1.9 2004/06/08 22:00:25 mickey Exp $ */ +/* $OpenBSD: pcb.h,v 1.10 2005/03/26 20:04:37 mickey Exp $ */ /* * Copyright (c) 1999-2004 Michael Shalayeff @@ -34,10 +34,15 @@ struct pcb { u_int64_t pcb_fpregs[HPPA_NFPREGS+1]; /* not in the trapframe */ - u_int pcb_onfault; /* SW copy fault handler */ - pa_space_t pcb_space; /* copy pmap_space, for asm's sake */ - vaddr_t pcb_uva; /* KVA for U-area */ - u_int pcb_ksp; /* kernel sp for ctxsw */ + u_int pcb_onfault; /* SW copy fault handler */ + pa_space_t pcb_space; /* copy pmap_space, for asm's sake */ + vaddr_t pcb_uva; /* KVA for U-area */ + u_int pcb_ksp; /* kernel sp for ctxsw */ + + /* things used for hpux emulation */ + void *pcb_sigreturn; + u_int pcb_srcookie; + u_int pcb_sclen; }; struct md_coredump { |