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