1179335Syongari/*- 2179335Syongari * Copyright (c) 2003 Peter Wemm 3179335Syongari * Copyright (c) 1982, 1987, 1990 The Regents of the University of California. 4179335Syongari * All rights reserved. 5179335Syongari * 6179335Syongari * This code is derived from software contributed to Berkeley by 7179335Syongari * William Jolitz. 8179335Syongari * 9179335Syongari * Redistribution and use in source and binary forms, with or without 10179335Syongari * modification, are permitted provided that the following conditions 11179335Syongari * are met: 12179335Syongari * 1. Redistributions of source code must retain the above copyright 13179335Syongari * notice, this list of conditions and the following disclaimer. 14179335Syongari * 2. Redistributions in binary form must reproduce the above copyright 15179335Syongari * notice, this list of conditions and the following disclaimer in the 16179335Syongari * documentation and/or other materials provided with the distribution. 17179335Syongari * 4. Neither the name of the University nor the names of its contributors 18179335Syongari * may be used to endorse or promote products derived from this software 19179335Syongari * without specific prior written permission. 20179335Syongari * 21179335Syongari * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22179335Syongari * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23179335Syongari * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24179335Syongari * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25179335Syongari * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26179335Syongari * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27179335Syongari * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28179335Syongari * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29179335Syongari * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30179335Syongari * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31179335Syongari * SUCH DAMAGE. 32179335Syongari */ 33179335Syongari 34179335Syongari#include <sys/cdefs.h> 35179335Syongari__FBSDID("$FreeBSD$"); 36179335Syongari 37179335Syongari#include "opt_compat.h" 38179335Syongari 39179335Syongari#include <sys/param.h> 40179335Syongari#include <sys/exec.h> 41179335Syongari#include <sys/fcntl.h> 42179335Syongari#include <sys/imgact.h> 43179335Syongari#include <sys/kernel.h> 44179335Syongari#include <sys/lock.h> 45179335Syongari#include <sys/malloc.h> 46179335Syongari#include <sys/mutex.h> 47179335Syongari#include <sys/mman.h> 48179335Syongari#include <sys/namei.h> 49179335Syongari#include <sys/pioctl.h> 50179335Syongari#include <sys/proc.h> 51179335Syongari#include <sys/procfs.h> 52179335Syongari#include <sys/resourcevar.h> 53215298Smarius#include <sys/systm.h> 54215298Smarius#include <sys/signalvar.h> 55179335Syongari#include <sys/stat.h> 56179335Syongari#include <sys/sx.h> 57215298Smarius#include <sys/syscall.h> 58179335Syongari#include <sys/syscallsubr.h> 59179335Syongari#include <sys/sysctl.h> 60179335Syongari#include <sys/sysent.h> 61179335Syongari#include <sys/vnode.h> 62179335Syongari 63179335Syongari#include <vm/vm.h> 64179335Syongari#include <vm/vm_kern.h> 65227908Smarius#include <vm/vm_param.h> 66179335Syongari#include <vm/pmap.h> 67179335Syongari#include <vm/vm_map.h> 68179335Syongari#include <vm/vm_object.h> 69179335Syongari#include <vm/vm_extern.h> 70179335Syongari 71179335Syongari#include <compat/freebsd32/freebsd32_signal.h> 72221407Smarius#include <compat/freebsd32/freebsd32_util.h> 73179335Syongari#include <compat/freebsd32/freebsd32_proto.h> 74179335Syongari#include <compat/freebsd32/freebsd32.h> 75179335Syongari#include <compat/ia32/ia32_signal.h> 76179335Syongari#include <machine/psl.h> 77179335Syongari#include <machine/segments.h> 78179335Syongari#include <machine/specialreg.h> 79179335Syongari#include <machine/frame.h> 80179335Syongari#include <machine/md_var.h> 81179335Syongari#include <machine/pcb.h> 82179335Syongari#include <machine/cpufunc.h> 83179335Syongari 84179335Syongari#ifdef COMPAT_FREEBSD4 85179335Syongaristatic void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *); 86221407Smarius#endif 87221407Smarius 88221407Smarius#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) 89221407Smarius#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) 90221407Smarius 91221407Smariusstatic void 92179335Syongariia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp, 93179335Syongari char *xfpusave, size_t xfpusave_len) 94179335Syongari{ 95179335Syongari size_t max_len, len; 96179335Syongari 97179335Syongari /* 98179335Syongari * XXX Format of 64bit and 32bit FXSAVE areas differs. FXSAVE 99179335Syongari * in 32bit mode saves %cs and %ds, while on 64bit it saves 100179335Syongari * 64bit instruction and data pointers. Ignore the difference 101179335Syongari * for now, it should be irrelevant for most applications. 102179335Syongari */ 103221407Smarius mcp->mc_ownedfp = fpugetregs(td); 104179335Syongari bcopy(get_pcb_user_save_td(td), &mcp->mc_fpstate[0], 105179335Syongari sizeof(mcp->mc_fpstate)); 106221407Smarius mcp->mc_fpformat = fpuformat(); 107221407Smarius if (!use_xsave || xfpusave_len == 0) 108221407Smarius return; 109221407Smarius max_len = cpu_max_ext_state_size - sizeof(struct savefpu); 110221407Smarius len = xfpusave_len; 111213364Smarius if (len > max_len) { 112179335Syongari len = max_len; 113179335Syongari bzero(xfpusave + max_len, len - max_len); 114179335Syongari } 115179335Syongari mcp->mc_flags |= _MC_IA32_HASFPXSTATE; 116179335Syongari mcp->mc_xfpustate_len = len; 117179335Syongari bcopy(get_pcb_user_save_td(td) + 1, xfpusave, len); 118179335Syongari} 119179335Syongari 120179335Syongaristatic int 121179335Syongariia32_set_fpcontext(struct thread *td, struct ia32_mcontext *mcp, 122179335Syongari char *xfpustate, size_t xfpustate_len) 123179335Syongari{ 124179335Syongari int error; 125179335Syongari 126179335Syongari if (mcp->mc_fpformat == _MC_FPFMT_NODEV) 127179335Syongari return (0); 128179335Syongari else if (mcp->mc_fpformat != _MC_FPFMT_XMM) 129179335Syongari return (EINVAL); 130215298Smarius else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) { 131179335Syongari /* We don't care what state is left in the FPU or PCB. */ 132179335Syongari fpstate_drop(td); 133179335Syongari error = 0; 134179335Syongari } else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || 135179335Syongari mcp->mc_ownedfp == _MC_FPOWNED_PCB) { 136179335Syongari error = fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate, 137179335Syongari xfpustate, xfpustate_len); 138179335Syongari } else 139179335Syongari return (EINVAL); 140179335Syongari return (error); 141179335Syongari} 142179335Syongari 143179335Syongari/* 144179335Syongari * Get machine context. 145179335Syongari */ 146179335Syongaristatic int 147179335Syongariia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags) 148179335Syongari{ 149179335Syongari struct pcb *pcb; 150179335Syongari struct trapframe *tp; 151179335Syongari 152179335Syongari pcb = td->td_pcb; 153179335Syongari tp = td->td_frame; 154179335Syongari 155179335Syongari PROC_LOCK(curthread->td_proc); 156179335Syongari mcp->mc_onstack = sigonstack(tp->tf_rsp); 157179335Syongari PROC_UNLOCK(curthread->td_proc); 158179335Syongari /* Entry into kernel always sets TF_HASSEGS */ 159179335Syongari mcp->mc_gs = tp->tf_gs; 160179335Syongari mcp->mc_fs = tp->tf_fs; 161179335Syongari mcp->mc_es = tp->tf_es; 162215298Smarius mcp->mc_ds = tp->tf_ds; 163179335Syongari mcp->mc_edi = tp->tf_rdi; 164179335Syongari mcp->mc_esi = tp->tf_rsi; 165179335Syongari mcp->mc_ebp = tp->tf_rbp; 166179335Syongari mcp->mc_isp = tp->tf_rsp; 167221407Smarius mcp->mc_eflags = tp->tf_rflags; 168179335Syongari if (flags & GET_MC_CLEAR_RET) { 169179335Syongari mcp->mc_eax = 0; 170179335Syongari mcp->mc_edx = 0; 171179335Syongari mcp->mc_eflags &= ~PSL_C; 172179335Syongari } else { 173179335Syongari mcp->mc_eax = tp->tf_rax; 174179335Syongari mcp->mc_edx = tp->tf_rdx; 175179335Syongari } 176179335Syongari mcp->mc_ebx = tp->tf_rbx; 177179335Syongari mcp->mc_ecx = tp->tf_rcx; 178179335Syongari mcp->mc_eip = tp->tf_rip; 179179335Syongari mcp->mc_cs = tp->tf_cs; 180179335Syongari mcp->mc_esp = tp->tf_rsp; 181179335Syongari mcp->mc_ss = tp->tf_ss; 182179335Syongari mcp->mc_len = sizeof(*mcp); 183179335Syongari mcp->mc_flags = tp->tf_flags; 184179335Syongari ia32_get_fpcontext(td, mcp, NULL, 0); 185179335Syongari mcp->mc_fsbase = pcb->pcb_fsbase; 186179335Syongari mcp->mc_gsbase = pcb->pcb_gsbase; 187179335Syongari mcp->mc_xfpustate = 0; 188179335Syongari mcp->mc_xfpustate_len = 0; 189179335Syongari bzero(mcp->mc_spare2, sizeof(mcp->mc_spare2)); 190179335Syongari return (0); 191179335Syongari} 192179335Syongari 193179335Syongari/* 194179335Syongari * Set machine context. 195179335Syongari * 196179335Syongari * However, we don't set any but the user modifiable flags, and we won't 197179335Syongari * touch the cs selector. 198179335Syongari */ 199179335Syongaristatic int 200179335Syongariia32_set_mcontext(struct thread *td, struct ia32_mcontext *mcp) 201179335Syongari{ 202179335Syongari struct trapframe *tp; 203179335Syongari char *xfpustate; 204179335Syongari long rflags; 205179335Syongari int ret; 206179335Syongari 207179335Syongari tp = td->td_frame; 208179335Syongari if (mcp->mc_len != sizeof(*mcp)) 209179335Syongari return (EINVAL); 210179335Syongari rflags = (mcp->mc_eflags & PSL_USERCHANGE) | 211179335Syongari (tp->tf_rflags & ~PSL_USERCHANGE); 212179335Syongari if (mcp->mc_flags & _MC_IA32_HASFPXSTATE) { 213179335Syongari if (mcp->mc_xfpustate_len > cpu_max_ext_state_size - 214179335Syongari sizeof(struct savefpu)) 215179335Syongari return (EINVAL); 216179335Syongari xfpustate = __builtin_alloca(mcp->mc_xfpustate_len); 217179335Syongari ret = copyin(PTRIN(mcp->mc_xfpustate), xfpustate, 218179335Syongari mcp->mc_xfpustate_len); 219179335Syongari if (ret != 0) 220179335Syongari return (ret); 221179335Syongari } else 222179335Syongari xfpustate = NULL; 223179335Syongari ret = ia32_set_fpcontext(td, mcp, xfpustate, mcp->mc_xfpustate_len); 224179335Syongari if (ret != 0) 225179335Syongari return (ret); 226179335Syongari tp->tf_gs = mcp->mc_gs; 227215298Smarius tp->tf_fs = mcp->mc_fs; 228179335Syongari tp->tf_es = mcp->mc_es; 229179335Syongari tp->tf_ds = mcp->mc_ds; 230215298Smarius tp->tf_flags = TF_HASSEGS; 231179335Syongari tp->tf_rdi = mcp->mc_edi; 232179335Syongari tp->tf_rsi = mcp->mc_esi; 233179335Syongari tp->tf_rbp = mcp->mc_ebp; 234179335Syongari tp->tf_rbx = mcp->mc_ebx; 235179335Syongari tp->tf_rdx = mcp->mc_edx; 236179335Syongari tp->tf_rcx = mcp->mc_ecx; 237179335Syongari tp->tf_rax = mcp->mc_eax; 238179335Syongari /* trapno, err */ 239179335Syongari tp->tf_rip = mcp->mc_eip; 240216551Syongari tp->tf_rflags = rflags; 241179335Syongari tp->tf_rsp = mcp->mc_esp; 242179335Syongari tp->tf_ss = mcp->mc_ss; 243179335Syongari set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 244179335Syongari return (0); 245179335Syongari} 246179335Syongari 247179335Syongari/* 248179335Syongari * The first two fields of a ucontext_t are the signal mask and 249179335Syongari * the machine context. The next field is uc_link; we want to 250179335Syongari * avoid destroying the link when copying out contexts. 251179335Syongari */ 252179335Syongari#define UC_COPY_SIZE offsetof(struct ia32_ucontext, uc_link) 253216551Syongari 254216551Syongariint 255216551Syongarifreebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 256216551Syongari{ 257216551Syongari struct ia32_ucontext uc; 258216551Syongari int ret; 259216551Syongari 260216551Syongari if (uap->ucp == NULL) 261216551Syongari ret = EINVAL; 262216551Syongari else { 263216551Syongari ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 264216551Syongari PROC_LOCK(td->td_proc); 265216551Syongari uc.uc_sigmask = td->td_sigmask; 266216551Syongari PROC_UNLOCK(td->td_proc); 267216551Syongari bzero(&uc.__spare__, sizeof(uc.__spare__)); 268216551Syongari ret = copyout(&uc, uap->ucp, UC_COPY_SIZE); 269216551Syongari } 270216551Syongari return (ret); 271216551Syongari} 272216551Syongari 273216551Syongariint 274216551Syongarifreebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 275216551Syongari{ 276216551Syongari struct ia32_ucontext uc; 277216551Syongari int ret; 278216551Syongari 279216551Syongari if (uap->ucp == NULL) 280216551Syongari ret = EINVAL; 281216551Syongari else { 282216551Syongari ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 283216551Syongari if (ret == 0) { 284216551Syongari ret = ia32_set_mcontext(td, &uc.uc_mcontext); 285216551Syongari if (ret == 0) { 286179335Syongari kern_sigprocmask(td, SIG_SETMASK, 287179335Syongari &uc.uc_sigmask, NULL, 0); 288179335Syongari } 289179335Syongari } 290179335Syongari } 291179335Syongari return (ret == 0 ? EJUSTRETURN : ret); 292179335Syongari} 293179335Syongari 294179335Syongariint 295179335Syongarifreebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 296179335Syongari{ 297179335Syongari struct ia32_ucontext uc; 298179335Syongari int ret; 299179335Syongari 300179335Syongari if (uap->oucp == NULL || uap->ucp == NULL) 301179335Syongari ret = EINVAL; 302179335Syongari else { 303179335Syongari ia32_get_mcontext(td, &uc.uc_mcontext, GET_MC_CLEAR_RET); 304179335Syongari PROC_LOCK(td->td_proc); 305179335Syongari uc.uc_sigmask = td->td_sigmask; 306179335Syongari PROC_UNLOCK(td->td_proc); 307179335Syongari ret = copyout(&uc, uap->oucp, UC_COPY_SIZE); 308179335Syongari if (ret == 0) { 309179335Syongari ret = copyin(uap->ucp, &uc, UC_COPY_SIZE); 310179335Syongari if (ret == 0) { 311179335Syongari ret = ia32_set_mcontext(td, &uc.uc_mcontext); 312179335Syongari if (ret == 0) { 313179335Syongari kern_sigprocmask(td, SIG_SETMASK, 314215298Smarius &uc.uc_sigmask, NULL, 0); 315179335Syongari } 316179335Syongari } 317179335Syongari } 318179335Syongari } 319179335Syongari return (ret == 0 ? EJUSTRETURN : ret); 320179335Syongari} 321179335Syongari 322179335Syongari/* 323179335Syongari * Send an interrupt to process. 324179335Syongari * 325179335Syongari * Stack is set up to allow sigcode stored 326179335Syongari * at top to call routine, followed by kcall 327179335Syongari * to sigreturn routine below. After sigreturn 328179335Syongari * resets the signal mask, the stack, and the 329179335Syongari * frame pointer, it returns to the user 330179335Syongari * specified pc, psl. 331179335Syongari */ 332179335Syongari 333179335Syongari#ifdef COMPAT_43 334179335Syongaristatic void 335179335Syongariia32_osendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 336179335Syongari{ 337179335Syongari struct ia32_sigframe3 sf, *fp; 338217414Smarius struct proc *p; 339215298Smarius struct thread *td; 340217414Smarius struct sigacts *psp; 341217414Smarius struct trapframe *regs; 342215298Smarius int sig; 343179335Syongari int oonstack; 344179335Syongari 345215298Smarius td = curthread; 346215298Smarius p = td->td_proc; 347215298Smarius PROC_LOCK_ASSERT(p, MA_OWNED); 348215298Smarius sig = ksi->ksi_signo; 349215298Smarius psp = p->p_sigacts; 350179335Syongari mtx_assert(&psp->ps_mtx, MA_OWNED); 351179335Syongari regs = td->td_frame; 352179335Syongari oonstack = sigonstack(regs->tf_rsp); 353179335Syongari 354179335Syongari /* Allocate space for the signal handler context. */ 355179335Syongari if ((td->td_pflags & TDP_ALTSTACK) && !oonstack && 356179335Syongari SIGISMEMBER(psp->ps_sigonstack, sig)) { 357 fp = (struct ia32_sigframe3 *)(td->td_sigstk.ss_sp + 358 td->td_sigstk.ss_size - sizeof(sf)); 359 td->td_sigstk.ss_flags |= SS_ONSTACK; 360 } else 361 fp = (struct ia32_sigframe3 *)regs->tf_rsp - 1; 362 363 /* Build the argument list for the signal handler. */ 364 sf.sf_signum = sig; 365 sf.sf_scp = (register_t)&fp->sf_siginfo.si_sc; 366 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 367 /* Signal handler installed with SA_SIGINFO. */ 368 sf.sf_arg2 = (register_t)&fp->sf_siginfo; 369 sf.sf_siginfo.si_signo = sig; 370 sf.sf_siginfo.si_code = ksi->ksi_code; 371 sf.sf_ah = (uintptr_t)catcher; 372 } else { 373 /* Old FreeBSD-style arguments. */ 374 sf.sf_arg2 = ksi->ksi_code; 375 sf.sf_addr = (register_t)ksi->ksi_addr; 376 sf.sf_ah = (uintptr_t)catcher; 377 } 378 mtx_unlock(&psp->ps_mtx); 379 PROC_UNLOCK(p); 380 381 /* Save most if not all of trap frame. */ 382 sf.sf_siginfo.si_sc.sc_eax = regs->tf_rax; 383 sf.sf_siginfo.si_sc.sc_ebx = regs->tf_rbx; 384 sf.sf_siginfo.si_sc.sc_ecx = regs->tf_rcx; 385 sf.sf_siginfo.si_sc.sc_edx = regs->tf_rdx; 386 sf.sf_siginfo.si_sc.sc_esi = regs->tf_rsi; 387 sf.sf_siginfo.si_sc.sc_edi = regs->tf_rdi; 388 sf.sf_siginfo.si_sc.sc_cs = regs->tf_cs; 389 sf.sf_siginfo.si_sc.sc_ds = regs->tf_ds; 390 sf.sf_siginfo.si_sc.sc_ss = regs->tf_ss; 391 sf.sf_siginfo.si_sc.sc_es = regs->tf_es; 392 sf.sf_siginfo.si_sc.sc_fs = regs->tf_fs; 393 sf.sf_siginfo.si_sc.sc_gs = regs->tf_gs; 394 sf.sf_siginfo.si_sc.sc_isp = regs->tf_rsp; 395 396 /* Build the signal context to be used by osigreturn(). */ 397 sf.sf_siginfo.si_sc.sc_onstack = (oonstack) ? 1 : 0; 398 SIG2OSIG(*mask, sf.sf_siginfo.si_sc.sc_mask); 399 sf.sf_siginfo.si_sc.sc_esp = regs->tf_rsp; 400 sf.sf_siginfo.si_sc.sc_ebp = regs->tf_rbp; 401 sf.sf_siginfo.si_sc.sc_eip = regs->tf_rip; 402 sf.sf_siginfo.si_sc.sc_eflags = regs->tf_rflags; 403 sf.sf_siginfo.si_sc.sc_trapno = regs->tf_trapno; 404 sf.sf_siginfo.si_sc.sc_err = regs->tf_err; 405 406 /* 407 * Copy the sigframe out to the user's stack. 408 */ 409 if (copyout(&sf, fp, sizeof(*fp)) != 0) { 410#ifdef DEBUG 411 printf("process %ld has trashed its stack\n", (long)p->p_pid); 412#endif 413 PROC_LOCK(p); 414 sigexit(td, SIGILL); 415 } 416 417 regs->tf_rsp = (uintptr_t)fp; 418 regs->tf_rip = p->p_sysent->sv_psstrings - sz_ia32_osigcode; 419 regs->tf_rflags &= ~(PSL_T | PSL_D); 420 regs->tf_cs = _ucode32sel; 421 regs->tf_ds = _udatasel; 422 regs->tf_es = _udatasel; 423 regs->tf_fs = _udatasel; 424 regs->tf_ss = _udatasel; 425 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 426 PROC_LOCK(p); 427 mtx_lock(&psp->ps_mtx); 428} 429#endif 430 431#ifdef COMPAT_FREEBSD4 432static void 433freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 434{ 435 struct ia32_sigframe4 sf, *sfp; 436 struct siginfo32 siginfo; 437 struct proc *p; 438 struct thread *td; 439 struct sigacts *psp; 440 struct trapframe *regs; 441 int oonstack; 442 int sig; 443 444 td = curthread; 445 p = td->td_proc; 446 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo); 447 448 PROC_LOCK_ASSERT(p, MA_OWNED); 449 sig = siginfo.si_signo; 450 psp = p->p_sigacts; 451 mtx_assert(&psp->ps_mtx, MA_OWNED); 452 regs = td->td_frame; 453 oonstack = sigonstack(regs->tf_rsp); 454 455 /* Save user context. */ 456 bzero(&sf, sizeof(sf)); 457 sf.sf_uc.uc_sigmask = *mask; 458 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 459 sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; 460 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 461 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 462 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 463 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 464 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 465 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 466 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 467 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 468 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 469 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 470 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 471 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 472 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 473 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 474 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 475 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 476 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 477 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 478 sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds; 479 sf.sf_uc.uc_mcontext.mc_es = regs->tf_es; 480 sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs; 481 sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs; 482 bzero(sf.sf_uc.uc_mcontext.mc_fpregs, 483 sizeof(sf.sf_uc.uc_mcontext.mc_fpregs)); 484 bzero(sf.sf_uc.uc_mcontext.__spare__, 485 sizeof(sf.sf_uc.uc_mcontext.__spare__)); 486 bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__)); 487 488 /* Allocate space for the signal handler context. */ 489 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 490 SIGISMEMBER(psp->ps_sigonstack, sig)) { 491 sfp = (struct ia32_sigframe4 *)(td->td_sigstk.ss_sp + 492 td->td_sigstk.ss_size - sizeof(sf)); 493 } else 494 sfp = (struct ia32_sigframe4 *)regs->tf_rsp - 1; 495 PROC_UNLOCK(p); 496 497 /* Build the argument list for the signal handler. */ 498 sf.sf_signum = sig; 499 sf.sf_ucontext = (register_t)&sfp->sf_uc; 500 bzero(&sf.sf_si, sizeof(sf.sf_si)); 501 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 502 /* Signal handler installed with SA_SIGINFO. */ 503 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 504 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 505 506 /* Fill in POSIX parts */ 507 sf.sf_si = siginfo; 508 sf.sf_si.si_signo = sig; 509 } else { 510 /* Old FreeBSD-style arguments. */ 511 sf.sf_siginfo = siginfo.si_code; 512 sf.sf_addr = (u_int32_t)siginfo.si_addr; 513 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 514 } 515 mtx_unlock(&psp->ps_mtx); 516 517 /* 518 * Copy the sigframe out to the user's stack. 519 */ 520 if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { 521#ifdef DEBUG 522 printf("process %ld has trashed its stack\n", (long)p->p_pid); 523#endif 524 PROC_LOCK(p); 525 sigexit(td, SIGILL); 526 } 527 528 regs->tf_rsp = (uintptr_t)sfp; 529 regs->tf_rip = p->p_sysent->sv_sigcode_base + sz_ia32_sigcode - 530 sz_freebsd4_ia32_sigcode; 531 regs->tf_rflags &= ~(PSL_T | PSL_D); 532 regs->tf_cs = _ucode32sel; 533 regs->tf_ss = _udatasel; 534 regs->tf_ds = _udatasel; 535 regs->tf_es = _udatasel; 536 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 537 /* leave user %fs and %gs untouched */ 538 PROC_LOCK(p); 539 mtx_lock(&psp->ps_mtx); 540} 541#endif /* COMPAT_FREEBSD4 */ 542 543void 544ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 545{ 546 struct ia32_sigframe sf, *sfp; 547 struct siginfo32 siginfo; 548 struct proc *p; 549 struct thread *td; 550 struct sigacts *psp; 551 char *sp; 552 struct trapframe *regs; 553 char *xfpusave; 554 size_t xfpusave_len; 555 int oonstack; 556 int sig; 557 558 siginfo_to_siginfo32(&ksi->ksi_info, &siginfo); 559 td = curthread; 560 p = td->td_proc; 561 PROC_LOCK_ASSERT(p, MA_OWNED); 562 sig = siginfo.si_signo; 563 psp = p->p_sigacts; 564#ifdef COMPAT_FREEBSD4 565 if (SIGISMEMBER(psp->ps_freebsd4, sig)) { 566 freebsd4_ia32_sendsig(catcher, ksi, mask); 567 return; 568 } 569#endif 570#ifdef COMPAT_43 571 if (SIGISMEMBER(psp->ps_osigset, sig)) { 572 ia32_osendsig(catcher, ksi, mask); 573 return; 574 } 575#endif 576 mtx_assert(&psp->ps_mtx, MA_OWNED); 577 regs = td->td_frame; 578 oonstack = sigonstack(regs->tf_rsp); 579 580 if (cpu_max_ext_state_size > sizeof(struct savefpu) && use_xsave) { 581 xfpusave_len = cpu_max_ext_state_size - sizeof(struct savefpu); 582 xfpusave = __builtin_alloca(xfpusave_len); 583 } else { 584 xfpusave_len = 0; 585 xfpusave = NULL; 586 } 587 588 /* Save user context. */ 589 bzero(&sf, sizeof(sf)); 590 sf.sf_uc.uc_sigmask = *mask; 591 sf.sf_uc.uc_stack.ss_sp = (uintptr_t)td->td_sigstk.ss_sp; 592 sf.sf_uc.uc_stack.ss_size = td->td_sigstk.ss_size; 593 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) 594 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; 595 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; 596 sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi; 597 sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi; 598 sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp; 599 sf.sf_uc.uc_mcontext.mc_isp = regs->tf_rsp; /* XXX */ 600 sf.sf_uc.uc_mcontext.mc_ebx = regs->tf_rbx; 601 sf.sf_uc.uc_mcontext.mc_edx = regs->tf_rdx; 602 sf.sf_uc.uc_mcontext.mc_ecx = regs->tf_rcx; 603 sf.sf_uc.uc_mcontext.mc_eax = regs->tf_rax; 604 sf.sf_uc.uc_mcontext.mc_trapno = regs->tf_trapno; 605 sf.sf_uc.uc_mcontext.mc_err = regs->tf_err; 606 sf.sf_uc.uc_mcontext.mc_eip = regs->tf_rip; 607 sf.sf_uc.uc_mcontext.mc_cs = regs->tf_cs; 608 sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags; 609 sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp; 610 sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss; 611 sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds; 612 sf.sf_uc.uc_mcontext.mc_es = regs->tf_es; 613 sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs; 614 sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs; 615 sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */ 616 ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext, xfpusave, xfpusave_len); 617 fpstate_drop(td); 618 sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase; 619 sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase; 620 bzero(sf.sf_uc.__spare__, sizeof(sf.sf_uc.__spare__)); 621 622 /* Allocate space for the signal handler context. */ 623 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack && 624 SIGISMEMBER(psp->ps_sigonstack, sig)) 625 sp = td->td_sigstk.ss_sp + td->td_sigstk.ss_size; 626 else 627 sp = (char *)regs->tf_rsp; 628 if (xfpusave != NULL) { 629 sp -= xfpusave_len; 630 sp = (char *)((unsigned long)sp & ~0x3Ful); 631 sf.sf_uc.uc_mcontext.mc_xfpustate = (register_t)sp; 632 } 633 sp -= sizeof(sf); 634 /* Align to 16 bytes. */ 635 sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF); 636 PROC_UNLOCK(p); 637 638 /* Build the argument list for the signal handler. */ 639 sf.sf_signum = sig; 640 sf.sf_ucontext = (register_t)&sfp->sf_uc; 641 bzero(&sf.sf_si, sizeof(sf.sf_si)); 642 if (SIGISMEMBER(psp->ps_siginfo, sig)) { 643 /* Signal handler installed with SA_SIGINFO. */ 644 sf.sf_siginfo = (u_int32_t)(uintptr_t)&sfp->sf_si; 645 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 646 647 /* Fill in POSIX parts */ 648 sf.sf_si = siginfo; 649 sf.sf_si.si_signo = sig; 650 } else { 651 /* Old FreeBSD-style arguments. */ 652 sf.sf_siginfo = siginfo.si_code; 653 sf.sf_addr = (u_int32_t)siginfo.si_addr; 654 sf.sf_ah = (u_int32_t)(uintptr_t)catcher; 655 } 656 mtx_unlock(&psp->ps_mtx); 657 658 /* 659 * Copy the sigframe out to the user's stack. 660 */ 661 if (copyout(&sf, sfp, sizeof(*sfp)) != 0 || 662 (xfpusave != NULL && copyout(xfpusave, 663 PTRIN(sf.sf_uc.uc_mcontext.mc_xfpustate), xfpusave_len) 664 != 0)) { 665#ifdef DEBUG 666 printf("process %ld has trashed its stack\n", (long)p->p_pid); 667#endif 668 PROC_LOCK(p); 669 sigexit(td, SIGILL); 670 } 671 672 regs->tf_rsp = (uintptr_t)sfp; 673 regs->tf_rip = p->p_sysent->sv_sigcode_base; 674 regs->tf_rflags &= ~(PSL_T | PSL_D); 675 regs->tf_cs = _ucode32sel; 676 regs->tf_ss = _udatasel; 677 regs->tf_ds = _udatasel; 678 regs->tf_es = _udatasel; 679 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 680 /* XXXKIB leave user %fs and %gs untouched */ 681 PROC_LOCK(p); 682 mtx_lock(&psp->ps_mtx); 683} 684 685/* 686 * System call to cleanup state after a signal 687 * has been taken. Reset signal mask and 688 * stack state from context left by sendsig (above). 689 * Return to previous pc and psl as specified by 690 * context left by sendsig. Check carefully to 691 * make sure that the user has not modified the 692 * state to gain improper privileges. 693 */ 694 695#ifdef COMPAT_43 696int 697ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap) 698{ 699 struct ia32_sigcontext3 sc, *scp; 700 struct trapframe *regs; 701 int eflags, error; 702 ksiginfo_t ksi; 703 704 regs = td->td_frame; 705 error = copyin(uap->sigcntxp, &sc, sizeof(sc)); 706 if (error != 0) 707 return (error); 708 scp = ≻ 709 eflags = scp->sc_eflags; 710 if (!EFL_SECURE(eflags, regs->tf_rflags)) { 711 return (EINVAL); 712 } 713 if (!CS_SECURE(scp->sc_cs)) { 714 ksiginfo_init_trap(&ksi); 715 ksi.ksi_signo = SIGBUS; 716 ksi.ksi_code = BUS_OBJERR; 717 ksi.ksi_trapno = T_PROTFLT; 718 ksi.ksi_addr = (void *)regs->tf_rip; 719 trapsignal(td, &ksi); 720 return (EINVAL); 721 } 722 regs->tf_ds = scp->sc_ds; 723 regs->tf_es = scp->sc_es; 724 regs->tf_fs = scp->sc_fs; 725 regs->tf_gs = scp->sc_gs; 726 727 regs->tf_rax = scp->sc_eax; 728 regs->tf_rbx = scp->sc_ebx; 729 regs->tf_rcx = scp->sc_ecx; 730 regs->tf_rdx = scp->sc_edx; 731 regs->tf_rsi = scp->sc_esi; 732 regs->tf_rdi = scp->sc_edi; 733 regs->tf_cs = scp->sc_cs; 734 regs->tf_ss = scp->sc_ss; 735 regs->tf_rbp = scp->sc_ebp; 736 regs->tf_rsp = scp->sc_esp; 737 regs->tf_rip = scp->sc_eip; 738 regs->tf_rflags = eflags; 739 740 if (scp->sc_onstack & 1) 741 td->td_sigstk.ss_flags |= SS_ONSTACK; 742 else 743 td->td_sigstk.ss_flags &= ~SS_ONSTACK; 744 745 kern_sigprocmask(td, SIG_SETMASK, (sigset_t *)&scp->sc_mask, NULL, 746 SIGPROCMASK_OLD); 747 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 748 return (EJUSTRETURN); 749} 750#endif 751 752#ifdef COMPAT_FREEBSD4 753/* 754 * MPSAFE 755 */ 756int 757freebsd4_freebsd32_sigreturn(td, uap) 758 struct thread *td; 759 struct freebsd4_freebsd32_sigreturn_args /* { 760 const struct freebsd4_freebsd32_ucontext *sigcntxp; 761 } */ *uap; 762{ 763 struct ia32_ucontext4 uc; 764 struct trapframe *regs; 765 struct ia32_ucontext4 *ucp; 766 int cs, eflags, error; 767 ksiginfo_t ksi; 768 769 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 770 if (error != 0) 771 return (error); 772 ucp = &uc; 773 regs = td->td_frame; 774 eflags = ucp->uc_mcontext.mc_eflags; 775 /* 776 * Don't allow users to change privileged or reserved flags. 777 */ 778 if (!EFL_SECURE(eflags, regs->tf_rflags)) { 779 uprintf("pid %d (%s): freebsd4_freebsd32_sigreturn eflags = 0x%x\n", 780 td->td_proc->p_pid, td->td_name, eflags); 781 return (EINVAL); 782 } 783 784 /* 785 * Don't allow users to load a valid privileged %cs. Let the 786 * hardware check for invalid selectors, excess privilege in 787 * other selectors, invalid %eip's and invalid %esp's. 788 */ 789 cs = ucp->uc_mcontext.mc_cs; 790 if (!CS_SECURE(cs)) { 791 uprintf("pid %d (%s): freebsd4_sigreturn cs = 0x%x\n", 792 td->td_proc->p_pid, td->td_name, cs); 793 ksiginfo_init_trap(&ksi); 794 ksi.ksi_signo = SIGBUS; 795 ksi.ksi_code = BUS_OBJERR; 796 ksi.ksi_trapno = T_PROTFLT; 797 ksi.ksi_addr = (void *)regs->tf_rip; 798 trapsignal(td, &ksi); 799 return (EINVAL); 800 } 801 802 regs->tf_rdi = ucp->uc_mcontext.mc_edi; 803 regs->tf_rsi = ucp->uc_mcontext.mc_esi; 804 regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 805 regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 806 regs->tf_rdx = ucp->uc_mcontext.mc_edx; 807 regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 808 regs->tf_rax = ucp->uc_mcontext.mc_eax; 809 regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 810 regs->tf_err = ucp->uc_mcontext.mc_err; 811 regs->tf_rip = ucp->uc_mcontext.mc_eip; 812 regs->tf_cs = cs; 813 regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 814 regs->tf_rsp = ucp->uc_mcontext.mc_esp; 815 regs->tf_ss = ucp->uc_mcontext.mc_ss; 816 regs->tf_ds = ucp->uc_mcontext.mc_ds; 817 regs->tf_es = ucp->uc_mcontext.mc_es; 818 regs->tf_fs = ucp->uc_mcontext.mc_fs; 819 regs->tf_gs = ucp->uc_mcontext.mc_gs; 820 821 kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 822 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 823 return (EJUSTRETURN); 824} 825#endif /* COMPAT_FREEBSD4 */ 826 827/* 828 * MPSAFE 829 */ 830int 831freebsd32_sigreturn(td, uap) 832 struct thread *td; 833 struct freebsd32_sigreturn_args /* { 834 const struct freebsd32_ucontext *sigcntxp; 835 } */ *uap; 836{ 837 struct ia32_ucontext uc; 838 struct trapframe *regs; 839 struct ia32_ucontext *ucp; 840 char *xfpustate; 841 size_t xfpustate_len; 842 int cs, eflags, error, ret; 843 ksiginfo_t ksi; 844 845 error = copyin(uap->sigcntxp, &uc, sizeof(uc)); 846 if (error != 0) 847 return (error); 848 ucp = &uc; 849 regs = td->td_frame; 850 eflags = ucp->uc_mcontext.mc_eflags; 851 /* 852 * Don't allow users to change privileged or reserved flags. 853 */ 854 if (!EFL_SECURE(eflags, regs->tf_rflags)) { 855 uprintf("pid %d (%s): freebsd32_sigreturn eflags = 0x%x\n", 856 td->td_proc->p_pid, td->td_name, eflags); 857 return (EINVAL); 858 } 859 860 /* 861 * Don't allow users to load a valid privileged %cs. Let the 862 * hardware check for invalid selectors, excess privilege in 863 * other selectors, invalid %eip's and invalid %esp's. 864 */ 865 cs = ucp->uc_mcontext.mc_cs; 866 if (!CS_SECURE(cs)) { 867 uprintf("pid %d (%s): sigreturn cs = 0x%x\n", 868 td->td_proc->p_pid, td->td_name, cs); 869 ksiginfo_init_trap(&ksi); 870 ksi.ksi_signo = SIGBUS; 871 ksi.ksi_code = BUS_OBJERR; 872 ksi.ksi_trapno = T_PROTFLT; 873 ksi.ksi_addr = (void *)regs->tf_rip; 874 trapsignal(td, &ksi); 875 return (EINVAL); 876 } 877 878 if ((ucp->uc_mcontext.mc_flags & _MC_HASFPXSTATE) != 0) { 879 xfpustate_len = uc.uc_mcontext.mc_xfpustate_len; 880 if (xfpustate_len > cpu_max_ext_state_size - 881 sizeof(struct savefpu)) { 882 uprintf("pid %d (%s): sigreturn xfpusave_len = 0x%zx\n", 883 td->td_proc->p_pid, td->td_name, xfpustate_len); 884 return (EINVAL); 885 } 886 xfpustate = __builtin_alloca(xfpustate_len); 887 error = copyin(PTRIN(ucp->uc_mcontext.mc_xfpustate), 888 xfpustate, xfpustate_len); 889 if (error != 0) { 890 uprintf( 891 "pid %d (%s): sigreturn copying xfpustate failed\n", 892 td->td_proc->p_pid, td->td_name); 893 return (error); 894 } 895 } else { 896 xfpustate = NULL; 897 xfpustate_len = 0; 898 } 899 ret = ia32_set_fpcontext(td, &ucp->uc_mcontext, xfpustate, 900 xfpustate_len); 901 if (ret != 0) { 902 uprintf("pid %d (%s): sigreturn set_fpcontext err %d\n", 903 td->td_proc->p_pid, td->td_name, ret); 904 return (ret); 905 } 906 907 regs->tf_rdi = ucp->uc_mcontext.mc_edi; 908 regs->tf_rsi = ucp->uc_mcontext.mc_esi; 909 regs->tf_rbp = ucp->uc_mcontext.mc_ebp; 910 regs->tf_rbx = ucp->uc_mcontext.mc_ebx; 911 regs->tf_rdx = ucp->uc_mcontext.mc_edx; 912 regs->tf_rcx = ucp->uc_mcontext.mc_ecx; 913 regs->tf_rax = ucp->uc_mcontext.mc_eax; 914 regs->tf_trapno = ucp->uc_mcontext.mc_trapno; 915 regs->tf_err = ucp->uc_mcontext.mc_err; 916 regs->tf_rip = ucp->uc_mcontext.mc_eip; 917 regs->tf_cs = cs; 918 regs->tf_rflags = ucp->uc_mcontext.mc_eflags; 919 regs->tf_rsp = ucp->uc_mcontext.mc_esp; 920 regs->tf_ss = ucp->uc_mcontext.mc_ss; 921 regs->tf_ds = ucp->uc_mcontext.mc_ds; 922 regs->tf_es = ucp->uc_mcontext.mc_es; 923 regs->tf_fs = ucp->uc_mcontext.mc_fs; 924 regs->tf_gs = ucp->uc_mcontext.mc_gs; 925 regs->tf_flags = TF_HASSEGS; 926 927 kern_sigprocmask(td, SIG_SETMASK, &ucp->uc_sigmask, NULL, 0); 928 set_pcb_flags(td->td_pcb, PCB_FULL_IRET); 929 return (EJUSTRETURN); 930} 931 932/* 933 * Clear registers on exec 934 */ 935void 936ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 937{ 938 struct trapframe *regs = td->td_frame; 939 struct pcb *pcb = td->td_pcb; 940 941 mtx_lock(&dt_lock); 942 if (td->td_proc->p_md.md_ldt != NULL) 943 user_ldt_free(td); 944 else 945 mtx_unlock(&dt_lock); 946#ifdef COMPAT_43 947 setup_lcall_gate(); 948#endif 949 950 pcb->pcb_fsbase = 0; 951 pcb->pcb_gsbase = 0; 952 pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__; 953 954 bzero((char *)regs, sizeof(struct trapframe)); 955 regs->tf_rip = imgp->entry_addr; 956 regs->tf_rsp = stack; 957 regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); 958 regs->tf_ss = _udatasel; 959 regs->tf_cs = _ucode32sel; 960 regs->tf_rbx = imgp->ps_strings; 961 regs->tf_ds = _udatasel; 962 regs->tf_es = _udatasel; 963 regs->tf_fs = _ufssel; 964 regs->tf_gs = _ugssel; 965 regs->tf_flags = TF_HASSEGS; 966 967 fpstate_drop(td); 968 969 /* Return via doreti so that we can change to a different %cs */ 970 set_pcb_flags(pcb, PCB_32BIT | PCB_FULL_IRET); 971 td->td_retval[1] = 0; 972} 973