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)