Module Name: src Committed By: matt Date: Sat Sep 12 17:37:00 UTC 2009
Modified Files: src/sys/arch/mips/mips [matt-nb5-mips64]: mips_machdep.c Added Files: src/sys/arch/mips/mips [matt-nb5-mips64]: netbsd32_machdep.c Log Message: Add COMPAT_NETBSD32 support. To generate a diff of this commit: cvs rdiff -u -r1.205.4.1.2.1.2.9 -r1.205.4.1.2.1.2.10 \ src/sys/arch/mips/mips/mips_machdep.c cvs rdiff -u -r0 -r1.1.2.1 src/sys/arch/mips/mips/netbsd32_machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/mips/mips/mips_machdep.c diff -u src/sys/arch/mips/mips/mips_machdep.c:1.205.4.1.2.1.2.9 src/sys/arch/mips/mips/mips_machdep.c:1.205.4.1.2.1.2.10 --- src/sys/arch/mips/mips/mips_machdep.c:1.205.4.1.2.1.2.9 Sat Sep 12 00:03:27 2009 +++ src/sys/arch/mips/mips/mips_machdep.c Sat Sep 12 17:37:00 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: mips_machdep.c,v 1.205.4.1.2.1.2.9 2009/09/12 00:03:27 matt Exp $ */ +/* $NetBSD: mips_machdep.c,v 1.205.4.1.2.1.2.10 2009/09/12 17:37:00 matt Exp $ */ /* * Copyright 2002 Wasabi Systems, Inc. @@ -112,9 +112,10 @@ #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ -__KERNEL_RCSID(0, "$NetBSD: mips_machdep.c,v 1.205.4.1.2.1.2.9 2009/09/12 00:03:27 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mips_machdep.c,v 1.205.4.1.2.1.2.10 2009/09/12 17:37:00 matt Exp $"); #include "opt_cputype.h" +#include "opt_compat_netbsd32.h" #include <sys/param.h> #include <sys/systm.h> @@ -137,8 +138,12 @@ #include <sys/cpu.h> #include <sys/ucontext.h> -#include <machine/kcore.h> -#include <machine/cpu.h> +#include <mips/kcore.h> +#include <mips/cpu.h> + +#ifdef COMPAT_NETBSD32 +#include <compat/netbsd32/netbsd32.h> +#endif #include <uvm/uvm_extern.h> @@ -1847,23 +1852,43 @@ * Start a new LWP */ void -startlwp(arg) - void *arg; +startlwp(void *arg) { - int err; ucontext_t *uc = arg; - struct lwp *l = curlwp; + int err; - err = cpu_setmcontext(l, &uc->uc_mcontext, uc->uc_flags); + err = cpu_setmcontext(curlwp, &uc->uc_mcontext, uc->uc_flags); #if DIAGNOSTIC if (err) { - printf("Error %d from cpu_setmcontext.", err); + printf("%s: Error %d from cpu_setmcontext", __func__, err); } #endif pool_put(&lwp_uc_pool, uc); - userret(l); + userret(curlwp); +} + +#ifdef COMPAT_NETBSD32 +/* + * Start a new LWP + */ +void +startlwp32(void *arg) +{ + ucontext32_t *uc = arg; + int err; + + err = cpu_setmcontext32(curlwp, &uc->uc_mcontext, uc->uc_flags); +#if DIAGNOSTIC + if (err) { + printf("%s: Error %d from cpu_setmcontext32", __func__, err); + } +#endif + pool_put(&lwp_uc_pool, uc); + + userret(curlwp); } +#endif /* COMPAT_NETBSD32 */ /* * XXX This is a terrible name. @@ -1878,8 +1903,13 @@ cpu_upcall(struct lwp *l, int type, int nevents, int ninterrupted, void *sas, void *ap, void *sp, sa_upcall_t upcall) { - struct saframe *sf, frame; struct frame *f = l->l_md.md_regs; + struct saframe frame; +#ifdef COMPAT_NETBSD32 + struct saframe32 frame32; +#endif + void *ksf, *usf; + size_t sfsz; #if 0 /* First 4 args in regs (see below). */ frame.sa_type = type; @@ -1887,11 +1917,29 @@ frame.sa_events = nevents; frame.sa_interrupted = ninterrupted; #endif - frame.sa_arg = ap; - frame.sa_upcall = upcall; +#ifdef COMPAT_NETBSD32 + switch (l->l_proc->p_md.md_abi) { + case _MIPS_BSD_API_O32: + case _MIPS_BSD_API_N32: + NETBSD32PTR32(frame32.sa_arg, ap); + NETBSD32PTR32(frame32.sa_upcall, upcall); + ksf = &frame32; + usf = (struct saframe32 *)sp - 1; + sfsz = sizeof(frame32); + break; + default: +#endif + frame.sa_arg = ap; + frame.sa_upcall = upcall; + ksf = &frame; + usf = (struct saframe *)sp - 1; + sfsz = sizeof(frame); +#ifdef COMPAT_NETBSD32 + break; + } +#endif - sf = (struct saframe *)sp - 1; - if (copyout(&frame, sf, sizeof(frame)) != 0) { + if (copyout(ksf, usf, sfsz) != 0) { /* Copying onto the stack didn't work. Die. */ mutex_enter(l->l_proc->p_lock); sigexit(l, SIGILL); @@ -1899,7 +1947,7 @@ } f->f_regs[_R_PC] = (intptr_t)upcall; - f->f_regs[_R_SP] = (intptr_t)sf; + f->f_regs[_R_SP] = (intptr_t)usf; f->f_regs[_R_A0] = type; f->f_regs[_R_A1] = (intptr_t)sas; f->f_regs[_R_A2] = nevents; @@ -1911,10 +1959,7 @@ void -cpu_getmcontext(l, mcp, flags) - struct lwp *l; - mcontext_t *mcp; - unsigned int *flags; +cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags) { const struct frame *f = l->l_md.md_regs; __greg_t *gr = mcp->__gregs; @@ -1937,6 +1982,7 @@ /* Save floating point register context, if any. */ if (l->l_md.md_flags & MDP_FPUSED) { + size_t fplen; /* * If this process is the current FP owner, dump its * context to the PCB first. @@ -1948,23 +1994,26 @@ * The PCB FP regs struct includes the FP CSR, so use the * size of __fpregs.__fp_r when copying. */ - memcpy(&mcp->__fpregs.__fp_r, - &l->l_addr->u_pcb.pcb_fpregs.r_regs, - sizeof(mcp->__fpregs.__fp_r)); - mcp->__fpregs.__fp_csr = l->l_addr->u_pcb.pcb_fpregs.r_regs[32]; +#if !defined(__mips_o32) + if (_MIPS_SIM_NEWABI_P(l->l_proc->p_md.md_abi)) { + fplen = sizeof(struct fpreg); + } else { +#endif + fplen = sizeof(struct fpreg_oabi); +#if !defined(__mips_o32) + } +#endif + memcpy(&mcp->__fpregs, &l->l_addr->u_pcb.pcb_fpregs, fplen); *flags |= _UC_FPU; } } int -cpu_setmcontext(l, mcp, flags) - struct lwp *l; - const mcontext_t *mcp; - unsigned int flags; +cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) { struct frame *f = l->l_md.md_regs; - const __greg_t *gr = mcp->__gregs; struct proc *p = l->l_proc; + const __greg_t *gr = mcp->__gregs; /* Restore register context, if any. */ if (flags & _UC_CPU) { @@ -1982,17 +2031,25 @@ /* Restore floating point register context, if any. */ if (flags & _UC_FPU) { + size_t fplen; /* Disable the FPU to fault in FP registers. */ f->f_regs[_R_SR] &= ~MIPS_SR_COP_1_BIT; fpcurlwp = &lwp0; +#if !defined(__mips_o32) + if (_MIPS_SIM_NEWABI_P(l->l_proc->p_md.md_abi)) { + fplen = sizeof(struct fpreg); + } else { +#endif + fplen = sizeof(struct fpreg_oabi); +#if !defined(__mips_o32) + } +#endif /* * The PCB FP regs struct includes the FP CSR, so use the - * size of __fpregs.__fp_r when copying. + * proper size of fpreg when copying. */ - memcpy(&l->l_addr->u_pcb.pcb_fpregs.r_regs, - &mcp->__fpregs.__fp_r, sizeof(mcp->__fpregs.__fp_r)); - l->l_addr->u_pcb.pcb_fpregs.r_regs[32] = mcp->__fpregs.__fp_csr; + memcpy(&l->l_addr->u_pcb.pcb_fpregs, &mcp->__fpregs, fplen); } mutex_enter(p->p_lock); Added files: Index: src/sys/arch/mips/mips/netbsd32_machdep.c diff -u /dev/null src/sys/arch/mips/mips/netbsd32_machdep.c:1.1.2.1 --- /dev/null Sat Sep 12 17:37:00 2009 +++ src/sys/arch/mips/mips/netbsd32_machdep.c Sat Sep 12 17:37:00 2009 @@ -0,0 +1,312 @@ +/* $NetBSD: netbsd32_machdep.c,v 1.1.2.1 2009/09/12 17:37:00 matt Exp $ */ + +/*- + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Matt Thomas <m...@3am-software.com>. + * + * 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``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 FOUNDATION OR CONTRIBUTORS + * 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 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/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.1.2.1 2009/09/12 17:37:00 matt Exp $"); + +#include "opt_compat_netbsd.h" +#include "opt_sa.h" +#include "opt_coredump.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ioctl.h> +#include <sys/exec.h> +#include <sys/core.h> +#include <sys/file.h> +#include <sys/time.h> +#include <sys/proc.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/buf.h> +#include <sys/signal.h> +#include <sys/signalvar.h> +#include <sys/mount.h> +#include <sys/user.h> +#include <sys/syscallargs.h> + +#include <compat/netbsd32/netbsd32.h> +#include <compat/netbsd32/netbsd32_exec.h> +#include <compat/netbsd32/netbsd32_syscallargs.h> + +#include <mips/cpu.h> +#include <mips/cache.h> +#include <mips/sysarch.h> +#include <mips/cachectl.h> +#include <mips/locore.h> +#include <mips/frame.h> +#include <mips/regnum.h> +#include <mips/reg.h> + +#include <uvm/uvm_extern.h> + +char machine32[] = MACHINE; +char machine_arch32[] = MACHINE32_ARCH; + +#if 0 +cpu_coredump32 +netbsd32_cpu_upcall +netbsd32_vm_default_addr +#endif + +int +netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, + register_t *retval) +{ + /* { + syscallarg(int) op; + syscallarg(netbsd32_voidp) parms; + } */ + struct proc *p = l->l_proc; + void *parms = SCARG_P32(uap, parms); + int error = 0; + + switch(SCARG(uap, op)) { + case MIPS_CACHEFLUSH: { + struct mips_cacheflush_args32 cfua; + + error = copyin(parms, &cfua, sizeof(cfua)); + if (error != 0) + return (error); + error = mips_user_cacheflush(p, cfua.va, cfua.nbytes, + cfua.whichcache); + break; + } + case MIPS_CACHECTL: { + struct mips_cachectl_args32 ccua; + + error = copyin(parms, &ccua, sizeof(ccua)); + if (error != 0) + return (error); + error = mips_user_cachectl(p, ccua.va, ccua.nbytes, ccua.ctl); + break; + } + default: + error = ENOSYS; + break; + } + return (error); +} + +#ifdef COMPAT_16 +int +compat_16_netbsd32___sigreturn14(struct lwp *l, + const struct compat_16_netbsd32___sigreturn14_args *uap, + register_t *retval) +{ + struct compat_16_sys___sigreturn14_args ua; + + NETBSD32TOP_UAP(sigcntxp, struct sigcontext *); + + return compat_16_sys___sigreturn14(l, &ua, retval); +} +#endif + +vaddr_t +netbsd32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t size) +{ + return VM_DEFAULT_ADDRESS32(base, size); +} + + +struct sigframe_siginfo32 { + siginfo32_t sf_si; + ucontext32_t sf_uc; +}; + +/* + * Send a signal to process. + */ +static void +netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) +{ + struct lwp * const l = curlwp; + struct proc * const p = l->l_proc; + struct sigacts * const ps = p->p_sigacts; + int onstack, error; + int sig = ksi->ksi_signo; + struct sigframe_siginfo32 *sfp = getframe(l, sig, &onstack); + struct sigframe_siginfo32 sf; + struct frame * const tf = l->l_md.md_regs; + size_t sfsz; + sig_t catcher = SIGACTION(p, sig).sa_handler; + + sfp--; + + netbsd32_si_to_si32(&sf.sf_si, (const siginfo_t *)&ksi->ksi_info); + + /* Build stack frame for signal trampoline. */ + switch (ps->sa_sigdesc[sig].sd_vers) { + case 0: /* handled by sendsig_sigcontext */ + case 1: /* handled by sendsig_sigcontext */ + default: /* unknown version */ + printf("sendsig_siginfo: bad version %d\n", + ps->sa_sigdesc[sig].sd_vers); + sigexit(l, SIGILL); + case 2: + break; + } + + sf.sf_uc.uc_flags = _UC_SIGMASK + | ((l->l_sigstk.ss_flags & SS_ONSTACK) + ? _UC_SETSTACK : _UC_CLRSTACK); + sf.sf_uc.uc_sigmask = *mask; + sf.sf_uc.uc_link = (intptr_t)l->l_ctxlink; + memset(&sf.sf_uc.uc_stack, 0, sizeof(sf.sf_uc.uc_stack)); + sfsz = offsetof(struct sigframe_siginfo32, sf_uc.uc_mcontext); + if (p->p_md.md_abi == _MIPS_BSD_API_O32) + sfsz += sizeof(mcontext_o32_t); + else + sfsz += sizeof(mcontext32_t); + sendsig_reset(l, sig); + mutex_exit(p->p_lock); + cpu_getmcontext32(l, &sf.sf_uc.uc_mcontext, &sf.sf_uc.uc_flags); + error = copyout(&sf, sfp, sfsz); + mutex_enter(p->p_lock); + + if (error != 0) { + /* + * Process has trashed its stack; give it an illegal + * instruction to halt it in its tracks. + */ + sigexit(l, SIGILL); + /* NOTREACHED */ + } + + /* + * Set up the registers to directly invoke the signal + * handler. The return address will be set up to point + * to the signal trampoline to bounce us back. + */ + tf->f_regs[_R_A0] = sig; + tf->f_regs[_R_A1] = (intptr_t)&sfp->sf_si; + tf->f_regs[_R_A2] = (intptr_t)&sfp->sf_uc; + + tf->f_regs[_R_PC] = (intptr_t)catcher; + tf->f_regs[_R_T9] = (intptr_t)catcher; + tf->f_regs[_R_SP] = (intptr_t)sfp; + tf->f_regs[_R_RA] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp; + + /* Remember that we're now on the signal stack. */ + if (onstack) + l->l_sigstk.ss_flags |= SS_ONSTACK; +} + +void +netbsd32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) +{ +#ifdef COMPAT_16 + if (curproc->p_sigacts->sa_sigdesc[ksi->ksi_signo].sd_vers < 2) + sendsig_sigcontext(ksi, mask); + else +#endif + netbsd32_sendsig_siginfo(ksi, mask); +} + +void +cpu_getmcontext32(struct lwp *l, mcontext32_t *mc32, unsigned int *flagsp) +{ + mcontext_o32_t * const mco32 = (mcontext_o32_t *)mc32; + mcontext_t mc; + size_t i; + + if (l->l_proc->p_md.md_abi == _MIPS_BSD_API_N32) { + cpu_getmcontext(l, (mcontext_t *)mc32, flagsp); + return; + } + + cpu_getmcontext(l, &mc, flagsp); + for (i = 0; i < __arraycount(mc.__gregs); i++) + mco32->__gregs[i] = mc.__gregs[i]; + if (*flagsp & _UC_FPU) + memcpy(&mco32->__fpregs, &mc.__fpregs, + sizeof(struct fpreg_oabi)); +} + +int +cpu_setmcontext32(struct lwp *l, const mcontext32_t *mc32, unsigned int flags) +{ + const mcontext_o32_t * const mco32 = (const mcontext_o32_t *)mc32; + mcontext_t mc; + size_t i; + + if (l->l_proc->p_md.md_abi == _MIPS_BSD_API_N32) + return cpu_setmcontext(l, (const mcontext_t *)mc32, flags); + + for (i = 0; i < __arraycount(mc.__gregs); i++) + mc.__gregs[i] = mco32->__gregs[i]; + if (flags & _UC_FPU) + memcpy(&mc.__fpregs, &mco32->__fpregs, + sizeof(struct fpreg_oabi)); + return cpu_setmcontext(l, &mc, flags); +} + +#ifdef COREDUMP +/* + * Dump the machine specific segment at the start of a core dump. + */ +int +cpu_coredump32(struct lwp *l, void *iocookie, struct core32 *chdr) +{ + int error; + struct coreseg cseg; + struct cpustate { + struct frame frame; + struct fpreg fpregs; + } cpustate; + + if (iocookie == NULL) { + CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0); + chdr->c_hdrsize = ALIGN(sizeof(struct core)); + chdr->c_seghdrsize = ALIGN(sizeof(struct coreseg)); + chdr->c_cpusize = sizeof(struct cpustate); + chdr->c_nseg++; + return 0; + } + + if ((l->l_md.md_flags & MDP_FPUSED) && l == fpcurlwp) + savefpregs(l); + cpustate.frame = *l->l_md.md_regs; + cpustate.fpregs = l->l_addr->u_pcb.pcb_fpregs; + + CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU); + cseg.c_addr = 0; + cseg.c_size = chdr->c_cpusize; + + error = coredump_write(iocookie, UIO_SYSSPACE, &cseg, + chdr->c_seghdrsize); + if (error) + return error; + + return coredump_write(iocookie, UIO_SYSSPACE, &cpustate, + chdr->c_cpusize); +} +#endif