xref: /netbsd-src/sys/arch/mips/mips/netbsd32_machdep.c (revision 3758c7a856ac957fce1bfc439a40b51e6420706e)
1 /*	$NetBSD: netbsd32_machdep.c,v 1.23 2021/11/06 20:42:56 thorpej 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@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.23 2021/11/06 20:42:56 thorpej 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
netbsd32_sendsig_siginfo(const ksiginfo_t * ksi,const sigset_t * mask)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 	struct sigframe_siginfo32 sf;
99 	struct trapframe * const tf = l->l_md.md_utf;
100 	size_t sfsz;
101 	sig_t catcher = SIGACTION(p, sig).sa_handler;
102 
103 	sfp--;
104 
105 	memset(&sf, 0, sizeof(sf));
106 	netbsd32_si_to_si32(&sf.sf_si, (const siginfo_t *)&ksi->ksi_info);
107 
108         /* Build stack frame for signal trampoline. */
109         switch (ps->sa_sigdesc[sig].sd_vers) {
110         case __SIGTRAMP_SIGCODE_VERSION:     /* handled by sendsig_sigcontext */
111         case __SIGTRAMP_SIGCONTEXT_VERSION: /* handled by sendsig_sigcontext */
112         default:        /* unknown version */
113                 printf("%s: bad version %d\n", __func__,
114                     ps->sa_sigdesc[sig].sd_vers);
115                 sigexit(l, SIGILL);
116         case __SIGTRAMP_SIGINFO_VERSION:
117                 break;
118         }
119 
120 	sf.sf_uc.uc_flags = _UC_SIGMASK
121 	    | ((l->l_sigstk.ss_flags & SS_ONSTACK)
122 	    ? _UC_SETSTACK : _UC_CLRSTACK);
123 	sf.sf_uc.uc_sigmask = *mask;
124 	sf.sf_uc.uc_link = (intptr_t)l->l_ctxlink;
125 	sfsz = offsetof(struct sigframe_siginfo32, sf_uc.uc_mcontext);
126 	if (p->p_md.md_abi == _MIPS_BSD_API_O32)
127 		sfsz += sizeof(mcontext_o32_t);
128 	else
129 		sfsz += sizeof(mcontext32_t);
130 	sendsig_reset(l, sig);
131 	mutex_exit(p->p_lock);
132 	cpu_getmcontext32(l, &sf.sf_uc.uc_mcontext, &sf.sf_uc.uc_flags);
133 	error = copyout(&sf, sfp, sfsz);
134 	mutex_enter(p->p_lock);
135 	if (error != 0) {
136 		/*
137 		 * Process has trashed its stack; give it an illegal
138 		 * instruction to halt it in its tracks.
139 		 */
140 		sigexit(l, SIGILL);
141 		/* NOTREACHED */
142 	}
143 
144 	/*
145 	 * Set up the registers to directly invoke the signal
146 	 * handler.  The return address will be set up to point
147 	 * to the signal trampoline to bounce us back.
148 	 */
149 	tf->tf_regs[_R_A0] = sig;
150 	tf->tf_regs[_R_A1] = (intptr_t)&sfp->sf_si;
151 	tf->tf_regs[_R_A2] = (intptr_t)&sfp->sf_uc;
152 
153 	tf->tf_regs[_R_PC] = (intptr_t)catcher;
154 	tf->tf_regs[_R_T9] = (intptr_t)catcher;
155 	tf->tf_regs[_R_SP] = (intptr_t)sfp;
156 	tf->tf_regs[_R_RA] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp;
157 
158 	/* Remember that we're now on the signal stack. */
159 	if (onstack)
160 		l->l_sigstk.ss_flags |= SS_ONSTACK;
161 }
162 
163 int
netbsd32_sysarch(struct lwp * l,const struct netbsd32_sysarch_args * uap,register_t * retval)164 netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap,
165 	register_t *retval)
166 {
167 	/* {
168 		syscallarg(int) op;
169 		syscallarg(netbsd32_voidp) parms;
170 	} */
171 	struct proc *p = l->l_proc;
172 	void *parms = SCARG_P32(uap, parms);
173 	int error = 0;
174 
175 	switch(SCARG(uap, op)) {
176 	case MIPS_CACHEFLUSH: {
177 		struct mips_cacheflush_args32 cfua;
178 
179 		error = copyin(parms, &cfua, sizeof(cfua));
180 		if (error != 0)
181 			return (error);
182 		error =  mips_user_cacheflush(p, cfua.va, cfua.nbytes,
183 		     cfua.whichcache);
184 		break;
185 	}
186 	case MIPS_CACHECTL: {
187 		struct mips_cachectl_args32 ccua;
188 
189 		error = copyin(parms, &ccua, sizeof(ccua));
190 		if (error != 0)
191 			return (error);
192 		error = mips_user_cachectl(p, ccua.va, ccua.nbytes, ccua.ctl);
193 		break;
194 	}
195 	default:
196 		error = ENOSYS;
197 		break;
198 	}
199 	return (error);
200 }
201 
202 vaddr_t
netbsd32_vm_default_addr(struct proc * p,vaddr_t base,vsize_t size,int topdown)203 netbsd32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t size,
204     int topdown)
205 {
206 	if (topdown)
207 		return VM_DEFAULT_ADDRESS32_TOPDOWN(base, size);
208 	else
209 		return VM_DEFAULT_ADDRESS32_BOTTOMUP(base, size);
210 }
211 
212 void
cpu_getmcontext32(struct lwp * l,mcontext32_t * mc32,unsigned int * flagsp)213 cpu_getmcontext32(struct lwp *l, mcontext32_t *mc32, unsigned int *flagsp)
214 {
215 	mcontext_o32_t * const mco32 = (mcontext_o32_t *)mc32;
216 	mcontext_t mc;
217 	size_t i;
218 
219 	if (l->l_proc->p_md.md_abi == _MIPS_BSD_API_N32) {
220 		cpu_getmcontext(l, (mcontext_t *)mc32, flagsp);
221 		return;
222 	}
223 
224 	cpu_getmcontext(l, &mc, flagsp);
225 	for (i = 1; i < __arraycount(mc.__gregs); i++)
226 		mco32->__gregs[i] = mc.__gregs[i];
227 	if (*flagsp & _UC_FPU)
228 		memcpy(&mco32->__fpregs, &mc.__fpregs,
229 		    sizeof(struct fpreg_oabi));
230 	mco32->_mc_tlsbase = mc._mc_tlsbase;
231 	*flagsp |= _UC_TLSBASE;
232 }
233 
234 int
cpu_mcontext32_validate(struct lwp * l,const mcontext32_t * mc32)235 cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mc32)
236 {
237 	return 0;
238 }
239 
240 int
cpu_setmcontext32(struct lwp * l,const mcontext32_t * mc32,unsigned int flags)241 cpu_setmcontext32(struct lwp *l, const mcontext32_t *mc32, unsigned int flags)
242 {
243 	const mcontext_o32_t * const mco32 = (const mcontext_o32_t *)mc32;
244 	mcontext_t mc;
245 	size_t i, error;
246 
247 	if (flags & _UC_CPU) {
248 		error = cpu_mcontext32_validate(l, mc32);
249 		if (error)
250 			return error;
251 	}
252 
253 	if (l->l_proc->p_md.md_abi == _MIPS_BSD_API_N32)
254 		return cpu_setmcontext(l, (const mcontext_t *)mc32, flags);
255 
256 	for (i = 0; i < __arraycount(mc.__gregs); i++)
257 		mc.__gregs[i] = mco32->__gregs[i];
258 	if (flags & _UC_FPU)
259 		memcpy(&mc.__fpregs, &mco32->__fpregs,
260 		    sizeof(struct fpreg_oabi));
261 	mc._mc_tlsbase = mco32->_mc_tlsbase;
262 	return cpu_setmcontext(l, &mc, flags);
263 }
264 
265 /*
266  * Dump the machine specific segment at the start of a core dump.
267  */
268 int
cpu_coredump32(struct lwp * l,struct coredump_iostate * iocookie,struct core32 * chdr)269 cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie,
270     struct core32 *chdr)
271 {
272 	int error;
273 	struct coreseg cseg;
274 	struct cpustate {
275 		struct trapframe frame;
276 		struct fpreg fpregs;
277 	} cpustate;
278 
279 	if (iocookie == NULL) {
280 		CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0);
281 		chdr->c_hdrsize = ALIGN(sizeof(struct core));
282 		chdr->c_seghdrsize = ALIGN(sizeof(struct coreseg));
283 		chdr->c_cpusize = sizeof(struct cpustate);
284 		chdr->c_nseg++;
285 		return 0;
286 	}
287 
288 	fpu_save(l);
289 
290 	struct pcb * const pcb = lwp_getpcb(l);
291 	cpustate.frame = *l->l_md.md_utf;
292 	cpustate.fpregs = pcb->pcb_fpregs;
293 
294 	CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU);
295 	cseg.c_addr = 0;
296 	cseg.c_size = chdr->c_cpusize;
297 
298 	MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE, &cseg,
299 	    chdr->c_seghdrsize), ENOSYS, error);
300 	if (error)
301 		return error;
302 
303 	MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE,
304 	    &cpustate, chdr->c_cpusize), ENOSYS, error);
305 
306 	return error;
307 }
308 
309 static const char *
netbsd32_machine32(void)310 netbsd32_machine32(void)
311 {
312 
313 	return PROC_MACHINE_ARCH32(curproc);
314 }
315 
316 void
netbsd32_machdep_md_init(void)317 netbsd32_machdep_md_init(void)
318 {
319 
320 	MODULE_HOOK_SET(netbsd32_machine32_hook, netbsd32_machine32);
321 }
322 
323 void
netbsd32_machdep_md_fini(void)324 netbsd32_machdep_md_fini(void)
325 {
326 
327 	MODULE_HOOK_UNSET(netbsd32_machine32_hook);
328 }
329 
330 
331