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