2 * Copyright (c) 2018 Olivier Houchard
3 * Copyright (c) 2017 Nuxi, https://nuxi.nl/
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
34 #include <sys/mutex.h>
35 #include <sys/syscallsubr.h>
37 #include <sys/sysctl.h>
38 #include <sys/sysent.h>
39 #include <sys/sysproto.h>
40 #include <machine/armreg.h>
41 #include <machine/pcb.h>
43 #include <machine/vfp.h>
45 #include <compat/freebsd32/freebsd32_proto.h>
46 #include <compat/freebsd32/freebsd32_signal.h>
49 #include <vm/vm_param.h>
51 #include <vm/vm_map.h>
53 _Static_assert(sizeof(mcontext32_t) == 208, "mcontext32_t size incorrect");
54 _Static_assert(sizeof(ucontext32_t) == 260, "ucontext32_t size incorrect");
55 _Static_assert(sizeof(struct siginfo32) == 64, "struct siginfo32 size incorrect");
57 extern void freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
59 SYSCTL_NODE(_compat, OID_AUTO, arm, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
63 * The first two fields of a ucontext_t are the signal mask and the machine
64 * context. The next field is uc_link; we want to avoid destroying the link
65 * when copying out contexts.
67 #define UC32_COPY_SIZE offsetof(ucontext32_t, uc_link)
70 * Stubs for machine dependent 32-bits system calls.
74 freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
78 #define ARM_SYNC_ICACHE 0
79 #define ARM_DRAIN_WRITEBUF 1
82 #define ARM_GET_VFPSTATE 4
86 WRITE_SPECIALREG(tpidr_el0, uap->parms);
87 WRITE_SPECIALREG(tpidrro_el0, uap->parms);
96 if ((error = copyin(uap->parms, &args, sizeof(args))) != 0)
98 if ((uint64_t)args.addr + (uint64_t)args.size > 0xffffffff)
100 cpu_icache_sync_range_checked(args.addr, args.size);
103 case ARM_GET_VFPSTATE:
105 mcontext32_vfp_t mcontext_vfp;
108 uint32_t mc_vfp_size;
111 if ((error = copyin(uap->parms, &args, sizeof(args))) != 0)
113 if (args.mc_vfp_size != sizeof(mcontext_vfp))
116 get_fpcontext32(td, &mcontext_vfp);
118 bzero(&mcontext_vfp, sizeof(mcontext_vfp));
120 error = copyout(&mcontext_vfp,
121 (void *)(uintptr_t)args.mc_vfp,
122 sizeof(mcontext_vfp));
132 get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
137 KASSERT(td == curthread || TD_IS_SUSPENDED(td) ||
138 P_SHOULDSTOP(td->td_proc),
139 ("not suspended thread %p", td));
141 memset(mcp, 0, sizeof(*mcp));
144 if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
146 * If we have just been running VFP instructions we will
147 * need to save the state to memcpy it below.
150 vfp_save_state(td, pcb);
152 KASSERT(pcb->pcb_fpusaved == &pcb->pcb_fpustate,
153 ("Called get_fpcontext32 while the kernel is using the VFP"));
154 KASSERT((pcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0,
155 ("Non-userspace FPU flags set in get_fpcontext32"));
156 for (i = 0; i < 32; i++)
157 mcp->mcv_reg[i] = (uint64_t)pcb->pcb_fpustate.vfp_regs[i];
158 mcp->mcv_fpscr = VFP_FPSCR_FROM_SRCR(pcb->pcb_fpustate.vfp_fpcr,
159 pcb->pcb_fpustate.vfp_fpsr);
164 set_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp)
173 for (i = 0; i < 32; i++)
174 pcb->pcb_fpustate.vfp_regs[i] = mcp->mcv_reg[i];
175 pcb->pcb_fpustate.vfp_fpsr = VFP_FPSR_FROM_FPSCR(mcp->mcv_fpscr);
176 pcb->pcb_fpustate.vfp_fpcr = VFP_FPSR_FROM_FPSCR(mcp->mcv_fpscr);
182 get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags)
184 struct trapframe *tf;
189 if ((flags & GET_MC_CLEAR_RET) != 0) {
190 mcp->mc_gregset[0] = 0;
191 mcp->mc_gregset[16] = tf->tf_spsr & ~PSR_C;
193 mcp->mc_gregset[0] = tf->tf_x[0];
194 mcp->mc_gregset[16] = tf->tf_spsr;
196 for (i = 1; i < 15; i++)
197 mcp->mc_gregset[i] = tf->tf_x[i];
198 mcp->mc_gregset[15] = tf->tf_elr;
200 mcp->mc_vfp_size = 0;
203 memset(mcp->mc_spare, 0, sizeof(mcp->mc_spare));
207 set_mcontext32(struct thread *td, mcontext32_t *mcp)
209 struct trapframe *tf;
210 mcontext32_vfp_t mc_vfp;
216 spsr = mcp->mc_gregset[16];
218 * There is no PSR_SS in the 32-bit kernel so ignore it if it's set
219 * as we will set it later if needed.
221 if ((spsr & ~(PSR_SETTABLE_32 | PSR_SS)) !=
222 (tf->tf_spsr & ~(PSR_SETTABLE_32 | PSR_SS)))
225 spsr &= PSR_SETTABLE_32;
226 spsr |= tf->tf_spsr & ~PSR_SETTABLE_32;
228 if ((td->td_dbgflags & TDB_STEP) != 0) {
230 td->td_pcb->pcb_flags |= PCB_SINGLE_STEP;
231 WRITE_SPECIALREG(mdscr_el1,
232 READ_SPECIALREG(mdscr_el1) | MDSCR_SS);
235 for (i = 0; i < 15; i++)
236 tf->tf_x[i] = mcp->mc_gregset[i];
237 tf->tf_elr = mcp->mc_gregset[15];
240 if (mcp->mc_vfp_size == sizeof(mc_vfp) && mcp->mc_vfp_ptr != 0) {
241 if (copyin((void *)(uintptr_t)mcp->mc_vfp_ptr, &mc_vfp,
242 sizeof(mc_vfp)) != 0)
244 set_fpcontext32(td, &mc_vfp);
251 #define UC_COPY_SIZE offsetof(ucontext32_t, uc_link)
254 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap)
259 if (uap->ucp == NULL)
262 memset(&uc, 0, sizeof(uc));
263 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
264 PROC_LOCK(td->td_proc);
265 uc.uc_sigmask = td->td_sigmask;
266 PROC_UNLOCK(td->td_proc);
267 ret = copyout(&uc, uap->ucp, UC_COPY_SIZE);
273 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap)
278 if (uap->ucp == NULL)
281 ret = copyin(uap->ucp, &uc, UC_COPY_SIZE);
283 ret = set_mcontext32(td, &uc.uc_mcontext);
285 kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask,
293 freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap)
300 if (copyin(uap->sigcntxp, &uc, sizeof(uc)))
302 error = set_mcontext32(td, &uc.uc_mcontext);
306 /* Restore signal mask. */
307 kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
309 return (EJUSTRETURN);
314 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap)
319 if (uap->oucp == NULL || uap->ucp == NULL)
322 bzero(&uc, sizeof(uc));
323 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET);
324 PROC_LOCK(td->td_proc);
325 uc.uc_sigmask = td->td_sigmask;
326 PROC_UNLOCK(td->td_proc);
327 ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE);
329 ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE);
331 ret = set_mcontext32(td, &uc.uc_mcontext);
332 kern_sigprocmask(td, SIG_SETMASK,
333 &uc.uc_sigmask, NULL, 0);
341 freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
345 struct trapframe *tf;
346 struct sigframe32 *fp, frame;
348 struct siginfo32 siginfo;
349 struct sysentvec *sysent;
353 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo);
356 PROC_LOCK_ASSERT(p, MA_OWNED);
357 sig = ksi->ksi_signo;
359 mtx_assert(&psp->ps_mtx, MA_OWNED);
361 onstack = sigonstack(tf->tf_x[13]);
363 CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
366 /* Allocate and validate space for the signal handler context. */
367 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !(onstack) &&
368 SIGISMEMBER(psp->ps_sigonstack, sig)) {
369 fp = (struct sigframe32 *)((uintptr_t)td->td_sigstk.ss_sp +
370 td->td_sigstk.ss_size);
371 #if defined(COMPAT_43)
372 td->td_sigstk.ss_flags |= SS_ONSTACK;
375 fp = (struct sigframe32 *)td->td_frame->tf_x[13];
377 /* make room on the stack */
380 /* make the stack aligned */
381 fp = (struct sigframe32 *)((unsigned long)(fp) &~ (8 - 1));
382 /* Populate the siginfo frame. */
383 get_mcontext32(td, &frame.sf_uc.uc_mcontext, 0);
385 get_fpcontext32(td, &frame.sf_vfp);
386 frame.sf_uc.uc_mcontext.mc_vfp_size = sizeof(fp->sf_vfp);
387 frame.sf_uc.uc_mcontext.mc_vfp_ptr = (uint32_t)(uintptr_t)&fp->sf_vfp;
389 frame.sf_uc.uc_mcontext.mc_vfp_size = 0;
390 frame.sf_uc.uc_mcontext.mc_vfp_ptr = (uint32_t)NULL;
392 frame.sf_si = siginfo;
393 frame.sf_uc.uc_sigmask = *mask;
394 frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK )
395 ? ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE;
396 frame.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp;
397 frame.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size;
399 mtx_unlock(&psp->ps_mtx);
400 PROC_UNLOCK(td->td_proc);
402 /* Copy the sigframe out to the user's stack. */
403 if (copyout(&frame, fp, sizeof(*fp)) != 0) {
404 /* Process has trashed its stack. Kill it. */
405 CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp);
411 * Build context to run handler in. We invoke the handler
412 * directly, only returning via the trampoline. Note the
413 * trampoline version numbers are coordinated with machine-
414 * dependent code in libc.
418 tf->tf_x[1] = (register_t)&fp->sf_si;
419 tf->tf_x[2] = (register_t)&fp->sf_uc;
421 /* the trampoline uses r5 as the uc address */
422 tf->tf_x[5] = (register_t)&fp->sf_uc;
423 tf->tf_elr = (register_t)catcher;
424 tf->tf_x[13] = (register_t)fp;
425 sysent = p->p_sysent;
427 tf->tf_x[14] = (register_t)PROC_SIGCODE(p);
429 tf->tf_x[14] = (register_t)(PROC_PS_STRINGS(p) -
430 *(sysent->sv_szsigcode));
431 /* Set the mode to enter in the signal handler */
432 if ((register_t)catcher & 1)
433 tf->tf_spsr |= PSR_T;
435 tf->tf_spsr &= ~PSR_T;
437 /* Clear the single step flag while in the signal handler */
438 if ((td->td_pcb->pcb_flags & PCB_SINGLE_STEP) != 0) {
439 td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP;
440 WRITE_SPECIALREG(mdscr_el1,
441 READ_SPECIALREG(mdscr_el1) & ~MDSCR_SS);
445 CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_x[14],
449 mtx_lock(&psp->ps_mtx);
455 * Mirror the osigreturn definition in kern_sig.c for !i386 platforms. This
456 * mirrors what's connected to the FreeBSD/arm syscall.
459 ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap)
462 return (nosys(td, (struct nosys_args *)uap));