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 62 #include <sys/param.h> 63 #include <sys/proc.h> 64 #include <sys/systm.h> 65 #include <sys/bio.h> 66 #include <sys/buf.h> 67 #include <sys/bus.h> 68 #include <sys/cons.h> 69 #include <sys/cpu.h> 70 #include <sys/exec.h> 71 #include <sys/imgact.h> 72 #include <sys/kernel.h> 73 #include <sys/ktr.h> 74 #include <sys/lock.h> 75 #include <sys/malloc.h> 76 #include <sys/mutex.h> 77 #include <sys/signalvar.h> 78 #include <sys/syscallsubr.h> 79 #include <sys/syscall.h> 80 #include <sys/sysent.h> 81 #include <sys/sysproto.h> 82 #include <sys/ucontext.h> 83 #include <sys/uio.h> 84 85 #include <machine/altivec.h> 86 #include <machine/cpu.h> 87 #include <machine/elf.h> 88 #include <machine/fpu.h> 89 #include <machine/pcb.h> 90 #include <machine/reg.h> 91 #include <machine/sigframe.h> 92 #include <machine/trap.h> 93 #include <machine/vmparam.h> 94 95 #ifdef COMPAT_FREEBSD32 96 #include <compat/freebsd32/freebsd32_signal.h> 97 #include <compat/freebsd32/freebsd32_util.h> 98 #include <compat/freebsd32/freebsd32_proto.h> 99 100 typedef struct __ucontext32 { 101 sigset_t uc_sigmask; 102 mcontext32_t uc_mcontext; 103 uint32_t uc_link; 104 struct sigaltstack32 uc_stack; 105 uint32_t uc_flags; 106 uint32_t __spare__[4]; 107 } ucontext32_t; 108 109 struct sigframe32 { 110 ucontext32_t sf_uc; 111 struct siginfo32 sf_si; 112 }; 113 114 static int grab_mcontext32(struct thread *td, mcontext32_t *, int flags); 115 #endif 116 117 static int grab_mcontext(struct thread *, mcontext_t *, int); 118 119 void 120 sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 121 { 122 struct trapframe *tf; 123 struct sigacts *psp; 124 struct sigframe sf; 125 struct thread *td; 126 struct proc *p; 127 #ifdef COMPAT_FREEBSD32 128 struct siginfo32 siginfo32; 129 struct sigframe32 sf32; 130 #endif 131 size_t sfpsize; 132 caddr_t sfp, usfp; 133 int oonstack, rndfsize; 134 int sig; 135 int code; 136 137 td = curthread; 138 p = td->td_proc; 139 PROC_LOCK_ASSERT(p, MA_OWNED); 140 141 psp = p->p_sigacts; 142 mtx_assert(&psp->ps_mtx, MA_OWNED); 143 tf = td->td_frame; 144 oonstack = sigonstack(tf->fixreg[1]); 145 146 /* 147 * Fill siginfo structure. 148 */ 149 ksi->ksi_info.si_signo = ksi->ksi_signo; 150 #ifdef AIM 151 ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ? 152 tf->cpu.aim.dar : tf->srr0); 153 #else 154 ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ? 155 tf->cpu.booke.dear : tf->srr0); 156 #endif 157 158 #ifdef COMPAT_FREEBSD32 159 if (p->p_sysent->sv_flags & 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 = ((sizeof(sf32) + 15) / 16) * 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 + ((sizeof(sf) + 47) / 48) * 48; 193 #else 194 rndfsize = ((sizeof(sf) + 15) / 16) * 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 *)(td->td_sigstk.ss_sp + 223 td->td_sigstk.ss_size - rndfsize); 224 } else { 225 usfp = (void *)(tf->fixreg[1] - rndfsize); 226 } 227 228 /* 229 * Translate the signal if appropriate (Linux emu ?) 230 */ 231 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 232 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 233 234 /* 235 * Save the floating-point state, if necessary, then copy it. 236 */ 237 /* XXX */ 238 239 /* 240 * Set up the registers to return to sigcode. 241 * 242 * r1/sp - sigframe ptr 243 * lr - sig function, dispatched to by blrl in trampoline 244 * r3 - sig number 245 * r4 - SIGINFO ? &siginfo : exception code 246 * r5 - user context 247 * srr0 - trampoline function addr 248 */ 249 tf->lr = (register_t)catcher; 250 tf->fixreg[1] = (register_t)usfp; 251 tf->fixreg[FIRSTARG] = sig; 252 #ifdef COMPAT_FREEBSD32 253 tf->fixreg[FIRSTARG+2] = (register_t)usfp + 254 ((p->p_sysent->sv_flags & SV_ILP32) ? 255 offsetof(struct sigframe32, sf_uc) : 256 offsetof(struct sigframe, sf_uc)); 257 #else 258 tf->fixreg[FIRSTARG+2] = (register_t)usfp + 259 offsetof(struct sigframe, sf_uc); 260 #endif 261 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 262 /* 263 * Signal handler installed with SA_SIGINFO. 264 */ 265 #ifdef COMPAT_FREEBSD32 266 if (p->p_sysent->sv_flags & SV_ILP32) { 267 sf32.sf_si = siginfo32; 268 tf->fixreg[FIRSTARG+1] = (register_t)usfp + 269 offsetof(struct sigframe32, sf_si); 270 sf32.sf_si = siginfo32; 271 } else { 272 #endif 273 tf->fixreg[FIRSTARG+1] = (register_t)usfp + 274 offsetof(struct sigframe, sf_si); 275 sf.sf_si = ksi->ksi_info; 276 #ifdef COMPAT_FREEBSD32 277 } 278 #endif 279 } else { 280 /* Old FreeBSD-style arguments. */ 281 tf->fixreg[FIRSTARG+1] = code; 282 #ifdef AIM 283 tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 284 tf->cpu.aim.dar : tf->srr0; 285 #else 286 tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 287 tf->cpu.booke.dear : tf->srr0; 288 #endif 289 } 290 mtx_unlock(&psp->ps_mtx); 291 PROC_UNLOCK(p); 292 293 tf->srr0 = (register_t)(p->p_sysent->sv_psstrings - 294 *(p->p_sysent->sv_szsigcode)); 295 296 /* 297 * copy the frame out to userland. 298 */ 299 if (copyout(sfp, usfp, sfpsize) != 0) { 300 /* 301 * Process has trashed its stack. Kill it. 302 */ 303 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 304 PROC_LOCK(p); 305 sigexit(td, SIGILL); 306 } 307 308 CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, 309 tf->srr0, tf->fixreg[1]); 310 311 PROC_LOCK(p); 312 mtx_lock(&psp->ps_mtx); 313 } 314 315 int 316 sigreturn(struct thread *td, struct sigreturn_args *uap) 317 { 318 ucontext_t uc; 319 int error; 320 321 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 322 323 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 324 CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 325 return (EFAULT); 326 } 327 328 error = set_mcontext(td, &uc.uc_mcontext); 329 if (error != 0) 330 return (error); 331 332 kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 333 334 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 335 td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 336 337 return (EJUSTRETURN); 338 } 339 340 #ifdef COMPAT_FREEBSD4 341 int 342 freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) 343 { 344 345 return sigreturn(td, (struct sigreturn_args *)uap); 346 } 347 #endif 348 349 /* 350 * Construct a PCB from a trapframe. This is called from kdb_trap() where 351 * we want to start a backtrace from the function that caused us to enter 352 * the debugger. We have the context in the trapframe, but base the trace 353 * on the PCB. The PCB doesn't have to be perfect, as long as it contains 354 * enough for a backtrace. 355 */ 356 void 357 makectx(struct trapframe *tf, struct pcb *pcb) 358 { 359 360 pcb->pcb_lr = tf->srr0; 361 pcb->pcb_sp = tf->fixreg[1]; 362 } 363 364 /* 365 * get_mcontext/sendsig helper routine that doesn't touch the 366 * proc lock 367 */ 368 static int 369 grab_mcontext(struct thread *td, mcontext_t *mcp, int flags) 370 { 371 struct pcb *pcb; 372 373 pcb = td->td_pcb; 374 375 memset(mcp, 0, sizeof(mcontext_t)); 376 377 mcp->mc_vers = _MC_VERSION; 378 mcp->mc_flags = 0; 379 memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe)); 380 if (flags & GET_MC_CLEAR_RET) { 381 mcp->mc_gpr[3] = 0; 382 mcp->mc_gpr[4] = 0; 383 } 384 385 #ifdef AIM 386 /* 387 * This assumes that floating-point context is *not* lazy, 388 * so if the thread has used FP there would have been a 389 * FP-unavailable exception that would have set things up 390 * correctly. 391 */ 392 if (pcb->pcb_flags & PCB_FPU) { 393 KASSERT(td == curthread, 394 ("get_mcontext: fp save not curthread")); 395 critical_enter(); 396 save_fpu(td); 397 critical_exit(); 398 mcp->mc_flags |= _MC_FP_VALID; 399 memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double)); 400 memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*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 #endif 419 420 mcp->mc_len = sizeof(*mcp); 421 422 return (0); 423 } 424 425 int 426 get_mcontext(struct thread *td, mcontext_t *mcp, int flags) 427 { 428 int error; 429 430 error = grab_mcontext(td, mcp, flags); 431 if (error == 0) { 432 PROC_LOCK(curthread->td_proc); 433 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 434 PROC_UNLOCK(curthread->td_proc); 435 } 436 437 return (error); 438 } 439 440 int 441 set_mcontext(struct thread *td, const mcontext_t *mcp) 442 { 443 struct pcb *pcb; 444 struct trapframe *tf; 445 446 pcb = td->td_pcb; 447 tf = td->td_frame; 448 449 if (mcp->mc_vers != _MC_VERSION || mcp->mc_len != sizeof(*mcp)) 450 return (EINVAL); 451 452 #ifdef AIM 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 #endif 460 461 memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame)); 462 463 #ifdef AIM 464 if (mcp->mc_flags & _MC_FP_VALID) { 465 if ((pcb->pcb_flags & PCB_FPU) != PCB_FPU) { 466 critical_enter(); 467 enable_fpu(td); 468 critical_exit(); 469 } 470 memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double)); 471 memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double)); 472 } 473 474 if (mcp->mc_flags & _MC_AV_VALID) { 475 if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) { 476 critical_enter(); 477 enable_vec(td); 478 critical_exit(); 479 } 480 pcb->pcb_vec.vscr = mcp->mc_vscr; 481 pcb->pcb_vec.vrsave = mcp->mc_vrsave; 482 memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec)); 483 } 484 #endif 485 486 return (0); 487 } 488 489 /* 490 * Set set up registers on exec. 491 */ 492 void 493 exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) 494 { 495 struct trapframe *tf; 496 register_t argc; 497 #ifdef __powerpc64__ 498 register_t entry_desc[3]; 499 #endif 500 501 tf = trapframe(td); 502 bzero(tf, sizeof *tf); 503 #ifdef __powerpc64__ 504 tf->fixreg[1] = -roundup(-stack + 48, 16); 505 #else 506 tf->fixreg[1] = -roundup(-stack + 8, 16); 507 #endif 508 509 /* 510 * Set up arguments for _start(): 511 * _start(argc, argv, envp, obj, cleanup, ps_strings); 512 * 513 * Notes: 514 * - obj and cleanup are the auxilliary and termination 515 * vectors. They are fixed up by ld.elf_so. 516 * - ps_strings is a NetBSD extention, and will be 517 * ignored by executables which are strictly 518 * compliant with the SVR4 ABI. 519 * 520 * XXX We have to set both regs and retval here due to different 521 * XXX calling convention in trap.c and init_main.c. 522 */ 523 524 /* Collect argc from the user stack */ 525 argc = fuword((void *)stack); 526 527 /* 528 * XXX PG: these get overwritten in the syscall return code. 529 * execve() should return EJUSTRETURN, like it does on NetBSD. 530 * Emulate by setting the syscall return value cells. The 531 * registers still have to be set for init's fork trampoline. 532 */ 533 td->td_retval[0] = argc; 534 td->td_retval[1] = stack + sizeof(register_t); 535 tf->fixreg[3] = argc; 536 tf->fixreg[4] = stack + sizeof(register_t); 537 tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t); 538 tf->fixreg[6] = 0; /* auxillary vector */ 539 tf->fixreg[7] = 0; /* termination vector */ 540 tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 541 542 #ifdef __powerpc64__ 543 /* 544 * For 64-bit, we need to disentangle the function descriptor 545 * 546 * 0. entry point 547 * 1. TOC value (r2) 548 * 2. Environment pointer (r11) 549 */ 550 551 (void)copyin((void *)imgp->entry_addr, entry_desc, sizeof(entry_desc)); 552 tf->srr0 = entry_desc[0] + imgp->reloc_base; 553 tf->fixreg[2] = entry_desc[1] + imgp->reloc_base; 554 tf->fixreg[11] = entry_desc[2] + imgp->reloc_base; 555 tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT; 556 if (mfmsr() & PSL_HV) 557 tf->srr1 |= PSL_HV; 558 #else 559 tf->srr0 = imgp->entry_addr; 560 tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 561 #endif 562 td->td_pcb->pcb_flags = 0; 563 } 564 565 #ifdef COMPAT_FREEBSD32 566 void 567 ppc32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 568 { 569 struct trapframe *tf; 570 uint32_t argc; 571 572 tf = trapframe(td); 573 bzero(tf, sizeof *tf); 574 tf->fixreg[1] = -roundup(-stack + 8, 16); 575 576 argc = fuword32((void *)stack); 577 578 td->td_retval[0] = argc; 579 td->td_retval[1] = stack + sizeof(uint32_t); 580 tf->fixreg[3] = argc; 581 tf->fixreg[4] = stack + sizeof(uint32_t); 582 tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t); 583 tf->fixreg[6] = 0; /* auxillary vector */ 584 tf->fixreg[7] = 0; /* termination vector */ 585 tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 586 587 tf->srr0 = imgp->entry_addr; 588 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; 589 tf->srr1 &= ~PSL_SF; 590 if (mfmsr() & PSL_HV) 591 tf->srr1 |= PSL_HV; 592 td->td_pcb->pcb_flags = 0; 593 } 594 #endif 595 596 int 597 fill_regs(struct thread *td, struct reg *regs) 598 { 599 struct trapframe *tf; 600 601 tf = td->td_frame; 602 memcpy(regs, tf, sizeof(struct reg)); 603 604 return (0); 605 } 606 607 int 608 fill_dbregs(struct thread *td, struct dbreg *dbregs) 609 { 610 /* No debug registers on PowerPC */ 611 return (ENOSYS); 612 } 613 614 int 615 fill_fpregs(struct thread *td, struct fpreg *fpregs) 616 { 617 struct pcb *pcb; 618 619 pcb = td->td_pcb; 620 621 if ((pcb->pcb_flags & PCB_FPU) == 0) 622 memset(fpregs, 0, sizeof(struct fpreg)); 623 else 624 memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg)); 625 626 return (0); 627 } 628 629 int 630 set_regs(struct thread *td, struct reg *regs) 631 { 632 struct trapframe *tf; 633 634 tf = td->td_frame; 635 memcpy(tf, regs, sizeof(struct reg)); 636 637 return (0); 638 } 639 640 int 641 set_dbregs(struct thread *td, struct dbreg *dbregs) 642 { 643 /* No debug registers on PowerPC */ 644 return (ENOSYS); 645 } 646 647 int 648 set_fpregs(struct thread *td, struct fpreg *fpregs) 649 { 650 #ifdef AIM 651 struct pcb *pcb; 652 653 pcb = td->td_pcb; 654 if ((pcb->pcb_flags & PCB_FPU) == 0) 655 enable_fpu(td); 656 memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg)); 657 #endif 658 659 return (0); 660 } 661 662 #ifdef COMPAT_FREEBSD32 663 int 664 set_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 tf->fixreg[i] = regs->fixreg[i]; 672 tf->lr = regs->lr; 673 tf->cr = regs->cr; 674 tf->xer = regs->xer; 675 tf->ctr = regs->ctr; 676 tf->srr0 = regs->pc; 677 678 return (0); 679 } 680 681 int 682 fill_regs32(struct thread *td, struct reg32 *regs) 683 { 684 struct trapframe *tf; 685 int i; 686 687 tf = td->td_frame; 688 for (i = 0; i < 32; i++) 689 regs->fixreg[i] = tf->fixreg[i]; 690 regs->lr = tf->lr; 691 regs->cr = tf->cr; 692 regs->xer = tf->xer; 693 regs->ctr = tf->ctr; 694 regs->pc = tf->srr0; 695 696 return (0); 697 } 698 699 static int 700 grab_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 701 { 702 mcontext_t mcp64; 703 int i, error; 704 705 error = grab_mcontext(td, &mcp64, flags); 706 if (error != 0) 707 return (error); 708 709 mcp->mc_vers = mcp64.mc_vers; 710 mcp->mc_flags = mcp64.mc_flags; 711 mcp->mc_onstack = mcp64.mc_onstack; 712 mcp->mc_len = mcp64.mc_len; 713 memcpy(mcp->mc_avec,mcp64.mc_avec,sizeof(mcp64.mc_avec)); 714 memcpy(mcp->mc_av,mcp64.mc_av,sizeof(mcp64.mc_av)); 715 for (i = 0; i < 42; i++) 716 mcp->mc_frame[i] = mcp64.mc_frame[i]; 717 memcpy(mcp->mc_fpreg,mcp64.mc_fpreg,sizeof(mcp64.mc_fpreg)); 718 719 return (0); 720 } 721 722 static int 723 get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 724 { 725 int error; 726 727 error = grab_mcontext32(td, mcp, flags); 728 if (error == 0) { 729 PROC_LOCK(curthread->td_proc); 730 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 731 PROC_UNLOCK(curthread->td_proc); 732 } 733 734 return (error); 735 } 736 737 static int 738 set_mcontext32(struct thread *td, const mcontext32_t *mcp) 739 { 740 mcontext_t mcp64; 741 int i, error; 742 743 mcp64.mc_vers = mcp->mc_vers; 744 mcp64.mc_flags = mcp->mc_flags; 745 mcp64.mc_onstack = mcp->mc_onstack; 746 mcp64.mc_len = mcp->mc_len; 747 memcpy(mcp64.mc_avec,mcp->mc_avec,sizeof(mcp64.mc_avec)); 748 memcpy(mcp64.mc_av,mcp->mc_av,sizeof(mcp64.mc_av)); 749 for (i = 0; i < 42; i++) 750 mcp64.mc_frame[i] = mcp->mc_frame[i]; 751 memcpy(mcp64.mc_fpreg,mcp->mc_fpreg,sizeof(mcp64.mc_fpreg)); 752 753 error = set_mcontext(td, &mcp64); 754 755 return (error); 756 } 757 #endif 758 759 #ifdef COMPAT_FREEBSD32 760 int 761 freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap) 762 { 763 ucontext32_t uc; 764 int error; 765 766 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 767 768 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 769 CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 770 return (EFAULT); 771 } 772 773 error = set_mcontext32(td, &uc.uc_mcontext); 774 if (error != 0) 775 return (error); 776 777 kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 778 779 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 780 td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 781 782 return (EJUSTRETURN); 783 } 784 785 /* 786 * The first two fields of a ucontext_t are the signal mask and the machine 787 * context. The next field is uc_link; we want to avoid destroying the link 788 * when copying out contexts. 789 */ 790 #define UC32_COPY_SIZE offsetof(ucontext32_t, uc_link) 791 792 int 793 freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 794 { 795 ucontext32_t uc; 796 int ret; 797 798 if (uap->ucp == NULL) 799 ret = EINVAL; 800 else { 801 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 802 PROC_LOCK(td->td_proc); 803 uc.uc_sigmask = td->td_sigmask; 804 PROC_UNLOCK(td->td_proc); 805 ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE); 806 } 807 return (ret); 808 } 809 810 int 811 freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 812 { 813 ucontext32_t uc; 814 int ret; 815 816 if (uap->ucp == NULL) 817 ret = EINVAL; 818 else { 819 ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 820 if (ret == 0) { 821 ret = set_mcontext32(td, &uc.uc_mcontext); 822 if (ret == 0) { 823 kern_sigprocmask(td, SIG_SETMASK, 824 &uc.uc_sigmask, NULL, 0); 825 } 826 } 827 } 828 return (ret == 0 ? EJUSTRETURN : ret); 829 } 830 831 int 832 freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 833 { 834 ucontext32_t uc; 835 int ret; 836 837 if (uap->oucp == NULL || uap->ucp == NULL) 838 ret = EINVAL; 839 else { 840 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 841 PROC_LOCK(td->td_proc); 842 uc.uc_sigmask = td->td_sigmask; 843 PROC_UNLOCK(td->td_proc); 844 ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE); 845 if (ret == 0) { 846 ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 847 if (ret == 0) { 848 ret = set_mcontext32(td, &uc.uc_mcontext); 849 if (ret == 0) { 850 kern_sigprocmask(td, SIG_SETMASK, 851 &uc.uc_sigmask, NULL, 0); 852 } 853 } 854 } 855 } 856 return (ret == 0 ? EJUSTRETURN : ret); 857 } 858 859 #endif 860 861 void 862 cpu_set_syscall_retval(struct thread *td, int error) 863 { 864 struct proc *p; 865 struct trapframe *tf; 866 int fixup; 867 868 if (error == EJUSTRETURN) 869 return; 870 871 p = td->td_proc; 872 tf = td->td_frame; 873 874 if (tf->fixreg[0] == SYS___syscall && 875 (p->p_sysent->sv_flags & SV_ILP32)) { 876 int code = tf->fixreg[FIRSTARG + 1]; 877 if (p->p_sysent->sv_mask) 878 code &= p->p_sysent->sv_mask; 879 fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek) ? 880 1 : 0; 881 } else 882 fixup = 0; 883 884 switch (error) { 885 case 0: 886 if (fixup) { 887 /* 888 * 64-bit return, 32-bit syscall. Fixup byte order 889 */ 890 tf->fixreg[FIRSTARG] = 0; 891 tf->fixreg[FIRSTARG + 1] = td->td_retval[0]; 892 } else { 893 tf->fixreg[FIRSTARG] = td->td_retval[0]; 894 tf->fixreg[FIRSTARG + 1] = td->td_retval[1]; 895 } 896 tf->cr &= ~0x10000000; /* Unset summary overflow */ 897 break; 898 case ERESTART: 899 /* 900 * Set user's pc back to redo the system call. 901 */ 902 tf->srr0 -= 4; 903 break; 904 default: 905 if (p->p_sysent->sv_errsize) { 906 error = (error < p->p_sysent->sv_errsize) ? 907 p->p_sysent->sv_errtbl[error] : -1; 908 } 909 tf->fixreg[FIRSTARG] = error; 910 tf->cr |= 0x10000000; /* Set summary overflow */ 911 break; 912 } 913 } 914 915 /* 916 * Threading functions 917 */ 918 void 919 cpu_thread_exit(struct thread *td) 920 { 921 } 922 923 void 924 cpu_thread_clean(struct thread *td) 925 { 926 } 927 928 void 929 cpu_thread_alloc(struct thread *td) 930 { 931 struct pcb *pcb; 932 933 pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 934 sizeof(struct pcb)) & ~0x2fUL); 935 td->td_pcb = pcb; 936 td->td_frame = (struct trapframe *)pcb - 1; 937 } 938 939 void 940 cpu_thread_free(struct thread *td) 941 { 942 } 943 944 int 945 cpu_set_user_tls(struct thread *td, void *tls_base) 946 { 947 948 if (td->td_proc->p_sysent->sv_flags & SV_LP64) 949 td->td_frame->fixreg[13] = (register_t)tls_base + 0x7010; 950 else 951 td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008; 952 return (0); 953 } 954 955 void 956 cpu_set_upcall(struct thread *td, struct thread *td0) 957 { 958 struct pcb *pcb2; 959 struct trapframe *tf; 960 struct callframe *cf; 961 962 pcb2 = td->td_pcb; 963 964 /* Copy the upcall pcb */ 965 bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); 966 967 /* Create a stack for the new thread */ 968 tf = td->td_frame; 969 bcopy(td0->td_frame, tf, sizeof(struct trapframe)); 970 tf->fixreg[FIRSTARG] = 0; 971 tf->fixreg[FIRSTARG + 1] = 0; 972 tf->cr &= ~0x10000000; 973 974 /* Set registers for trampoline to user mode. */ 975 cf = (struct callframe *)tf - 1; 976 memset(cf, 0, sizeof(struct callframe)); 977 cf->cf_func = (register_t)fork_return; 978 cf->cf_arg0 = (register_t)td; 979 cf->cf_arg1 = (register_t)tf; 980 981 pcb2->pcb_sp = (register_t)cf; 982 #ifdef __powerpc64__ 983 pcb2->pcb_lr = ((register_t *)fork_trampoline)[0]; 984 pcb2->pcb_toc = ((register_t *)fork_trampoline)[1]; 985 #else 986 pcb2->pcb_lr = (register_t)fork_trampoline; 987 #endif 988 pcb2->pcb_cpu.aim.usr_vsid = 0; 989 990 /* Setup to release spin count in fork_exit(). */ 991 td->td_md.md_spinlock_count = 1; 992 td->td_md.md_saved_msr = PSL_KERNSET; 993 } 994 995 void 996 cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, 997 stack_t *stack) 998 { 999 struct trapframe *tf; 1000 uintptr_t sp; 1001 1002 tf = td->td_frame; 1003 /* align stack and alloc space for frame ptr and saved LR */ 1004 #ifdef __powerpc64__ 1005 sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 48) & 1006 ~0x1f; 1007 #else 1008 sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) & 1009 ~0x1f; 1010 #endif 1011 bzero(tf, sizeof(struct trapframe)); 1012 1013 tf->fixreg[1] = (register_t)sp; 1014 tf->fixreg[3] = (register_t)arg; 1015 if (td->td_proc->p_sysent->sv_flags & SV_ILP32) { 1016 tf->srr0 = (register_t)entry; 1017 #ifdef AIM 1018 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; 1019 #else 1020 tf->srr1 = PSL_USERSET; 1021 #endif 1022 } else { 1023 #ifdef __powerpc64__ 1024 register_t entry_desc[3]; 1025 (void)copyin((void *)entry, entry_desc, sizeof(entry_desc)); 1026 tf->srr0 = entry_desc[0]; 1027 tf->fixreg[2] = entry_desc[1]; 1028 tf->fixreg[11] = entry_desc[2]; 1029 tf->srr1 = PSL_SF | PSL_MBO | PSL_USERSET | PSL_FE_DFLT; 1030 #endif 1031 } 1032 1033 #ifdef __powerpc64__ 1034 if (mfmsr() & PSL_HV) 1035 tf->srr1 |= PSL_HV; 1036 #endif 1037 td->td_pcb->pcb_flags = 0; 1038 1039 td->td_retval[0] = (register_t)entry; 1040 td->td_retval[1] = 0; 1041 } 1042 1043