Home | History | Annotate | Line # | Download | only in mips
      1 /*	$NetBSD: netbsd32_machdep.c,v 1.24 2025/04/25 00:26:59 riastradh Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2009 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Matt Thomas <matt (at) 3am-software.com>.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.24 2025/04/25 00:26:59 riastradh Exp $");
     34 
     35 #include "opt_compat_netbsd.h"
     36 
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/ioctl.h>
     40 #include <sys/exec.h>
     41 #include <sys/cpu.h>
     42 #include <sys/core.h>
     43 #include <sys/file.h>
     44 #include <sys/time.h>
     45 #include <sys/proc.h>
     46 #include <sys/uio.h>
     47 #include <sys/kernel.h>
     48 #include <sys/buf.h>
     49 #include <sys/signal.h>
     50 #include <sys/signalvar.h>
     51 #include <sys/mount.h>
     52 #include <sys/syscallargs.h>
     53 #include <sys/compat_stub.h>
     54 
     55 #include <compat/netbsd32/netbsd32.h>
     56 #include <compat/netbsd32/netbsd32_exec.h>
     57 #include <compat/netbsd32/netbsd32_syscallargs.h>
     58 
     59 #include <mips/cache.h>
     60 #include <mips/sysarch.h>
     61 #include <mips/cachectl.h>
     62 #include <mips/locore.h>
     63 #include <mips/frame.h>
     64 #include <mips/regnum.h>
     65 #include <mips/pcb.h>
     66 
     67 #include <uvm/uvm_extern.h>
     68 
     69 const char machine32[] = MACHINE;
     70 const char machine_archo32[] = MACHINE32_OARCH;
     71 #ifdef MACHINE32_NARCH
     72 const char machine_archn32[] = MACHINE32_NARCH;
     73 #endif
     74 
     75 #if 0
     76 cpu_coredump32
     77 netbsd32_cpu_upcall
     78 netbsd32_vm_default_addr
     79 #endif
     80 
     81 struct sigframe_siginfo32 {
     82 	siginfo32_t sf_si;
     83 	ucontext32_t sf_uc;
     84 };
     85 
     86 /*
     87  * Send a signal to process.
     88  */
     89 void
     90 netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask)
     91 {
     92 	struct lwp * const l = curlwp;
     93 	struct proc * const p = l->l_proc;
     94 	struct sigacts * const ps = p->p_sigacts;
     95 	int onstack, error;
     96 	int sig = ksi->ksi_signo;
     97 	struct sigframe_siginfo32 *sfp = getframe(l, sig, &onstack,
     98 	    sizeof(*sfp), _Alignof(*sfp));
     99 	struct sigframe_siginfo32 sf;
    100 	struct trapframe * const tf = l->l_md.md_utf;
    101 	size_t sfsz;
    102 	sig_t catcher = SIGACTION(p, sig).sa_handler;
    103 
    104 	memset(&sf, 0, sizeof(sf));
    105 	netbsd32_si_to_si32(&sf.sf_si, (const siginfo_t *)&ksi->ksi_info);
    106 
    107         /* Build stack frame for signal trampoline. */
    108         switch (ps->sa_sigdesc[sig].sd_vers) {
    109         case __SIGTRAMP_SIGCODE_VERSION:     /* handled by sendsig_sigcontext */
    110         case __SIGTRAMP_SIGCONTEXT_VERSION: /* handled by sendsig_sigcontext */
    111         default:        /* unknown version */
    112                 printf("%s: bad version %d\n", __func__,
    113                     ps->sa_sigdesc[sig].sd_vers);
    114                 sigexit(l, SIGILL);
    115         case __SIGTRAMP_SIGINFO_VERSION:
    116                 break;
    117         }
    118 
    119 	sf.sf_uc.uc_flags = _UC_SIGMASK
    120 	    | ((l->l_sigstk.ss_flags & SS_ONSTACK)
    121 	    ? _UC_SETSTACK : _UC_CLRSTACK);
    122 	sf.sf_uc.uc_sigmask = *mask;
    123 	sf.sf_uc.uc_link = (intptr_t)l->l_ctxlink;
    124 	sfsz = offsetof(struct sigframe_siginfo32, sf_uc.uc_mcontext);
    125 	if (p->p_md.md_abi == _MIPS_BSD_API_O32)
    126 		sfsz += sizeof(mcontext_o32_t);
    127 	else
    128 		sfsz += sizeof(mcontext32_t);
    129 	sendsig_reset(l, sig);
    130 	mutex_exit(p->p_lock);
    131 	cpu_getmcontext32(l, &sf.sf_uc.uc_mcontext, &sf.sf_uc.uc_flags);
    132 	error = copyout(&sf, sfp, sfsz);
    133 	mutex_enter(p->p_lock);
    134 	if (error != 0) {
    135 		/*
    136 		 * Process has trashed its stack; give it an illegal
    137 		 * instruction to halt it in its tracks.
    138 		 */
    139 		sigexit(l, SIGILL);
    140 		/* NOTREACHED */
    141 	}
    142 
    143 	/*
    144 	 * Set up the registers to directly invoke the signal
    145 	 * handler.  The return address will be set up to point
    146 	 * to the signal trampoline to bounce us back.
    147 	 */
    148 	tf->tf_regs[_R_A0] = sig;
    149 	tf->tf_regs[_R_A1] = (intptr_t)&sfp->sf_si;
    150 	tf->tf_regs[_R_A2] = (intptr_t)&sfp->sf_uc;
    151 
    152 	tf->tf_regs[_R_PC] = (intptr_t)catcher;
    153 	tf->tf_regs[_R_T9] = (intptr_t)catcher;
    154 	tf->tf_regs[_R_SP] = (intptr_t)sfp;
    155 	tf->tf_regs[_R_RA] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp;
    156 
    157 	/* Remember that we're now on the signal stack. */
    158 	if (onstack)
    159 		l->l_sigstk.ss_flags |= SS_ONSTACK;
    160 }
    161 
    162 int
    163 netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap,
    164 	register_t *retval)
    165 {
    166 	/* {
    167 		syscallarg(int) op;
    168 		syscallarg(netbsd32_voidp) parms;
    169 	} */
    170 	struct proc *p = l->l_proc;
    171 	void *parms = SCARG_P32(uap, parms);
    172 	int error = 0;
    173 
    174 	switch(SCARG(uap, op)) {
    175 	case MIPS_CACHEFLUSH: {
    176 		struct mips_cacheflush_args32 cfua;
    177 
    178 		error = copyin(parms, &cfua, sizeof(cfua));
    179 		if (error != 0)
    180 			return (error);
    181 		error =  mips_user_cacheflush(p, cfua.va, cfua.nbytes,
    182 		     cfua.whichcache);
    183 		break;
    184 	}
    185 	case MIPS_CACHECTL: {
    186 		struct mips_cachectl_args32 ccua;
    187 
    188 		error = copyin(parms, &ccua, sizeof(ccua));
    189 		if (error != 0)
    190 			return (error);
    191 		error = mips_user_cachectl(p, ccua.va, ccua.nbytes, ccua.ctl);
    192 		break;
    193 	}
    194 	default:
    195 		error = ENOSYS;
    196 		break;
    197 	}
    198 	return (error);
    199 }
    200 
    201 vaddr_t
    202 netbsd32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t size,
    203     int topdown)
    204 {
    205 	if (topdown)
    206 		return VM_DEFAULT_ADDRESS32_TOPDOWN(base, size);
    207 	else
    208 		return VM_DEFAULT_ADDRESS32_BOTTOMUP(base, size);
    209 }
    210 
    211 void
    212 cpu_getmcontext32(struct lwp *l, mcontext32_t *mc32, unsigned int *flagsp)
    213 {
    214 	mcontext_o32_t * const mco32 = (mcontext_o32_t *)mc32;
    215 	mcontext_t mc;
    216 	size_t i;
    217 
    218 	if (l->l_proc->p_md.md_abi == _MIPS_BSD_API_N32) {
    219 		cpu_getmcontext(l, (mcontext_t *)mc32, flagsp);
    220 		return;
    221 	}
    222 
    223 	cpu_getmcontext(l, &mc, flagsp);
    224 	for (i = 1; i < __arraycount(mc.__gregs); i++)
    225 		mco32->__gregs[i] = mc.__gregs[i];
    226 	if (*flagsp & _UC_FPU)
    227 		memcpy(&mco32->__fpregs, &mc.__fpregs,
    228 		    sizeof(struct fpreg_oabi));
    229 	mco32->_mc_tlsbase = mc._mc_tlsbase;
    230 	*flagsp |= _UC_TLSBASE;
    231 }
    232 
    233 int
    234 cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mc32)
    235 {
    236 	return 0;
    237 }
    238 
    239 int
    240 cpu_setmcontext32(struct lwp *l, const mcontext32_t *mc32, unsigned int flags)
    241 {
    242 	const mcontext_o32_t * const mco32 = (const mcontext_o32_t *)mc32;
    243 	mcontext_t mc;
    244 	size_t i, error;
    245 
    246 	if (flags & _UC_CPU) {
    247 		error = cpu_mcontext32_validate(l, mc32);
    248 		if (error)
    249 			return error;
    250 	}
    251 
    252 	if (l->l_proc->p_md.md_abi == _MIPS_BSD_API_N32)
    253 		return cpu_setmcontext(l, (const mcontext_t *)mc32, flags);
    254 
    255 	for (i = 0; i < __arraycount(mc.__gregs); i++)
    256 		mc.__gregs[i] = mco32->__gregs[i];
    257 	if (flags & _UC_FPU)
    258 		memcpy(&mc.__fpregs, &mco32->__fpregs,
    259 		    sizeof(struct fpreg_oabi));
    260 	mc._mc_tlsbase = mco32->_mc_tlsbase;
    261 	return cpu_setmcontext(l, &mc, flags);
    262 }
    263 
    264 /*
    265  * Dump the machine specific segment at the start of a core dump.
    266  */
    267 int
    268 cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie,
    269     struct core32 *chdr)
    270 {
    271 	int error;
    272 	struct coreseg cseg;
    273 	struct cpustate {
    274 		struct trapframe frame;
    275 		struct fpreg fpregs;
    276 	} cpustate;
    277 
    278 	if (iocookie == NULL) {
    279 		CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0);
    280 		chdr->c_hdrsize = ALIGN(sizeof(struct core));
    281 		chdr->c_seghdrsize = ALIGN(sizeof(struct coreseg));
    282 		chdr->c_cpusize = sizeof(struct cpustate);
    283 		chdr->c_nseg++;
    284 		return 0;
    285 	}
    286 
    287 	fpu_save(l);
    288 
    289 	struct pcb * const pcb = lwp_getpcb(l);
    290 	cpustate.frame = *l->l_md.md_utf;
    291 	cpustate.fpregs = pcb->pcb_fpregs;
    292 
    293 	CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU);
    294 	cseg.c_addr = 0;
    295 	cseg.c_size = chdr->c_cpusize;
    296 
    297 	MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE, &cseg,
    298 	    chdr->c_seghdrsize), ENOSYS, error);
    299 	if (error)
    300 		return error;
    301 
    302 	MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE,
    303 	    &cpustate, chdr->c_cpusize), ENOSYS, error);
    304 
    305 	return error;
    306 }
    307 
    308 static const char *
    309 netbsd32_machine32(void)
    310 {
    311 
    312 	return PROC_MACHINE_ARCH32(curproc);
    313 }
    314 
    315 void
    316 netbsd32_machdep_md_init(void)
    317 {
    318 
    319 	MODULE_HOOK_SET(netbsd32_machine32_hook, netbsd32_machine32);
    320 }
    321 
    322 void
    323 netbsd32_machdep_md_fini(void)
    324 {
    325 
    326 	MODULE_HOOK_UNSET(netbsd32_machine32_hook);
    327 }
    328 
    329 
    330