Print this page
manifest

*** 25,35 **** /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Copyright (c) 2018, Joyent, Inc. * Copyright 2012 Nexenta Systems, Inc. All rights reserved. ! * Copyright 2022 Oxide Computer Company */ #include <sys/param.h> #include <sys/types.h> #include <sys/vmparam.h> --- 25,35 ---- /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Copyright (c) 2018, Joyent, Inc. * Copyright 2012 Nexenta Systems, Inc. All rights reserved. ! * Copyright 2023 Oxide Computer Company */ #include <sys/param.h> #include <sys/types.h> #include <sys/vmparam.h>
*** 237,364 **** * Set floating-point registers from a native fpregset_t. */ void setfpregs(klwp_t *lwp, fpregset_t *fp) { ! struct fpu_ctx *fpu = &lwp->lwp_pcb.pcb_fpu; ! ! if (fpu->fpu_flags & FPU_EN) { ! if (!(fpu->fpu_flags & FPU_VALID)) { ! /* ! * FPU context is still active, release the ! * ownership. ! */ ! fp_free(fpu); ! } ! } ! /* ! * Else: if we are trying to change the FPU state of a thread which ! * hasn't yet initialized floating point, store the state in ! * the pcb and indicate that the state is valid. When the ! * thread enables floating point, it will use this state instead ! * of the default state. ! */ ! ! switch (fp_save_mech) { ! case FP_FXSAVE: ! fpregset_to_fxsave(fp, fpu->fpu_regs.kfpu_u.kfpu_fx); ! fpu->fpu_regs.kfpu_xstatus = ! fp->fp_reg_set.fpchip_state.xstatus; ! break; ! ! case FP_XSAVE: ! fpregset_to_fxsave(fp, ! &fpu->fpu_regs.kfpu_u.kfpu_xs->xs_fxsave); ! fpu->fpu_regs.kfpu_xstatus = ! fp->fp_reg_set.fpchip_state.xstatus; ! fpu->fpu_regs.kfpu_u.kfpu_xs->xs_header.xsh_xstate_bv |= ! (XFEATURE_LEGACY_FP | XFEATURE_SSE); ! break; ! default: ! panic("Invalid fp_save_mech"); ! /*NOTREACHED*/ ! } ! ! fpu->fpu_regs.kfpu_status = fp->fp_reg_set.fpchip_state.status; ! fpu->fpu_flags |= FPU_VALID; ! PCB_SET_UPDATE_FPU(&lwp->lwp_pcb); } /* * Get floating-point registers into a native fpregset_t. */ void getfpregs(klwp_t *lwp, fpregset_t *fp) { ! struct fpu_ctx *fpu = &lwp->lwp_pcb.pcb_fpu; ! ! kpreempt_disable(); ! if (fpu->fpu_flags & FPU_EN) { ! /* ! * If we have FPU hw and the thread's pcb doesn't have ! * a valid FPU state then get the state from the hw. ! */ ! if (fpu_exists && ttolwp(curthread) == lwp && ! !(fpu->fpu_flags & FPU_VALID)) ! fp_save(fpu); /* get the current FPU state */ ! } ! ! /* ! * There are 3 possible cases we have to be aware of here: ! * ! * 1. FPU is enabled. FPU state is stored in the current LWP. ! * ! * 2. FPU is not enabled, and there have been no intervening /proc ! * modifications. Return initial FPU state. ! * ! * 3. FPU is not enabled, but a /proc consumer has modified FPU state. ! * FPU state is stored in the current LWP. ! */ ! if ((fpu->fpu_flags & FPU_EN) || (fpu->fpu_flags & FPU_VALID)) { ! /* ! * Cases 1 and 3. ! */ ! switch (fp_save_mech) { ! case FP_FXSAVE: ! fxsave_to_fpregset(fpu->fpu_regs.kfpu_u.kfpu_fx, fp); ! fp->fp_reg_set.fpchip_state.xstatus = ! fpu->fpu_regs.kfpu_xstatus; ! break; ! case FP_XSAVE: ! fxsave_to_fpregset( ! &fpu->fpu_regs.kfpu_u.kfpu_xs->xs_fxsave, fp); ! fp->fp_reg_set.fpchip_state.xstatus = ! fpu->fpu_regs.kfpu_xstatus; ! break; ! default: ! panic("Invalid fp_save_mech"); ! /*NOTREACHED*/ ! } ! fp->fp_reg_set.fpchip_state.status = fpu->fpu_regs.kfpu_status; ! } else { ! /* ! * Case 2. ! */ ! switch (fp_save_mech) { ! case FP_FXSAVE: ! case FP_XSAVE: ! /* ! * For now, we don't have any AVX specific field in ABI. ! * If we add any in the future, we need to initial them ! * as well. ! */ ! fxsave_to_fpregset(&sse_initial, fp); ! fp->fp_reg_set.fpchip_state.xstatus = ! fpu->fpu_regs.kfpu_xstatus; ! break; ! default: ! panic("Invalid fp_save_mech"); ! /*NOTREACHED*/ ! } ! fp->fp_reg_set.fpchip_state.status = fpu->fpu_regs.kfpu_status; ! } ! kpreempt_enable(); } #if defined(_SYSCALL32_IMPL) /* --- 237,257 ---- * Set floating-point registers from a native fpregset_t. */ void setfpregs(klwp_t *lwp, fpregset_t *fp) { ! fpu_set_fpregset(lwp, fp); } /* * Get floating-point registers into a native fpregset_t. */ void getfpregs(klwp_t *lwp, fpregset_t *fp) { ! bzero(fp, sizeof (*fp)); ! fpu_get_fpregset(lwp, fp); } #if defined(_SYSCALL32_IMPL) /*
*** 526,545 **** * Copy the brand-private data: */ dst->uc_brand_data[0] = (void *)(uintptr_t)src->uc_brand_data[0]; dst->uc_brand_data[1] = (void *)(uintptr_t)src->uc_brand_data[1]; dst->uc_brand_data[2] = (void *)(uintptr_t)src->uc_brand_data[2]; } #endif /* _SYSCALL32_IMPL */ /* * Return the user-level PC. * If in a system call, return the address of the syscall trap. */ greg_t ! getuserpc() { greg_t upc = lwptoregs(ttolwp(curthread))->r_pc; uint32_t insn; if (curthread->t_sysnum == 0) --- 419,444 ---- * Copy the brand-private data: */ dst->uc_brand_data[0] = (void *)(uintptr_t)src->uc_brand_data[0]; dst->uc_brand_data[1] = (void *)(uintptr_t)src->uc_brand_data[1]; dst->uc_brand_data[2] = (void *)(uintptr_t)src->uc_brand_data[2]; + + if (src->uc_flags & UC_XSAVE) { + dst->uc_xsave = (long)(uint32_t)src->uc_xsave; + } else { + dst->uc_xsave = 0; + } } #endif /* _SYSCALL32_IMPL */ /* * Return the user-level PC. * If in a system call, return the address of the syscall trap. */ greg_t ! getuserpc(void) { greg_t upc = lwptoregs(ttolwp(curthread))->r_pc; uint32_t insn; if (curthread->t_sysnum == 0)