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