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