Print this page
manifest
@@ -25,11 +25,11 @@
/* 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
+ * Copyright 2023 Oxide Computer Company
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/vmparam.h>
@@ -237,128 +237,21 @@
* 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);
+ fpu_set_fpregset(lwp, fp);
}
/*
* 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();
+ bzero(fp, sizeof (*fp));
+ fpu_get_fpregset(lwp, fp);
}
#if defined(_SYSCALL32_IMPL)
/*
@@ -526,20 +419,26 @@
* 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()
+getuserpc(void)
{
greg_t upc = lwptoregs(ttolwp(curthread))->r_pc;
uint32_t insn;
if (curthread->t_sysnum == 0)