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