exec_machdep.c revision 331722
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/11/sys/powerpc/powerpc/exec_machdep.c 331722 2018-03-29 02:50:57Z eadler $"); 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 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 303int 304sys_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 329int 330freebsd4_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 */ 344void 345makectx(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 */ 356static int 357grab_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 422int 423get_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 437int 438set_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 */ 499void 500exec_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 tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT; 550 if (mfmsr() & PSL_HV) 551 tf->srr1 |= PSL_HV; 552 #else 553 tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 554 #endif 555 td->td_pcb->pcb_flags = 0; 556} 557 558#ifdef COMPAT_FREEBSD32 559void 560ppc32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 561{ 562 struct trapframe *tf; 563 uint32_t argc; 564 565 tf = trapframe(td); 566 bzero(tf, sizeof *tf); 567 tf->fixreg[1] = -roundup(-stack + 8, 16); 568 569 argc = fuword32((void *)stack); 570 571 td->td_retval[0] = argc; 572 td->td_retval[1] = stack + sizeof(uint32_t); 573 tf->fixreg[3] = argc; 574 tf->fixreg[4] = stack + sizeof(uint32_t); 575 tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t); 576 tf->fixreg[6] = 0; /* auxillary vector */ 577 tf->fixreg[7] = 0; /* termination vector */ 578 tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 579 580 tf->srr0 = imgp->entry_addr; 581 tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 582 tf->srr1 &= ~PSL_SF; 583 if (mfmsr() & PSL_HV) 584 tf->srr1 |= PSL_HV; 585 td->td_pcb->pcb_flags = 0; 586} 587#endif 588 589int 590fill_regs(struct thread *td, struct reg *regs) 591{ 592 struct trapframe *tf; 593 594 tf = td->td_frame; 595 memcpy(regs, tf, sizeof(struct reg)); 596 597 return (0); 598} 599 600int 601fill_dbregs(struct thread *td, struct dbreg *dbregs) 602{ 603 /* No debug registers on PowerPC */ 604 return (ENOSYS); 605} 606 607int 608fill_fpregs(struct thread *td, struct fpreg *fpregs) 609{ 610 struct pcb *pcb; 611 int i; 612 613 pcb = td->td_pcb; 614 615 if ((pcb->pcb_flags & PCB_FPREGS) == 0) 616 memset(fpregs, 0, sizeof(struct fpreg)); 617 else { 618 memcpy(&fpregs->fpscr, &pcb->pcb_fpu.fpscr, sizeof(double)); 619 for (i = 0; i < 32; i++) 620 memcpy(&fpregs->fpreg[i], &pcb->pcb_fpu.fpr[i].fpr, 621 sizeof(double)); 622 } 623 624 return (0); 625} 626 627int 628set_regs(struct thread *td, struct reg *regs) 629{ 630 struct trapframe *tf; 631 632 tf = td->td_frame; 633 memcpy(tf, regs, sizeof(struct reg)); 634 635 return (0); 636} 637 638int 639set_dbregs(struct thread *td, struct dbreg *dbregs) 640{ 641 /* No debug registers on PowerPC */ 642 return (ENOSYS); 643} 644 645int 646set_fpregs(struct thread *td, struct fpreg *fpregs) 647{ 648 struct pcb *pcb; 649 int i; 650 651 pcb = td->td_pcb; 652 pcb->pcb_flags |= PCB_FPREGS; 653 memcpy(&pcb->pcb_fpu.fpscr, &fpregs->fpscr, sizeof(double)); 654 for (i = 0; i < 32; i++) { 655 memcpy(&pcb->pcb_fpu.fpr[i].fpr, &fpregs->fpreg[i], 656 sizeof(double)); 657 } 658 659 return (0); 660} 661 662#ifdef COMPAT_FREEBSD32 663int 664set_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 681int 682fill_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 699static int 700grab_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 memcpy(mcp->mc_vsxfpreg,mcp64.mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg)); 719 720 return (0); 721} 722 723static int 724get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 725{ 726 int error; 727 728 error = grab_mcontext32(td, mcp, flags); 729 if (error == 0) { 730 PROC_LOCK(curthread->td_proc); 731 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 732 PROC_UNLOCK(curthread->td_proc); 733 } 734 735 return (error); 736} 737 738static int 739set_mcontext32(struct thread *td, mcontext32_t *mcp) 740{ 741 mcontext_t mcp64; 742 int i, error; 743 744 mcp64.mc_vers = mcp->mc_vers; 745 mcp64.mc_flags = mcp->mc_flags; 746 mcp64.mc_onstack = mcp->mc_onstack; 747 mcp64.mc_len = mcp->mc_len; 748 memcpy(mcp64.mc_avec,mcp->mc_avec,sizeof(mcp64.mc_avec)); 749 memcpy(mcp64.mc_av,mcp->mc_av,sizeof(mcp64.mc_av)); 750 for (i = 0; i < 42; i++) 751 mcp64.mc_frame[i] = mcp->mc_frame[i]; 752 mcp64.mc_srr1 |= (td->td_frame->srr1 & 0xFFFFFFFF00000000ULL); 753 memcpy(mcp64.mc_fpreg,mcp->mc_fpreg,sizeof(mcp64.mc_fpreg)); 754 memcpy(mcp64.mc_vsxfpreg,mcp->mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg)); 755 756 error = set_mcontext(td, &mcp64); 757 758 return (error); 759} 760#endif 761 762#ifdef COMPAT_FREEBSD32 763int 764freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap) 765{ 766 ucontext32_t uc; 767 int error; 768 769 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 770 771 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 772 CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 773 return (EFAULT); 774 } 775 776 error = set_mcontext32(td, &uc.uc_mcontext); 777 if (error != 0) 778 return (error); 779 780 kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 781 782 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 783 td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 784 785 return (EJUSTRETURN); 786} 787 788/* 789 * The first two fields of a ucontext_t are the signal mask and the machine 790 * context. The next field is uc_link; we want to avoid destroying the link 791 * when copying out contexts. 792 */ 793#define UC32_COPY_SIZE offsetof(ucontext32_t, uc_link) 794 795int 796freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 797{ 798 ucontext32_t uc; 799 int ret; 800 801 if (uap->ucp == NULL) 802 ret = EINVAL; 803 else { 804 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 805 PROC_LOCK(td->td_proc); 806 uc.uc_sigmask = td->td_sigmask; 807 PROC_UNLOCK(td->td_proc); 808 ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE); 809 } 810 return (ret); 811} 812 813int 814freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 815{ 816 ucontext32_t uc; 817 int ret; 818 819 if (uap->ucp == NULL) 820 ret = EINVAL; 821 else { 822 ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 823 if (ret == 0) { 824 ret = set_mcontext32(td, &uc.uc_mcontext); 825 if (ret == 0) { 826 kern_sigprocmask(td, SIG_SETMASK, 827 &uc.uc_sigmask, NULL, 0); 828 } 829 } 830 } 831 return (ret == 0 ? EJUSTRETURN : ret); 832} 833 834int 835freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 836{ 837 ucontext32_t uc; 838 int ret; 839 840 if (uap->oucp == NULL || uap->ucp == NULL) 841 ret = EINVAL; 842 else { 843 get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 844 PROC_LOCK(td->td_proc); 845 uc.uc_sigmask = td->td_sigmask; 846 PROC_UNLOCK(td->td_proc); 847 ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE); 848 if (ret == 0) { 849 ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 850 if (ret == 0) { 851 ret = set_mcontext32(td, &uc.uc_mcontext); 852 if (ret == 0) { 853 kern_sigprocmask(td, SIG_SETMASK, 854 &uc.uc_sigmask, NULL, 0); 855 } 856 } 857 } 858 } 859 return (ret == 0 ? EJUSTRETURN : ret); 860} 861 862#endif 863 864void 865cpu_set_syscall_retval(struct thread *td, int error) 866{ 867 struct proc *p; 868 struct trapframe *tf; 869 int fixup; 870 871 if (error == EJUSTRETURN) 872 return; 873 874 p = td->td_proc; 875 tf = td->td_frame; 876 877 if (tf->fixreg[0] == SYS___syscall && 878 (SV_PROC_FLAG(p, SV_ILP32))) { 879 int code = tf->fixreg[FIRSTARG + 1]; 880 if (p->p_sysent->sv_mask) 881 code &= p->p_sysent->sv_mask; 882 fixup = ( 883#if defined(COMPAT_FREEBSD6) && defined(SYS_freebsd6_lseek) 884 code != SYS_freebsd6_lseek && 885#endif 886 code != SYS_lseek) ? 1 : 0; 887 } else 888 fixup = 0; 889 890 switch (error) { 891 case 0: 892 if (fixup) { 893 /* 894 * 64-bit return, 32-bit syscall. Fixup byte order 895 */ 896 tf->fixreg[FIRSTARG] = 0; 897 tf->fixreg[FIRSTARG + 1] = td->td_retval[0]; 898 } else { 899 tf->fixreg[FIRSTARG] = td->td_retval[0]; 900 tf->fixreg[FIRSTARG + 1] = td->td_retval[1]; 901 } 902 tf->cr &= ~0x10000000; /* Unset summary overflow */ 903 break; 904 case ERESTART: 905 /* 906 * Set user's pc back to redo the system call. 907 */ 908 tf->srr0 -= 4; 909 break; 910 default: 911 tf->fixreg[FIRSTARG] = SV_ABI_ERRNO(p, error); 912 tf->cr |= 0x10000000; /* Set summary overflow */ 913 break; 914 } 915} 916 917/* 918 * Threading functions 919 */ 920void 921cpu_thread_exit(struct thread *td) 922{ 923} 924 925void 926cpu_thread_clean(struct thread *td) 927{ 928} 929 930void 931cpu_thread_alloc(struct thread *td) 932{ 933 struct pcb *pcb; 934 935 pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 936 sizeof(struct pcb)) & ~0x2fUL); 937 td->td_pcb = pcb; 938 td->td_frame = (struct trapframe *)pcb - 1; 939} 940 941void 942cpu_thread_free(struct thread *td) 943{ 944} 945 946int 947cpu_set_user_tls(struct thread *td, void *tls_base) 948{ 949 950 if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 951 td->td_frame->fixreg[13] = (register_t)tls_base + 0x7010; 952 else 953 td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008; 954 return (0); 955} 956 957void 958cpu_copy_thread(struct thread *td, struct thread *td0) 959{ 960 struct pcb *pcb2; 961 struct trapframe *tf; 962 struct callframe *cf; 963 964 pcb2 = td->td_pcb; 965 966 /* Copy the upcall pcb */ 967 bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); 968 969 /* Create a stack for the new thread */ 970 tf = td->td_frame; 971 bcopy(td0->td_frame, tf, sizeof(struct trapframe)); 972 tf->fixreg[FIRSTARG] = 0; 973 tf->fixreg[FIRSTARG + 1] = 0; 974 tf->cr &= ~0x10000000; 975 976 /* Set registers for trampoline to user mode. */ 977 cf = (struct callframe *)tf - 1; 978 memset(cf, 0, sizeof(struct callframe)); 979 cf->cf_func = (register_t)fork_return; 980 cf->cf_arg0 = (register_t)td; 981 cf->cf_arg1 = (register_t)tf; 982 983 pcb2->pcb_sp = (register_t)cf; 984 #if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1) 985 pcb2->pcb_lr = ((register_t *)fork_trampoline)[0]; 986 pcb2->pcb_toc = ((register_t *)fork_trampoline)[1]; 987 #else 988 pcb2->pcb_lr = (register_t)fork_trampoline; 989 pcb2->pcb_context[0] = pcb2->pcb_lr; 990 #endif 991 pcb2->pcb_cpu.aim.usr_vsid = 0; 992 993 /* Setup to release spin count in fork_exit(). */ 994 td->td_md.md_spinlock_count = 1; 995 td->td_md.md_saved_msr = PSL_KERNSET; 996} 997 998void 999cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg, 1000 stack_t *stack) 1001{ 1002 struct trapframe *tf; 1003 uintptr_t sp; 1004 1005 tf = td->td_frame; 1006 /* align stack and alloc space for frame ptr and saved LR */ 1007 #ifdef __powerpc64__ 1008 sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 48) & 1009 ~0x1f; 1010 #else 1011 sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) & 1012 ~0x1f; 1013 #endif 1014 bzero(tf, sizeof(struct trapframe)); 1015 1016 tf->fixreg[1] = (register_t)sp; 1017 tf->fixreg[3] = (register_t)arg; 1018 if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) { 1019 tf->srr0 = (register_t)entry; 1020 tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 1021 #ifdef __powerpc64__ 1022 tf->srr1 &= ~PSL_SF; 1023 #endif 1024 } else { 1025 #ifdef __powerpc64__ 1026 register_t entry_desc[3]; 1027 (void)copyin((void *)entry, entry_desc, sizeof(entry_desc)); 1028 tf->srr0 = entry_desc[0]; 1029 tf->fixreg[2] = entry_desc[1]; 1030 tf->fixreg[11] = entry_desc[2]; 1031 tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT; 1032 #endif 1033 } 1034 1035 #ifdef __powerpc64__ 1036 if (mfmsr() & PSL_HV) 1037 tf->srr1 |= PSL_HV; 1038 #endif 1039 td->td_pcb->pcb_flags = 0; 1040 1041 td->td_retval[0] = (register_t)entry; 1042 td->td_retval[1] = 0; 1043} 1044 1045int 1046ppc_instr_emulate(struct trapframe *frame, struct pcb *pcb) 1047{ 1048 uint32_t instr; 1049 int reg, sig; 1050 1051 instr = fuword32((void *)frame->srr0); 1052 sig = SIGILL; 1053 1054 if ((instr & 0xfc1fffff) == 0x7c1f42a6) { /* mfpvr */ 1055 reg = (instr & ~0xfc1fffff) >> 21; 1056 frame->fixreg[reg] = mfpvr(); 1057 frame->srr0 += 4; 1058 return (0); 1059 } 1060 1061 if ((instr & 0xfc000ffe) == 0x7c0004ac) { /* various sync */ 1062 powerpc_sync(); /* Do a heavy-weight sync */ 1063 frame->srr0 += 4; 1064 return (0); 1065 } 1066 1067#ifdef FPU_EMU 1068 if (!(pcb->pcb_flags & PCB_FPREGS)) { 1069 bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu)); 1070 pcb->pcb_flags |= PCB_FPREGS; 1071 } 1072 sig = fpu_emulate(frame, &pcb->pcb_fpu); 1073#endif 1074 1075 return (sig); 1076} 1077 1078