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)