Page MenuHomeFreeBSD

D47394.id147327.diff
No OneTemporary

D47394.id147327.diff

diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c
--- a/sys/amd64/amd64/fpu.c
+++ b/sys/amd64/amd64/fpu.c
@@ -1289,3 +1289,154 @@
bcopy(fpu_initialstate, fsa, cpu_max_ext_state_size);
}
+
+#define EXTSTATE_INFO_LEN (ilog2_const(XFEATURE_ENABLED_TILEDATA) + 1)
+struct extstate_info {
+ size_t offset;
+ size_t size;
+ uint64_t flags;
+};
+static struct extstate_info extstate_info[EXTSTATE_INFO_LEN] __read_mostly;
+static uint64_t extstate_extensions;
+static uint64_t extfeatures_user;
+static uint64_t extfeatures_supervisor;
+
+static void
+cpu_extstate_info_init(void *arg __unused)
+{
+ int i;
+ uint32_t regs[4];
+ struct extstate_info *fip;
+
+ if (!use_xsave)
+ return;
+
+ cpuid_count(0xd, 0, regs);
+ extfeatures_user = regs[0] | ((uint64_t)regs[3] << 32);
+
+ cpuid_count(0xd, 1, regs);
+ extstate_extensions = regs[0];
+ extfeatures_supervisor = regs[2] | ((uint64_t)regs[3] << 32);
+
+ for (i = 0; i < EXTSTATE_INFO_LEN; i++) {
+ fip = &extstate_info[i];
+ cpuid_count(0xd, i, regs);
+ fip->size = regs[0];
+ fip->flags = regs[2];
+ fip->offset = (fip->flags & CPUID_EXTSTATE_SUPERVISOR) ?
+ -1 : regs[1];
+ }
+}
+SYSINIT(extstate_info_init, SI_SUB_CPU, SI_ORDER_MIDDLE,
+ cpu_extstate_info_init, NULL);
+
+static __inline void
+cpu_extfeature_check(uint64_t feature)
+{
+
+ KASSERT((feature & (feature - 1)) == 0,
+ ("%s: invalid XFEATURE 0x%lx", __func__, feature));
+ KASSERT(feature <= XFEATURE_ENABLED_TILEDATA,
+ ("%s: unknown XFEATURE 0x%lx", __func__, feature));
+}
+
+static __inline void
+cpu_extstate_bv_check(uint64_t xstate_bv)
+{
+
+ KASSERT(xstate_bv != 0 &&
+ fls(xstate_bv) - 1 <= XFEATURE_ENABLED_TILEDATA,
+ ("%s: invalid XSTATE_BV 0x%lx", __func__, xstate_bv));
+}
+
+/*
+ * Returns whether the XFEATURE 'feature' is supported as a user state
+ * or supervisor state component.
+ *
+ * Always returns false if XSAVE is not supported.
+ */
+bool
+xsave_extfeature_supported(uint64_t feature, bool supervisor)
+{
+ KASSERT(use_xsave, ("%s: XSAVE not supported", __func__));
+
+ cpu_extfeature_check(feature);
+ if (supervisor)
+ return ((extfeatures_supervisor & feature) != 0);
+ return ((extfeatures_user & feature) != 0);
+}
+
+/*
+ * Returns whether the XFEATURE 'feature' is supported as a user state
+ * or supervisor state component.
+ *
+ * Always returns false if XSAVE is not supported.
+ */
+bool
+xsave_extension_supported(uint64_t extension)
+{
+ KASSERT(use_xsave, ("%s: XSAVE not supported", __func__));
+
+ return ((extstate_extensions & extension) != 0);
+}
+
+/*
+ * Returns offset for XFEATURE 'feature' given the requested feature bitmap
+ * 'xstate_bv', and extended region format ('compact').
+ *
+ * Returns -1 if XSAVE is not supported.
+ */
+size_t
+xsave_area_offset(uint64_t xstate_bv, uint64_t feature,
+ bool compact)
+{
+ int i, idx;
+ size_t offs;
+ struct extstate_info *xip;
+
+ KASSERT(use_xsave, ("%s: XSAVE not supported", __func__));
+
+ cpu_extstate_bv_check(xstate_bv);
+ cpu_extfeature_check(feature);
+ idx = ilog2_const(feature);
+
+ if (!compact)
+ return (extstate_info[idx].offset);
+ offs = sizeof(struct savefpu) + sizeof(struct xstate_hdr);
+ xstate_bv &= ~(XFEATURE_ENABLED_X87 | XFEATURE_ENABLED_SSE);
+ while ((i = ffs(xstate_bv) - 1) > 0 && i < idx) {
+ xip = &extstate_info[i];
+ if (xip->flags & CPUID_EXTSTATE_ALIGNED)
+ offs = roundup2(offs, 64);
+ offs += xip->size;
+ xstate_bv &= ~(1 << i);
+ }
+
+ return (offs);
+}
+
+/*
+ * Returns the XSAVE area size for the requested feature bitmap
+ * 'xstate_bv' and extended region format ('compact').
+ *
+ * Returns 0 if XSAVE is not supported.
+ */
+size_t
+xsave_area_size(uint64_t xstate_bv, bool compact)
+{
+ int last_idx;
+
+ KASSERT(use_xsave, ("%s: XSAVE not supported", __func__));
+
+ cpu_extstate_bv_check(xstate_bv);
+ last_idx = fls(xstate_bv) - 1;
+
+ return (xsave_area_offset(xstate_bv, 1 << last_idx, compact) +
+ extstate_info[last_idx].size);
+}
+
+size_t
+xsave_area_hdr_offset(void)
+{
+ return (sizeof(struct savefpu));
+}
diff --git a/sys/x86/include/fpu.h b/sys/x86/include/fpu.h
--- a/sys/x86/include/fpu.h
+++ b/sys/x86/include/fpu.h
@@ -233,6 +233,12 @@
*/
#define fpu_enable() clts()
#define fpu_disable() load_cr0(rcr0() | CR0_TS)
+
+bool xsave_extfeature_supported(uint64_t feature, bool supervisor);
+bool xsave_extension_supported(uint64_t extension);
+size_t xsave_area_hdr_offset(void);
+size_t xsave_area_offset(uint64_t xstate_bv, uint64_t feature, bool compact);
+size_t xsave_area_size(uint64_t xstate_bv, bool compact);
#endif
#endif /* !_X86_FPU_H_ */

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 2, 4:40 PM (1 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28415078
Default Alt Text
D47394.id147327.diff (4 KB)

Event Timeline