1 /*- 2 * SPDX-License-Identifier: BSD-4-Clause AND BSD-2-Clause-FreeBSD 3 * 4 * Copyright (C) 1995, 1996 Wolfgang Solfrank. 5 * Copyright (C) 1995, 1996 TooLs GmbH. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by TooLs GmbH. 19 * 4. The name of TooLs GmbH may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 /*- 34 * Copyright (C) 2001 Benno Rice 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 46 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 49 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 52 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 53 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 54 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 55 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $ 57 */ 58 59 #include <sys/cdefs.h> 60 __FBSDID("$FreeBSD$"); 61 62 #include "opt_fpu_emu.h" 63 64 #include <sys/param.h> 65 #include <sys/proc.h> 66 #include <sys/systm.h> 67 #include <sys/bio.h> 68 #include <sys/buf.h> 69 #include <sys/bus.h> 70 #include <sys/cons.h> 71 #include <sys/cpu.h> 72 #include <sys/exec.h> 73 #include <sys/imgact.h> 74 #include <sys/kernel.h> 75 #include <sys/ktr.h> 76 #include <sys/lock.h> 77 #include <sys/malloc.h> 78 #include <sys/mutex.h> 79 #include <sys/signalvar.h> 80 #include <sys/syscallsubr.h> 81 #include <sys/syscall.h> 82 #include <sys/sysent.h> 83 #include <sys/sysproto.h> 84 #include <sys/ucontext.h> 85 #include <sys/uio.h> 86 87 #include <machine/altivec.h> 88 #include <machine/cpu.h> 89 #include <machine/elf.h> 90 #include <machine/fpu.h> 91 #include <machine/pcb.h> 92 #include <machine/reg.h> 93 #include <machine/sigframe.h> 94 #include <machine/trap.h> 95 #include <machine/vmparam.h> 96 97 #include <vm/pmap.h> 98 99 #ifdef FPU_EMU 100 #include <powerpc/fpu/fpu_extern.h> 101 #endif 102 103 #ifdef COMPAT_FREEBSD32 104 #include <compat/freebsd32/freebsd32_signal.h> 105 #include <compat/freebsd32/freebsd32_util.h> 106 #include <compat/freebsd32/freebsd32_proto.h> 107 108 typedef struct __ucontext32 { 109 sigset_t uc_sigmask; 110 mcontext32_t uc_mcontext; 111 uint32_t uc_link; 112 struct sigaltstack32 uc_stack; 113 uint32_t uc_flags; 114 uint32_t __spare__[4]; 115 } ucontext32_t; 116 117 struct sigframe32 { 118 ucontext32_t sf_uc; 119 struct siginfo32 sf_si; 120 }; 121 122 static int grab_mcontext32(struct thread *td, mcontext32_t *, int flags); 123 #endif 124 125 static int grab_mcontext(struct thread *, mcontext_t *, int); 126 127 #ifdef __powerpc64__ 128 extern struct sysentvec elf64_freebsd_sysvec_v2; 129 #endif 130 131 void 132 sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 133 { 134 struct trapframe *tf; 135 struct sigacts *psp; 136 struct sigframe sf; 137 struct thread *td; 138 struct proc *p; 139 #ifdef COMPAT_FREEBSD32 140 struct siginfo32 siginfo32; 141 struct sigframe32 sf32; 142 #endif 143 size_t sfpsize; 144 caddr_t sfp, usfp; 145 int oonstack, rndfsize; 146 int sig; 147 int code; 148 149 td = curthread; 150 p = td->td_proc; 151 PROC_LOCK_ASSERT(p, MA_OWNED); 152 153 psp = p->p_sigacts; 154 mtx_assert(&psp->ps_mtx, MA_OWNED); 155 tf = td->td_frame; 156 oonstack = sigonstack(tf->fixreg[1]); 157 158 /* 159 * Fill siginfo structure. 160 */ 161 ksi->ksi_info.si_signo = ksi->ksi_signo; 162 ksi->ksi_info.si_addr = 163 (void *)((tf->exc == EXC_DSI || tf->exc == EXC_DSE) ? 164 tf->dar : tf->srr0); 165 166 #ifdef COMPAT_FREEBSD32 167 if (SV_PROC_FLAG(p, SV_ILP32)) { 168 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo32); 169 sig = siginfo32.si_signo; 170 code = siginfo32.si_code; 171 sfp = (caddr_t)&sf32; 172 sfpsize = sizeof(sf32); 173 rndfsize = roundup(sizeof(sf32), 16); 174 175 /* 176 * Save user context 177 */ 178 179 memset(&sf32, 0, sizeof(sf32)); 180 grab_mcontext32(td, &sf32.sf_uc.uc_mcontext, 0); 181 182 sf32.sf_uc.uc_sigmask = *mask; 183 sf32.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 184 sf32.sf_uc.uc_stack.ss_size = (uint32_t)td->td_sigstk.ss_size; 185 sf32.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 186 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 187 188 sf32.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 189 } else { 190 #endif 191 sig = ksi->ksi_signo; 192 code = ksi->ksi_code; 193 sfp = (caddr_t)&sf; 194 sfpsize = sizeof(sf); 195 #ifdef __powerpc64__ 196 /* 197 * 64-bit PPC defines a 288 byte scratch region 198 * below the stack. 199 */ 200 rndfsize = 288 + roundup(sizeof(sf), 48); 201 #else 202 rndfsize = roundup(sizeof(sf), 16); 203 #endif 204 205 /* 206 * Save user context 207 */ 208 209 memset(&sf, 0, sizeof(sf)); 210 grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0); 211 212 sf.sf_uc.uc_sigmask = *mask; 213 sf.sf_uc.uc_stack = td->td_sigstk; 214 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 215 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 216 217 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 218 #ifdef COMPAT_FREEBSD32 219 } 220 #endif 221 222 CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 223 catcher, sig); 224 225 /* 226 * Allocate and validate space for the signal handler context. 227 */ 228 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 229 SIGISMEMBER(psp->ps_sigonstack, sig)) { 230 usfp = (void *)(((uintptr_t)td->td_sigstk.ss_sp + 231 td->td_sigstk.ss_size - rndfsize) & ~0xFul); 232 } else { 233 usfp = (void *)((tf->fixreg[1] - rndfsize) & ~0xFul); 234 } 235 236 /* 237 * Save the floating-point state, if necessary, then copy it. 238 */ 239 /* XXX */ 240 241 /* 242 * Set up the registers to return to sigcode. 243 * 244 * r1/sp - sigframe ptr 245 * lr - sig function, dispatched to by blrl in trampoline 246 * r3 - sig number 247 * r4 - SIGINFO ? &siginfo : exception code 248 * r5 - user context 249 * srr0 - trampoline function addr 250 */ 251 tf->lr = (register_t)catcher; 252 tf->fixreg[1] = (register_t)usfp; 253 tf->fixreg[FIRSTARG] = sig; 254 #ifdef COMPAT_FREEBSD32 255 tf->fixreg[FIRSTARG+2] = (register_t)usfp + 256 ((SV_PROC_FLAG(p, SV_ILP32)) ? 257 offsetof(struct sigframe32, sf_uc) : 258 offsetof(struct sigframe, sf_uc)); 259 #else 260 tf->fixreg[FIRSTARG+2] = (register_t)usfp + 261 offsetof(struct sigframe, sf_uc); 262 #endif 263 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 264 /* 265 * Signal handler installed with SA_SIGINFO. 266 */ 267 #ifdef COMPAT_FREEBSD32 268 if (SV_PROC_FLAG(p, SV_ILP32)) { 269 sf32.sf_si = siginfo32; 270 tf->fixreg[FIRSTARG+1] = (register_t)usfp + 271 offsetof(struct sigframe32, sf_si); 272 sf32.sf_si = siginfo32; 273 } else { 274 #endif 275 tf->fixreg[FIRSTARG+1] = (register_t)usfp + 276 offsetof(struct sigframe, sf_si); 277 sf.sf_si = ksi->ksi_info; 278 #ifdef COMPAT_FREEBSD32 279 } 280 #endif 281 } else { 282 /* Old FreeBSD-style arguments. */ 283 tf->fixreg[FIRSTARG+1] = code; 284 tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 285 tf->dar : tf->srr0; 286 } 287 mtx_unlock(&psp->ps_mtx); 288 PROC_UNLOCK(p); 289 290 tf->srr0 = (register_t)p->p_sysent->sv_sigcode_base; 291 292 /* 293 * copy the frame out to userland. 294 */ 295 if (copyout(sfp, usfp, sfpsize) != 0) { 296 /* 297 * Process has trashed its stack. Kill it. 298 */ 299 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 300 PROC_LOCK(p); 301 sigexit(td, SIGILL); 302 } 303 304 CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, 305 tf->srr0, tf->fixreg[1]); 306 307 PROC_LOCK(p); 308 mtx_lock(&psp->ps_mtx); 309 } 310 311 int 312 sys_sigreturn(struct thread *td, struct sigreturn_args *uap) 313 { 314 ucontext_t uc; 315 int error; 316 317 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 318 319 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 320 CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 321 return (EFAULT); 322 } 323 324 error = set_mcontext(td, &uc.uc_mcontext); 325 if (error != 0) 326 return (error); 327 328 kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 329 330 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 331 td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 332 333 return (EJUSTRETURN); 334 } 335 336 #ifdef COMPAT_FREEBSD4 337 int 338 freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) 339 { 340 341 return sys_sigreturn(td, (struct sigreturn_args *)uap); 342 } 343 #endif 344 345 /* 346 * Construct a PCB from a trapframe. This is called from kdb_trap() where 347 * we want to start a backtrace from the function that caused us to enter 348 * the debugger. We have the context in the trapframe, but base the trace 349 * on the PCB. The PCB doesn't have to be perfect, as long as it contains 350 * enough for a backtrace. 351 */ 352 void 353 makectx(struct trapframe *tf, struct pcb *pcb) 354 { 355 356 pcb->pcb_lr = tf->srr0; 357 pcb->pcb_sp = tf->fixreg[1]; 358 } 359 360 /* 361 * get_mcontext/sendsig helper routine that doesn't touch the 362 * proc lock 363 */ 364 static int 365 grab_mcontext(struct thread *td, mcontext_t *mcp, int flags) 366 { 367 struct pcb *pcb; 368 int i; 369 370 pcb = td->td_pcb; 371 372 memset(mcp, 0, sizeof(mcontext_t)); 373 374 mcp->mc_vers = _MC_VERSION; 375 mcp->mc_flags = 0; 376 memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe)); 377 if (flags & GET_MC_CLEAR_RET) { 378 mcp->mc_gpr[3] = 0; 379 mcp->mc_gpr[4] = 0; 380 } 381 382 /* 383 * This assumes that floating-point context is *not* lazy, 384 * so if the thread has used FP there would have been a 385 * FP-unavailable exception that would have set things up 386 * correctly. 387 */ 388 if (pcb->pcb_flags & PCB_FPREGS) { 389 if (pcb->pcb_flags & PCB_FPU) { 390 KASSERT(td == curthread, 391 ("get_mcontext: fp save not curthread")); 392 critical_enter(); 393 save_fpu(td); 394 critical_exit(); 395 } 396 mcp->mc_flags |= _MC_FP_VALID; 397 memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double)); 398 for (i = 0; i < 32; i++) 399 memcpy(&mcp->mc_fpreg[i], &pcb->pcb_fpu.fpr[i].fpr, 400 sizeof(double)); 401 } 402 403 if (pcb->pcb_flags & PCB_VSX) { 404 for (i = 0; i < 32; i++) 405 memcpy(&mcp->mc_vsxfpreg[i], 406 &pcb->pcb_fpu.fpr[i].vsr[2], sizeof(double)); 407 } 408 409 /* 410 * Repeat for Altivec context 411 */ 412 413 if (pcb->pcb_flags & PCB_VEC) { 414 KASSERT(td == curthread, 415 ("get_mcontext: fp save not curthread")); 416 critical_enter(); 417 save_vec(td); 418 critical_exit(); 419 mcp->mc_flags |= _MC_AV_VALID; 420 mcp->mc_vscr = pcb->pcb_vec.vscr; 421 mcp->mc_vrsave = pcb->pcb_vec.vrsave; 422 memcpy(mcp->mc_avec, pcb->pcb_vec.vr, sizeof(mcp->mc_avec)); 423 } 424 425 mcp->mc_len = sizeof(*mcp); 426 427 return (0); 428 } 429 430 int 431 get_mcontext(struct thread *td, mcontext_t *mcp, int flags) 432 { 433 int error; 434 435 error = grab_mcontext(td, mcp, flags); 436 if (error == 0) { 437 PROC_LOCK(curthread->td_proc); 438 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 439 PROC_UNLOCK(curthread->td_proc); 440 } 441 442 return (error); 443 } 444 445 int 446 set_mcontext(struct thread *td, mcontext_t *mcp) 447 { 448 struct pcb *pcb; 449 struct trapframe *tf; 450 register_t tls; 451 int i; 452 453 pcb = td->td_pcb; 454 tf = td->td_frame; 455 456 if (mcp->mc_vers != _MC_VERSION || mcp->mc_len != sizeof(*mcp)) 457 return (EINVAL); 458 459 /* 460 * Don't let the user set privileged MSR bits 461 */ 462 if ((mcp->mc_srr1 & psl_userstatic) != (tf->srr1 & psl_userstatic)) { 463 return (EINVAL); 464 } 465 466 /* Copy trapframe, preserving TLS pointer across context change */ 467 if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 468 tls = tf->fixreg[13]; 469 else 470 tls = tf->fixreg[2]; 471 memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame)); 472 if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 473 tf->fixreg[13] = tls; 474 else 475 tf->fixreg[2] = tls; 476 477 /* Disable FPU */ 478 tf->srr1 &= ~PSL_FP; 479 pcb->pcb_flags &= ~PCB_FPU; 480 481 if (mcp->mc_flags & _MC_FP_VALID) { 482 /* enable_fpu() will happen lazily on a fault */ 483 pcb->pcb_flags |= PCB_FPREGS; 484 memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double)); 485 bzero(pcb->pcb_fpu.fpr, sizeof(pcb->pcb_fpu.fpr)); 486 for (i = 0; i < 32; i++) { 487 memcpy(&pcb->pcb_fpu.fpr[i].fpr, &mcp->mc_fpreg[i], 488 sizeof(double)); 489 memcpy(&pcb->pcb_fpu.fpr[i].vsr[2], 490 &mcp->mc_vsxfpreg[i], sizeof(double)); 491 } 492 } 493 494 if (mcp->mc_flags & _MC_AV_VALID) { 495 if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) { 496 critical_enter(); 497 enable_vec(td); 498 critical_exit(); 499 } 500 pcb->pcb_vec.vscr = mcp->mc_vscr; 501 pcb->pcb_vec.vrsave = mcp->mc_vrsave; 502 memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec)); 503 } 504 505 return (0); 506 } 507 508 /* 509 * Set set up registers on exec. 510 */ 511 void 512 exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) 513 { 514 struct trapframe *tf; 515 register_t argc; 516 517 tf = trapframe(td); 518 bzero(tf, sizeof *tf); 519 #ifdef __powerpc64__ 520 tf->fixreg[1] = -roundup(-stack + 48, 16); 521 #else 522 tf->fixreg[1] = -roundup(-stack + 8, 16); 523 #endif 524 525 /* 526 * Set up arguments for _start(): 527 * _start(argc, argv, envp, obj, cleanup, ps_strings); 528 * 529 * Notes: 530 * - obj and cleanup are the auxilliary and termination 531 * vectors. They are fixed up by ld.elf_so. 532 * - ps_strings is a NetBSD extention, and will be 533 * ignored by executables which are strictly 534 * compliant with the SVR4 ABI. 535 */ 536 537 /* Collect argc from the user stack */ 538 argc = fuword((void *)stack); 539 540 tf->fixreg[3] = argc; 541 tf->fixreg[4] = stack + sizeof(register_t); 542 tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t); 543 tf->fixreg[6] = 0; /* auxillary vector */ 544 tf->fixreg[7] = 0; /* termination vector */ 545 tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 546 547 tf->srr0 = imgp->entry_addr; 548 #ifdef __powerpc64__ 549 tf->fixreg[12] = imgp->entry_addr; 550 #endif 551 tf->srr1 = psl_userset | PSL_FE_DFLT; 552 td->td_pcb->pcb_flags = 0; 553 } 554 555 #ifdef COMPAT_FREEBSD32 556 void 557 ppc32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 558 { 559 struct trapframe *tf; 560 uint32_t argc; 561 562 tf = trapframe(td); 563 bzero(tf, sizeof *tf); 564 tf->fixreg[1] = -roundup(-stack + 8, 16); 565 566 argc = fuword32((void *)stack); 567 568 tf->fixreg[3] = argc; 569 tf->fixreg[4] = stack + sizeof(uint32_t); 570 tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t); 571 tf->fixreg[6] = 0; /* auxillary vector */ 572 tf->fixreg[7] = 0; /* termination vector */ 573 tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 574 575 tf->srr0 = imgp->entry_addr; 576 tf->srr1 = psl_userset32 | PSL_FE_DFLT; 577 td->td_pcb->pcb_flags = 0; 578 } 579 #endif 580 581 int 582 fill_regs(struct thread *td, struct reg *regs) 583 { 584 struct trapframe *tf; 585 586 tf = td->td_frame; 587 memcpy(regs, tf, sizeof(struct reg)); 588 589 return (0); 590 } 591 592 int 593 fill_dbregs(struct thread *td, struct dbreg *dbregs) 594 { 595 /* No debug registers on PowerPC */ 596 return (ENOSYS); 597 } 598 599 int 600 fill_fpregs(struct thread *td, struct fpreg *fpregs) 601 { 602 struct pcb *pcb; 603 int i; 604 605 pcb = td->td_pcb; 606 607 if ((pcb->pcb_flags & PCB_FPREGS) == 0) 608 memset(fpregs, 0, sizeof(struct fpreg)); 609 else { 610 memcpy(&fpregs->fpscr, &pcb->pcb_fpu.fpscr, sizeof(double)); 611 for (i = 0; i < 32; i++) 612 memcpy(&fpregs->fpreg[i], &pcb->pcb_fpu.fpr[i].fpr, 613 sizeof(double)); 614 } 615 616 return (0); 617 } 618 619 int 620 set_regs(struct thread *td, struct reg *regs) 621 { 622 struct trapframe *tf; 623 624 tf = td->td_frame; 625 memcpy(tf, regs, sizeof(struct reg)); 626 627 return (0); 628 } 629 630 int 631 set_dbregs(struct thread *td, struct dbreg *dbregs) 632 { 633 /* No debug registers on PowerPC */ 634 return (ENOSYS); 635 } 636 637 int 638 set_fpregs(struct thread *td, struct fpreg *fpregs) 639 { 640 struct pcb *pcb; 641 int i; 642 643 pcb = td->td_pcb; 644 pcb->pcb_flags |= PCB_FPREGS; 645 memcpy(&pcb->pcb_fpu.fpscr, &fpregs->fpscr, sizeof(double)); 646 for (i = 0; i < 32; i++) { 647 memcpy(&pcb->pcb_fpu.fpr[i].fpr, &fpregs->fpreg[i], 648 sizeof(double)); 649 } 650 651 return (0); 652 } 653 654 #ifdef COMPAT_FREEBSD32 655 int 656 set_regs32(struct thread *td, struct reg32 *regs) 657 { 658 struct trapframe *tf; 659 int i; 660 661 tf = td->td_frame; 662 for (i = 0; i < 32; i++) 663 tf->fixreg[i] = regs->fixreg[i]; 664 tf->lr = regs->lr; 665 tf->cr = regs->cr; 666 tf->xer = regs->xer; 667 tf->ctr = regs->ctr; 668 tf->srr0 = regs->pc; 669 670 return (0); 671 } 672 673 int 674 fill_regs32(struct thread *td, struct reg32 *regs) 675 { 676 struct trapframe *tf; 677 int i; 678 679 tf = td->td_frame; 680 for (i = 0; i < 32; i++) 681 regs->fixreg[i] = tf->fixreg[i]; 682 regs->lr = tf->lr; 683 regs->cr = tf->cr; 684 regs->xer = tf->xer; 685 regs->ctr = tf->ctr; 686 regs->pc = tf->srr0; 687 688 return (0); 689 } 690 691 static int 692 grab_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 693 { 694 mcontext_t mcp64; 695 int i, error; 696 697 error = grab_mcontext(td, &mcp64, flags); 698 if (error != 0) 699 return (error); 700 701 mcp->mc_vers = mcp64.mc_vers; 702 mcp->mc_flags = mcp64.mc_flags; 703 mcp->mc_onstack = mcp64.mc_onstack; 704 mcp->mc_len = mcp64.mc_len; 705 memcpy(mcp->mc_avec,mcp64.mc_avec,sizeof(mcp64.mc_avec)); 706 memcpy(mcp->mc_av,mcp64.mc_av,sizeof(mcp64.mc_av)); 707 for (i = 0; i < 42; i++) 708 mcp->mc_frame[i] = mcp64.mc_frame[i]; 709 memcpy(mcp->mc_fpreg,mcp64.mc_fpreg,sizeof(mcp64.mc_fpreg)); 710 memcpy(mcp->mc_vsxfpreg,mcp64.mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg)); 711 712 return (0); 713 } 714 715 static int 716 get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 717 { 718 int error; 719 720 error = grab_mcontext32(td, mcp, flags); 721 if (error == 0) { 722 PROC_LOCK(curthread->td_proc); 723 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 724 PROC_UNLOCK(curthread->td_proc); 725 } 726 727 return (error); 728 } 729 730 static int 731 set_mcontext32(struct thread *td, mcontext32_t *mcp) 732 { 733 mcontext_t mcp64; 734 int i, error; 735 736 mcp64.mc_vers = mcp->mc_vers; 737 mcp64.mc_flags = mcp->mc_flags; 738 mcp64.mc_onstack = mcp->mc_onstack; 739 mcp64.mc_len = mcp->mc_len; 740 memcpy(mcp64.mc_avec,mcp->mc_avec,sizeof(mcp64.mc_avec)); 741 memcpy(mcp64.mc_av,mcp->mc_av,sizeof(mcp64.mc_av)); 742 for (i = 0; i < 42; i++) 743 mcp64.mc_frame[i] = mcp->mc_frame[i]; 744 mcp64.mc_srr1 |= (td->td_frame->srr1 & 0xFFFFFFFF00000000ULL); 745 memcpy(mcp64.mc_fpreg,mcp->mc_fpreg,sizeof(mcp64.mc_fpreg)); 746 memcpy(mcp64.mc_vsxfpreg,mcp->mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg)); 747 748 error = set_mcontext(td, &mcp64); 749 750 return (error); 751 } 752 #endif 753 754 #ifdef COMPAT_FREEBSD32 755 int 756 freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap) 757 { 758 ucontext32_t uc; 759 int error; 760 761 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 762 763 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 764 CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 765 return (EFAULT); 766 } 767 768 error = set_mcontext32(td, &uc.uc_mcontext); 769 if (error != 0) 770 return (error); 771 772 kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 773 774 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 775 td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 776 777 return (EJUSTRETURN); 778 } 779 780 /* 781 * The first two fields of a ucontext_t are the signal mask and the machine 782 * context. The next field is uc_link; we want to avoid destroying the link 783 * when copying out contexts. 784 */ 785 #define UC32_COPY_SIZE offsetof(ucontext32_t, uc_link) 786 787 int 788 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 789 { 790 ucontext32_t uc; 791 int ret; 792 793 if (uap->ucp == NULL) 794 ret = EINVAL; 795 else { 796 bzero(&uc, sizeof(uc)); 797 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 798 PROC_LOCK(td->td_proc); 799 uc.uc_sigmask = td->td_sigmask; 800 PROC_UNLOCK(td->td_proc); 801 ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE); 802 } 803 return (ret); 804 } 805 806 int 807 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 808 { 809 ucontext32_t uc; 810 int ret; 811 812 if (uap->ucp == NULL) 813 ret = EINVAL; 814 else { 815 ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 816 if (ret == 0) { 817 ret = set_mcontext32(td, &uc.uc_mcontext); 818 if (ret == 0) { 819 kern_sigprocmask(td, SIG_SETMASK, 820 &uc.uc_sigmask, NULL, 0); 821 } 822 } 823 } 824 return (ret == 0 ? EJUSTRETURN : ret); 825 } 826 827 int 828 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 829 { 830 ucontext32_t uc; 831 int ret; 832 833 if (uap->oucp == NULL || uap->ucp == NULL) 834 ret = EINVAL; 835 else { 836 bzero(&uc, sizeof(uc)); 837 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 838 PROC_LOCK(td->td_proc); 839 uc.uc_sigmask = td->td_sigmask; 840 PROC_UNLOCK(td->td_proc); 841 ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE); 842 if (ret == 0) { 843 ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 844 if (ret == 0) { 845 ret = set_mcontext32(td, &uc.uc_mcontext); 846 if (ret == 0) { 847 kern_sigprocmask(td, SIG_SETMASK, 848 &uc.uc_sigmask, NULL, 0); 849 } 850 } 851 } 852 } 853 return (ret == 0 ? EJUSTRETURN : ret); 854 } 855 856 #endif 857 858 void 859 cpu_set_syscall_retval(struct thread *td, int error) 860 { 861 struct proc *p; 862 struct trapframe *tf; 863 int fixup; 864 865 if (error == EJUSTRETURN) 866 return; 867 868 p = td->td_proc; 869 tf = td->td_frame; 870 871 if (tf->fixreg[0] == SYS___syscall && 872 (SV_PROC_FLAG(p, SV_ILP32))) { 873 int code = tf->fixreg[FIRSTARG + 1]; 874 fixup = ( 875 #if defined(COMPAT_FREEBSD6) && defined(SYS_freebsd6_lseek) 876 code != SYS_freebsd6_lseek && 877 #endif 878 code != SYS_lseek) ? 1 : 0; 879 } else 880 fixup = 0; 881 882 switch (error) { 883 case 0: 884 if (fixup) { 885 /* 886 * 64-bit return, 32-bit syscall. Fixup byte order 887 */ 888 tf->fixreg[FIRSTARG] = 0; 889 tf->fixreg[FIRSTARG + 1] = td->td_retval[0]; 890 } else { 891 tf->fixreg[FIRSTARG] = td->td_retval[0]; 892 tf->fixreg[FIRSTARG + 1] = td->td_retval[1]; 893 } 894 tf->cr &= ~0x10000000; /* Unset summary overflow */ 895 break; 896 case ERESTART: 897 /* 898 * Set user's pc back to redo the system call. 899 */ 900 tf->srr0 -= 4; 901 break; 902 default: 903 tf->fixreg[FIRSTARG] = SV_ABI_ERRNO(p, error); 904 tf->cr |= 0x10000000; /* Set summary overflow */ 905 break; 906 } 907 } 908 909 /* 910 * Threading functions 911 */ 912 void 913 cpu_thread_exit(struct thread *td) 914 { 915 } 916 917 void 918 cpu_thread_clean(struct thread *td) 919 { 920 } 921 922 void 923 cpu_thread_alloc(struct thread *td) 924 { 925 struct pcb *pcb; 926 927 pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 928 sizeof(struct pcb)) & ~0x2fUL); 929 td->td_pcb = pcb; 930 td->td_frame = (struct trapframe *)pcb - 1; 931 } 932 933 void 934 cpu_thread_free(struct thread *td) 935 { 936 } 937 938 int 939 cpu_set_user_tls(struct thread *td, void *tls_base) 940 { 941 942 if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 943 td->td_frame->fixreg[13] = (register_t)tls_base + 0x7010; 944 else 945 td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008; 946 return (0); 947 } 948 949 void 950 cpu_copy_thread(struct thread *td, struct thread *td0) 951 { 952 struct pcb *pcb2; 953 struct trapframe *tf; 954 struct callframe *cf; 955 956 pcb2 = td->td_pcb; 957 958 /* Copy the upcall pcb */ 959 bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); 960 961 /* Create a stack for the new thread */ 962 tf = td->td_frame; 963 bcopy(td0->td_frame, tf, sizeof(struct trapframe)); 964 tf->fixreg[FIRSTARG] = 0; 965 tf->fixreg[FIRSTARG + 1] = 0; 966 tf->cr &= ~0x10000000; 967 968 /* Set registers for trampoline to user mode. */ 969 cf = (struct callframe *)tf - 1; 970 memset(cf, 0, sizeof(struct callframe)); 971 cf->cf_func = (register_t)fork_return; 972 cf->cf_arg0 = (register_t)td; 973 cf->cf_arg1 = (register_t)tf; 974 975 pcb2->pcb_sp = (register_t)cf; 976 #if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1) 977 pcb2->pcb_lr = ((register_t *)fork_trampoline)[0]; 978 pcb2->pcb_toc = ((register_t *)fork_trampoline)[1]; 979 #else 980 pcb2->pcb_lr = (register_t)fork_trampoline; 981 pcb2->pcb_context[0] = pcb2->pcb_lr; 982 #endif 983 pcb2->pcb_cpu.aim.usr_vsid = 0; 984 #ifdef __SPE__ 985 pcb2->pcb_vec.vscr = SPEFSCR_FINVE | SPEFSCR_FDBZE | 986 SPEFSCR_FUNFE | SPEFSCR_FOVFE; 987 #endif 988 989 /* Setup to release spin count in fork_exit(). */ 990 td->td_md.md_spinlock_count = 1; 991 td->td_md.md_saved_msr = psl_kernset; 992 } 993 994 void 995 cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg, 996 stack_t *stack) 997 { 998 struct trapframe *tf; 999 uintptr_t sp; 1000 1001 tf = td->td_frame; 1002 /* align stack and alloc space for frame ptr and saved LR */ 1003 #ifdef __powerpc64__ 1004 sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 48) & 1005 ~0x1f; 1006 #else 1007 sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) & 1008 ~0x1f; 1009 #endif 1010 bzero(tf, sizeof(struct trapframe)); 1011 1012 tf->fixreg[1] = (register_t)sp; 1013 tf->fixreg[3] = (register_t)arg; 1014 if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) { 1015 tf->srr0 = (register_t)entry; 1016 #ifdef __powerpc64__ 1017 tf->srr1 = psl_userset32 | PSL_FE_DFLT; 1018 #else 1019 tf->srr1 = psl_userset | PSL_FE_DFLT; 1020 #endif 1021 } else { 1022 #ifdef __powerpc64__ 1023 if (td->td_proc->p_sysent == &elf64_freebsd_sysvec_v2) { 1024 tf->srr0 = (register_t)entry; 1025 /* ELFv2 ABI requires that the global entry point be in r12. */ 1026 tf->fixreg[12] = (register_t)entry; 1027 } 1028 else { 1029 register_t entry_desc[3]; 1030 (void)copyin((void *)entry, entry_desc, sizeof(entry_desc)); 1031 tf->srr0 = entry_desc[0]; 1032 tf->fixreg[2] = entry_desc[1]; 1033 tf->fixreg[11] = entry_desc[2]; 1034 } 1035 tf->srr1 = psl_userset | PSL_FE_DFLT; 1036 #endif 1037 } 1038 1039 td->td_pcb->pcb_flags = 0; 1040 #ifdef __SPE__ 1041 td->td_pcb->pcb_vec.vscr = SPEFSCR_FINVE | SPEFSCR_FDBZE | 1042 SPEFSCR_FUNFE | SPEFSCR_FOVFE; 1043 #endif 1044 1045 td->td_retval[0] = (register_t)entry; 1046 td->td_retval[1] = 0; 1047 } 1048 1049 static int 1050 emulate_mfspr(int spr, int reg, struct trapframe *frame){ 1051 struct thread *td; 1052 1053 td = curthread; 1054 1055 if (spr == SPR_DSCR) { 1056 // If DSCR was never set, get the default DSCR 1057 if ((td->td_pcb->pcb_flags & PCB_CDSCR) == 0) 1058 td->td_pcb->pcb_dscr = mfspr(SPR_DSCR); 1059 1060 frame->fixreg[reg] = td->td_pcb->pcb_dscr; 1061 frame->srr0 += 4; 1062 return 0; 1063 } else 1064 return SIGILL; 1065 } 1066 1067 static int 1068 emulate_mtspr(int spr, int reg, struct trapframe *frame){ 1069 struct thread *td; 1070 1071 td = curthread; 1072 1073 if (spr == SPR_DSCR) { 1074 td->td_pcb->pcb_flags |= PCB_CDSCR; 1075 td->td_pcb->pcb_dscr = frame->fixreg[reg]; 1076 frame->srr0 += 4; 1077 return 0; 1078 } else 1079 return SIGILL; 1080 } 1081 1082 #define XFX 0xFC0007FF 1083 int 1084 ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb) 1085 { 1086 uint32_t instr; 1087 int reg, sig; 1088 int rs, spr; 1089 1090 instr = fuword32((void *)frame->srr0); 1091 sig = SIGILL; 1092 1093 if ((instr & 0xfc1fffff) == 0x7c1f42a6) { /* mfpvr */ 1094 reg = (instr & ~0xfc1fffff) >> 21; 1095 frame->fixreg[reg] = mfpvr(); 1096 frame->srr0 += 4; 1097 return (0); 1098 } else if ((instr & XFX) == 0x7c0002a6) { /* mfspr */ 1099 rs = (instr & 0x3e00000) >> 21; 1100 spr = (instr & 0x1ff800) >> 16; 1101 return emulate_mfspr(spr, rs, frame); 1102 } else if ((instr & XFX) == 0x7c0003a6) { /* mtspr */ 1103 rs = (instr & 0x3e00000) >> 21; 1104 spr = (instr & 0x1ff800) >> 16; 1105 return emulate_mtspr(spr, rs, frame); 1106 } else if ((instr & 0xfc000ffe) == 0x7c0004ac) { /* various sync */ 1107 powerpc_sync(); /* Do a heavy-weight sync */ 1108 frame->srr0 += 4; 1109 return (0); 1110 } 1111 1112 #ifdef FPU_EMU 1113 if (!(pcb->pcb_flags & PCB_FPREGS)) { 1114 bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu)); 1115 pcb->pcb_flags |= PCB_FPREGS; 1116 } 1117 sig = fpu_emulate(frame, &pcb->pcb_fpu); 1118 #endif 1119 if (sig == SIGILL) { 1120 if (pcb->pcb_lastill != frame->srr0) { 1121 /* Allow a second chance, in case of cache sync issues. */ 1122 sig = 0; 1123 pmap_sync_icache(PCPU_GET(curpmap), frame->srr0, 4); 1124 pcb->pcb_lastill = frame->srr0; 1125 } 1126 } 1127 1128 return (sig); 1129 } 1130 1131