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" 61209950Snwhitehorn 62209950Snwhitehorn#include <sys/param.h> 63209950Snwhitehorn#include <sys/proc.h> 64209950Snwhitehorn#include <sys/systm.h> 65209950Snwhitehorn#include <sys/bio.h> 66209950Snwhitehorn#include <sys/buf.h> 67209950Snwhitehorn#include <sys/bus.h> 68209950Snwhitehorn#include <sys/cons.h> 69209950Snwhitehorn#include <sys/cpu.h> 70209950Snwhitehorn#include <sys/exec.h> 71209950Snwhitehorn#include <sys/imgact.h> 72209950Snwhitehorn#include <sys/kernel.h> 73209950Snwhitehorn#include <sys/ktr.h> 74209950Snwhitehorn#include <sys/lock.h> 75209950Snwhitehorn#include <sys/malloc.h> 76209950Snwhitehorn#include <sys/mutex.h> 77209950Snwhitehorn#include <sys/signalvar.h> 78209950Snwhitehorn#include <sys/syscallsubr.h> 79209950Snwhitehorn#include <sys/syscall.h> 80209950Snwhitehorn#include <sys/sysent.h> 81209950Snwhitehorn#include <sys/sysproto.h> 82209950Snwhitehorn#include <sys/ucontext.h> 83209950Snwhitehorn#include <sys/uio.h> 84209950Snwhitehorn 85209950Snwhitehorn#include <machine/altivec.h> 86209950Snwhitehorn#include <machine/cpu.h> 87209950Snwhitehorn#include <machine/elf.h> 88209950Snwhitehorn#include <machine/fpu.h> 89209950Snwhitehorn#include <machine/pcb.h> 90209950Snwhitehorn#include <machine/reg.h> 91209950Snwhitehorn#include <machine/sigframe.h> 92209950Snwhitehorn#include <machine/trap.h> 93209950Snwhitehorn#include <machine/vmparam.h> 94209950Snwhitehorn 95209975Snwhitehorn#ifdef COMPAT_FREEBSD32 96209975Snwhitehorn#include <compat/freebsd32/freebsd32_signal.h> 97209975Snwhitehorn#include <compat/freebsd32/freebsd32_util.h> 98209975Snwhitehorn#include <compat/freebsd32/freebsd32_proto.h> 99209975Snwhitehorn 100209975Snwhitehorntypedef struct __ucontext32 { 101209975Snwhitehorn sigset_t uc_sigmask; 102209975Snwhitehorn mcontext32_t uc_mcontext; 103209975Snwhitehorn uint32_t uc_link; 104209975Snwhitehorn struct sigaltstack32 uc_stack; 105209975Snwhitehorn uint32_t uc_flags; 106209975Snwhitehorn uint32_t __spare__[4]; 107209975Snwhitehorn} ucontext32_t; 108209975Snwhitehorn 109209975Snwhitehornstruct sigframe32 { 110209975Snwhitehorn ucontext32_t sf_uc; 111209975Snwhitehorn struct siginfo32 sf_si; 112209975Snwhitehorn}; 113209975Snwhitehorn 114209975Snwhitehornstatic int grab_mcontext32(struct thread *td, mcontext32_t *, int flags); 115209975Snwhitehorn#endif 116209975Snwhitehorn 117209950Snwhitehornstatic int grab_mcontext(struct thread *, mcontext_t *, int); 118209950Snwhitehorn 119209950Snwhitehornvoid 120209950Snwhitehornsendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 121209950Snwhitehorn{ 122209950Snwhitehorn struct trapframe *tf; 123209950Snwhitehorn struct sigacts *psp; 124209950Snwhitehorn struct sigframe sf; 125209950Snwhitehorn struct thread *td; 126209950Snwhitehorn struct proc *p; 127209975Snwhitehorn #ifdef COMPAT_FREEBSD32 128209975Snwhitehorn struct siginfo32 siginfo32; 129209975Snwhitehorn struct sigframe32 sf32; 130209975Snwhitehorn #endif 131209950Snwhitehorn size_t sfpsize; 132209950Snwhitehorn caddr_t sfp, usfp; 133209950Snwhitehorn int oonstack, rndfsize; 134209950Snwhitehorn int sig; 135209950Snwhitehorn int code; 136209950Snwhitehorn 137209950Snwhitehorn td = curthread; 138209950Snwhitehorn p = td->td_proc; 139209950Snwhitehorn PROC_LOCK_ASSERT(p, MA_OWNED); 140209950Snwhitehorn 141209950Snwhitehorn psp = p->p_sigacts; 142209950Snwhitehorn mtx_assert(&psp->ps_mtx, MA_OWNED); 143209950Snwhitehorn tf = td->td_frame; 144209950Snwhitehorn oonstack = sigonstack(tf->fixreg[1]); 145209950Snwhitehorn 146209950Snwhitehorn /* 147209950Snwhitehorn * Fill siginfo structure. 148209950Snwhitehorn */ 149209950Snwhitehorn ksi->ksi_info.si_signo = ksi->ksi_signo; 150209950Snwhitehorn #ifdef AIM 151209950Snwhitehorn ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ? 152209950Snwhitehorn tf->cpu.aim.dar : tf->srr0); 153209950Snwhitehorn #else 154209950Snwhitehorn ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ? 155209950Snwhitehorn tf->cpu.booke.dear : tf->srr0); 156209950Snwhitehorn #endif 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); 165209975Snwhitehorn rndfsize = ((sizeof(sf32) + 15) / 16) * 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 */ 192209975Snwhitehorn rndfsize = 288 + ((sizeof(sf) + 47) / 48) * 48; 193209975Snwhitehorn #else 194209975Snwhitehorn rndfsize = ((sizeof(sf) + 15) / 16) * 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)) { 222209950Snwhitehorn usfp = (void *)(td->td_sigstk.ss_sp + 223209950Snwhitehorn td->td_sigstk.ss_size - rndfsize); 224209950Snwhitehorn } else { 225209950Snwhitehorn usfp = (void *)(tf->fixreg[1] - rndfsize); 226209950Snwhitehorn } 227209950Snwhitehorn 228209950Snwhitehorn /* 229209950Snwhitehorn * Translate the signal if appropriate (Linux emu ?) 230209950Snwhitehorn */ 231209950Snwhitehorn if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) 232209950Snwhitehorn sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; 233209950Snwhitehorn 234209950Snwhitehorn /* 235209950Snwhitehorn * Save the floating-point state, if necessary, then copy it. 236209950Snwhitehorn */ 237209950Snwhitehorn /* XXX */ 238209950Snwhitehorn 239209950Snwhitehorn /* 240209950Snwhitehorn * Set up the registers to return to sigcode. 241209950Snwhitehorn * 242209950Snwhitehorn * r1/sp - sigframe ptr 243209950Snwhitehorn * lr - sig function, dispatched to by blrl in trampoline 244209950Snwhitehorn * r3 - sig number 245209950Snwhitehorn * r4 - SIGINFO ? &siginfo : exception code 246209950Snwhitehorn * r5 - user context 247209950Snwhitehorn * srr0 - trampoline function addr 248209950Snwhitehorn */ 249209950Snwhitehorn tf->lr = (register_t)catcher; 250209950Snwhitehorn tf->fixreg[1] = (register_t)usfp; 251209950Snwhitehorn tf->fixreg[FIRSTARG] = sig; 252209975Snwhitehorn #ifdef COMPAT_FREEBSD32 253209950Snwhitehorn tf->fixreg[FIRSTARG+2] = (register_t)usfp + 254217896Sdchagin ((SV_PROC_FLAG(p, SV_ILP32)) ? 255209975Snwhitehorn offsetof(struct sigframe32, sf_uc) : 256212586Snwhitehorn offsetof(struct sigframe, sf_uc)); 257209975Snwhitehorn #else 258209975Snwhitehorn tf->fixreg[FIRSTARG+2] = (register_t)usfp + 259209975Snwhitehorn offsetof(struct sigframe, sf_uc); 260209975Snwhitehorn #endif 261209950Snwhitehorn if (SIGISMEMBER(psp->ps_siginfo, sig)) { 262209950Snwhitehorn /* 263209950Snwhitehorn * Signal handler installed with SA_SIGINFO. 264209950Snwhitehorn */ 265209975Snwhitehorn #ifdef COMPAT_FREEBSD32 266217896Sdchagin if (SV_PROC_FLAG(p, SV_ILP32)) { 267209975Snwhitehorn sf32.sf_si = siginfo32; 268209950Snwhitehorn tf->fixreg[FIRSTARG+1] = (register_t)usfp + 269209975Snwhitehorn offsetof(struct sigframe32, sf_si); 270209975Snwhitehorn sf32.sf_si = siginfo32; 271209975Snwhitehorn } else { 272209975Snwhitehorn #endif 273209975Snwhitehorn tf->fixreg[FIRSTARG+1] = (register_t)usfp + 274209950Snwhitehorn offsetof(struct sigframe, sf_si); 275209950Snwhitehorn sf.sf_si = ksi->ksi_info; 276209975Snwhitehorn #ifdef COMPAT_FREEBSD32 277209975Snwhitehorn } 278209975Snwhitehorn #endif 279209950Snwhitehorn } else { 280209950Snwhitehorn /* Old FreeBSD-style arguments. */ 281209950Snwhitehorn tf->fixreg[FIRSTARG+1] = code; 282209950Snwhitehorn #ifdef AIM 283209950Snwhitehorn tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 284209950Snwhitehorn tf->cpu.aim.dar : tf->srr0; 285209950Snwhitehorn #else 286209950Snwhitehorn tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ? 287209950Snwhitehorn tf->cpu.booke.dear : tf->srr0; 288209950Snwhitehorn #endif 289209950Snwhitehorn } 290209950Snwhitehorn mtx_unlock(&psp->ps_mtx); 291209950Snwhitehorn PROC_UNLOCK(p); 292209950Snwhitehorn 293217400Skib tf->srr0 = (register_t)p->p_sysent->sv_sigcode_base; 294209950Snwhitehorn 295209950Snwhitehorn /* 296209950Snwhitehorn * copy the frame out to userland. 297209950Snwhitehorn */ 298209950Snwhitehorn if (copyout(sfp, usfp, sfpsize) != 0) { 299209950Snwhitehorn /* 300209950Snwhitehorn * Process has trashed its stack. Kill it. 301209950Snwhitehorn */ 302209950Snwhitehorn CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp); 303209950Snwhitehorn PROC_LOCK(p); 304209950Snwhitehorn sigexit(td, SIGILL); 305209950Snwhitehorn } 306209950Snwhitehorn 307209950Snwhitehorn CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, 308209950Snwhitehorn tf->srr0, tf->fixreg[1]); 309209950Snwhitehorn 310209950Snwhitehorn PROC_LOCK(p); 311209950Snwhitehorn mtx_lock(&psp->ps_mtx); 312209950Snwhitehorn} 313209950Snwhitehorn 314209950Snwhitehornint 315225617Skmacysys_sigreturn(struct thread *td, struct sigreturn_args *uap) 316209950Snwhitehorn{ 317209950Snwhitehorn ucontext_t uc; 318209950Snwhitehorn int error; 319209950Snwhitehorn 320209950Snwhitehorn CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 321209950Snwhitehorn 322209950Snwhitehorn if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 323209950Snwhitehorn CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 324209950Snwhitehorn return (EFAULT); 325209950Snwhitehorn } 326209950Snwhitehorn 327209950Snwhitehorn error = set_mcontext(td, &uc.uc_mcontext); 328209950Snwhitehorn if (error != 0) 329209950Snwhitehorn return (error); 330209950Snwhitehorn 331209950Snwhitehorn kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 332209950Snwhitehorn 333209950Snwhitehorn CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 334209950Snwhitehorn td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 335209950Snwhitehorn 336209950Snwhitehorn return (EJUSTRETURN); 337209950Snwhitehorn} 338209950Snwhitehorn 339209950Snwhitehorn#ifdef COMPAT_FREEBSD4 340209950Snwhitehornint 341209950Snwhitehornfreebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap) 342209950Snwhitehorn{ 343209950Snwhitehorn 344225617Skmacy return sys_sigreturn(td, (struct sigreturn_args *)uap); 345209950Snwhitehorn} 346209950Snwhitehorn#endif 347209950Snwhitehorn 348209950Snwhitehorn/* 349209950Snwhitehorn * Construct a PCB from a trapframe. This is called from kdb_trap() where 350209950Snwhitehorn * we want to start a backtrace from the function that caused us to enter 351209950Snwhitehorn * the debugger. We have the context in the trapframe, but base the trace 352209950Snwhitehorn * on the PCB. The PCB doesn't have to be perfect, as long as it contains 353209950Snwhitehorn * enough for a backtrace. 354209950Snwhitehorn */ 355209950Snwhitehornvoid 356209950Snwhitehornmakectx(struct trapframe *tf, struct pcb *pcb) 357209950Snwhitehorn{ 358209950Snwhitehorn 359209950Snwhitehorn pcb->pcb_lr = tf->srr0; 360209950Snwhitehorn pcb->pcb_sp = tf->fixreg[1]; 361209950Snwhitehorn} 362209950Snwhitehorn 363209950Snwhitehorn/* 364209950Snwhitehorn * get_mcontext/sendsig helper routine that doesn't touch the 365209950Snwhitehorn * proc lock 366209950Snwhitehorn */ 367209950Snwhitehornstatic int 368209950Snwhitehorngrab_mcontext(struct thread *td, mcontext_t *mcp, int flags) 369209950Snwhitehorn{ 370209950Snwhitehorn struct pcb *pcb; 371209950Snwhitehorn 372209950Snwhitehorn pcb = td->td_pcb; 373209950Snwhitehorn 374209950Snwhitehorn memset(mcp, 0, sizeof(mcontext_t)); 375209950Snwhitehorn 376209950Snwhitehorn mcp->mc_vers = _MC_VERSION; 377209950Snwhitehorn mcp->mc_flags = 0; 378209950Snwhitehorn memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe)); 379209950Snwhitehorn if (flags & GET_MC_CLEAR_RET) { 380209950Snwhitehorn mcp->mc_gpr[3] = 0; 381209950Snwhitehorn mcp->mc_gpr[4] = 0; 382209950Snwhitehorn } 383209950Snwhitehorn 384209950Snwhitehorn#ifdef AIM 385209950Snwhitehorn /* 386209950Snwhitehorn * This assumes that floating-point context is *not* lazy, 387209950Snwhitehorn * so if the thread has used FP there would have been a 388209950Snwhitehorn * FP-unavailable exception that would have set things up 389209950Snwhitehorn * correctly. 390209950Snwhitehorn */ 391209950Snwhitehorn if (pcb->pcb_flags & PCB_FPU) { 392209950Snwhitehorn KASSERT(td == curthread, 393209950Snwhitehorn ("get_mcontext: fp save not curthread")); 394209950Snwhitehorn critical_enter(); 395209950Snwhitehorn save_fpu(td); 396209950Snwhitehorn critical_exit(); 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#endif 418209950Snwhitehorn 419209950Snwhitehorn mcp->mc_len = sizeof(*mcp); 420209950Snwhitehorn 421209950Snwhitehorn return (0); 422209950Snwhitehorn} 423209950Snwhitehorn 424209950Snwhitehornint 425209950Snwhitehornget_mcontext(struct thread *td, mcontext_t *mcp, int flags) 426209950Snwhitehorn{ 427209950Snwhitehorn int error; 428209950Snwhitehorn 429209950Snwhitehorn error = grab_mcontext(td, mcp, flags); 430209950Snwhitehorn if (error == 0) { 431209950Snwhitehorn PROC_LOCK(curthread->td_proc); 432209950Snwhitehorn mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 433209950Snwhitehorn PROC_UNLOCK(curthread->td_proc); 434209950Snwhitehorn } 435209950Snwhitehorn 436209950Snwhitehorn return (error); 437209950Snwhitehorn} 438209950Snwhitehorn 439209950Snwhitehornint 440209950Snwhitehornset_mcontext(struct thread *td, const mcontext_t *mcp) 441209950Snwhitehorn{ 442209950Snwhitehorn struct pcb *pcb; 443209950Snwhitehorn struct trapframe *tf; 444234115Snwhitehorn register_t tls; 445209950Snwhitehorn 446209950Snwhitehorn pcb = td->td_pcb; 447209950Snwhitehorn tf = td->td_frame; 448209950Snwhitehorn 449209950Snwhitehorn if (mcp->mc_vers != _MC_VERSION || mcp->mc_len != sizeof(*mcp)) 450209950Snwhitehorn return (EINVAL); 451209950Snwhitehorn 452234115Snwhitehorn#ifdef AIM 453209950Snwhitehorn /* 454209950Snwhitehorn * Don't let the user set privileged MSR bits 455209950Snwhitehorn */ 456209950Snwhitehorn if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) { 457209950Snwhitehorn return (EINVAL); 458209950Snwhitehorn } 459234115Snwhitehorn#endif 460209950Snwhitehorn 461234115Snwhitehorn /* Copy trapframe, preserving TLS pointer across context change */ 462234115Snwhitehorn if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 463234115Snwhitehorn tls = tf->fixreg[13]; 464234115Snwhitehorn else 465234115Snwhitehorn tls = tf->fixreg[2]; 466209950Snwhitehorn memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame)); 467234115Snwhitehorn if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 468234115Snwhitehorn tf->fixreg[13] = tls; 469234115Snwhitehorn else 470234115Snwhitehorn tf->fixreg[2] = tls; 471209950Snwhitehorn 472209975Snwhitehorn#ifdef AIM 473209950Snwhitehorn if (mcp->mc_flags & _MC_FP_VALID) { 474209950Snwhitehorn if ((pcb->pcb_flags & PCB_FPU) != PCB_FPU) { 475209950Snwhitehorn critical_enter(); 476209950Snwhitehorn enable_fpu(td); 477209950Snwhitehorn critical_exit(); 478209950Snwhitehorn } 479209950Snwhitehorn memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double)); 480209950Snwhitehorn memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double)); 481209950Snwhitehorn } 482209950Snwhitehorn 483209950Snwhitehorn if (mcp->mc_flags & _MC_AV_VALID) { 484209950Snwhitehorn if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) { 485209950Snwhitehorn critical_enter(); 486209950Snwhitehorn enable_vec(td); 487209950Snwhitehorn critical_exit(); 488209950Snwhitehorn } 489209950Snwhitehorn pcb->pcb_vec.vscr = mcp->mc_vscr; 490209950Snwhitehorn pcb->pcb_vec.vrsave = mcp->mc_vrsave; 491209950Snwhitehorn memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec)); 492209950Snwhitehorn } 493209975Snwhitehorn#endif 494209950Snwhitehorn 495209950Snwhitehorn return (0); 496209950Snwhitehorn} 497209950Snwhitehorn 498209950Snwhitehorn/* 499209950Snwhitehorn * Set set up registers on exec. 500209950Snwhitehorn */ 501209950Snwhitehornvoid 502209950Snwhitehornexec_setregs(struct thread *td, struct image_params *imgp, u_long stack) 503209950Snwhitehorn{ 504209950Snwhitehorn struct trapframe *tf; 505209950Snwhitehorn register_t argc; 506209975Snwhitehorn #ifdef __powerpc64__ 507209975Snwhitehorn register_t entry_desc[3]; 508209975Snwhitehorn #endif 509209950Snwhitehorn 510209950Snwhitehorn tf = trapframe(td); 511209950Snwhitehorn bzero(tf, sizeof *tf); 512209975Snwhitehorn #ifdef __powerpc64__ 513209975Snwhitehorn tf->fixreg[1] = -roundup(-stack + 48, 16); 514209975Snwhitehorn #else 515209950Snwhitehorn tf->fixreg[1] = -roundup(-stack + 8, 16); 516209975Snwhitehorn #endif 517209950Snwhitehorn 518209950Snwhitehorn /* 519209950Snwhitehorn * Set up arguments for _start(): 520209950Snwhitehorn * _start(argc, argv, envp, obj, cleanup, ps_strings); 521209950Snwhitehorn * 522209950Snwhitehorn * Notes: 523209950Snwhitehorn * - obj and cleanup are the auxilliary and termination 524209950Snwhitehorn * vectors. They are fixed up by ld.elf_so. 525209950Snwhitehorn * - ps_strings is a NetBSD extention, and will be 526209950Snwhitehorn * ignored by executables which are strictly 527209950Snwhitehorn * compliant with the SVR4 ABI. 528209950Snwhitehorn * 529209950Snwhitehorn * XXX We have to set both regs and retval here due to different 530209950Snwhitehorn * XXX calling convention in trap.c and init_main.c. 531209950Snwhitehorn */ 532209950Snwhitehorn 533209950Snwhitehorn /* Collect argc from the user stack */ 534209950Snwhitehorn argc = fuword((void *)stack); 535209950Snwhitehorn 536209950Snwhitehorn /* 537209950Snwhitehorn * XXX PG: these get overwritten in the syscall return code. 538209950Snwhitehorn * execve() should return EJUSTRETURN, like it does on NetBSD. 539209950Snwhitehorn * Emulate by setting the syscall return value cells. The 540209950Snwhitehorn * registers still have to be set for init's fork trampoline. 541209950Snwhitehorn */ 542209950Snwhitehorn td->td_retval[0] = argc; 543209950Snwhitehorn td->td_retval[1] = stack + sizeof(register_t); 544209950Snwhitehorn tf->fixreg[3] = argc; 545209950Snwhitehorn tf->fixreg[4] = stack + sizeof(register_t); 546209950Snwhitehorn tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t); 547209950Snwhitehorn tf->fixreg[6] = 0; /* auxillary vector */ 548209950Snwhitehorn tf->fixreg[7] = 0; /* termination vector */ 549209950Snwhitehorn tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 550209950Snwhitehorn 551209975Snwhitehorn #ifdef __powerpc64__ 552209975Snwhitehorn /* 553209975Snwhitehorn * For 64-bit, we need to disentangle the function descriptor 554209975Snwhitehorn * 555209975Snwhitehorn * 0. entry point 556209975Snwhitehorn * 1. TOC value (r2) 557209975Snwhitehorn * 2. Environment pointer (r11) 558209975Snwhitehorn */ 559209975Snwhitehorn 560209975Snwhitehorn (void)copyin((void *)imgp->entry_addr, entry_desc, sizeof(entry_desc)); 561209975Snwhitehorn tf->srr0 = entry_desc[0] + imgp->reloc_base; 562209975Snwhitehorn tf->fixreg[2] = entry_desc[1] + imgp->reloc_base; 563209975Snwhitehorn tf->fixreg[11] = entry_desc[2] + imgp->reloc_base; 564209975Snwhitehorn tf->srr1 = PSL_SF | PSL_USERSET | PSL_FE_DFLT; 565209975Snwhitehorn if (mfmsr() & PSL_HV) 566209975Snwhitehorn tf->srr1 |= PSL_HV; 567209975Snwhitehorn #else 568209950Snwhitehorn tf->srr0 = imgp->entry_addr; 569209950Snwhitehorn tf->srr1 = PSL_USERSET | PSL_FE_DFLT; 570209975Snwhitehorn #endif 571209950Snwhitehorn td->td_pcb->pcb_flags = 0; 572209950Snwhitehorn} 573209950Snwhitehorn 574209975Snwhitehorn#ifdef COMPAT_FREEBSD32 575209975Snwhitehornvoid 576209975Snwhitehornppc32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 577209975Snwhitehorn{ 578209975Snwhitehorn struct trapframe *tf; 579209975Snwhitehorn uint32_t argc; 580209950Snwhitehorn 581209975Snwhitehorn tf = trapframe(td); 582209975Snwhitehorn bzero(tf, sizeof *tf); 583209975Snwhitehorn tf->fixreg[1] = -roundup(-stack + 8, 16); 584209975Snwhitehorn 585209975Snwhitehorn argc = fuword32((void *)stack); 586209975Snwhitehorn 587209975Snwhitehorn td->td_retval[0] = argc; 588209975Snwhitehorn td->td_retval[1] = stack + sizeof(uint32_t); 589209975Snwhitehorn tf->fixreg[3] = argc; 590209975Snwhitehorn tf->fixreg[4] = stack + sizeof(uint32_t); 591209975Snwhitehorn tf->fixreg[5] = stack + (2 + argc)*sizeof(uint32_t); 592209975Snwhitehorn tf->fixreg[6] = 0; /* auxillary vector */ 593209975Snwhitehorn tf->fixreg[7] = 0; /* termination vector */ 594209975Snwhitehorn tf->fixreg[8] = (register_t)imgp->ps_strings; /* NetBSD extension */ 595209975Snwhitehorn 596209975Snwhitehorn tf->srr0 = imgp->entry_addr; 597209975Snwhitehorn tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; 598209975Snwhitehorn tf->srr1 &= ~PSL_SF; 599209975Snwhitehorn if (mfmsr() & PSL_HV) 600209975Snwhitehorn tf->srr1 |= PSL_HV; 601209975Snwhitehorn td->td_pcb->pcb_flags = 0; 602209975Snwhitehorn} 603209975Snwhitehorn#endif 604209975Snwhitehorn 605209950Snwhitehornint 606209950Snwhitehornfill_regs(struct thread *td, struct reg *regs) 607209950Snwhitehorn{ 608209950Snwhitehorn struct trapframe *tf; 609209950Snwhitehorn 610209950Snwhitehorn tf = td->td_frame; 611209950Snwhitehorn memcpy(regs, tf, sizeof(struct reg)); 612209950Snwhitehorn 613209950Snwhitehorn return (0); 614209950Snwhitehorn} 615209950Snwhitehorn 616209950Snwhitehornint 617209950Snwhitehornfill_dbregs(struct thread *td, struct dbreg *dbregs) 618209950Snwhitehorn{ 619209950Snwhitehorn /* No debug registers on PowerPC */ 620209950Snwhitehorn return (ENOSYS); 621209950Snwhitehorn} 622209950Snwhitehorn 623209950Snwhitehornint 624209950Snwhitehornfill_fpregs(struct thread *td, struct fpreg *fpregs) 625209950Snwhitehorn{ 626209950Snwhitehorn struct pcb *pcb; 627209950Snwhitehorn 628209950Snwhitehorn pcb = td->td_pcb; 629209950Snwhitehorn 630209950Snwhitehorn if ((pcb->pcb_flags & PCB_FPU) == 0) 631209950Snwhitehorn memset(fpregs, 0, sizeof(struct fpreg)); 632209950Snwhitehorn else 633209950Snwhitehorn memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg)); 634209950Snwhitehorn 635209950Snwhitehorn return (0); 636209950Snwhitehorn} 637209950Snwhitehorn 638209950Snwhitehornint 639209950Snwhitehornset_regs(struct thread *td, struct reg *regs) 640209950Snwhitehorn{ 641209950Snwhitehorn struct trapframe *tf; 642209950Snwhitehorn 643209950Snwhitehorn tf = td->td_frame; 644209950Snwhitehorn memcpy(tf, regs, sizeof(struct reg)); 645209950Snwhitehorn 646209950Snwhitehorn return (0); 647209950Snwhitehorn} 648209950Snwhitehorn 649209950Snwhitehornint 650209950Snwhitehornset_dbregs(struct thread *td, struct dbreg *dbregs) 651209950Snwhitehorn{ 652209950Snwhitehorn /* No debug registers on PowerPC */ 653209950Snwhitehorn return (ENOSYS); 654209950Snwhitehorn} 655209950Snwhitehorn 656209950Snwhitehornint 657209950Snwhitehornset_fpregs(struct thread *td, struct fpreg *fpregs) 658209950Snwhitehorn{ 659209950Snwhitehorn#ifdef AIM 660209950Snwhitehorn struct pcb *pcb; 661209950Snwhitehorn 662209950Snwhitehorn pcb = td->td_pcb; 663209950Snwhitehorn if ((pcb->pcb_flags & PCB_FPU) == 0) 664209950Snwhitehorn enable_fpu(td); 665209950Snwhitehorn memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg)); 666209950Snwhitehorn#endif 667209950Snwhitehorn 668209950Snwhitehorn return (0); 669209950Snwhitehorn} 670209950Snwhitehorn 671209975Snwhitehorn#ifdef COMPAT_FREEBSD32 672209975Snwhitehornint 673209975Snwhitehornset_regs32(struct thread *td, struct reg32 *regs) 674209975Snwhitehorn{ 675209975Snwhitehorn struct trapframe *tf; 676209975Snwhitehorn int i; 677209950Snwhitehorn 678209975Snwhitehorn tf = td->td_frame; 679209975Snwhitehorn for (i = 0; i < 32; i++) 680209975Snwhitehorn tf->fixreg[i] = regs->fixreg[i]; 681209975Snwhitehorn tf->lr = regs->lr; 682209975Snwhitehorn tf->cr = regs->cr; 683209975Snwhitehorn tf->xer = regs->xer; 684209975Snwhitehorn tf->ctr = regs->ctr; 685209975Snwhitehorn tf->srr0 = regs->pc; 686209950Snwhitehorn 687209975Snwhitehorn return (0); 688209975Snwhitehorn} 689209975Snwhitehorn 690209975Snwhitehornint 691209975Snwhitehornfill_regs32(struct thread *td, struct reg32 *regs) 692209975Snwhitehorn{ 693209975Snwhitehorn struct trapframe *tf; 694209975Snwhitehorn int i; 695209975Snwhitehorn 696209975Snwhitehorn tf = td->td_frame; 697209975Snwhitehorn for (i = 0; i < 32; i++) 698209975Snwhitehorn regs->fixreg[i] = tf->fixreg[i]; 699209975Snwhitehorn regs->lr = tf->lr; 700209975Snwhitehorn regs->cr = tf->cr; 701209975Snwhitehorn regs->xer = tf->xer; 702209975Snwhitehorn regs->ctr = tf->ctr; 703209975Snwhitehorn regs->pc = tf->srr0; 704209975Snwhitehorn 705209975Snwhitehorn return (0); 706209975Snwhitehorn} 707209975Snwhitehorn 708209975Snwhitehornstatic int 709209975Snwhitehorngrab_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 710209975Snwhitehorn{ 711209975Snwhitehorn mcontext_t mcp64; 712209975Snwhitehorn int i, error; 713209975Snwhitehorn 714209975Snwhitehorn error = grab_mcontext(td, &mcp64, flags); 715209975Snwhitehorn if (error != 0) 716209975Snwhitehorn return (error); 717209975Snwhitehorn 718209975Snwhitehorn mcp->mc_vers = mcp64.mc_vers; 719209975Snwhitehorn mcp->mc_flags = mcp64.mc_flags; 720209975Snwhitehorn mcp->mc_onstack = mcp64.mc_onstack; 721209975Snwhitehorn mcp->mc_len = mcp64.mc_len; 722209975Snwhitehorn memcpy(mcp->mc_avec,mcp64.mc_avec,sizeof(mcp64.mc_avec)); 723209975Snwhitehorn memcpy(mcp->mc_av,mcp64.mc_av,sizeof(mcp64.mc_av)); 724209975Snwhitehorn for (i = 0; i < 42; i++) 725209975Snwhitehorn mcp->mc_frame[i] = mcp64.mc_frame[i]; 726209975Snwhitehorn memcpy(mcp->mc_fpreg,mcp64.mc_fpreg,sizeof(mcp64.mc_fpreg)); 727209975Snwhitehorn 728209975Snwhitehorn return (0); 729209975Snwhitehorn} 730209975Snwhitehorn 731209975Snwhitehornstatic int 732209975Snwhitehornget_mcontext32(struct thread *td, mcontext32_t *mcp, int flags) 733209975Snwhitehorn{ 734209975Snwhitehorn int error; 735209975Snwhitehorn 736209975Snwhitehorn error = grab_mcontext32(td, mcp, flags); 737209975Snwhitehorn if (error == 0) { 738209975Snwhitehorn PROC_LOCK(curthread->td_proc); 739209975Snwhitehorn mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]); 740209975Snwhitehorn PROC_UNLOCK(curthread->td_proc); 741209975Snwhitehorn } 742209975Snwhitehorn 743209975Snwhitehorn return (error); 744209975Snwhitehorn} 745209975Snwhitehorn 746209975Snwhitehornstatic int 747209975Snwhitehornset_mcontext32(struct thread *td, const mcontext32_t *mcp) 748209975Snwhitehorn{ 749209975Snwhitehorn mcontext_t mcp64; 750209975Snwhitehorn int i, error; 751209975Snwhitehorn 752209975Snwhitehorn mcp64.mc_vers = mcp->mc_vers; 753209975Snwhitehorn mcp64.mc_flags = mcp->mc_flags; 754209975Snwhitehorn mcp64.mc_onstack = mcp->mc_onstack; 755209975Snwhitehorn mcp64.mc_len = mcp->mc_len; 756209975Snwhitehorn memcpy(mcp64.mc_avec,mcp->mc_avec,sizeof(mcp64.mc_avec)); 757209975Snwhitehorn memcpy(mcp64.mc_av,mcp->mc_av,sizeof(mcp64.mc_av)); 758209975Snwhitehorn for (i = 0; i < 42; i++) 759209975Snwhitehorn mcp64.mc_frame[i] = mcp->mc_frame[i]; 760209975Snwhitehorn memcpy(mcp64.mc_fpreg,mcp->mc_fpreg,sizeof(mcp64.mc_fpreg)); 761209975Snwhitehorn 762209975Snwhitehorn error = set_mcontext(td, &mcp64); 763209975Snwhitehorn 764209975Snwhitehorn return (error); 765209975Snwhitehorn} 766209975Snwhitehorn#endif 767209975Snwhitehorn 768209975Snwhitehorn#ifdef COMPAT_FREEBSD32 769209975Snwhitehornint 770209975Snwhitehornfreebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap) 771209975Snwhitehorn{ 772209975Snwhitehorn ucontext32_t uc; 773209975Snwhitehorn int error; 774209975Snwhitehorn 775209975Snwhitehorn CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp); 776209975Snwhitehorn 777209975Snwhitehorn if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) { 778209975Snwhitehorn CTR1(KTR_SIG, "sigreturn: efault td=%p", td); 779209975Snwhitehorn return (EFAULT); 780209975Snwhitehorn } 781209975Snwhitehorn 782209975Snwhitehorn error = set_mcontext32(td, &uc.uc_mcontext); 783209975Snwhitehorn if (error != 0) 784209975Snwhitehorn return (error); 785209975Snwhitehorn 786209975Snwhitehorn kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0); 787209975Snwhitehorn 788209975Snwhitehorn CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x", 789209975Snwhitehorn td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]); 790209975Snwhitehorn 791209975Snwhitehorn return (EJUSTRETURN); 792209975Snwhitehorn} 793209975Snwhitehorn 794209975Snwhitehorn/* 795209975Snwhitehorn * The first two fields of a ucontext_t are the signal mask and the machine 796209975Snwhitehorn * context. The next field is uc_link; we want to avoid destroying the link 797209975Snwhitehorn * when copying out contexts. 798209975Snwhitehorn */ 799209975Snwhitehorn#define UC32_COPY_SIZE offsetof(ucontext32_t, uc_link) 800209975Snwhitehorn 801209975Snwhitehornint 802209975Snwhitehornfreebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 803209975Snwhitehorn{ 804209975Snwhitehorn ucontext32_t uc; 805209975Snwhitehorn int ret; 806209975Snwhitehorn 807209975Snwhitehorn if (uap->ucp == NULL) 808209975Snwhitehorn ret = EINVAL; 809209975Snwhitehorn else { 810209975Snwhitehorn get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 811209975Snwhitehorn PROC_LOCK(td->td_proc); 812209975Snwhitehorn uc.uc_sigmask = td->td_sigmask; 813209975Snwhitehorn PROC_UNLOCK(td->td_proc); 814209975Snwhitehorn ret = copyout(&uc, uap->ucp, UC32_COPY_SIZE); 815209975Snwhitehorn } 816209975Snwhitehorn return (ret); 817209975Snwhitehorn} 818209975Snwhitehorn 819209975Snwhitehornint 820209975Snwhitehornfreebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 821209975Snwhitehorn{ 822209975Snwhitehorn ucontext32_t uc; 823209975Snwhitehorn int ret; 824209975Snwhitehorn 825209975Snwhitehorn if (uap->ucp == NULL) 826209975Snwhitehorn ret = EINVAL; 827209975Snwhitehorn else { 828209975Snwhitehorn ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 829209975Snwhitehorn if (ret == 0) { 830209975Snwhitehorn ret = set_mcontext32(td, &uc.uc_mcontext); 831209975Snwhitehorn if (ret == 0) { 832209975Snwhitehorn kern_sigprocmask(td, SIG_SETMASK, 833209975Snwhitehorn &uc.uc_sigmask, NULL, 0); 834209975Snwhitehorn } 835209975Snwhitehorn } 836209975Snwhitehorn } 837209975Snwhitehorn return (ret == 0 ? EJUSTRETURN : ret); 838209975Snwhitehorn} 839209975Snwhitehorn 840209975Snwhitehornint 841209975Snwhitehornfreebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 842209975Snwhitehorn{ 843209975Snwhitehorn ucontext32_t uc; 844209975Snwhitehorn int ret; 845209975Snwhitehorn 846209975Snwhitehorn if (uap->oucp == NULL || uap->ucp == NULL) 847209975Snwhitehorn ret = EINVAL; 848209975Snwhitehorn else { 849209975Snwhitehorn get_mcontext32(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 850209975Snwhitehorn PROC_LOCK(td->td_proc); 851209975Snwhitehorn uc.uc_sigmask = td->td_sigmask; 852209975Snwhitehorn PROC_UNLOCK(td->td_proc); 853209975Snwhitehorn ret = copyout(&uc, uap->oucp, UC32_COPY_SIZE); 854209975Snwhitehorn if (ret == 0) { 855209975Snwhitehorn ret = copyin(uap->ucp, &uc, UC32_COPY_SIZE); 856209975Snwhitehorn if (ret == 0) { 857209975Snwhitehorn ret = set_mcontext32(td, &uc.uc_mcontext); 858209975Snwhitehorn if (ret == 0) { 859209975Snwhitehorn kern_sigprocmask(td, SIG_SETMASK, 860209975Snwhitehorn &uc.uc_sigmask, NULL, 0); 861209975Snwhitehorn } 862209975Snwhitehorn } 863209975Snwhitehorn } 864209975Snwhitehorn } 865209975Snwhitehorn return (ret == 0 ? EJUSTRETURN : ret); 866209975Snwhitehorn} 867209975Snwhitehorn 868209975Snwhitehorn#endif 869209975Snwhitehorn 870209950Snwhitehornvoid 871209950Snwhitehorncpu_set_syscall_retval(struct thread *td, int error) 872209950Snwhitehorn{ 873209950Snwhitehorn struct proc *p; 874209950Snwhitehorn struct trapframe *tf; 875209950Snwhitehorn int fixup; 876209950Snwhitehorn 877209950Snwhitehorn if (error == EJUSTRETURN) 878209950Snwhitehorn return; 879209950Snwhitehorn 880209950Snwhitehorn p = td->td_proc; 881209950Snwhitehorn tf = td->td_frame; 882209950Snwhitehorn 883209975Snwhitehorn if (tf->fixreg[0] == SYS___syscall && 884217896Sdchagin (SV_PROC_FLAG(p, SV_ILP32))) { 885209950Snwhitehorn int code = tf->fixreg[FIRSTARG + 1]; 886209950Snwhitehorn if (p->p_sysent->sv_mask) 887209950Snwhitehorn code &= p->p_sysent->sv_mask; 888209950Snwhitehorn fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek) ? 889209950Snwhitehorn 1 : 0; 890209950Snwhitehorn } else 891209950Snwhitehorn fixup = 0; 892209950Snwhitehorn 893209950Snwhitehorn switch (error) { 894209950Snwhitehorn case 0: 895209950Snwhitehorn if (fixup) { 896209950Snwhitehorn /* 897209950Snwhitehorn * 64-bit return, 32-bit syscall. Fixup byte order 898209950Snwhitehorn */ 899209950Snwhitehorn tf->fixreg[FIRSTARG] = 0; 900209950Snwhitehorn tf->fixreg[FIRSTARG + 1] = td->td_retval[0]; 901209950Snwhitehorn } else { 902209950Snwhitehorn tf->fixreg[FIRSTARG] = td->td_retval[0]; 903209950Snwhitehorn tf->fixreg[FIRSTARG + 1] = td->td_retval[1]; 904209950Snwhitehorn } 905209950Snwhitehorn tf->cr &= ~0x10000000; /* Unset summary overflow */ 906209950Snwhitehorn break; 907209950Snwhitehorn case ERESTART: 908209950Snwhitehorn /* 909209950Snwhitehorn * Set user's pc back to redo the system call. 910209950Snwhitehorn */ 911209950Snwhitehorn tf->srr0 -= 4; 912209950Snwhitehorn break; 913209950Snwhitehorn default: 914209950Snwhitehorn if (p->p_sysent->sv_errsize) { 915209950Snwhitehorn error = (error < p->p_sysent->sv_errsize) ? 916209950Snwhitehorn p->p_sysent->sv_errtbl[error] : -1; 917209950Snwhitehorn } 918209950Snwhitehorn tf->fixreg[FIRSTARG] = error; 919209950Snwhitehorn tf->cr |= 0x10000000; /* Set summary overflow */ 920209950Snwhitehorn break; 921209950Snwhitehorn } 922209950Snwhitehorn} 923209950Snwhitehorn 924209950Snwhitehorn/* 925209950Snwhitehorn * Threading functions 926209950Snwhitehorn */ 927209950Snwhitehornvoid 928209950Snwhitehorncpu_thread_exit(struct thread *td) 929209950Snwhitehorn{ 930209950Snwhitehorn} 931209950Snwhitehorn 932209950Snwhitehornvoid 933209950Snwhitehorncpu_thread_clean(struct thread *td) 934209950Snwhitehorn{ 935209950Snwhitehorn} 936209950Snwhitehorn 937209950Snwhitehornvoid 938209950Snwhitehorncpu_thread_alloc(struct thread *td) 939209950Snwhitehorn{ 940209950Snwhitehorn struct pcb *pcb; 941209950Snwhitehorn 942209950Snwhitehorn pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE - 943209950Snwhitehorn sizeof(struct pcb)) & ~0x2fUL); 944209950Snwhitehorn td->td_pcb = pcb; 945209950Snwhitehorn td->td_frame = (struct trapframe *)pcb - 1; 946209950Snwhitehorn} 947209950Snwhitehorn 948209950Snwhitehornvoid 949209950Snwhitehorncpu_thread_free(struct thread *td) 950209950Snwhitehorn{ 951209950Snwhitehorn} 952209950Snwhitehorn 953209950Snwhitehornint 954209950Snwhitehorncpu_set_user_tls(struct thread *td, void *tls_base) 955209950Snwhitehorn{ 956209950Snwhitehorn 957217896Sdchagin if (SV_PROC_FLAG(td->td_proc, SV_LP64)) 958209975Snwhitehorn td->td_frame->fixreg[13] = (register_t)tls_base + 0x7010; 959209975Snwhitehorn else 960209975Snwhitehorn td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008; 961209950Snwhitehorn return (0); 962209950Snwhitehorn} 963209950Snwhitehorn 964209950Snwhitehornvoid 965209950Snwhitehorncpu_set_upcall(struct thread *td, struct thread *td0) 966209950Snwhitehorn{ 967209950Snwhitehorn struct pcb *pcb2; 968209950Snwhitehorn struct trapframe *tf; 969209950Snwhitehorn struct callframe *cf; 970209950Snwhitehorn 971209950Snwhitehorn pcb2 = td->td_pcb; 972209950Snwhitehorn 973209950Snwhitehorn /* Copy the upcall pcb */ 974209950Snwhitehorn bcopy(td0->td_pcb, pcb2, sizeof(*pcb2)); 975209950Snwhitehorn 976209950Snwhitehorn /* Create a stack for the new thread */ 977209950Snwhitehorn tf = td->td_frame; 978209950Snwhitehorn bcopy(td0->td_frame, tf, sizeof(struct trapframe)); 979209950Snwhitehorn tf->fixreg[FIRSTARG] = 0; 980209950Snwhitehorn tf->fixreg[FIRSTARG + 1] = 0; 981209950Snwhitehorn tf->cr &= ~0x10000000; 982209950Snwhitehorn 983209950Snwhitehorn /* Set registers for trampoline to user mode. */ 984209950Snwhitehorn cf = (struct callframe *)tf - 1; 985209950Snwhitehorn memset(cf, 0, sizeof(struct callframe)); 986209950Snwhitehorn cf->cf_func = (register_t)fork_return; 987209950Snwhitehorn cf->cf_arg0 = (register_t)td; 988209950Snwhitehorn cf->cf_arg1 = (register_t)tf; 989209950Snwhitehorn 990209950Snwhitehorn pcb2->pcb_sp = (register_t)cf; 991209975Snwhitehorn #ifdef __powerpc64__ 992209975Snwhitehorn pcb2->pcb_lr = ((register_t *)fork_trampoline)[0]; 993209975Snwhitehorn pcb2->pcb_toc = ((register_t *)fork_trampoline)[1]; 994209975Snwhitehorn #else 995209950Snwhitehorn pcb2->pcb_lr = (register_t)fork_trampoline; 996209975Snwhitehorn #endif 997209975Snwhitehorn pcb2->pcb_cpu.aim.usr_vsid = 0; 998209950Snwhitehorn 999209950Snwhitehorn /* Setup to release spin count in fork_exit(). */ 1000209950Snwhitehorn td->td_md.md_spinlock_count = 1; 1001209950Snwhitehorn td->td_md.md_saved_msr = PSL_KERNSET; 1002209950Snwhitehorn} 1003209950Snwhitehorn 1004209950Snwhitehornvoid 1005209950Snwhitehorncpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg, 1006209950Snwhitehorn stack_t *stack) 1007209950Snwhitehorn{ 1008209950Snwhitehorn struct trapframe *tf; 1009209950Snwhitehorn uintptr_t sp; 1010209950Snwhitehorn 1011209950Snwhitehorn tf = td->td_frame; 1012209950Snwhitehorn /* align stack and alloc space for frame ptr and saved LR */ 1013209975Snwhitehorn #ifdef __powerpc64__ 1014209975Snwhitehorn sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 48) & 1015209975Snwhitehorn ~0x1f; 1016209975Snwhitehorn #else 1017209950Snwhitehorn sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) & 1018209950Snwhitehorn ~0x1f; 1019209975Snwhitehorn #endif 1020209950Snwhitehorn bzero(tf, sizeof(struct trapframe)); 1021209950Snwhitehorn 1022209950Snwhitehorn tf->fixreg[1] = (register_t)sp; 1023209950Snwhitehorn tf->fixreg[3] = (register_t)arg; 1024217896Sdchagin if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) { 1025209975Snwhitehorn tf->srr0 = (register_t)entry; 1026209975Snwhitehorn #ifdef AIM 1027209975Snwhitehorn tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT; 1028220597Snwhitehorn #ifdef __powerpc64__ 1029220597Snwhitehorn tf->srr1 &= ~PSL_SF; 1030220597Snwhitehorn #endif 1031209975Snwhitehorn #else 1032209975Snwhitehorn tf->srr1 = PSL_USERSET; 1033209975Snwhitehorn #endif 1034209975Snwhitehorn } else { 1035209975Snwhitehorn #ifdef __powerpc64__ 1036209975Snwhitehorn register_t entry_desc[3]; 1037209975Snwhitehorn (void)copyin((void *)entry, entry_desc, sizeof(entry_desc)); 1038209975Snwhitehorn tf->srr0 = entry_desc[0]; 1039209975Snwhitehorn tf->fixreg[2] = entry_desc[1]; 1040209975Snwhitehorn tf->fixreg[11] = entry_desc[2]; 1041209975Snwhitehorn tf->srr1 = PSL_SF | PSL_MBO | PSL_USERSET | PSL_FE_DFLT; 1042209975Snwhitehorn #endif 1043209975Snwhitehorn } 1044209950Snwhitehorn 1045209975Snwhitehorn #ifdef __powerpc64__ 1046209975Snwhitehorn if (mfmsr() & PSL_HV) 1047209975Snwhitehorn tf->srr1 |= PSL_HV; 1048209975Snwhitehorn #endif 1049209950Snwhitehorn td->td_pcb->pcb_flags = 0; 1050209950Snwhitehorn 1051209950Snwhitehorn td->td_retval[0] = (register_t)entry; 1052209950Snwhitehorn td->td_retval[1] = 0; 1053209950Snwhitehorn} 1054209950Snwhitehorn 1055