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$"); 59209950Snwhitehorn 60209950Snwhitehorn#include "opt_compat.h" 61266005Sian#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 96266005Sian#ifdef FPU_EMU 97266005Sian#include <powerpc/fpu/fpu_extern.h> 98266005Sian#endif 99266005Sian 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 #ifdef AIM 156209950Snwhitehorn ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ? 157209950Snwhitehorn tf->cpu.aim.dar : tf->srr0); 158209950Snwhitehorn #else 159209950Snwhitehorn ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ? 160209950Snwhitehorn tf->cpu.booke.dear : tf->srr0); 161209950Snwhitehorn #endif 162209950Snwhitehorn 163209975Snwhitehorn #ifdef COMPAT_FREEBSD32 164217896Sdchagin if (SV_PROC_FLAG(p, SV_ILP32)) { 165209975Snwhitehorn siginfo_to_siginfo32(&ksi->ksi_info, &siginfo32); 166209975Snwhitehorn sig = siginfo32.si_signo; 167209975Snwhitehorn code = siginfo32.si_code; 168209975Snwhitehorn sfp = (caddr_t)&sf32; 169209975Snwhitehorn sfpsize = sizeof(sf32); 170209975Snwhitehorn rndfsize = ((sizeof(sf32) + 15) / 16) * 16; 171209950Snwhitehorn 172209975Snwhitehorn /* 173209975Snwhitehorn * Save user context 174209975Snwhitehorn */ 175209950Snwhitehorn 176209975Snwhitehorn memset(&sf32, 0, sizeof(sf32)); 177209975Snwhitehorn grab_mcontext32(td, &sf32.sf_uc.uc_mcontext, 0); 178209950Snwhitehorn 179209975Snwhitehorn sf32.sf_uc.uc_sigmask = *mask; 180209975Snwhitehorn sf32.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 181209975Snwhitehorn sf32.sf_uc.uc_stack.ss_size = (uint32_t)td->td_sigstk.ss_size; 182209975Snwhitehorn sf32.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 183209975Snwhitehorn ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 184209950Snwhitehorn 185209975Snwhitehorn sf32.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 186209975Snwhitehorn } else { 187209975Snwhitehorn #endif 188209975Snwhitehorn sig = ksi->ksi_signo; 189209975Snwhitehorn code = ksi->ksi_code; 190209975Snwhitehorn sfp = (caddr_t)&sf; 191209975Snwhitehorn sfpsize = sizeof(sf); 192209975Snwhitehorn #ifdef __powerpc64__ 193209975Snwhitehorn /* 194209975Snwhitehorn * 64-bit PPC defines a 288 byte scratch region 195209975Snwhitehorn * below the stack. 196209975Snwhitehorn */ 197209975Snwhitehorn rndfsize = 288 + ((sizeof(sf) + 47) / 48) * 48; 198209975Snwhitehorn #else 199209975Snwhitehorn rndfsize = ((sizeof(sf) + 15) / 16) * 16; 200209975Snwhitehorn #endif 201209950Snwhitehorn 202209975Snwhitehorn /* 203209975Snwhitehorn * Save user context 204209975Snwhitehorn */ 205209975Snwhitehorn 206209975Snwhitehorn memset(&sf, 0, sizeof(sf)); 207209975Snwhitehorn grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0); 208209975Snwhitehorn 209209975Snwhitehorn sf.sf_uc.uc_sigmask = *mask; 210209975Snwhitehorn sf.sf_uc.uc_stack = td->td_sigstk; 211209975Snwhitehorn sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 212209975Snwhitehorn ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 213209975Snwhitehorn 214209975Snwhitehorn sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 215209975Snwhitehorn #ifdef COMPAT_FREEBSD32 216209975Snwhitehorn } 217209975Snwhitehorn #endif 218209975Snwhitehorn 219209950Snwhitehorn CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm, 220209950Snwhitehorn catcher, sig); 221209950Snwhitehorn 222209950Snwhitehorn /* 223209950Snwhitehorn * Allocate and validate space for the signal handler context. 224209950Snwhitehorn */ 225209950Snwhitehorn if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 226209950Snwhitehorn SIGISMEMBER(psp->ps_sigonstack, sig)) { 227297630Sjhibbits usfp = (void *)(((uintptr_t)td->td_sigstk.ss_sp + 228297630Sjhibbits td->td_sigstk.ss_size - rndfsize) & ~0xFul); 229209950Snwhitehorn } else { 230297630Sjhibbits usfp = (void *)((tf->fixreg[1] - rndfsize) & ~0xFul); 231209950Snwhitehorn } 232209950Snwhitehorn 233209950Snwhitehorn /* 234209950Snwhitehorn * Save the floating-point state, if necessary, then copy it. 235209950Snwhitehorn */ 236209950Snwhitehorn /* XXX */ 237209950Snwhitehorn 238209950Snwhitehorn /* 239209950Snwhitehorn * Set up the registers to return to sigcode. 240209950Snwhitehorn * 241209950Snwhitehorn * r1/sp - sigframe ptr 242209950Snwhitehorn * lr - sig function, dispatched to by blrl in trampoline 243209950Snwhitehorn * r3 - sig number 244209950Snwhitehorn * r4 - SIGINFO ? &siginfo : exception code 245209950Snwhitehorn * r5 - user context 246209950Snwhitehorn * srr0 - trampoline function addr 247209950Snwhitehorn */ 248209950Snwhitehorn tf->lr = (register_t)catcher; 249209950Snwhitehorn tf->fixreg[1] = (register_t)usfp; 250209950Snwhitehorn tf->fixreg[FIRSTARG] = sig; 251209975Snwhitehorn #ifdef COMPAT_FREEBSD32 252209950Snwhitehorn tf->fixreg[FIRSTARG+2] = (register_t)usfp + 253217896Sdchagin ((SV_PROC_FLAG(p, SV_ILP32)) ? 254209975Snwhitehorn offsetof(struct sigframe32, sf_uc) : 255212586Snwhitehorn offsetof(struct sigframe, sf_uc)); 256209975Snwhitehorn #else 257209975Snwhitehorn tf->fixreg[FIRSTARG+2] = (register_t)usfp + 258209975Snwhitehorn offsetof(struct sigframe, sf_uc); 259209975Snwhitehorn #endif 260209950Snwhitehorn if (SIGISMEMBER(psp->ps_siginfo, sig)) { 261209950Snwhitehorn /* 262209950Snwhitehorn * Signal handler installed with SA_SIGINFO. 263209950Snwhitehorn */ 264209975Snwhitehorn #ifdef COMPAT_FREEBSD32 265217896Sdchagin if (SV_PROC_FLAG(p, SV_ILP32)) { 266209975Snwhitehorn sf32.sf_si = siginfo32; 267209950Snwhitehorn tf->fixreg[FIRSTARG+1] = (register_t)usfp + 268209975Snwhitehorn offsetof(struct sigframe32, sf_si); 269209975Snwhitehorn sf32.sf_si = siginfo32; 270209975Snwhitehorn } else { 271209975Snwhitehorn #endif 272209975Snwhitehorn tf->fixreg[FIRSTARG+1] = (register_t)usfp + 273209950Snwhitehorn offsetof(struct sigframe, sf_si); 274209950Snwhitehorn sf.sf_si = ksi->ksi_info; 275209975Snwhitehorn #ifdef COMPAT_FREEBSD32 276209975Snwhitehorn } 277209975Snwhitehorn #endif 278209950Snwhitehorn } else { 279209950Snwhitehorn /* Old FreeBSD-style arguments. */ 280209950Snwhitehorn tf->fixreg[FIRSTARG+1] = code; 281209950Snwhitehorn #ifdef AIM 282209950Snwhitehorn tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 283209950Snwhitehorn tf->cpu.aim.dar : tf->srr0; 284209950Snwhitehorn #else 285209950Snwhitehorn tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 286209950Snwhitehorn tf->cpu.booke.dear : tf->srr0; 287209950Snwhitehorn #endif 288209950Snwhitehorn } 289209950Snwhitehorn mtx_unlock(&psp->ps_mtx); 290209950Snwhitehorn PROC_UNLOCK(p); 291209950Snwhitehorn 292217400Skib tf->srr0 = (register_t)p->p_sysent->sv_sigcode_base; 293209950Snwhitehorn 294209950Snwhitehorn /* 295209950Snwhitehorn * copy the frame out to userland. 296209950Snwhitehorn */ 297209950Snwhitehorn if (copyout(sfp, usfp, sfpsize) != 0) { 298209950Snwhitehorn /* 299209950Snwhitehorn * Process has trashed its stack. Kill it. 300209950Snwhitehorn */ 301209950Snwhitehorn CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 302209950Snwhitehorn PROC_LOCK(p); 303209950Snwhitehorn sigexit(td, SIGILL); 304209950Snwhitehorn } 305209950Snwhitehorn 306209950Snwhitehorn CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, 307209950Snwhitehorn tf->srr0, tf->fixreg[1]); 308209950Snwhitehorn 309209950Snwhitehorn PROC_LOCK(p); 310209950Snwhitehorn mtx_lock(&psp->ps_mtx); 311209950Snwhitehorn} 312209950Snwhitehorn 313209950Snwhitehornint 314225617Skmacysys_sigreturn(struct thread *td, struct sigreturn_args *uap) 315209950Snwhitehorn{ 316209950Snwhitehorn ucontext_t uc; 317209950Snwhitehorn int error; 318209950Snwhitehorn 319209950Snwhitehorn CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 320209950Snwhitehorn 321209950Snwhitehorn if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 322209950Snwhitehorn CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 323209950Snwhitehorn return (EFAULT); 324209950Snwhitehorn } 325209950Snwhitehorn 326209950Snwhitehorn error = set_mcontext(td, &uc.uc_mcontext); 327209950Snwhitehorn if (error != 0) 328209950Snwhitehorn return (error); 329209950Snwhitehorn 330209950Snwhitehorn kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 331209950Snwhitehorn 332209950Snwhitehorn CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 333209950Snwhitehorn td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 334209950Snwhitehorn 335209950Snwhitehorn return (EJUSTRETURN); 336209950Snwhitehorn} 337209950Snwhitehorn 338209950Snwhitehorn#ifdef COMPAT_FREEBSD4 339209950Snwhitehornint 340209950Snwhitehornfreebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) 341209950Snwhitehorn{ 342209950Snwhitehorn 343225617Skmacy return sys_sigreturn(td, (struct sigreturn_args *)uap); 344209950Snwhitehorn} 345209950Snwhitehorn#endif 346209950Snwhitehorn 347209950Snwhitehorn/* 348209950Snwhitehorn * Construct a PCB from a trapframe. This is called from kdb_trap() where 349209950Snwhitehorn * we want to start a backtrace from the function that caused us to enter 350209950Snwhitehorn * the debugger. We have the context in the trapframe, but base the trace 351209950Snwhitehorn * on the PCB. The PCB doesn't have to be perfect, as long as it contains 352209950Snwhitehorn * enough for a backtrace. 353209950Snwhitehorn */ 354209950Snwhitehornvoid 355209950Snwhitehornmakectx(struct trapframe *tf, struct pcb *pcb) 356209950Snwhitehorn{ 357209950Snwhitehorn 358209950Snwhitehorn pcb->pcb_lr = tf->srr0; 359209950Snwhitehorn pcb->pcb_sp = tf->fixreg[1]; 360209950Snwhitehorn} 361209950Snwhitehorn 362209950Snwhitehorn/* 363209950Snwhitehorn * get_mcontext/sendsig helper routine that doesn't touch the 364209950Snwhitehorn * proc lock 365209950Snwhitehorn */ 366209950Snwhitehornstatic int 367209950Snwhitehorngrab_mcontext(struct thread *td, mcontext_t *mcp, int flags) 368209950Snwhitehorn{ 369209950Snwhitehorn struct pcb *pcb; 370209950Snwhitehorn 371209950Snwhitehorn pcb = td->td_pcb; 372209950Snwhitehorn 373209950Snwhitehorn memset(mcp, 0, sizeof(mcontext_t)); 374209950Snwhitehorn 375209950Snwhitehorn mcp->mc_vers = _MC_VERSION; 376209950Snwhitehorn mcp->mc_flags = 0; 377209950Snwhitehorn memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe)); 378209950Snwhitehorn if (flags & GET_MC_CLEAR_RET) { 379209950Snwhitehorn mcp->mc_gpr[3] = 0; 380209950Snwhitehorn mcp->mc_gpr[4] = 0; 381209950Snwhitehorn } 382209950Snwhitehorn 383209950Snwhitehorn /* 384209950Snwhitehorn * This assumes that floating-point context is *not* lazy, 385209950Snwhitehorn * so if the thread has used FP there would have been a 386209950Snwhitehorn * FP-unavailable exception that would have set things up 387209950Snwhitehorn * correctly. 388209950Snwhitehorn */ 389266004Sian if (pcb->pcb_flags & PCB_FPREGS) { 390266004Sian if (pcb->pcb_flags & PCB_FPU) { 391266004Sian KASSERT(td == curthread, 392266004Sian ("get_mcontext: fp save not curthread")); 393266004Sian critical_enter(); 394266004Sian save_fpu(td); 395266004Sian critical_exit(); 396266004Sian } 397209950Snwhitehorn mcp->mc_flags |= _MC_FP_VALID; 398209950Snwhitehorn memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double)); 399209950Snwhitehorn memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*sizeof(double)); 400209950Snwhitehorn } 401209950Snwhitehorn 402209950Snwhitehorn /* 403209950Snwhitehorn * Repeat for Altivec context 404209950Snwhitehorn */ 405209950Snwhitehorn 406209950Snwhitehorn if (pcb->pcb_flags & PCB_VEC) { 407209950Snwhitehorn KASSERT(td == curthread, 408209950Snwhitehorn ("get_mcontext: fp save not curthread")); 409209950Snwhitehorn critical_enter(); 410209950Snwhitehorn save_vec(td); 411209950Snwhitehorn critical_exit(); 412209950Snwhitehorn mcp->mc_flags |= _MC_AV_VALID; 413209950Snwhitehorn mcp->mc_vscr = pcb->pcb_vec.vscr; 414209950Snwhitehorn mcp->mc_vrsave = pcb->pcb_vec.vrsave; 415209950Snwhitehorn memcpy(mcp->mc_avec, pcb->pcb_vec.vr, sizeof(mcp->mc_avec)); 416209950Snwhitehorn } 417209950Snwhitehorn 418209950Snwhitehorn mcp->mc_len = sizeof(*mcp); 419209950Snwhitehorn 420209950Snwhitehorn return (0); 421209950Snwhitehorn} 422209950Snwhitehorn 423209950Snwhitehornint 424209950Snwhitehornget_mcontext(struct thread *td, mcontext_t *mcp, int flags) 425209950Snwhitehorn{ 426209950Snwhitehorn int error; 427209950Snwhitehorn 428209950Snwhitehorn error = grab_mcontext(td, mcp, flags); 429209950Snwhitehorn if (error == 0) { 430209950Snwhitehorn PROC_LOCK(curthread->td_proc); 431209950Snwhitehorn mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 432209950Snwhitehorn PROC_UNLOCK(curthread->td_proc); 433209950Snwhitehorn } 434209950Snwhitehorn 435209950Snwhitehorn return (error); 436209950Snwhitehorn} 437209950Snwhitehorn 438209950Snwhitehornint 439278347Skibset_mcontext(struct thread *td, mcontext_t *mcp) 440209950Snwhitehorn{ 441209950Snwhitehorn struct pcb *pcb; 442209950Snwhitehorn struct trapframe *tf; 443234115Snwhitehorn register_t tls; 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) { 470266004Sian /* enable_fpu() will happen lazily on a fault */ 471266004Sian pcb->pcb_flags |= PCB_FPREGS; 472209950Snwhitehorn memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double)); 473209950Snwhitehorn memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double)); 474209950Snwhitehorn } 475209950Snwhitehorn 476209950Snwhitehorn if (mcp->mc_flags & _MC_AV_VALID) { 477209950Snwhitehorn if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) { 478209950Snwhitehorn critical_enter(); 479209950Snwhitehorn enable_vec(td); 480209950Snwhitehorn critical_exit(); 481209950Snwhitehorn } 482209950Snwhitehorn pcb->pcb_vec.vscr = mcp->mc_vscr; 483209950Snwhitehorn pcb->pcb_vec.vrsave = mcp->mc_vrsave; 484209950Snwhitehorn memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec)); 485209950Snwhitehorn } 486209950Snwhitehorn 487209950Snwhitehorn return (0); 488209950Snwhitehorn} 489209950Snwhitehorn 490209950Snwhitehorn/* 491209950Snwhitehorn * Set set up registers on exec. 492209950Snwhitehorn */ 493209950Snwhitehornvoid 494209950Snwhitehornexec_setregs(struct thread *td, struct image_params *imgp, u_long stack) 495209950Snwhitehorn{ 496209950Snwhitehorn struct trapframe *tf; 497209950Snwhitehorn register_t argc; 498209975Snwhitehorn #ifdef __powerpc64__ 499209975Snwhitehorn register_t entry_desc[3]; 500209975Snwhitehorn #endif 501209950Snwhitehorn 502209950Snwhitehorn tf = trapframe(td); 503209950Snwhitehorn bzero(tf, sizeof *tf); 504209975Snwhitehorn #ifdef __powerpc64__ 505209975Snwhitehorn tf->fixreg[1] = -roundup(-stack + 48, 16); 506209975Snwhitehorn #else 507209950Snwhitehorn tf->fixreg[1] = -roundup(-stack + 8, 16); 508209975Snwhitehorn #endif 509209950Snwhitehorn 510209950Snwhitehorn /* 511209950Snwhitehorn * Set up arguments for _start(): 512209950Snwhitehorn * _start(argc, argv, envp, obj, cleanup, ps_strings); 513209950Snwhitehorn * 514209950Snwhitehorn * Notes: 515209950Snwhitehorn * - obj and cleanup are the auxilliary and termination 516209950Snwhitehorn * vectors. They are fixed up by ld.elf_so. 517209950Snwhitehorn * - ps_strings is a NetBSD extention, and will be 518209950Snwhitehorn * ignored by executables which are strictly 519209950Snwhitehorn * compliant with the SVR4 ABI. 520209950Snwhitehorn * 521209950Snwhitehorn * XXX We have to set both regs and retval here due to different 522209950Snwhitehorn * XXX calling convention in trap.c and init_main.c. 523209950Snwhitehorn */ 524209950Snwhitehorn 525209950Snwhitehorn /* Collect argc from the user stack */ 526209950Snwhitehorn argc = fuword((void *)stack); 527209950Snwhitehorn 528209950Snwhitehorn /* 529209950Snwhitehorn * XXX PG: these get overwritten in the syscall return code. 530209950Snwhitehorn * execve() should return EJUSTRETURN, like it does on NetBSD. 531209950Snwhitehorn * Emulate by setting the syscall return value cells. The 532209950Snwhitehorn * registers still have to be set for init's fork trampoline. 533209950Snwhitehorn */ 534209950Snwhitehorn td->td_retval[0] = argc; 535209950Snwhitehorn td->td_retval[1] = stack + sizeof(register_t); 536209950Snwhitehorn tf->fixreg[3] = argc; 537209950Snwhitehorn tf->fixreg[4] = stack + sizeof(register_t); 538209950Snwhitehorn tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t); 539209950Snwhitehorn tf->fixreg[6] = 0; /* auxillary vector */ 540209950Snwhitehorn tf->fixreg[7] = 0; /* termination vector */ 541209950Snwhitehorn tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 542209950Snwhitehorn 543209975Snwhitehorn #ifdef __powerpc64__ 544209975Snwhitehorn /* 545209975Snwhitehorn * For 64-bit, we need to disentangle the function descriptor 546209975Snwhitehorn * 547209975Snwhitehorn * 0. entry point 548209975Snwhitehorn * 1. TOC value (r2) 549209975Snwhitehorn * 2. Environment pointer (r11) 550209975Snwhitehorn */ 551209975Snwhitehorn 552209975Snwhitehorn (void)copyin((void *)imgp->entry_addr, entry_desc, sizeof(entry_desc)); 553209975Snwhitehorn tf->srr0 = entry_desc[0] + imgp->reloc_base; 554209975Snwhitehorn tf->fixreg[2] = entry_desc[1] + imgp->reloc_base; 555209975Snwhitehorn tf->fixreg[11] = entry_desc[2] + imgp->reloc_base; 556209975Snwhitehorn tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT; 557209975Snwhitehorn if (mfmsr() & PSL_HV) 558209975Snwhitehorn tf->srr1 |= PSL_HV; 559209975Snwhitehorn #else 560209950Snwhitehorn tf->srr0 = imgp->entry_addr; 561209950Snwhitehorn tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 562209975Snwhitehorn #endif 563209950Snwhitehorn td->td_pcb->pcb_flags = 0; 564209950Snwhitehorn} 565209950Snwhitehorn 566209975Snwhitehorn#ifdef COMPAT_FREEBSD32 567209975Snwhitehornvoid 568209975Snwhitehornppc32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 569209975Snwhitehorn{ 570209975Snwhitehorn struct trapframe *tf; 571209975Snwhitehorn uint32_t argc; 572209950Snwhitehorn 573209975Snwhitehorn tf = trapframe(td); 574209975Snwhitehorn bzero(tf, sizeof *tf); 575209975Snwhitehorn tf->fixreg[1] = -roundup(-stack + 8, 16); 576209975Snwhitehorn 577209975Snwhitehorn argc = fuword32((void *)stack); 578209975Snwhitehorn 579209975Snwhitehorn td->td_retval[0] = argc; 580209975Snwhitehorn td->td_retval[1] = stack + sizeof(uint32_t); 581209975Snwhitehorn tf->fixreg[3] = argc; 582209975Snwhitehorn tf->fixreg[4] = stack + sizeof(uint32_t); 583209975Snwhitehorn tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t); 584209975Snwhitehorn tf->fixreg[6] = 0; /* auxillary vector */ 585209975Snwhitehorn tf->fixreg[7] = 0; /* termination vector */ 586209975Snwhitehorn tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 587209975Snwhitehorn 588209975Snwhitehorn tf->srr0 = imgp->entry_addr; 589265972Sian tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 590209975Snwhitehorn tf->srr1 &= ~PSL_SF; 591209975Snwhitehorn if (mfmsr() & PSL_HV) 592209975Snwhitehorn tf->srr1 |= PSL_HV; 593209975Snwhitehorn td->td_pcb->pcb_flags = 0; 594209975Snwhitehorn} 595209975Snwhitehorn#endif 596209975Snwhitehorn 597209950Snwhitehornint 598209950Snwhitehornfill_regs(struct thread *td, struct reg *regs) 599209950Snwhitehorn{ 600209950Snwhitehorn struct trapframe *tf; 601209950Snwhitehorn 602209950Snwhitehorn tf = td->td_frame; 603209950Snwhitehorn memcpy(regs, tf, sizeof(struct reg)); 604209950Snwhitehorn 605209950Snwhitehorn return (0); 606209950Snwhitehorn} 607209950Snwhitehorn 608209950Snwhitehornint 609209950Snwhitehornfill_dbregs(struct thread *td, struct dbreg *dbregs) 610209950Snwhitehorn{ 611209950Snwhitehorn /* No debug registers on PowerPC */ 612209950Snwhitehorn return (ENOSYS); 613209950Snwhitehorn} 614209950Snwhitehorn 615209950Snwhitehornint 616209950Snwhitehornfill_fpregs(struct thread *td, struct fpreg *fpregs) 617209950Snwhitehorn{ 618209950Snwhitehorn struct pcb *pcb; 619209950Snwhitehorn 620209950Snwhitehorn pcb = td->td_pcb; 621209950Snwhitehorn 622266004Sian if ((pcb->pcb_flags & PCB_FPREGS) == 0) 623209950Snwhitehorn memset(fpregs, 0, sizeof(struct fpreg)); 624209950Snwhitehorn else 625209950Snwhitehorn memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg)); 626209950Snwhitehorn 627209950Snwhitehorn return (0); 628209950Snwhitehorn} 629209950Snwhitehorn 630209950Snwhitehornint 631209950Snwhitehornset_regs(struct thread *td, struct reg *regs) 632209950Snwhitehorn{ 633209950Snwhitehorn struct trapframe *tf; 634209950Snwhitehorn 635209950Snwhitehorn tf = td->td_frame; 636209950Snwhitehorn memcpy(tf, regs, sizeof(struct reg)); 637209950Snwhitehorn 638209950Snwhitehorn return (0); 639209950Snwhitehorn} 640209950Snwhitehorn 641209950Snwhitehornint 642209950Snwhitehornset_dbregs(struct thread *td, struct dbreg *dbregs) 643209950Snwhitehorn{ 644209950Snwhitehorn /* No debug registers on PowerPC */ 645209950Snwhitehorn return (ENOSYS); 646209950Snwhitehorn} 647209950Snwhitehorn 648209950Snwhitehornint 649209950Snwhitehornset_fpregs(struct thread *td, struct fpreg *fpregs) 650209950Snwhitehorn{ 651209950Snwhitehorn struct pcb *pcb; 652209950Snwhitehorn 653209950Snwhitehorn pcb = td->td_pcb; 654266004Sian pcb->pcb_flags |= PCB_FPREGS; 655209950Snwhitehorn memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg)); 656209950Snwhitehorn 657209950Snwhitehorn return (0); 658209950Snwhitehorn} 659209950Snwhitehorn 660209975Snwhitehorn#ifdef COMPAT_FREEBSD32 661209975Snwhitehornint 662209975Snwhitehornset_regs32(struct thread *td, struct reg32 *regs) 663209975Snwhitehorn{ 664209975Snwhitehorn struct trapframe *tf; 665209975Snwhitehorn int i; 666209950Snwhitehorn 667209975Snwhitehorn tf = td->td_frame; 668209975Snwhitehorn for (i = 0; i < 32; i++) 669209975Snwhitehorn tf->fixreg[i] = regs->fixreg[i]; 670209975Snwhitehorn tf->lr = regs->lr; 671209975Snwhitehorn tf->cr = regs->cr; 672209975Snwhitehorn tf->xer = regs->xer; 673209975Snwhitehorn tf->ctr = regs->ctr; 674209975Snwhitehorn tf->srr0 = regs->pc; 675209950Snwhitehorn 676209975Snwhitehorn return (0); 677209975Snwhitehorn} 678209975Snwhitehorn 679209975Snwhitehornint 680209975Snwhitehornfill_regs32(struct thread *td, struct reg32 *regs) 681209975Snwhitehorn{ 682209975Snwhitehorn struct trapframe *tf; 683209975Snwhitehorn int i; 684209975Snwhitehorn 685209975Snwhitehorn tf = td->td_frame; 686209975Snwhitehorn for (i = 0; i < 32; i++) 687209975Snwhitehorn regs->fixreg[i] = tf->fixreg[i]; 688209975Snwhitehorn regs->lr = tf->lr; 689209975Snwhitehorn regs->cr = tf->cr; 690209975Snwhitehorn regs->xer = tf->xer; 691209975Snwhitehorn regs->ctr = tf->ctr; 692209975Snwhitehorn regs->pc = tf->srr0; 693209975Snwhitehorn 694209975Snwhitehorn return (0); 695209975Snwhitehorn} 696209975Snwhitehorn 697209975Snwhitehornstatic int 698209975Snwhitehorngrab_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 699209975Snwhitehorn{ 700209975Snwhitehorn mcontext_t mcp64; 701209975Snwhitehorn int i, error; 702209975Snwhitehorn 703209975Snwhitehorn error = grab_mcontext(td, &mcp64, flags); 704209975Snwhitehorn if (error != 0) 705209975Snwhitehorn return (error); 706209975Snwhitehorn 707209975Snwhitehorn mcp->mc_vers = mcp64.mc_vers; 708209975Snwhitehorn mcp->mc_flags = mcp64.mc_flags; 709209975Snwhitehorn mcp->mc_onstack = mcp64.mc_onstack; 710209975Snwhitehorn mcp->mc_len = mcp64.mc_len; 711209975Snwhitehorn memcpy(mcp->mc_avec,mcp64.mc_avec,sizeof(mcp64.mc_avec)); 712209975Snwhitehorn memcpy(mcp->mc_av,mcp64.mc_av,sizeof(mcp64.mc_av)); 713209975Snwhitehorn for (i = 0; i < 42; i++) 714209975Snwhitehorn mcp->mc_frame[i] = mcp64.mc_frame[i]; 715209975Snwhitehorn memcpy(mcp->mc_fpreg,mcp64.mc_fpreg,sizeof(mcp64.mc_fpreg)); 716209975Snwhitehorn 717209975Snwhitehorn return (0); 718209975Snwhitehorn} 719209975Snwhitehorn 720209975Snwhitehornstatic int 721209975Snwhitehornget_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 722209975Snwhitehorn{ 723209975Snwhitehorn int error; 724209975Snwhitehorn 725209975Snwhitehorn error = grab_mcontext32(td, mcp, flags); 726209975Snwhitehorn if (error == 0) { 727209975Snwhitehorn PROC_LOCK(curthread->td_proc); 728209975Snwhitehorn mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 729209975Snwhitehorn PROC_UNLOCK(curthread->td_proc); 730209975Snwhitehorn } 731209975Snwhitehorn 732209975Snwhitehorn return (error); 733209975Snwhitehorn} 734209975Snwhitehorn 735209975Snwhitehornstatic int 736278347Skibset_mcontext32(struct thread *td, mcontext32_t *mcp) 737209975Snwhitehorn{ 738209975Snwhitehorn mcontext_t mcp64; 739209975Snwhitehorn int i, error; 740209975Snwhitehorn 741209975Snwhitehorn mcp64.mc_vers = mcp->mc_vers; 742209975Snwhitehorn mcp64.mc_flags = mcp->mc_flags; 743209975Snwhitehorn mcp64.mc_onstack = mcp->mc_onstack; 744209975Snwhitehorn mcp64.mc_len = mcp->mc_len; 745209975Snwhitehorn memcpy(mcp64.mc_avec,mcp->mc_avec,sizeof(mcp64.mc_avec)); 746209975Snwhitehorn memcpy(mcp64.mc_av,mcp->mc_av,sizeof(mcp64.mc_av)); 747209975Snwhitehorn for (i = 0; i < 42; i++) 748209975Snwhitehorn mcp64.mc_frame[i] = mcp->mc_frame[i]; 749271171Sjhibbits mcp64.mc_srr1 |= (td->td_frame->srr1 & 0xFFFFFFFF00000000ULL); 750209975Snwhitehorn memcpy(mcp64.mc_fpreg,mcp->mc_fpreg,sizeof(mcp64.mc_fpreg)); 751209975Snwhitehorn 752209975Snwhitehorn error = set_mcontext(td, &mcp64); 753209975Snwhitehorn 754209975Snwhitehorn return (error); 755209975Snwhitehorn} 756209975Snwhitehorn#endif 757209975Snwhitehorn 758209975Snwhitehorn#ifdef COMPAT_FREEBSD32 759209975Snwhitehornint 760209975Snwhitehornfreebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap) 761209975Snwhitehorn{ 762209975Snwhitehorn ucontext32_t uc; 763209975Snwhitehorn int error; 764209975Snwhitehorn 765209975Snwhitehorn CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 766209975Snwhitehorn 767209975Snwhitehorn if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 768209975Snwhitehorn CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 769209975Snwhitehorn return (EFAULT); 770209975Snwhitehorn } 771209975Snwhitehorn 772209975Snwhitehorn error = set_mcontext32(td, &uc.uc_mcontext); 773209975Snwhitehorn if (error != 0) 774209975Snwhitehorn return (error); 775209975Snwhitehorn 776209975Snwhitehorn kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 777209975Snwhitehorn 778209975Snwhitehorn CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 779209975Snwhitehorn td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 780209975Snwhitehorn 781209975Snwhitehorn return (EJUSTRETURN); 782209975Snwhitehorn} 783209975Snwhitehorn 784209975Snwhitehorn/* 785209975Snwhitehorn * The first two fields of a ucontext_t are the signal mask and the machine 786209975Snwhitehorn * context. The next field is uc_link; we want to avoid destroying the link 787209975Snwhitehorn * when copying out contexts. 788209975Snwhitehorn */ 789209975Snwhitehorn#define UC32_COPY_SIZE offsetof(ucontext32_t, uc_link) 790209975Snwhitehorn 791209975Snwhitehornint 792209975Snwhitehornfreebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 793209975Snwhitehorn{ 794209975Snwhitehorn ucontext32_t uc; 795209975Snwhitehorn int ret; 796209975Snwhitehorn 797209975Snwhitehorn if (uap->ucp == NULL) 798209975Snwhitehorn ret = EINVAL; 799209975Snwhitehorn else { 800209975Snwhitehorn get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 801209975Snwhitehorn PROC_LOCK(td->td_proc); 802209975Snwhitehorn uc.uc_sigmask = td->td_sigmask; 803209975Snwhitehorn PROC_UNLOCK(td->td_proc); 804209975Snwhitehorn ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE); 805209975Snwhitehorn } 806209975Snwhitehorn return (ret); 807209975Snwhitehorn} 808209975Snwhitehorn 809209975Snwhitehornint 810209975Snwhitehornfreebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 811209975Snwhitehorn{ 812209975Snwhitehorn ucontext32_t uc; 813209975Snwhitehorn int ret; 814209975Snwhitehorn 815209975Snwhitehorn if (uap->ucp == NULL) 816209975Snwhitehorn ret = EINVAL; 817209975Snwhitehorn else { 818209975Snwhitehorn ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 819209975Snwhitehorn if (ret == 0) { 820209975Snwhitehorn ret = set_mcontext32(td, &uc.uc_mcontext); 821209975Snwhitehorn if (ret == 0) { 822209975Snwhitehorn kern_sigprocmask(td, SIG_SETMASK, 823209975Snwhitehorn &uc.uc_sigmask, NULL, 0); 824209975Snwhitehorn } 825209975Snwhitehorn } 826209975Snwhitehorn } 827209975Snwhitehorn return (ret == 0 ? EJUSTRETURN : ret); 828209975Snwhitehorn} 829209975Snwhitehorn 830209975Snwhitehornint 831209975Snwhitehornfreebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 832209975Snwhitehorn{ 833209975Snwhitehorn ucontext32_t uc; 834209975Snwhitehorn int ret; 835209975Snwhitehorn 836209975Snwhitehorn if (uap->oucp == NULL || uap->ucp == NULL) 837209975Snwhitehorn ret = EINVAL; 838209975Snwhitehorn else { 839209975Snwhitehorn get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 840209975Snwhitehorn PROC_LOCK(td->td_proc); 841209975Snwhitehorn uc.uc_sigmask = td->td_sigmask; 842209975Snwhitehorn PROC_UNLOCK(td->td_proc); 843209975Snwhitehorn ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE); 844209975Snwhitehorn if (ret == 0) { 845209975Snwhitehorn ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 846209975Snwhitehorn if (ret == 0) { 847209975Snwhitehorn ret = set_mcontext32(td, &uc.uc_mcontext); 848209975Snwhitehorn if (ret == 0) { 849209975Snwhitehorn kern_sigprocmask(td, SIG_SETMASK, 850209975Snwhitehorn &uc.uc_sigmask, NULL, 0); 851209975Snwhitehorn } 852209975Snwhitehorn } 853209975Snwhitehorn } 854209975Snwhitehorn } 855209975Snwhitehorn return (ret == 0 ? EJUSTRETURN : ret); 856209975Snwhitehorn} 857209975Snwhitehorn 858209975Snwhitehorn#endif 859209975Snwhitehorn 860209950Snwhitehornvoid 861209950Snwhitehorncpu_set_syscall_retval(struct thread *td, int error) 862209950Snwhitehorn{ 863209950Snwhitehorn struct proc *p; 864209950Snwhitehorn struct trapframe *tf; 865209950Snwhitehorn int fixup; 866209950Snwhitehorn 867209950Snwhitehorn if (error == EJUSTRETURN) 868209950Snwhitehorn return; 869209950Snwhitehorn 870209950Snwhitehorn p = td->td_proc; 871209950Snwhitehorn tf = td->td_frame; 872209950Snwhitehorn 873209975Snwhitehorn if (tf->fixreg[0] == SYS___syscall && 874217896Sdchagin (SV_PROC_FLAG(p, SV_ILP32))) { 875209950Snwhitehorn int code = tf->fixreg[FIRSTARG + 1]; 876209950Snwhitehorn if (p->p_sysent->sv_mask) 877209950Snwhitehorn code &= p->p_sysent->sv_mask; 878209950Snwhitehorn fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek) ? 879209950Snwhitehorn 1 : 0; 880209950Snwhitehorn } else 881209950Snwhitehorn fixup = 0; 882209950Snwhitehorn 883209950Snwhitehorn switch (error) { 884209950Snwhitehorn case 0: 885209950Snwhitehorn if (fixup) { 886209950Snwhitehorn /* 887209950Snwhitehorn * 64-bit return, 32-bit syscall. Fixup byte order 888209950Snwhitehorn */ 889209950Snwhitehorn tf->fixreg[FIRSTARG] = 0; 890209950Snwhitehorn tf->fixreg[FIRSTARG + 1] = td->td_retval[0]; 891209950Snwhitehorn } else { 892209950Snwhitehorn tf->fixreg[FIRSTARG] = td->td_retval[0]; 893209950Snwhitehorn tf->fixreg[FIRSTARG + 1] = td->td_retval[1]; 894209950Snwhitehorn } 895209950Snwhitehorn tf->cr &= ~0x10000000; /* Unset summary overflow */ 896209950Snwhitehorn break; 897209950Snwhitehorn case ERESTART: 898209950Snwhitehorn /* 899209950Snwhitehorn * Set user's pc back to redo the system call. 900209950Snwhitehorn */ 901209950Snwhitehorn tf->srr0 -= 4; 902209950Snwhitehorn break; 903209950Snwhitehorn default: 904301428Sdchagin tf->fixreg[FIRSTARG] = SV_ABI_ERRNO(p, error); 905209950Snwhitehorn tf->cr |= 0x10000000; /* Set summary overflow */ 906209950Snwhitehorn break; 907209950Snwhitehorn } 908209950Snwhitehorn} 909209950Snwhitehorn 910209950Snwhitehorn/* 911209950Snwhitehorn * Threading functions 912209950Snwhitehorn */ 913209950Snwhitehornvoid 914209950Snwhitehorncpu_thread_exit(struct thread *td) 915209950Snwhitehorn{ 916209950Snwhitehorn} 917209950Snwhitehorn 918209950Snwhitehornvoid 919209950Snwhitehorncpu_thread_clean(struct thread *td) 920209950Snwhitehorn{ 921209950Snwhitehorn} 922209950Snwhitehorn 923209950Snwhitehornvoid 924209950Snwhitehorncpu_thread_alloc(struct thread *td) 925209950Snwhitehorn{ 926209950Snwhitehorn struct pcb *pcb; 927209950Snwhitehorn 928209950Snwhitehorn pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 929209950Snwhitehorn sizeof(struct pcb)) & ~0x2fUL); 930209950Snwhitehorn td->td_pcb = pcb; 931209950Snwhitehorn td->td_frame = (struct trapframe *)pcb - 1; 932209950Snwhitehorn} 933209950Snwhitehorn 934209950Snwhitehornvoid 935209950Snwhitehorncpu_thread_free(struct thread *td) 936209950Snwhitehorn{ 937209950Snwhitehorn} 938209950Snwhitehorn 939209950Snwhitehornint 940209950Snwhitehorncpu_set_user_tls(struct thread *td, void *tls_base) 941209950Snwhitehorn{ 942209950Snwhitehorn 943217896Sdchagin if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 944209975Snwhitehorn td->td_frame->fixreg[13] = (register_t)tls_base + 0x7010; 945209975Snwhitehorn else 946209975Snwhitehorn td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008; 947209950Snwhitehorn return (0); 948209950Snwhitehorn} 949209950Snwhitehorn 950209950Snwhitehornvoid 951209950Snwhitehorncpu_set_upcall(struct thread *td, struct thread *td0) 952209950Snwhitehorn{ 953209950Snwhitehorn struct pcb *pcb2; 954209950Snwhitehorn struct trapframe *tf; 955209950Snwhitehorn struct callframe *cf; 956209950Snwhitehorn 957209950Snwhitehorn pcb2 = td->td_pcb; 958209950Snwhitehorn 959209950Snwhitehorn /* Copy the upcall pcb */ 960209950Snwhitehorn bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); 961209950Snwhitehorn 962209950Snwhitehorn /* Create a stack for the new thread */ 963209950Snwhitehorn tf = td->td_frame; 964209950Snwhitehorn bcopy(td0->td_frame, tf, sizeof(struct trapframe)); 965209950Snwhitehorn tf->fixreg[FIRSTARG] = 0; 966209950Snwhitehorn tf->fixreg[FIRSTARG + 1] = 0; 967209950Snwhitehorn tf->cr &= ~0x10000000; 968209950Snwhitehorn 969209950Snwhitehorn /* Set registers for trampoline to user mode. */ 970209950Snwhitehorn cf = (struct callframe *)tf - 1; 971209950Snwhitehorn memset(cf, 0, sizeof(struct callframe)); 972209950Snwhitehorn cf->cf_func = (register_t)fork_return; 973209950Snwhitehorn cf->cf_arg0 = (register_t)td; 974209950Snwhitehorn cf->cf_arg1 = (register_t)tf; 975209950Snwhitehorn 976209950Snwhitehorn pcb2->pcb_sp = (register_t)cf; 977209975Snwhitehorn #ifdef __powerpc64__ 978209975Snwhitehorn pcb2->pcb_lr = ((register_t *)fork_trampoline)[0]; 979209975Snwhitehorn pcb2->pcb_toc = ((register_t *)fork_trampoline)[1]; 980209975Snwhitehorn #else 981209950Snwhitehorn pcb2->pcb_lr = (register_t)fork_trampoline; 982209975Snwhitehorn #endif 983209975Snwhitehorn pcb2->pcb_cpu.aim.usr_vsid = 0; 984209950Snwhitehorn 985209950Snwhitehorn /* Setup to release spin count in fork_exit(). */ 986209950Snwhitehorn td->td_md.md_spinlock_count = 1; 987209950Snwhitehorn td->td_md.md_saved_msr = PSL_KERNSET; 988209950Snwhitehorn} 989209950Snwhitehorn 990209950Snwhitehornvoid 991209950Snwhitehorncpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, 992209950Snwhitehorn stack_t *stack) 993209950Snwhitehorn{ 994209950Snwhitehorn struct trapframe *tf; 995209950Snwhitehorn uintptr_t sp; 996209950Snwhitehorn 997209950Snwhitehorn tf = td->td_frame; 998209950Snwhitehorn /* align stack and alloc space for frame ptr and saved LR */ 999209975Snwhitehorn #ifdef __powerpc64__ 1000209975Snwhitehorn sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 48) & 1001209975Snwhitehorn ~0x1f; 1002209975Snwhitehorn #else 1003209950Snwhitehorn sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) & 1004209950Snwhitehorn ~0x1f; 1005209975Snwhitehorn #endif 1006209950Snwhitehorn bzero(tf, sizeof(struct trapframe)); 1007209950Snwhitehorn 1008209950Snwhitehorn tf->fixreg[1] = (register_t)sp; 1009209950Snwhitehorn tf->fixreg[3] = (register_t)arg; 1010217896Sdchagin if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) { 1011209975Snwhitehorn tf->srr0 = (register_t)entry; 1012265972Sian tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 1013220597Snwhitehorn #ifdef __powerpc64__ 1014220597Snwhitehorn tf->srr1 &= ~PSL_SF; 1015220597Snwhitehorn #endif 1016209975Snwhitehorn } else { 1017209975Snwhitehorn #ifdef __powerpc64__ 1018209975Snwhitehorn register_t entry_desc[3]; 1019209975Snwhitehorn (void)copyin((void *)entry, entry_desc, sizeof(entry_desc)); 1020209975Snwhitehorn tf->srr0 = entry_desc[0]; 1021209975Snwhitehorn tf->fixreg[2] = entry_desc[1]; 1022209975Snwhitehorn tf->fixreg[11] = entry_desc[2]; 1023265972Sian tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT; 1024209975Snwhitehorn #endif 1025209975Snwhitehorn } 1026209950Snwhitehorn 1027209975Snwhitehorn #ifdef __powerpc64__ 1028209975Snwhitehorn if (mfmsr() & PSL_HV) 1029209975Snwhitehorn tf->srr1 |= PSL_HV; 1030209975Snwhitehorn #endif 1031209950Snwhitehorn td->td_pcb->pcb_flags = 0; 1032209950Snwhitehorn 1033209950Snwhitehorn td->td_retval[0] = (register_t)entry; 1034209950Snwhitehorn td->td_retval[1] = 0; 1035209950Snwhitehorn} 1036209950Snwhitehorn 1037266005Sianint 1038266005Sianppc_instr_emulate(struct trapframe *frame, struct pcb *pcb) 1039266005Sian{ 1040266005Sian uint32_t instr; 1041266005Sian int reg, sig; 1042266005Sian 1043266005Sian instr = fuword32((void *)frame->srr0); 1044266005Sian sig = SIGILL; 1045266005Sian 1046266005Sian if ((instr & 0xfc1fffff) == 0x7c1f42a6) { /* mfpvr */ 1047266005Sian reg = (instr & ~0xfc1fffff) >> 21; 1048266005Sian frame->fixreg[reg] = mfpvr(); 1049266005Sian frame->srr0 += 4; 1050266005Sian return (0); 1051266005Sian } 1052266005Sian 1053266005Sian if ((instr & 0xfc000ffe) == 0x7c0004ac) { /* various sync */ 1054266005Sian powerpc_sync(); /* Do a heavy-weight sync */ 1055266005Sian frame->srr0 += 4; 1056266005Sian return (0); 1057266005Sian } 1058266005Sian 1059266005Sian#ifdef FPU_EMU 1060266005Sian if (!(pcb->pcb_flags & PCB_FPREGS)) { 1061266005Sian bzero(&pcb->pcb_fpu, sizeof(pcb->pcb_fpu)); 1062266005Sian pcb->pcb_flags |= PCB_FPREGS; 1063266005Sian } 1064266005Sian sig = fpu_emulate(frame, (struct fpreg *)&pcb->pcb_fpu); 1065266005Sian#endif 1066266005Sian 1067266005Sian return (sig); 1068266005Sian} 1069266005Sian 1070