1209950Snwhitehorn/*- 2209950Snwhitehorn * Copyright (C) 1995, 1996 Wolfgang Solfrank. 3209950Snwhitehorn * Copyright (C) 1995, 1996 TooLs GmbH. 4209950Snwhitehorn * All rights reserved. 5209950Snwhitehorn * 6209950Snwhitehorn * Redistribution and use in source and binary forms, with or without 7209950Snwhitehorn * modification, are permitted provided that the following conditions 8209950Snwhitehorn * are met: 9209950Snwhitehorn * 1. Redistributions of source code must retain the above copyright 10209950Snwhitehorn * notice, this list of conditions and the following disclaimer. 11209950Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 12209950Snwhitehorn * notice, this list of conditions and the following disclaimer in the 13209950Snwhitehorn * documentation and/or other materials provided with the distribution. 14209950Snwhitehorn * 3. All advertising materials mentioning features or use of this software 15209950Snwhitehorn * must display the following acknowledgement: 16209950Snwhitehorn * This product includes software developed by TooLs GmbH. 17209950Snwhitehorn * 4. The name of TooLs GmbH may not be used to endorse or promote products 18209950Snwhitehorn * derived from this software without specific prior written permission. 19209950Snwhitehorn * 20209950Snwhitehorn * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR 21209950Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22209950Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23209950Snwhitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24209950Snwhitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25209950Snwhitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 26209950Snwhitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27209950Snwhitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 28209950Snwhitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 29209950Snwhitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30209950Snwhitehorn */ 31209950Snwhitehorn/*- 32209950Snwhitehorn * Copyright (C) 2001 Benno Rice 33209950Snwhitehorn * All rights reserved. 34209950Snwhitehorn * 35209950Snwhitehorn * Redistribution and use in source and binary forms, with or without 36209950Snwhitehorn * modification, are permitted provided that the following conditions 37209950Snwhitehorn * are met: 38209950Snwhitehorn * 1. Redistributions of source code must retain the above copyright 39209950Snwhitehorn * notice, this list of conditions and the following disclaimer. 40209950Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 41209950Snwhitehorn * notice, this list of conditions and the following disclaimer in the 42209950Snwhitehorn * documentation and/or other materials provided with the distribution. 43209950Snwhitehorn * 44209950Snwhitehorn * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR 45209950Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 46209950Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 47209950Snwhitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 48209950Snwhitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 49209950Snwhitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 50209950Snwhitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 51209950Snwhitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 52209950Snwhitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 53209950Snwhitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54209950Snwhitehorn * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $ 55209950Snwhitehorn */ 56209950Snwhitehorn 57209950Snwhitehorn#include <sys/cdefs.h> 58209950Snwhitehorn__FBSDID("$FreeBSD: stable/11/sys/powerpc/powerpc/exec_machdep.c 341165 2018-11-28 21:19:58Z vangyzen $"); 59209950Snwhitehorn 60209950Snwhitehorn#include "opt_compat.h" 61258259Snwhitehorn#include "opt_fpu_emu.h" 62209950Snwhitehorn 63209950Snwhitehorn#include <sys/param.h> 64209950Snwhitehorn#include <sys/proc.h> 65209950Snwhitehorn#include <sys/systm.h> 66209950Snwhitehorn#include <sys/bio.h> 67209950Snwhitehorn#include <sys/buf.h> 68209950Snwhitehorn#include <sys/bus.h> 69209950Snwhitehorn#include <sys/cons.h> 70209950Snwhitehorn#include <sys/cpu.h> 71209950Snwhitehorn#include <sys/exec.h> 72209950Snwhitehorn#include <sys/imgact.h> 73209950Snwhitehorn#include <sys/kernel.h> 74209950Snwhitehorn#include <sys/ktr.h> 75209950Snwhitehorn#include <sys/lock.h> 76209950Snwhitehorn#include <sys/malloc.h> 77209950Snwhitehorn#include <sys/mutex.h> 78209950Snwhitehorn#include <sys/signalvar.h> 79209950Snwhitehorn#include <sys/syscallsubr.h> 80209950Snwhitehorn#include <sys/syscall.h> 81209950Snwhitehorn#include <sys/sysent.h> 82209950Snwhitehorn#include <sys/sysproto.h> 83209950Snwhitehorn#include <sys/ucontext.h> 84209950Snwhitehorn#include <sys/uio.h> 85209950Snwhitehorn 86209950Snwhitehorn#include <machine/altivec.h> 87209950Snwhitehorn#include <machine/cpu.h> 88209950Snwhitehorn#include <machine/elf.h> 89209950Snwhitehorn#include <machine/fpu.h> 90209950Snwhitehorn#include <machine/pcb.h> 91209950Snwhitehorn#include <machine/reg.h> 92209950Snwhitehorn#include <machine/sigframe.h> 93209950Snwhitehorn#include <machine/trap.h> 94209950Snwhitehorn#include <machine/vmparam.h> 95209950Snwhitehorn 96258259Snwhitehorn#ifdef FPU_EMU 97258259Snwhitehorn#include <powerpc/fpu/fpu_extern.h> 98258259Snwhitehorn#endif 99258259Snwhitehorn 100209975Snwhitehorn#ifdef COMPAT_FREEBSD32 101209975Snwhitehorn#include <compat/freebsd32/freebsd32_signal.h> 102209975Snwhitehorn#include <compat/freebsd32/freebsd32_util.h> 103209975Snwhitehorn#include <compat/freebsd32/freebsd32_proto.h> 104209975Snwhitehorn 105209975Snwhitehorntypedef struct __ucontext32 { 106209975Snwhitehorn sigset_t uc_sigmask; 107209975Snwhitehorn mcontext32_t uc_mcontext; 108209975Snwhitehorn uint32_t uc_link; 109209975Snwhitehorn struct sigaltstack32 uc_stack; 110209975Snwhitehorn uint32_t uc_flags; 111209975Snwhitehorn uint32_t __spare__[4]; 112209975Snwhitehorn} ucontext32_t; 113209975Snwhitehorn 114209975Snwhitehornstruct sigframe32 { 115209975Snwhitehorn ucontext32_t sf_uc; 116209975Snwhitehorn struct siginfo32 sf_si; 117209975Snwhitehorn}; 118209975Snwhitehorn 119209975Snwhitehornstatic int grab_mcontext32(struct thread *td, mcontext32_t *, int flags); 120209975Snwhitehorn#endif 121209975Snwhitehorn 122209950Snwhitehornstatic int grab_mcontext(struct thread *, mcontext_t *, int); 123209950Snwhitehorn 124209950Snwhitehornvoid 125209950Snwhitehornsendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 126209950Snwhitehorn{ 127209950Snwhitehorn struct trapframe *tf; 128209950Snwhitehorn struct sigacts *psp; 129209950Snwhitehorn struct sigframe sf; 130209950Snwhitehorn struct thread *td; 131209950Snwhitehorn struct proc *p; 132209975Snwhitehorn #ifdef COMPAT_FREEBSD32 133209975Snwhitehorn struct siginfo32 siginfo32; 134209975Snwhitehorn struct sigframe32 sf32; 135209975Snwhitehorn #endif 136209950Snwhitehorn size_t sfpsize; 137209950Snwhitehorn caddr_t sfp, usfp; 138209950Snwhitehorn int oonstack, rndfsize; 139209950Snwhitehorn int sig; 140209950Snwhitehorn int code; 141209950Snwhitehorn 142209950Snwhitehorn td = curthread; 143209950Snwhitehorn p = td->td_proc; 144209950Snwhitehorn PROC_LOCK_ASSERT(p, MA_OWNED); 145209950Snwhitehorn 146209950Snwhitehorn psp = p->p_sigacts; 147209950Snwhitehorn mtx_assert(&psp->ps_mtx, MA_OWNED); 148209950Snwhitehorn tf = td->td_frame; 149209950Snwhitehorn oonstack = sigonstack(tf->fixreg[1]); 150209950Snwhitehorn 151209950Snwhitehorn /* 152209950Snwhitehorn * Fill siginfo structure. 153209950Snwhitehorn */ 154209950Snwhitehorn ksi->ksi_info.si_signo = ksi->ksi_signo; 155209950Snwhitehorn ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ? 156279601Snwhitehorn tf->dar : tf->srr0); 157209950Snwhitehorn 158209975Snwhitehorn #ifdef COMPAT_FREEBSD32 159217896Sdchagin if (SV_PROC_FLAG(p, SV_ILP32)) { 160209975Snwhitehorn siginfo_to_siginfo32(&ksi->ksi_info, &siginfo32); 161209975Snwhitehorn sig = siginfo32.si_signo; 162209975Snwhitehorn code = siginfo32.si_code; 163209975Snwhitehorn sfp = (caddr_t)&sf32; 164209975Snwhitehorn sfpsize = sizeof(sf32); 165298860Spfg rndfsize = roundup(sizeof(sf32), 16); 166209950Snwhitehorn 167209975Snwhitehorn /* 168209975Snwhitehorn * Save user context 169209975Snwhitehorn */ 170209950Snwhitehorn 171209975Snwhitehorn memset(&sf32, 0, sizeof(sf32)); 172209975Snwhitehorn grab_mcontext32(td, &sf32.sf_uc.uc_mcontext, 0); 173209950Snwhitehorn 174209975Snwhitehorn sf32.sf_uc.uc_sigmask = *mask; 175209975Snwhitehorn sf32.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 176209975Snwhitehorn sf32.sf_uc.uc_stack.ss_size = (uint32_t)td->td_sigstk.ss_size; 177209975Snwhitehorn sf32.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 178209975Snwhitehorn ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 179209950Snwhitehorn 180209975Snwhitehorn sf32.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 181209975Snwhitehorn } else { 182209975Snwhitehorn #endif 183209975Snwhitehorn sig = ksi->ksi_signo; 184209975Snwhitehorn code = ksi->ksi_code; 185209975Snwhitehorn sfp = (caddr_t)&sf; 186209975Snwhitehorn sfpsize = sizeof(sf); 187209975Snwhitehorn #ifdef __powerpc64__ 188209975Snwhitehorn /* 189209975Snwhitehorn * 64-bit PPC defines a 288 byte scratch region 190209975Snwhitehorn * below the stack. 191209975Snwhitehorn */ 192298860Spfg rndfsize = 288 + roundup(sizeof(sf), 48); 193209975Snwhitehorn #else 194298860Spfg rndfsize = roundup(sizeof(sf), 16); 195209975Snwhitehorn #endif 196209950Snwhitehorn 197209975Snwhitehorn /* 198209975Snwhitehorn * Save user context 199209975Snwhitehorn */ 200209975Snwhitehorn 201209975Snwhitehorn memset(&sf, 0, sizeof(sf)); 202209975Snwhitehorn grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0); 203209975Snwhitehorn 204209975Snwhitehorn sf.sf_uc.uc_sigmask = *mask; 205209975Snwhitehorn sf.sf_uc.uc_stack = td->td_sigstk; 206209975Snwhitehorn sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 207209975Snwhitehorn ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 208209975Snwhitehorn 209209975Snwhitehorn sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 210209975Snwhitehorn #ifdef COMPAT_FREEBSD32 211209975Snwhitehorn } 212209975Snwhitehorn #endif 213209975Snwhitehorn 214209950Snwhitehorn CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 215209950Snwhitehorn catcher, sig); 216209950Snwhitehorn 217209950Snwhitehorn /* 218209950Snwhitehorn * Allocate and validate space for the signal handler context. 219209950Snwhitehorn */ 220209950Snwhitehorn if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 221209950Snwhitehorn SIGISMEMBER(psp->ps_sigonstack, sig)) { 222295186Sjhibbits usfp = (void *)(((uintptr_t)td->td_sigstk.ss_sp + 223295186Sjhibbits td->td_sigstk.ss_size - rndfsize) & ~0xFul); 224209950Snwhitehorn } else { 225295186Sjhibbits usfp = (void *)((tf->fixreg[1] - rndfsize) & ~0xFul); 226209950Snwhitehorn } 227209950Snwhitehorn 228209950Snwhitehorn /* 229209950Snwhitehorn * Save the floating-point state, if necessary, then copy it. 230209950Snwhitehorn */ 231209950Snwhitehorn /* XXX */ 232209950Snwhitehorn 233209950Snwhitehorn /* 234209950Snwhitehorn * Set up the registers to return to sigcode. 235209950Snwhitehorn * 236209950Snwhitehorn * r1/sp - sigframe ptr 237209950Snwhitehorn * lr - sig function, dispatched to by blrl in trampoline 238209950Snwhitehorn * r3 - sig number 239209950Snwhitehorn * r4 - SIGINFO ? &siginfo : exception code 240209950Snwhitehorn * r5 - user context 241209950Snwhitehorn * srr0 - trampoline function addr 242209950Snwhitehorn */ 243209950Snwhitehorn tf->lr = (register_t)catcher; 244209950Snwhitehorn tf->fixreg[1] = (register_t)usfp; 245209950Snwhitehorn tf->fixreg[FIRSTARG] = sig; 246209975Snwhitehorn #ifdef COMPAT_FREEBSD32 247209950Snwhitehorn tf->fixreg[FIRSTARG+2] = (register_t)usfp + 248217896Sdchagin ((SV_PROC_FLAG(p, SV_ILP32)) ? 249209975Snwhitehorn offsetof(struct sigframe32, sf_uc) : 250212586Snwhitehorn offsetof(struct sigframe, sf_uc)); 251209975Snwhitehorn #else 252209975Snwhitehorn tf->fixreg[FIRSTARG+2] = (register_t)usfp + 253209975Snwhitehorn offsetof(struct sigframe, sf_uc); 254209975Snwhitehorn #endif 255209950Snwhitehorn if (SIGISMEMBER(psp->ps_siginfo, sig)) { 256209950Snwhitehorn /* 257209950Snwhitehorn * Signal handler installed with SA_SIGINFO. 258209950Snwhitehorn */ 259209975Snwhitehorn #ifdef COMPAT_FREEBSD32 260217896Sdchagin if (SV_PROC_FLAG(p, SV_ILP32)) { 261209975Snwhitehorn sf32.sf_si = siginfo32; 262209950Snwhitehorn tf->fixreg[FIRSTARG+1] = (register_t)usfp + 263209975Snwhitehorn offsetof(struct sigframe32, sf_si); 264209975Snwhitehorn sf32.sf_si = siginfo32; 265209975Snwhitehorn } else { 266209975Snwhitehorn #endif 267209975Snwhitehorn tf->fixreg[FIRSTARG+1] = (register_t)usfp + 268209950Snwhitehorn offsetof(struct sigframe, sf_si); 269209950Snwhitehorn sf.sf_si = ksi->ksi_info; 270209975Snwhitehorn #ifdef COMPAT_FREEBSD32 271209975Snwhitehorn } 272209975Snwhitehorn #endif 273209950Snwhitehorn } else { 274209950Snwhitehorn /* Old FreeBSD-style arguments. */ 275209950Snwhitehorn tf->fixreg[FIRSTARG+1] = code; 276209950Snwhitehorn tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 277279601Snwhitehorn tf->dar : tf->srr0; 278209950Snwhitehorn } 279209950Snwhitehorn mtx_unlock(&psp->ps_mtx); 280209950Snwhitehorn PROC_UNLOCK(p); 281209950Snwhitehorn 282217400Skib tf->srr0 = (register_t)p->p_sysent->sv_sigcode_base; 283209950Snwhitehorn 284209950Snwhitehorn /* 285209950Snwhitehorn * copy the frame out to userland. 286209950Snwhitehorn */ 287209950Snwhitehorn if (copyout(sfp, usfp, sfpsize) != 0) { 288209950Snwhitehorn /* 289209950Snwhitehorn * Process has trashed its stack. Kill it. 290209950Snwhitehorn */ 291209950Snwhitehorn CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 292209950Snwhitehorn PROC_LOCK(p); 293209950Snwhitehorn sigexit(td, SIGILL); 294209950Snwhitehorn } 295209950Snwhitehorn 296209950Snwhitehorn CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, 297209950Snwhitehorn tf->srr0, tf->fixreg[1]); 298209950Snwhitehorn 299209950Snwhitehorn PROC_LOCK(p); 300209950Snwhitehorn mtx_lock(&psp->ps_mtx); 301209950Snwhitehorn} 302209950Snwhitehorn 303209950Snwhitehornint 304225617Skmacysys_sigreturn(struct thread *td, struct sigreturn_args *uap) 305209950Snwhitehorn{ 306209950Snwhitehorn ucontext_t uc; 307209950Snwhitehorn int error; 308209950Snwhitehorn 309209950Snwhitehorn CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 310209950Snwhitehorn 311209950Snwhitehorn if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 312209950Snwhitehorn CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 313209950Snwhitehorn return (EFAULT); 314209950Snwhitehorn } 315209950Snwhitehorn 316209950Snwhitehorn error = set_mcontext(td, &uc.uc_mcontext); 317209950Snwhitehorn if (error != 0) 318209950Snwhitehorn return (error); 319209950Snwhitehorn 320209950Snwhitehorn kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 321209950Snwhitehorn 322209950Snwhitehorn CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 323209950Snwhitehorn td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 324209950Snwhitehorn 325209950Snwhitehorn return (EJUSTRETURN); 326209950Snwhitehorn} 327209950Snwhitehorn 328209950Snwhitehorn#ifdef COMPAT_FREEBSD4 329209950Snwhitehornint 330209950Snwhitehornfreebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) 331209950Snwhitehorn{ 332209950Snwhitehorn 333225617Skmacy return sys_sigreturn(td, (struct sigreturn_args *)uap); 334209950Snwhitehorn} 335209950Snwhitehorn#endif 336209950Snwhitehorn 337209950Snwhitehorn/* 338209950Snwhitehorn * Construct a PCB from a trapframe. This is called from kdb_trap() where 339209950Snwhitehorn * we want to start a backtrace from the function that caused us to enter 340209950Snwhitehorn * the debugger. We have the context in the trapframe, but base the trace 341209950Snwhitehorn * on the PCB. The PCB doesn't have to be perfect, as long as it contains 342209950Snwhitehorn * enough for a backtrace. 343209950Snwhitehorn */ 344209950Snwhitehornvoid 345209950Snwhitehornmakectx(struct trapframe *tf, struct pcb *pcb) 346209950Snwhitehorn{ 347209950Snwhitehorn 348209950Snwhitehorn pcb->pcb_lr = tf->srr0; 349209950Snwhitehorn pcb->pcb_sp = tf->fixreg[1]; 350209950Snwhitehorn} 351209950Snwhitehorn 352209950Snwhitehorn/* 353209950Snwhitehorn * get_mcontext/sendsig helper routine that doesn't touch the 354209950Snwhitehorn * proc lock 355209950Snwhitehorn */ 356209950Snwhitehornstatic int 357209950Snwhitehorngrab_mcontext(struct thread *td, mcontext_t *mcp, int flags) 358209950Snwhitehorn{ 359209950Snwhitehorn struct pcb *pcb; 360279189Snwhitehorn int i; 361209950Snwhitehorn 362209950Snwhitehorn pcb = td->td_pcb; 363209950Snwhitehorn 364209950Snwhitehorn memset(mcp, 0, sizeof(mcontext_t)); 365209950Snwhitehorn 366209950Snwhitehorn mcp->mc_vers = _MC_VERSION; 367209950Snwhitehorn mcp->mc_flags = 0; 368209950Snwhitehorn memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe)); 369209950Snwhitehorn if (flags & GET_MC_CLEAR_RET) { 370209950Snwhitehorn mcp->mc_gpr[3] = 0; 371209950Snwhitehorn mcp->mc_gpr[4] = 0; 372209950Snwhitehorn } 373209950Snwhitehorn 374209950Snwhitehorn /* 375209950Snwhitehorn * This assumes that floating-point context is *not* lazy, 376209950Snwhitehorn * so if the thread has used FP there would have been a 377209950Snwhitehorn * FP-unavailable exception that would have set things up 378209950Snwhitehorn * correctly. 379209950Snwhitehorn */ 380258257Snwhitehorn if (pcb->pcb_flags & PCB_FPREGS) { 381258257Snwhitehorn if (pcb->pcb_flags & PCB_FPU) { 382258257Snwhitehorn KASSERT(td == curthread, 383258257Snwhitehorn ("get_mcontext: fp save not curthread")); 384258257Snwhitehorn critical_enter(); 385258257Snwhitehorn save_fpu(td); 386258257Snwhitehorn critical_exit(); 387258257Snwhitehorn } 388209950Snwhitehorn mcp->mc_flags |= _MC_FP_VALID; 389209950Snwhitehorn memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double)); 390279189Snwhitehorn for (i = 0; i < 32; i++) 391279189Snwhitehorn memcpy(&mcp->mc_fpreg[i], &pcb->pcb_fpu.fpr[i].fpr, 392279189Snwhitehorn sizeof(double)); 393209950Snwhitehorn } 394209950Snwhitehorn 395279937Snwhitehorn if (pcb->pcb_flags & PCB_VSX) { 396279937Snwhitehorn for (i = 0; i < 32; i++) 397279937Snwhitehorn memcpy(&mcp->mc_vsxfpreg[i], 398279937Snwhitehorn &pcb->pcb_fpu.fpr[i].vsr[2], sizeof(double)); 399279937Snwhitehorn } 400279937Snwhitehorn 401209950Snwhitehorn /* 402209950Snwhitehorn * Repeat for Altivec context 403209950Snwhitehorn */ 404209950Snwhitehorn 405209950Snwhitehorn if (pcb->pcb_flags & PCB_VEC) { 406209950Snwhitehorn KASSERT(td == curthread, 407209950Snwhitehorn ("get_mcontext: fp save not curthread")); 408209950Snwhitehorn critical_enter(); 409209950Snwhitehorn save_vec(td); 410209950Snwhitehorn critical_exit(); 411209950Snwhitehorn mcp->mc_flags |= _MC_AV_VALID; 412209950Snwhitehorn mcp->mc_vscr = pcb->pcb_vec.vscr; 413209950Snwhitehorn mcp->mc_vrsave = pcb->pcb_vec.vrsave; 414209950Snwhitehorn memcpy(mcp->mc_avec, pcb->pcb_vec.vr, sizeof(mcp->mc_avec)); 415209950Snwhitehorn } 416209950Snwhitehorn 417209950Snwhitehorn mcp->mc_len = sizeof(*mcp); 418209950Snwhitehorn 419209950Snwhitehorn return (0); 420209950Snwhitehorn} 421209950Snwhitehorn 422209950Snwhitehornint 423209950Snwhitehornget_mcontext(struct thread *td, mcontext_t *mcp, int flags) 424209950Snwhitehorn{ 425209950Snwhitehorn int error; 426209950Snwhitehorn 427209950Snwhitehorn error = grab_mcontext(td, mcp, flags); 428209950Snwhitehorn if (error == 0) { 429209950Snwhitehorn PROC_LOCK(curthread->td_proc); 430209950Snwhitehorn mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 431209950Snwhitehorn PROC_UNLOCK(curthread->td_proc); 432209950Snwhitehorn } 433209950Snwhitehorn 434209950Snwhitehorn return (error); 435209950Snwhitehorn} 436209950Snwhitehorn 437209950Snwhitehornint 438278001Skibset_mcontext(struct thread *td, mcontext_t *mcp) 439209950Snwhitehorn{ 440209950Snwhitehorn struct pcb *pcb; 441209950Snwhitehorn struct trapframe *tf; 442234115Snwhitehorn register_t tls; 443279189Snwhitehorn int i; 444209950Snwhitehorn 445209950Snwhitehorn pcb = td->td_pcb; 446209950Snwhitehorn tf = td->td_frame; 447209950Snwhitehorn 448209950Snwhitehorn if (mcp->mc_vers != _MC_VERSION || mcp->mc_len != sizeof(*mcp)) 449209950Snwhitehorn return (EINVAL); 450209950Snwhitehorn 451209950Snwhitehorn /* 452209950Snwhitehorn * Don't let the user set privileged MSR bits 453209950Snwhitehorn */ 454209950Snwhitehorn if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) { 455209950Snwhitehorn return (EINVAL); 456209950Snwhitehorn } 457209950Snwhitehorn 458234115Snwhitehorn /* Copy trapframe, preserving TLS pointer across context change */ 459234115Snwhitehorn if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 460234115Snwhitehorn tls = tf->fixreg[13]; 461234115Snwhitehorn else 462234115Snwhitehorn tls = tf->fixreg[2]; 463209950Snwhitehorn memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame)); 464234115Snwhitehorn if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 465234115Snwhitehorn tf->fixreg[13] = tls; 466234115Snwhitehorn else 467234115Snwhitehorn tf->fixreg[2] = tls; 468209950Snwhitehorn 469209950Snwhitehorn if (mcp->mc_flags & _MC_FP_VALID) { 470258257Snwhitehorn /* enable_fpu() will happen lazily on a fault */ 471258257Snwhitehorn pcb->pcb_flags |= PCB_FPREGS; 472209950Snwhitehorn memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double)); 473279189Snwhitehorn bzero(pcb->pcb_fpu.fpr, sizeof(pcb->pcb_fpu.fpr)); 474279937Snwhitehorn for (i = 0; i < 32; i++) { 475279189Snwhitehorn memcpy(&pcb->pcb_fpu.fpr[i].fpr, &mcp->mc_fpreg[i], 476279189Snwhitehorn sizeof(double)); 477279937Snwhitehorn memcpy(&pcb->pcb_fpu.fpr[i].vsr[2], 478279937Snwhitehorn &mcp->mc_vsxfpreg[i], sizeof(double)); 479279937Snwhitehorn } 480209950Snwhitehorn } 481209950Snwhitehorn 482209950Snwhitehorn if (mcp->mc_flags & _MC_AV_VALID) { 483209950Snwhitehorn if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) { 484209950Snwhitehorn critical_enter(); 485209950Snwhitehorn enable_vec(td); 486209950Snwhitehorn critical_exit(); 487209950Snwhitehorn } 488209950Snwhitehorn pcb->pcb_vec.vscr = mcp->mc_vscr; 489209950Snwhitehorn pcb->pcb_vec.vrsave = mcp->mc_vrsave; 490209950Snwhitehorn memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec)); 491209950Snwhitehorn } 492209950Snwhitehorn 493209950Snwhitehorn return (0); 494209950Snwhitehorn} 495209950Snwhitehorn 496209950Snwhitehorn/* 497209950Snwhitehorn * Set set up registers on exec. 498209950Snwhitehorn */ 499209950Snwhitehornvoid 500209950Snwhitehornexec_setregs(struct thread *td, struct image_params *imgp, u_long stack) 501209950Snwhitehorn{ 502209950Snwhitehorn struct trapframe *tf; 503209950Snwhitehorn register_t argc; 504209950Snwhitehorn 505209950Snwhitehorn tf = trapframe(td); 506209950Snwhitehorn bzero(tf, sizeof *tf); 507209975Snwhitehorn #ifdef __powerpc64__ 508209975Snwhitehorn tf->fixreg[1] = -roundup(-stack + 48, 16); 509209975Snwhitehorn #else 510209950Snwhitehorn tf->fixreg[1] = -roundup(-stack + 8, 16); 511209975Snwhitehorn #endif 512209950Snwhitehorn 513209950Snwhitehorn /* 514209950Snwhitehorn * Set up arguments for _start(): 515209950Snwhitehorn * _start(argc, argv, envp, obj, cleanup, ps_strings); 516209950Snwhitehorn * 517209950Snwhitehorn * Notes: 518209950Snwhitehorn * - obj and cleanup are the auxilliary and termination 519209950Snwhitehorn * vectors. They are fixed up by ld.elf_so. 520209950Snwhitehorn * - ps_strings is a NetBSD extention, and will be 521209950Snwhitehorn * ignored by executables which are strictly 522209950Snwhitehorn * compliant with the SVR4 ABI. 523209950Snwhitehorn * 524209950Snwhitehorn * XXX We have to set both regs and retval here due to different 525209950Snwhitehorn * XXX calling convention in trap.c and init_main.c. 526209950Snwhitehorn */ 527209950Snwhitehorn 528209950Snwhitehorn /* Collect argc from the user stack */ 529209950Snwhitehorn argc = fuword((void *)stack); 530209950Snwhitehorn 531209950Snwhitehorn /* 532209950Snwhitehorn * XXX PG: these get overwritten in the syscall return code. 533209950Snwhitehorn * execve() should return EJUSTRETURN, like it does on NetBSD. 534209950Snwhitehorn * Emulate by setting the syscall return value cells. The 535209950Snwhitehorn * registers still have to be set for init's fork trampoline. 536209950Snwhitehorn */ 537209950Snwhitehorn td->td_retval[0] = argc; 538209950Snwhitehorn td->td_retval[1] = stack + sizeof(register_t); 539209950Snwhitehorn tf->fixreg[3] = argc; 540209950Snwhitehorn tf->fixreg[4] = stack + sizeof(register_t); 541209950Snwhitehorn tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t); 542209950Snwhitehorn tf->fixreg[6] = 0; /* auxillary vector */ 543209950Snwhitehorn tf->fixreg[7] = 0; /* termination vector */ 544209950Snwhitehorn tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 545209950Snwhitehorn 546291211Snwhitehorn tf->srr0 = imgp->entry_addr; 547209975Snwhitehorn #ifdef __powerpc64__ 548291211Snwhitehorn tf->fixreg[12] = imgp->entry_addr; 549209975Snwhitehorn tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT; 550209975Snwhitehorn if (mfmsr() & PSL_HV) 551209975Snwhitehorn tf->srr1 |= PSL_HV; 552209975Snwhitehorn #else 553209950Snwhitehorn tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 554209975Snwhitehorn #endif 555209950Snwhitehorn td->td_pcb->pcb_flags = 0; 556209950Snwhitehorn} 557209950Snwhitehorn 558209975Snwhitehorn#ifdef COMPAT_FREEBSD32 559209975Snwhitehornvoid 560209975Snwhitehornppc32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 561209975Snwhitehorn{ 562209975Snwhitehorn struct trapframe *tf; 563209975Snwhitehorn uint32_t argc; 564209950Snwhitehorn 565209975Snwhitehorn tf = trapframe(td); 566209975Snwhitehorn bzero(tf, sizeof *tf); 567209975Snwhitehorn tf->fixreg[1] = -roundup(-stack + 8, 16); 568209975Snwhitehorn 569209975Snwhitehorn argc = fuword32((void *)stack); 570209975Snwhitehorn 571209975Snwhitehorn td->td_retval[0] = argc; 572209975Snwhitehorn td->td_retval[1] = stack + sizeof(uint32_t); 573209975Snwhitehorn tf->fixreg[3] = argc; 574209975Snwhitehorn tf->fixreg[4] = stack + sizeof(uint32_t); 575209975Snwhitehorn tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t); 576209975Snwhitehorn tf->fixreg[6] = 0; /* auxillary vector */ 577209975Snwhitehorn tf->fixreg[7] = 0; /* termination vector */ 578209975Snwhitehorn tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 579209975Snwhitehorn 580209975Snwhitehorn tf->srr0 = imgp->entry_addr; 581257115Snwhitehorn tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 582209975Snwhitehorn tf->srr1 &= ~PSL_SF; 583209975Snwhitehorn if (mfmsr() & PSL_HV) 584209975Snwhitehorn tf->srr1 |= PSL_HV; 585209975Snwhitehorn td->td_pcb->pcb_flags = 0; 586209975Snwhitehorn} 587209975Snwhitehorn#endif 588209975Snwhitehorn 589209950Snwhitehornint 590209950Snwhitehornfill_regs(struct thread *td, struct reg *regs) 591209950Snwhitehorn{ 592209950Snwhitehorn struct trapframe *tf; 593209950Snwhitehorn 594209950Snwhitehorn tf = td->td_frame; 595209950Snwhitehorn memcpy(regs, tf, sizeof(struct reg)); 596209950Snwhitehorn 597209950Snwhitehorn return (0); 598209950Snwhitehorn} 599209950Snwhitehorn 600209950Snwhitehornint 601209950Snwhitehornfill_dbregs(struct thread *td, struct dbreg *dbregs) 602209950Snwhitehorn{ 603209950Snwhitehorn /* No debug registers on PowerPC */ 604209950Snwhitehorn return (ENOSYS); 605209950Snwhitehorn} 606209950Snwhitehorn 607209950Snwhitehornint 608209950Snwhitehornfill_fpregs(struct thread *td, struct fpreg *fpregs) 609209950Snwhitehorn{ 610209950Snwhitehorn struct pcb *pcb; 611295132Sjhb int i; 612209950Snwhitehorn 613209950Snwhitehorn pcb = td->td_pcb; 614209950Snwhitehorn 615258257Snwhitehorn if ((pcb->pcb_flags & PCB_FPREGS) == 0) 616209950Snwhitehorn memset(fpregs, 0, sizeof(struct fpreg)); 617295132Sjhb else { 618295132Sjhb memcpy(&fpregs->fpscr, &pcb->pcb_fpu.fpscr, sizeof(double)); 619295132Sjhb for (i = 0; i < 32; i++) 620295132Sjhb memcpy(&fpregs->fpreg[i], &pcb->pcb_fpu.fpr[i].fpr, 621295132Sjhb sizeof(double)); 622295132Sjhb } 623209950Snwhitehorn 624209950Snwhitehorn return (0); 625209950Snwhitehorn} 626209950Snwhitehorn 627209950Snwhitehornint 628209950Snwhitehornset_regs(struct thread *td, struct reg *regs) 629209950Snwhitehorn{ 630209950Snwhitehorn struct trapframe *tf; 631209950Snwhitehorn 632209950Snwhitehorn tf = td->td_frame; 633209950Snwhitehorn memcpy(tf, regs, sizeof(struct reg)); 634209950Snwhitehorn 635209950Snwhitehorn return (0); 636209950Snwhitehorn} 637209950Snwhitehorn 638209950Snwhitehornint 639209950Snwhitehornset_dbregs(struct thread *td, struct dbreg *dbregs) 640209950Snwhitehorn{ 641209950Snwhitehorn /* No debug registers on PowerPC */ 642209950Snwhitehorn return (ENOSYS); 643209950Snwhitehorn} 644209950Snwhitehorn 645209950Snwhitehornint 646209950Snwhitehornset_fpregs(struct thread *td, struct fpreg *fpregs) 647209950Snwhitehorn{ 648209950Snwhitehorn struct pcb *pcb; 649295132Sjhb int i; 650209950Snwhitehorn 651209950Snwhitehorn pcb = td->td_pcb; 652258257Snwhitehorn pcb->pcb_flags |= PCB_FPREGS; 653295132Sjhb memcpy(&pcb->pcb_fpu.fpscr, &fpregs->fpscr, sizeof(double)); 654295132Sjhb for (i = 0; i < 32; i++) { 655295132Sjhb memcpy(&pcb->pcb_fpu.fpr[i].fpr, &fpregs->fpreg[i], 656295132Sjhb sizeof(double)); 657295132Sjhb } 658209950Snwhitehorn 659209950Snwhitehorn return (0); 660209950Snwhitehorn} 661209950Snwhitehorn 662209975Snwhitehorn#ifdef COMPAT_FREEBSD32 663209975Snwhitehornint 664209975Snwhitehornset_regs32(struct thread *td, struct reg32 *regs) 665209975Snwhitehorn{ 666209975Snwhitehorn struct trapframe *tf; 667209975Snwhitehorn int i; 668209950Snwhitehorn 669209975Snwhitehorn tf = td->td_frame; 670209975Snwhitehorn for (i = 0; i < 32; i++) 671209975Snwhitehorn tf->fixreg[i] = regs->fixreg[i]; 672209975Snwhitehorn tf->lr = regs->lr; 673209975Snwhitehorn tf->cr = regs->cr; 674209975Snwhitehorn tf->xer = regs->xer; 675209975Snwhitehorn tf->ctr = regs->ctr; 676209975Snwhitehorn tf->srr0 = regs->pc; 677209950Snwhitehorn 678209975Snwhitehorn return (0); 679209975Snwhitehorn} 680209975Snwhitehorn 681209975Snwhitehornint 682209975Snwhitehornfill_regs32(struct thread *td, struct reg32 *regs) 683209975Snwhitehorn{ 684209975Snwhitehorn struct trapframe *tf; 685209975Snwhitehorn int i; 686209975Snwhitehorn 687209975Snwhitehorn tf = td->td_frame; 688209975Snwhitehorn for (i = 0; i < 32; i++) 689209975Snwhitehorn regs->fixreg[i] = tf->fixreg[i]; 690209975Snwhitehorn regs->lr = tf->lr; 691209975Snwhitehorn regs->cr = tf->cr; 692209975Snwhitehorn regs->xer = tf->xer; 693209975Snwhitehorn regs->ctr = tf->ctr; 694209975Snwhitehorn regs->pc = tf->srr0; 695209975Snwhitehorn 696209975Snwhitehorn return (0); 697209975Snwhitehorn} 698209975Snwhitehorn 699209975Snwhitehornstatic int 700209975Snwhitehorngrab_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 701209975Snwhitehorn{ 702209975Snwhitehorn mcontext_t mcp64; 703209975Snwhitehorn int i, error; 704209975Snwhitehorn 705209975Snwhitehorn error = grab_mcontext(td, &mcp64, flags); 706209975Snwhitehorn if (error != 0) 707209975Snwhitehorn return (error); 708209975Snwhitehorn 709209975Snwhitehorn mcp->mc_vers = mcp64.mc_vers; 710209975Snwhitehorn mcp->mc_flags = mcp64.mc_flags; 711209975Snwhitehorn mcp->mc_onstack = mcp64.mc_onstack; 712209975Snwhitehorn mcp->mc_len = mcp64.mc_len; 713209975Snwhitehorn memcpy(mcp->mc_avec,mcp64.mc_avec,sizeof(mcp64.mc_avec)); 714209975Snwhitehorn memcpy(mcp->mc_av,mcp64.mc_av,sizeof(mcp64.mc_av)); 715209975Snwhitehorn for (i = 0; i < 42; i++) 716209975Snwhitehorn mcp->mc_frame[i] = mcp64.mc_frame[i]; 717209975Snwhitehorn memcpy(mcp->mc_fpreg,mcp64.mc_fpreg,sizeof(mcp64.mc_fpreg)); 718279937Snwhitehorn memcpy(mcp->mc_vsxfpreg,mcp64.mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg)); 719209975Snwhitehorn 720209975Snwhitehorn return (0); 721209975Snwhitehorn} 722209975Snwhitehorn 723209975Snwhitehornstatic int 724209975Snwhitehornget_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 725209975Snwhitehorn{ 726209975Snwhitehorn int error; 727209975Snwhitehorn 728209975Snwhitehorn error = grab_mcontext32(td, mcp, flags); 729209975Snwhitehorn if (error == 0) { 730209975Snwhitehorn PROC_LOCK(curthread->td_proc); 731209975Snwhitehorn mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 732209975Snwhitehorn PROC_UNLOCK(curthread->td_proc); 733209975Snwhitehorn } 734209975Snwhitehorn 735209975Snwhitehorn return (error); 736209975Snwhitehorn} 737209975Snwhitehorn 738209975Snwhitehornstatic int 739278001Skibset_mcontext32(struct thread *td, mcontext32_t *mcp) 740209975Snwhitehorn{ 741209975Snwhitehorn mcontext_t mcp64; 742209975Snwhitehorn int i, error; 743209975Snwhitehorn 744209975Snwhitehorn mcp64.mc_vers = mcp->mc_vers; 745209975Snwhitehorn mcp64.mc_flags = mcp->mc_flags; 746209975Snwhitehorn mcp64.mc_onstack = mcp->mc_onstack; 747209975Snwhitehorn mcp64.mc_len = mcp->mc_len; 748209975Snwhitehorn memcpy(mcp64.mc_avec,mcp->mc_avec,sizeof(mcp64.mc_avec)); 749209975Snwhitehorn memcpy(mcp64.mc_av,mcp->mc_av,sizeof(mcp64.mc_av)); 750209975Snwhitehorn for (i = 0; i < 42; i++) 751209975Snwhitehorn mcp64.mc_frame[i] = mcp->mc_frame[i]; 752261095Sjhibbits mcp64.mc_srr1 |= (td->td_frame->srr1 & 0xFFFFFFFF00000000ULL); 753209975Snwhitehorn memcpy(mcp64.mc_fpreg,mcp->mc_fpreg,sizeof(mcp64.mc_fpreg)); 754279937Snwhitehorn memcpy(mcp64.mc_vsxfpreg,mcp->mc_vsxfpreg,sizeof(mcp64.mc_vsxfpreg)); 755209975Snwhitehorn 756209975Snwhitehorn error = set_mcontext(td, &mcp64); 757209975Snwhitehorn 758209975Snwhitehorn return (error); 759209975Snwhitehorn} 760209975Snwhitehorn#endif 761209975Snwhitehorn 762209975Snwhitehorn#ifdef COMPAT_FREEBSD32 763209975Snwhitehornint 764209975Snwhitehornfreebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap) 765209975Snwhitehorn{ 766209975Snwhitehorn ucontext32_t uc; 767209975Snwhitehorn int error; 768209975Snwhitehorn 769209975Snwhitehorn CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 770209975Snwhitehorn 771209975Snwhitehorn if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 772209975Snwhitehorn CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 773209975Snwhitehorn return (EFAULT); 774209975Snwhitehorn } 775209975Snwhitehorn 776209975Snwhitehorn error = set_mcontext32(td, &uc.uc_mcontext); 777209975Snwhitehorn if (error != 0) 778209975Snwhitehorn return (error); 779209975Snwhitehorn 780209975Snwhitehorn kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 781209975Snwhitehorn 782209975Snwhitehorn CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 783209975Snwhitehorn td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 784209975Snwhitehorn 785209975Snwhitehorn return (EJUSTRETURN); 786209975Snwhitehorn} 787209975Snwhitehorn 788209975Snwhitehorn/* 789209975Snwhitehorn * The first two fields of a ucontext_t are the signal mask and the machine 790209975Snwhitehorn * context. The next field is uc_link; we want to avoid destroying the link 791209975Snwhitehorn * when copying out contexts. 792209975Snwhitehorn */ 793209975Snwhitehorn#define UC32_COPY_SIZE offsetof(ucontext32_t, uc_link) 794209975Snwhitehorn 795209975Snwhitehornint 796209975Snwhitehornfreebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 797209975Snwhitehorn{ 798209975Snwhitehorn ucontext32_t uc; 799209975Snwhitehorn int ret; 800209975Snwhitehorn 801209975Snwhitehorn if (uap->ucp == NULL) 802209975Snwhitehorn ret = EINVAL; 803209975Snwhitehorn else { 804341165Svangyzen bzero(&uc, sizeof(uc)); 805209975Snwhitehorn get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 806209975Snwhitehorn PROC_LOCK(td->td_proc); 807209975Snwhitehorn uc.uc_sigmask = td->td_sigmask; 808209975Snwhitehorn PROC_UNLOCK(td->td_proc); 809209975Snwhitehorn ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE); 810209975Snwhitehorn } 811209975Snwhitehorn return (ret); 812209975Snwhitehorn} 813209975Snwhitehorn 814209975Snwhitehornint 815209975Snwhitehornfreebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 816209975Snwhitehorn{ 817209975Snwhitehorn ucontext32_t uc; 818209975Snwhitehorn int ret; 819209975Snwhitehorn 820209975Snwhitehorn if (uap->ucp == NULL) 821209975Snwhitehorn ret = EINVAL; 822209975Snwhitehorn else { 823209975Snwhitehorn ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 824209975Snwhitehorn if (ret == 0) { 825209975Snwhitehorn ret = set_mcontext32(td, &uc.uc_mcontext); 826209975Snwhitehorn if (ret == 0) { 827209975Snwhitehorn kern_sigprocmask(td, SIG_SETMASK, 828209975Snwhitehorn &uc.uc_sigmask, NULL, 0); 829209975Snwhitehorn } 830209975Snwhitehorn } 831209975Snwhitehorn } 832209975Snwhitehorn return (ret == 0 ? EJUSTRETURN : ret); 833209975Snwhitehorn} 834209975Snwhitehorn 835209975Snwhitehornint 836209975Snwhitehornfreebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 837209975Snwhitehorn{ 838209975Snwhitehorn ucontext32_t uc; 839209975Snwhitehorn int ret; 840209975Snwhitehorn 841209975Snwhitehorn if (uap->oucp == NULL || uap->ucp == NULL) 842209975Snwhitehorn ret = EINVAL; 843209975Snwhitehorn else { 844341165Svangyzen bzero(&uc, sizeof(uc)); 845209975Snwhitehorn get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 846209975Snwhitehorn PROC_LOCK(td->td_proc); 847209975Snwhitehorn uc.uc_sigmask = td->td_sigmask; 848209975Snwhitehorn PROC_UNLOCK(td->td_proc); 849209975Snwhitehorn ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE); 850209975Snwhitehorn if (ret == 0) { 851209975Snwhitehorn ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 852209975Snwhitehorn if (ret == 0) { 853209975Snwhitehorn ret = set_mcontext32(td, &uc.uc_mcontext); 854209975Snwhitehorn if (ret == 0) { 855209975Snwhitehorn kern_sigprocmask(td, SIG_SETMASK, 856209975Snwhitehorn &uc.uc_sigmask, NULL, 0); 857209975Snwhitehorn } 858209975Snwhitehorn } 859209975Snwhitehorn } 860209975Snwhitehorn } 861209975Snwhitehorn return (ret == 0 ? EJUSTRETURN : ret); 862209975Snwhitehorn} 863209975Snwhitehorn 864209975Snwhitehorn#endif 865209975Snwhitehorn 866209950Snwhitehornvoid 867209950Snwhitehorncpu_set_syscall_retval(struct thread *td, int error) 868209950Snwhitehorn{ 869209950Snwhitehorn struct proc *p; 870209950Snwhitehorn struct trapframe *tf; 871209950Snwhitehorn int fixup; 872209950Snwhitehorn 873209950Snwhitehorn if (error == EJUSTRETURN) 874209950Snwhitehorn return; 875209950Snwhitehorn 876209950Snwhitehorn p = td->td_proc; 877209950Snwhitehorn tf = td->td_frame; 878209950Snwhitehorn 879209975Snwhitehorn if (tf->fixreg[0] == SYS___syscall && 880217896Sdchagin (SV_PROC_FLAG(p, SV_ILP32))) { 881209950Snwhitehorn int code = tf->fixreg[FIRSTARG + 1]; 882209950Snwhitehorn if (p->p_sysent->sv_mask) 883209950Snwhitehorn code &= p->p_sysent->sv_mask; 884296861Sbz fixup = ( 885296861Sbz#if defined(COMPAT_FREEBSD6) && defined(SYS_freebsd6_lseek) 886296861Sbz code != SYS_freebsd6_lseek && 887296861Sbz#endif 888296861Sbz code != SYS_lseek) ? 1 : 0; 889209950Snwhitehorn } else 890209950Snwhitehorn fixup = 0; 891209950Snwhitehorn 892209950Snwhitehorn switch (error) { 893209950Snwhitehorn case 0: 894209950Snwhitehorn if (fixup) { 895209950Snwhitehorn /* 896209950Snwhitehorn * 64-bit return, 32-bit syscall. Fixup byte order 897209950Snwhitehorn */ 898209950Snwhitehorn tf->fixreg[FIRSTARG] = 0; 899209950Snwhitehorn tf->fixreg[FIRSTARG + 1] = td->td_retval[0]; 900209950Snwhitehorn } else { 901209950Snwhitehorn tf->fixreg[FIRSTARG] = td->td_retval[0]; 902209950Snwhitehorn tf->fixreg[FIRSTARG + 1] = td->td_retval[1]; 903209950Snwhitehorn } 904209950Snwhitehorn tf->cr &= ~0x10000000; /* Unset summary overflow */ 905209950Snwhitehorn break; 906209950Snwhitehorn case ERESTART: 907209950Snwhitehorn /* 908209950Snwhitehorn * Set user's pc back to redo the system call. 909209950Snwhitehorn */ 910209950Snwhitehorn tf->srr0 -= 4; 911209950Snwhitehorn break; 912209950Snwhitehorn default: 913300415Sdchagin tf->fixreg[FIRSTARG] = SV_ABI_ERRNO(p, error); 914209950Snwhitehorn tf->cr |= 0x10000000; /* Set summary overflow */ 915209950Snwhitehorn break; 916209950Snwhitehorn } 917209950Snwhitehorn} 918209950Snwhitehorn 919209950Snwhitehorn/* 920209950Snwhitehorn * Threading functions 921209950Snwhitehorn */ 922209950Snwhitehornvoid 923209950Snwhitehorncpu_thread_exit(struct thread *td) 924209950Snwhitehorn{ 925209950Snwhitehorn} 926209950Snwhitehorn 927209950Snwhitehornvoid 928209950Snwhitehorncpu_thread_clean(struct thread *td) 929209950Snwhitehorn{ 930209950Snwhitehorn} 931209950Snwhitehorn 932209950Snwhitehornvoid 933209950Snwhitehorncpu_thread_alloc(struct thread *td) 934209950Snwhitehorn{ 935209950Snwhitehorn struct pcb *pcb; 936209950Snwhitehorn 937209950Snwhitehorn pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 938209950Snwhitehorn sizeof(struct pcb)) & ~0x2fUL); 939209950Snwhitehorn td->td_pcb = pcb; 940209950Snwhitehorn td->td_frame = (struct trapframe *)pcb - 1; 941209950Snwhitehorn} 942209950Snwhitehorn 943209950Snwhitehornvoid 944209950Snwhitehorncpu_thread_free(struct thread *td) 945209950Snwhitehorn{ 946209950Snwhitehorn} 947209950Snwhitehorn 948209950Snwhitehornint 949209950Snwhitehorncpu_set_user_tls(struct thread *td, void *tls_base) 950209950Snwhitehorn{ 951209950Snwhitehorn 952217896Sdchagin if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 953209975Snwhitehorn td->td_frame->fixreg[13] = (register_t)tls_base + 0x7010; 954209975Snwhitehorn else 955209975Snwhitehorn td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008; 956209950Snwhitehorn return (0); 957209950Snwhitehorn} 958209950Snwhitehorn 959209950Snwhitehornvoid 960301961Skibcpu_copy_thread(struct thread *td, struct thread *td0) 961209950Snwhitehorn{ 962209950Snwhitehorn struct pcb *pcb2; 963209950Snwhitehorn struct trapframe *tf; 964209950Snwhitehorn struct callframe *cf; 965209950Snwhitehorn 966209950Snwhitehorn pcb2 = td->td_pcb; 967209950Snwhitehorn 968209950Snwhitehorn /* Copy the upcall pcb */ 969209950Snwhitehorn bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); 970209950Snwhitehorn 971209950Snwhitehorn /* Create a stack for the new thread */ 972209950Snwhitehorn tf = td->td_frame; 973209950Snwhitehorn bcopy(td0->td_frame, tf, sizeof(struct trapframe)); 974209950Snwhitehorn tf->fixreg[FIRSTARG] = 0; 975209950Snwhitehorn tf->fixreg[FIRSTARG + 1] = 0; 976209950Snwhitehorn tf->cr &= ~0x10000000; 977209950Snwhitehorn 978209950Snwhitehorn /* Set registers for trampoline to user mode. */ 979209950Snwhitehorn cf = (struct callframe *)tf - 1; 980209950Snwhitehorn memset(cf, 0, sizeof(struct callframe)); 981209950Snwhitehorn cf->cf_func = (register_t)fork_return; 982209950Snwhitehorn cf->cf_arg0 = (register_t)td; 983209950Snwhitehorn cf->cf_arg1 = (register_t)tf; 984209950Snwhitehorn 985209950Snwhitehorn pcb2->pcb_sp = (register_t)cf; 986291442Snwhitehorn #if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1) 987209975Snwhitehorn pcb2->pcb_lr = ((register_t *)fork_trampoline)[0]; 988209975Snwhitehorn pcb2->pcb_toc = ((register_t *)fork_trampoline)[1]; 989209975Snwhitehorn #else 990209950Snwhitehorn pcb2->pcb_lr = (register_t)fork_trampoline; 991291442Snwhitehorn pcb2->pcb_context[0] = pcb2->pcb_lr; 992209975Snwhitehorn #endif 993209975Snwhitehorn pcb2->pcb_cpu.aim.usr_vsid = 0; 994209950Snwhitehorn 995209950Snwhitehorn /* Setup to release spin count in fork_exit(). */ 996209950Snwhitehorn td->td_md.md_spinlock_count = 1; 997209950Snwhitehorn td->td_md.md_saved_msr = PSL_KERNSET; 998209950Snwhitehorn} 999209950Snwhitehorn 1000209950Snwhitehornvoid 1001301961Skibcpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg, 1002301961Skib stack_t *stack) 1003209950Snwhitehorn{ 1004209950Snwhitehorn struct trapframe *tf; 1005209950Snwhitehorn uintptr_t sp; 1006209950Snwhitehorn 1007209950Snwhitehorn tf = td->td_frame; 1008209950Snwhitehorn /* align stack and alloc space for frame ptr and saved LR */ 1009209975Snwhitehorn #ifdef __powerpc64__ 1010209975Snwhitehorn sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 48) & 1011209975Snwhitehorn ~0x1f; 1012209975Snwhitehorn #else 1013209950Snwhitehorn sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) & 1014209950Snwhitehorn ~0x1f; 1015209975Snwhitehorn #endif 1016209950Snwhitehorn bzero(tf, sizeof(struct trapframe)); 1017209950Snwhitehorn 1018209950Snwhitehorn tf->fixreg[1] = (register_t)sp; 1019209950Snwhitehorn tf->fixreg[3] = (register_t)arg; 1020217896Sdchagin if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) { 1021209975Snwhitehorn tf->srr0 = (register_t)entry; 1022257115Snwhitehorn tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 1023220597Snwhitehorn #ifdef __powerpc64__ 1024220597Snwhitehorn tf->srr1 &= ~PSL_SF; 1025220597Snwhitehorn #endif 1026209975Snwhitehorn } else { 1027209975Snwhitehorn #ifdef __powerpc64__ 1028209975Snwhitehorn register_t entry_desc[3]; 1029209975Snwhitehorn (void)copyin((void *)entry, entry_desc, sizeof(entry_desc)); 1030209975Snwhitehorn tf->srr0 = entry_desc[0]; 1031209975Snwhitehorn tf->fixreg[2] = entry_desc[1]; 1032209975Snwhitehorn tf->fixreg[11] = entry_desc[2]; 1033257116Snwhitehorn tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT; 1034209975Snwhitehorn #endif 1035209975Snwhitehorn } 1036209950Snwhitehorn 1037209975Snwhitehorn #ifdef __powerpc64__ 1038209975Snwhitehorn if (mfmsr() & PSL_HV) 1039209975Snwhitehorn tf->srr1 |= PSL_HV; 1040209975Snwhitehorn #endif 1041209950Snwhitehorn td->td_pcb->pcb_flags = 0; 1042209950Snwhitehorn 1043209950Snwhitehorn td->td_retval[0] = (register_t)entry; 1044209950Snwhitehorn td->td_retval[1] = 0; 1045209950Snwhitehorn} 1046209950Snwhitehorn 1047258259Snwhitehornint 1048258259Snwhitehornppc_instr_emulate(struct trapframe *frame, struct pcb *pcb) 1049258259Snwhitehorn{ 1050258259Snwhitehorn uint32_t instr; 1051258259Snwhitehorn int reg, sig; 1052258259Snwhitehorn 1053258259Snwhitehorn instr = fuword32((void *)frame->srr0); 1054258259Snwhitehorn sig = SIGILL; 1055258259Snwhitehorn 1056258259Snwhitehorn if ((instr & 0xfc1fffff) == 0x7c1f42a6) { /* mfpvr */ 1057258259Snwhitehorn reg = (instr & ~0xfc1fffff) >> 21; 1058258259Snwhitehorn frame->fixreg[reg] = mfpvr(); 1059258259Snwhitehorn frame->srr0 += 4; 1060258259Snwhitehorn return (0); 1061258259Snwhitehorn } 1062258259Snwhitehorn 1063258259Snwhitehorn if ((instr & 0xfc000ffe) == 0x7c0004ac) { /* various sync */ 1064258259Snwhitehorn powerpc_sync(); /* Do a heavy-weight sync */ 1065258259Snwhitehorn frame->srr0 += 4; 1066258259Snwhitehorn return (0); 1067258259Snwhitehorn } 1068258259Snwhitehorn 1069258259Snwhitehorn#ifdef FPU_EMU 1070258259Snwhitehorn if (!(pcb->pcb_flags & PCB_FPREGS)) { 1071258259Snwhitehorn bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu)); 1072258259Snwhitehorn pcb->pcb_flags |= PCB_FPREGS; 1073258259Snwhitehorn } 1074295132Sjhb sig = fpu_emulate(frame, &pcb->pcb_fpu); 1075258259Snwhitehorn#endif 1076258259Snwhitehorn 1077258259Snwhitehorn return (sig); 1078258259Snwhitehorn} 1079258259Snwhitehorn 1080