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