1 /*- 2 * Copyright (c) 2018 Olivier Houchard 3 * Copyright (c) 2017 Nuxi, https://nuxi.nl/ 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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. 13 * 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 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 #include <sys/param.h> 29 #include <sys/exec.h> 30 #include <sys/proc.h> 31 #include <sys/lock.h> 32 #include <sys/mutex.h> 33 #include <sys/syscallsubr.h> 34 #include <sys/ktr.h> 35 #include <sys/sysctl.h> 36 #include <sys/sysent.h> 37 #include <sys/sysproto.h> 38 #include <machine/armreg.h> 39 #include <machine/pcb.h> 40 #ifdef VFP 41 #include <machine/vfp.h> 42 #endif 43 #include <compat/freebsd32/freebsd32_proto.h> 44 #include <compat/freebsd32/freebsd32_signal.h> 45 46 #include <vm/vm.h> 47 #include <vm/vm_param.h> 48 #include <vm/pmap.h> 49 #include <vm/vm_map.h> 50 51 _Static_assert(sizeof(mcontext32_t) == 208, "mcontext32_t size incorrect"); 52 _Static_assert(sizeof(ucontext32_t) == 260, "ucontext32_t size incorrect"); 53 _Static_assert(sizeof(struct siginfo32) == 64, "struct siginfo32 size incorrect"); 54 55 extern void freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask); 56 57 SYSCTL_NODE(_compat, OID_AUTO, arm, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 58 "32-bit mode"); 59 60 /* 61 * The first two fields of a ucontext_t are the signal mask and the machine 62 * context. The next field is uc_link; we want to avoid destroying the link 63 * when copying out contexts. 64 */ 65 #define UC32_COPY_SIZE offsetof(ucontext32_t, uc_link) 66 67 /* 68 * Stubs for machine dependent 32-bits system calls. 69 */ 70 71 int 72 freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap) 73 { 74 int error; 75 76 #define ARM_SYNC_ICACHE 0 77 #define ARM_DRAIN_WRITEBUF 1 78 #define ARM_SET_TP 2 79 #define ARM_GET_TP 3 80 #define ARM_GET_VFPSTATE 4 81 82 switch(uap->op) { 83 case ARM_SET_TP: 84 WRITE_SPECIALREG(tpidr_el0, uap->parms); 85 WRITE_SPECIALREG(tpidrro_el0, uap->parms); 86 return 0; 87 case ARM_SYNC_ICACHE: 88 { 89 struct { 90 uint32_t addr; 91 uint32_t size; 92 } args; 93 94 if ((error = copyin(uap->parms, &args, sizeof(args))) != 0) 95 return (error); 96 if ((uint64_t)args.addr + (uint64_t)args.size > 0xffffffff) 97 return (EINVAL); 98 cpu_icache_sync_range_checked(args.addr, args.size); 99 return 0; 100 } 101 case ARM_GET_VFPSTATE: 102 { 103 mcontext32_vfp_t mcontext_vfp; 104 105 struct { 106 uint32_t mc_vfp_size; 107 uint32_t mc_vfp; 108 } args; 109 if ((error = copyin(uap->parms, &args, sizeof(args))) != 0) 110 return (error); 111 if (args.mc_vfp_size != sizeof(mcontext_vfp)) 112 return (EINVAL); 113 #ifdef VFP 114 get_fpcontext32(td, &mcontext_vfp); 115 #else 116 bzero(&mcontext_vfp, sizeof(mcontext_vfp)); 117 #endif 118 error = copyout(&mcontext_vfp, 119 (void *)(uintptr_t)args.mc_vfp, 120 sizeof(mcontext_vfp)); 121 return error; 122 } 123 } 124 125 return (EINVAL); 126 } 127 128 #ifdef VFP 129 void 130 get_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp) 131 { 132 struct pcb *pcb; 133 int i; 134 135 KASSERT(td == curthread || TD_IS_SUSPENDED(td) || 136 P_SHOULDSTOP(td->td_proc), 137 ("not suspended thread %p", td)); 138 139 memset(mcp, 0, sizeof(*mcp)); 140 pcb = td->td_pcb; 141 142 if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0) { 143 /* 144 * If we have just been running VFP instructions we will 145 * need to save the state to memcpy it below. 146 */ 147 if (td == curthread) 148 vfp_save_state(td, pcb); 149 150 KASSERT(pcb->pcb_fpusaved == &pcb->pcb_fpustate, 151 ("Called get_fpcontext32 while the kernel is using the VFP")); 152 KASSERT((pcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0, 153 ("Non-userspace FPU flags set in get_fpcontext32")); 154 for (i = 0; i < 32; i++) 155 mcp->mcv_reg[i] = (uint64_t)pcb->pcb_fpustate.vfp_regs[i]; 156 mcp->mcv_fpscr = VFP_FPSCR_FROM_SRCR(pcb->pcb_fpustate.vfp_fpcr, 157 pcb->pcb_fpustate.vfp_fpsr); 158 } 159 } 160 161 void 162 set_fpcontext32(struct thread *td, mcontext32_vfp_t *mcp) 163 { 164 struct pcb *pcb; 165 int i; 166 167 critical_enter(); 168 pcb = td->td_pcb; 169 if (td == curthread) 170 vfp_discard(td); 171 for (i = 0; i < 32; i++) 172 pcb->pcb_fpustate.vfp_regs[i] = mcp->mcv_reg[i]; 173 pcb->pcb_fpustate.vfp_fpsr = VFP_FPSR_FROM_FPSCR(mcp->mcv_fpscr); 174 pcb->pcb_fpustate.vfp_fpcr = VFP_FPSR_FROM_FPSCR(mcp->mcv_fpscr); 175 critical_exit(); 176 } 177 #endif 178 179 static void 180 get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 181 { 182 struct trapframe *tf; 183 int i; 184 185 tf = td->td_frame; 186 187 if ((flags & GET_MC_CLEAR_RET) != 0) { 188 mcp->mc_gregset[0] = 0; 189 mcp->mc_gregset[16] = tf->tf_spsr & ~PSR_C; 190 } else { 191 mcp->mc_gregset[0] = tf->tf_x[0]; 192 mcp->mc_gregset[16] = tf->tf_spsr; 193 } 194 for (i = 1; i < 15; i++) 195 mcp->mc_gregset[i] = tf->tf_x[i]; 196 mcp->mc_gregset[15] = tf->tf_elr; 197 198 mcp->mc_vfp_size = 0; 199 mcp->mc_vfp_ptr = 0; 200 201 memset(mcp->mc_spare, 0, sizeof(mcp->mc_spare)); 202 } 203 204 static int 205 set_mcontext32(struct thread *td, mcontext32_t *mcp) 206 { 207 struct trapframe *tf; 208 mcontext32_vfp_t mc_vfp; 209 uint32_t spsr; 210 int i; 211 212 tf = td->td_frame; 213 214 spsr = mcp->mc_gregset[16]; 215 /* 216 * There is no PSR_SS in the 32-bit kernel so ignore it if it's set 217 * as we will set it later if needed. 218 */ 219 if ((spsr & ~(PSR_SETTABLE_32 | PSR_SS)) != 220 (tf->tf_spsr & ~(PSR_SETTABLE_32 | PSR_SS))) 221 return (EINVAL); 222 223 spsr &= PSR_SETTABLE_32; 224 spsr |= tf->tf_spsr & ~PSR_SETTABLE_32; 225 226 if ((td->td_dbgflags & TDB_STEP) != 0) { 227 spsr |= PSR_SS; 228 td->td_pcb->pcb_flags |= PCB_SINGLE_STEP; 229 WRITE_SPECIALREG(mdscr_el1, 230 READ_SPECIALREG(mdscr_el1) | MDSCR_SS); 231 } 232 233 for (i = 0; i < 15; i++) 234 tf->tf_x[i] = mcp->mc_gregset[i]; 235 tf->tf_elr = mcp->mc_gregset[15]; 236 tf->tf_spsr = spsr; 237 #ifdef VFP 238 if (mcp->mc_vfp_size == sizeof(mc_vfp) && mcp->mc_vfp_ptr != 0) { 239 if (copyin((void *)(uintptr_t)mcp->mc_vfp_ptr, &mc_vfp, 240 sizeof(mc_vfp)) != 0) 241 return (EFAULT); 242 set_fpcontext32(td, &mc_vfp); 243 } 244 #endif 245 246 return (0); 247 } 248 249 #define UC_COPY_SIZE offsetof(ucontext32_t, uc_link) 250 251 int 252 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 253 { 254 ucontext32_t uc; 255 int ret; 256 257 if (uap->ucp == NULL) 258 ret = EINVAL; 259 else { 260 memset(&uc, 0, sizeof(uc)); 261 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 262 PROC_LOCK(td->td_proc); 263 uc.uc_sigmask = td->td_sigmask; 264 PROC_UNLOCK(td->td_proc); 265 ret = copyout(&uc, uap->ucp, UC_COPY_SIZE); 266 } 267 return (ret); 268 } 269 270 int 271 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 272 { 273 ucontext32_t uc; 274 int ret; 275 276 if (uap->ucp == NULL) 277 ret = EINVAL; 278 else { 279 ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 280 if (ret == 0) { 281 ret = set_mcontext32(td, &uc.uc_mcontext); 282 if (ret == 0) 283 kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, 284 NULL, 0); 285 } 286 } 287 return (ret); 288 } 289 290 int 291 freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap) 292 { 293 ucontext32_t uc; 294 int error; 295 296 if (uap == NULL) 297 return (EFAULT); 298 if (copyin(uap->sigcntxp, &uc, sizeof(uc))) 299 return (EFAULT); 300 error = set_mcontext32(td, &uc.uc_mcontext); 301 if (error != 0) 302 return (0); 303 304 /* Restore signal mask. */ 305 kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 306 307 return (EJUSTRETURN); 308 309 } 310 311 int 312 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 313 { 314 ucontext32_t uc; 315 int ret; 316 317 if (uap->oucp == NULL || uap->ucp == NULL) 318 ret = EINVAL; 319 else { 320 bzero(&uc, sizeof(uc)); 321 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 322 PROC_LOCK(td->td_proc); 323 uc.uc_sigmask = td->td_sigmask; 324 PROC_UNLOCK(td->td_proc); 325 ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE); 326 if (ret == 0) { 327 ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 328 if (ret == 0) { 329 ret = set_mcontext32(td, &uc.uc_mcontext); 330 kern_sigprocmask(td, SIG_SETMASK, 331 &uc.uc_sigmask, NULL, 0); 332 } 333 } 334 } 335 return (ret); 336 } 337 338 void 339 freebsd32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 340 { 341 struct thread *td; 342 struct proc *p; 343 struct trapframe *tf; 344 struct sigframe32 *fp, frame; 345 struct sigacts *psp; 346 struct siginfo32 siginfo; 347 struct sysentvec *sysent; 348 int onstack; 349 int sig; 350 351 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo); 352 td = curthread; 353 p = td->td_proc; 354 PROC_LOCK_ASSERT(p, MA_OWNED); 355 sig = ksi->ksi_signo; 356 psp = p->p_sigacts; 357 mtx_assert(&psp->ps_mtx, MA_OWNED); 358 tf = td->td_frame; 359 onstack = sigonstack(tf->tf_x[13]); 360 361 CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 362 catcher, sig); 363 364 /* Allocate and validate space for the signal handler context. */ 365 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !(onstack) && 366 SIGISMEMBER(psp->ps_sigonstack, sig)) { 367 fp = (struct sigframe32 *)((uintptr_t)td->td_sigstk.ss_sp + 368 td->td_sigstk.ss_size); 369 #if defined(COMPAT_43) 370 td->td_sigstk.ss_flags |= SS_ONSTACK; 371 #endif 372 } else 373 fp = (struct sigframe32 *)td->td_frame->tf_x[13]; 374 375 /* make room on the stack */ 376 fp--; 377 378 /* make the stack aligned */ 379 fp = (struct sigframe32 *)((unsigned long)(fp) &~ (8 - 1)); 380 /* Populate the siginfo frame. */ 381 get_mcontext32(td, &frame.sf_uc.uc_mcontext, 0); 382 #ifdef VFP 383 get_fpcontext32(td, &frame.sf_vfp); 384 frame.sf_uc.uc_mcontext.mc_vfp_size = sizeof(fp->sf_vfp); 385 frame.sf_uc.uc_mcontext.mc_vfp_ptr = (uint32_t)(uintptr_t)&fp->sf_vfp; 386 #else 387 frame.sf_uc.uc_mcontext.mc_vfp_size = 0; 388 frame.sf_uc.uc_mcontext.mc_vfp_ptr = (uint32_t)NULL; 389 #endif 390 frame.sf_si = siginfo; 391 frame.sf_uc.uc_sigmask = *mask; 392 frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK ) 393 ? ((onstack) ? SS_ONSTACK : 0) : SS_DISABLE; 394 frame.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 395 frame.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; 396 397 mtx_unlock(&psp->ps_mtx); 398 PROC_UNLOCK(td->td_proc); 399 400 /* Copy the sigframe out to the user's stack. */ 401 if (copyout(&frame, fp, sizeof(*fp)) != 0) { 402 /* Process has trashed its stack. Kill it. */ 403 CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp); 404 PROC_LOCK(p); 405 sigexit(td, SIGILL); 406 } 407 408 /* 409 * Build context to run handler in. We invoke the handler 410 * directly, only returning via the trampoline. Note the 411 * trampoline version numbers are coordinated with machine- 412 * dependent code in libc. 413 */ 414 415 tf->tf_x[0] = sig; 416 tf->tf_x[1] = (register_t)&fp->sf_si; 417 tf->tf_x[2] = (register_t)&fp->sf_uc; 418 419 /* the trampoline uses r5 as the uc address */ 420 tf->tf_x[5] = (register_t)&fp->sf_uc; 421 tf->tf_elr = (register_t)catcher; 422 tf->tf_x[13] = (register_t)fp; 423 sysent = p->p_sysent; 424 if (PROC_HAS_SHP(p)) 425 tf->tf_x[14] = (register_t)PROC_SIGCODE(p); 426 else 427 tf->tf_x[14] = (register_t)(PROC_PS_STRINGS(p) - 428 *(sysent->sv_szsigcode)); 429 /* Set the mode to enter in the signal handler */ 430 if ((register_t)catcher & 1) 431 tf->tf_spsr |= PSR_T; 432 else 433 tf->tf_spsr &= ~PSR_T; 434 435 /* Clear the single step flag while in the signal handler */ 436 if ((td->td_pcb->pcb_flags & PCB_SINGLE_STEP) != 0) { 437 td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP; 438 WRITE_SPECIALREG(mdscr_el1, 439 READ_SPECIALREG(mdscr_el1) & ~MDSCR_SS); 440 isb(); 441 } 442 443 CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_x[14], 444 tf->tf_x[13]); 445 446 PROC_LOCK(p); 447 mtx_lock(&psp->ps_mtx); 448 449 } 450 451 #ifdef COMPAT_43 452 /* 453 * Mirror the osigreturn definition in kern_sig.c for !i386 platforms. This 454 * mirrors what's connected to the FreeBSD/arm syscall. 455 */ 456 int 457 ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap) 458 { 459 460 return (nosys(td, (struct nosys_args *)uap)); 461 } 462 #endif 463