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