exec_machdep.c revision 266004
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 266004 2014-05-14 04:42:38Z ian $"); 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 100typedef 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 109struct sigframe32 { 110 ucontext32_t sf_uc; 111 struct siginfo32 sf_si; 112}; 113 114static int grab_mcontext32(struct thread *td, mcontext32_t *, int flags); 115#endif 116 117static int grab_mcontext(struct thread *, mcontext_t *, int); 118 119void 120sendsig(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 (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 = ((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 ((SV_PROC_FLAG(p, 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 (SV_PROC_FLAG(p, 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_sigcode_base; 294 295 /* 296 * copy the frame out to userland. 297 */ 298 if (copyout(sfp, usfp, sfpsize) != 0) { 299 /* 300 * Process has trashed its stack. Kill it. 301 */ 302 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 303 PROC_LOCK(p); 304 sigexit(td, SIGILL); 305 } 306 307 CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, 308 tf->srr0, tf->fixreg[1]); 309 310 PROC_LOCK(p); 311 mtx_lock(&psp->ps_mtx); 312} 313 314int 315sys_sigreturn(struct thread *td, struct sigreturn_args *uap) 316{ 317 ucontext_t uc; 318 int error; 319 320 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 321 322 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 323 CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 324 return (EFAULT); 325 } 326 327 error = set_mcontext(td, &uc.uc_mcontext); 328 if (error != 0) 329 return (error); 330 331 kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 332 333 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 334 td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 335 336 return (EJUSTRETURN); 337} 338 339#ifdef COMPAT_FREEBSD4 340int 341freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) 342{ 343 344 return sys_sigreturn(td, (struct sigreturn_args *)uap); 345} 346#endif 347 348/* 349 * Construct a PCB from a trapframe. This is called from kdb_trap() where 350 * we want to start a backtrace from the function that caused us to enter 351 * the debugger. We have the context in the trapframe, but base the trace 352 * on the PCB. The PCB doesn't have to be perfect, as long as it contains 353 * enough for a backtrace. 354 */ 355void 356makectx(struct trapframe *tf, struct pcb *pcb) 357{ 358 359 pcb->pcb_lr = tf->srr0; 360 pcb->pcb_sp = tf->fixreg[1]; 361} 362 363/* 364 * get_mcontext/sendsig helper routine that doesn't touch the 365 * proc lock 366 */ 367static int 368grab_mcontext(struct thread *td, mcontext_t *mcp, int flags) 369{ 370 struct pcb *pcb; 371 372 pcb = td->td_pcb; 373 374 memset(mcp, 0, sizeof(mcontext_t)); 375 376 mcp->mc_vers = _MC_VERSION; 377 mcp->mc_flags = 0; 378 memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe)); 379 if (flags & GET_MC_CLEAR_RET) { 380 mcp->mc_gpr[3] = 0; 381 mcp->mc_gpr[4] = 0; 382 } 383 384 /* 385 * This assumes that floating-point context is *not* lazy, 386 * so if the thread has used FP there would have been a 387 * FP-unavailable exception that would have set things up 388 * correctly. 389 */ 390 if (pcb->pcb_flags & PCB_FPREGS) { 391 if (pcb->pcb_flags & PCB_FPU) { 392 KASSERT(td == curthread, 393 ("get_mcontext: fp save not curthread")); 394 critical_enter(); 395 save_fpu(td); 396 critical_exit(); 397 } 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 419 mcp->mc_len = sizeof(*mcp); 420 421 return (0); 422} 423 424int 425get_mcontext(struct thread *td, mcontext_t *mcp, int flags) 426{ 427 int error; 428 429 error = grab_mcontext(td, mcp, flags); 430 if (error == 0) { 431 PROC_LOCK(curthread->td_proc); 432 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 433 PROC_UNLOCK(curthread->td_proc); 434 } 435 436 return (error); 437} 438 439int 440set_mcontext(struct thread *td, const mcontext_t *mcp) 441{ 442 struct pcb *pcb; 443 struct trapframe *tf; 444 register_t tls; 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 /* 453 * Don't let the user set privileged MSR bits 454 */ 455 if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) { 456 return (EINVAL); 457 } 458 459 /* Copy trapframe, preserving TLS pointer across context change */ 460 if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 461 tls = tf->fixreg[13]; 462 else 463 tls = tf->fixreg[2]; 464 memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame)); 465 if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 466 tf->fixreg[13] = tls; 467 else 468 tf->fixreg[2] = tls; 469 470 if (mcp->mc_flags & _MC_FP_VALID) { 471 /* enable_fpu() will happen lazily on a fault */ 472 pcb->pcb_flags |= PCB_FPREGS; 473 memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double)); 474 memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double)); 475 } 476 477 if (mcp->mc_flags & _MC_AV_VALID) { 478 if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) { 479 critical_enter(); 480 enable_vec(td); 481 critical_exit(); 482 } 483 pcb->pcb_vec.vscr = mcp->mc_vscr; 484 pcb->pcb_vec.vrsave = mcp->mc_vrsave; 485 memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec)); 486 } 487 488 return (0); 489} 490 491/* 492 * Set set up registers on exec. 493 */ 494void 495exec_setregs(struct thread *td, struct image_params *imgp, u_long stack) 496{ 497 struct trapframe *tf; 498 register_t argc; 499 #ifdef __powerpc64__ 500 register_t entry_desc[3]; 501 #endif 502 503 tf = trapframe(td); 504 bzero(tf, sizeof *tf); 505 #ifdef __powerpc64__ 506 tf->fixreg[1] = -roundup(-stack + 48, 16); 507 #else 508 tf->fixreg[1] = -roundup(-stack + 8, 16); 509 #endif 510 511 /* 512 * Set up arguments for _start(): 513 * _start(argc, argv, envp, obj, cleanup, ps_strings); 514 * 515 * Notes: 516 * - obj and cleanup are the auxilliary and termination 517 * vectors. They are fixed up by ld.elf_so. 518 * - ps_strings is a NetBSD extention, and will be 519 * ignored by executables which are strictly 520 * compliant with the SVR4 ABI. 521 * 522 * XXX We have to set both regs and retval here due to different 523 * XXX calling convention in trap.c and init_main.c. 524 */ 525 526 /* Collect argc from the user stack */ 527 argc = fuword((void *)stack); 528 529 /* 530 * XXX PG: these get overwritten in the syscall return code. 531 * execve() should return EJUSTRETURN, like it does on NetBSD. 532 * Emulate by setting the syscall return value cells. The 533 * registers still have to be set for init's fork trampoline. 534 */ 535 td->td_retval[0] = argc; 536 td->td_retval[1] = stack + sizeof(register_t); 537 tf->fixreg[3] = argc; 538 tf->fixreg[4] = stack + sizeof(register_t); 539 tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t); 540 tf->fixreg[6] = 0; /* auxillary vector */ 541 tf->fixreg[7] = 0; /* termination vector */ 542 tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 543 544 #ifdef __powerpc64__ 545 /* 546 * For 64-bit, we need to disentangle the function descriptor 547 * 548 * 0. entry point 549 * 1. TOC value (r2) 550 * 2. Environment pointer (r11) 551 */ 552 553 (void)copyin((void *)imgp->entry_addr, entry_desc, sizeof(entry_desc)); 554 tf->srr0 = entry_desc[0] + imgp->reloc_base; 555 tf->fixreg[2] = entry_desc[1] + imgp->reloc_base; 556 tf->fixreg[11] = entry_desc[2] + imgp->reloc_base; 557 tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT; 558 if (mfmsr() & PSL_HV) 559 tf->srr1 |= PSL_HV; 560 #else 561 tf->srr0 = imgp->entry_addr; 562 tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 563 #endif 564 td->td_pcb->pcb_flags = 0; 565} 566 567#ifdef COMPAT_FREEBSD32 568void 569ppc32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 570{ 571 struct trapframe *tf; 572 uint32_t argc; 573 574 tf = trapframe(td); 575 bzero(tf, sizeof *tf); 576 tf->fixreg[1] = -roundup(-stack + 8, 16); 577 578 argc = fuword32((void *)stack); 579 580 td->td_retval[0] = argc; 581 td->td_retval[1] = stack + sizeof(uint32_t); 582 tf->fixreg[3] = argc; 583 tf->fixreg[4] = stack + sizeof(uint32_t); 584 tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t); 585 tf->fixreg[6] = 0; /* auxillary vector */ 586 tf->fixreg[7] = 0; /* termination vector */ 587 tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 588 589 tf->srr0 = imgp->entry_addr; 590 tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 591 tf->srr1 &= ~PSL_SF; 592 if (mfmsr() & PSL_HV) 593 tf->srr1 |= PSL_HV; 594 td->td_pcb->pcb_flags = 0; 595} 596#endif 597 598int 599fill_regs(struct thread *td, struct reg *regs) 600{ 601 struct trapframe *tf; 602 603 tf = td->td_frame; 604 memcpy(regs, tf, sizeof(struct reg)); 605 606 return (0); 607} 608 609int 610fill_dbregs(struct thread *td, struct dbreg *dbregs) 611{ 612 /* No debug registers on PowerPC */ 613 return (ENOSYS); 614} 615 616int 617fill_fpregs(struct thread *td, struct fpreg *fpregs) 618{ 619 struct pcb *pcb; 620 621 pcb = td->td_pcb; 622 623 if ((pcb->pcb_flags & PCB_FPREGS) == 0) 624 memset(fpregs, 0, sizeof(struct fpreg)); 625 else 626 memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg)); 627 628 return (0); 629} 630 631int 632set_regs(struct thread *td, struct reg *regs) 633{ 634 struct trapframe *tf; 635 636 tf = td->td_frame; 637 memcpy(tf, regs, sizeof(struct reg)); 638 639 return (0); 640} 641 642int 643set_dbregs(struct thread *td, struct dbreg *dbregs) 644{ 645 /* No debug registers on PowerPC */ 646 return (ENOSYS); 647} 648 649int 650set_fpregs(struct thread *td, struct fpreg *fpregs) 651{ 652 struct pcb *pcb; 653 654 pcb = td->td_pcb; 655 pcb->pcb_flags |= PCB_FPREGS; 656 memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg)); 657 658 return (0); 659} 660 661#ifdef COMPAT_FREEBSD32 662int 663set_regs32(struct thread *td, struct reg32 *regs) 664{ 665 struct trapframe *tf; 666 int i; 667 668 tf = td->td_frame; 669 for (i = 0; i < 32; i++) 670 tf->fixreg[i] = regs->fixreg[i]; 671 tf->lr = regs->lr; 672 tf->cr = regs->cr; 673 tf->xer = regs->xer; 674 tf->ctr = regs->ctr; 675 tf->srr0 = regs->pc; 676 677 return (0); 678} 679 680int 681fill_regs32(struct thread *td, struct reg32 *regs) 682{ 683 struct trapframe *tf; 684 int i; 685 686 tf = td->td_frame; 687 for (i = 0; i < 32; i++) 688 regs->fixreg[i] = tf->fixreg[i]; 689 regs->lr = tf->lr; 690 regs->cr = tf->cr; 691 regs->xer = tf->xer; 692 regs->ctr = tf->ctr; 693 regs->pc = tf->srr0; 694 695 return (0); 696} 697 698static int 699grab_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 700{ 701 mcontext_t mcp64; 702 int i, error; 703 704 error = grab_mcontext(td, &mcp64, flags); 705 if (error != 0) 706 return (error); 707 708 mcp->mc_vers = mcp64.mc_vers; 709 mcp->mc_flags = mcp64.mc_flags; 710 mcp->mc_onstack = mcp64.mc_onstack; 711 mcp->mc_len = mcp64.mc_len; 712 memcpy(mcp->mc_avec,mcp64.mc_avec,sizeof(mcp64.mc_avec)); 713 memcpy(mcp->mc_av,mcp64.mc_av,sizeof(mcp64.mc_av)); 714 for (i = 0; i < 42; i++) 715 mcp->mc_frame[i] = mcp64.mc_frame[i]; 716 memcpy(mcp->mc_fpreg,mcp64.mc_fpreg,sizeof(mcp64.mc_fpreg)); 717 718 return (0); 719} 720 721static int 722get_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 723{ 724 int error; 725 726 error = grab_mcontext32(td, mcp, flags); 727 if (error == 0) { 728 PROC_LOCK(curthread->td_proc); 729 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 730 PROC_UNLOCK(curthread->td_proc); 731 } 732 733 return (error); 734} 735 736static int 737set_mcontext32(struct thread *td, const mcontext32_t *mcp) 738{ 739 mcontext_t mcp64; 740 int i, error; 741 742 mcp64.mc_vers = mcp->mc_vers; 743 mcp64.mc_flags = mcp->mc_flags; 744 mcp64.mc_onstack = mcp->mc_onstack; 745 mcp64.mc_len = mcp->mc_len; 746 memcpy(mcp64.mc_avec,mcp->mc_avec,sizeof(mcp64.mc_avec)); 747 memcpy(mcp64.mc_av,mcp->mc_av,sizeof(mcp64.mc_av)); 748 for (i = 0; i < 42; i++) 749 mcp64.mc_frame[i] = mcp->mc_frame[i]; 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 if (p->p_sysent->sv_errsize) { 905 error = (error < p->p_sysent->sv_errsize) ? 906 p->p_sysent->sv_errtbl[error] : -1; 907 } 908 tf->fixreg[FIRSTARG] = error; 909 tf->cr |= 0x10000000; /* Set summary overflow */ 910 break; 911 } 912} 913 914/* 915 * Threading functions 916 */ 917void 918cpu_thread_exit(struct thread *td) 919{ 920} 921 922void 923cpu_thread_clean(struct thread *td) 924{ 925} 926 927void 928cpu_thread_alloc(struct thread *td) 929{ 930 struct pcb *pcb; 931 932 pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 933 sizeof(struct pcb)) & ~0x2fUL); 934 td->td_pcb = pcb; 935 td->td_frame = (struct trapframe *)pcb - 1; 936} 937 938void 939cpu_thread_free(struct thread *td) 940{ 941} 942 943int 944cpu_set_user_tls(struct thread *td, void *tls_base) 945{ 946 947 if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 948 td->td_frame->fixreg[13] = (register_t)tls_base + 0x7010; 949 else 950 td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008; 951 return (0); 952} 953 954void 955cpu_set_upcall(struct thread *td, struct thread *td0) 956{ 957 struct pcb *pcb2; 958 struct trapframe *tf; 959 struct callframe *cf; 960 961 pcb2 = td->td_pcb; 962 963 /* Copy the upcall pcb */ 964 bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); 965 966 /* Create a stack for the new thread */ 967 tf = td->td_frame; 968 bcopy(td0->td_frame, tf, sizeof(struct trapframe)); 969 tf->fixreg[FIRSTARG] = 0; 970 tf->fixreg[FIRSTARG + 1] = 0; 971 tf->cr &= ~0x10000000; 972 973 /* Set registers for trampoline to user mode. */ 974 cf = (struct callframe *)tf - 1; 975 memset(cf, 0, sizeof(struct callframe)); 976 cf->cf_func = (register_t)fork_return; 977 cf->cf_arg0 = (register_t)td; 978 cf->cf_arg1 = (register_t)tf; 979 980 pcb2->pcb_sp = (register_t)cf; 981 #ifdef __powerpc64__ 982 pcb2->pcb_lr = ((register_t *)fork_trampoline)[0]; 983 pcb2->pcb_toc = ((register_t *)fork_trampoline)[1]; 984 #else 985 pcb2->pcb_lr = (register_t)fork_trampoline; 986 #endif 987 pcb2->pcb_cpu.aim.usr_vsid = 0; 988 989 /* Setup to release spin count in fork_exit(). */ 990 td->td_md.md_spinlock_count = 1; 991 td->td_md.md_saved_msr = PSL_KERNSET; 992} 993 994void 995cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, 996 stack_t *stack) 997{ 998 struct trapframe *tf; 999 uintptr_t sp; 1000 1001 tf = td->td_frame; 1002 /* align stack and alloc space for frame ptr and saved LR */ 1003 #ifdef __powerpc64__ 1004 sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 48) & 1005 ~0x1f; 1006 #else 1007 sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) & 1008 ~0x1f; 1009 #endif 1010 bzero(tf, sizeof(struct trapframe)); 1011 1012 tf->fixreg[1] = (register_t)sp; 1013 tf->fixreg[3] = (register_t)arg; 1014 if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) { 1015 tf->srr0 = (register_t)entry; 1016 tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 1017 #ifdef __powerpc64__ 1018 tf->srr1 &= ~PSL_SF; 1019 #endif 1020 } else { 1021 #ifdef __powerpc64__ 1022 register_t entry_desc[3]; 1023 (void)copyin((void *)entry, entry_desc, sizeof(entry_desc)); 1024 tf->srr0 = entry_desc[0]; 1025 tf->fixreg[2] = entry_desc[1]; 1026 tf->fixreg[11] = entry_desc[2]; 1027 tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT; 1028 #endif 1029 } 1030 1031 #ifdef __powerpc64__ 1032 if (mfmsr() & PSL_HV) 1033 tf->srr1 |= PSL_HV; 1034 #endif 1035 td->td_pcb->pcb_flags = 0; 1036 1037 td->td_retval[0] = (register_t)entry; 1038 td->td_retval[1] = 0; 1039} 1040 1041