Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143897960
D47394.id147327.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D47394.id147327.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D47394: x86: Add routines for querying XSAVE feature information
Attached
Detach File
Event Timeline
Log In to Comment