Page MenuHomeFreeBSD

D47394.diff
No OneTemporary

D47394.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
@@ -164,12 +164,14 @@
int use_xsave; /* non-static for cpu_switch.S */
uint64_t xsave_mask; /* the same */
+static uint64_t xsave_extensions;
static uma_zone_t fpu_save_area_zone;
static struct savefpu *fpu_initialstate;
static struct xsave_area_elm_descr {
u_int offset;
u_int size;
+ u_int flags;
} *xsave_area_desc;
static void
@@ -452,6 +454,9 @@
* Region of an XSAVE Area" for the source of offsets/sizes.
*/
if (use_xsave) {
+ cpuid_count(0xd, 1, cp);
+ xsave_extensions = cp[0];
+
xstate_bv = (uint64_t *)((char *)(fpu_initialstate + 1) +
offsetof(struct xstate_hdr, xstate_bv));
*xstate_bv = XFEATURE_ENABLED_X87 | XFEATURE_ENABLED_SSE;
@@ -465,8 +470,9 @@
for (i = 2; i < max_ext_n; i++) {
cpuid_count(0xd, i, cp);
- xsave_area_desc[i].offset = cp[1];
xsave_area_desc[i].size = cp[0];
+ xsave_area_desc[i].offset = cp[1];
+ xsave_area_desc[i].flags = cp[2];
}
}
@@ -1285,3 +1291,106 @@
bcopy(fpu_initialstate, fsa, cpu_max_ext_state_size);
}
+
+static __inline void
+xsave_extfeature_check(uint64_t feature)
+{
+
+ KASSERT((feature & (feature - 1)) == 0,
+ ("%s: invalid XFEATURE 0x%lx", __func__, feature));
+ KASSERT(feature < flsl(xsave_mask),
+ ("%s: unsupported XFEATURE 0x%lx", __func__, feature));
+}
+
+static __inline void
+xsave_extstate_bv_check(uint64_t xstate_bv)
+{
+ KASSERT(xstate_bv != 0 && ilog2(xstate_bv) < flsl(xsave_mask),
+ ("%s: invalid XSTATE_BV 0x%lx", __func__, xstate_bv));
+}
+
+/*
+ * Returns whether the XFEATURE 'feature' is supported as a user state
+ * or supervisor state component.
+ */
+bool
+xsave_extfeature_supported(uint64_t feature, bool supervisor)
+{
+ int idx;
+
+ KASSERT(use_xsave, ("%s: XSAVE not supported", __func__));
+ xsave_extfeature_check(feature);
+
+ if ((xsave_mask & feature) == 0)
+ return (false);
+ idx = ilog2(feature);
+ return (((xsave_area_desc[idx].flags & CPUID_EXTSTATE_SUPERVISOR) != 0) ==
+ supervisor);
+}
+
+/*
+ * Returns whether the given XSAVE extension is supported.
+ */
+bool
+xsave_extension_supported(uint64_t extension)
+{
+ KASSERT(use_xsave, ("%s: XSAVE not supported", __func__));
+
+ return ((xsave_extensions & extension) != 0);
+}
+
+/*
+ * Returns offset for XFEATURE 'feature' given the requested feature bitmap
+ * 'xstate_bv', and extended region format ('compact').
+ */
+size_t
+xsave_area_offset(uint64_t xstate_bv, uint64_t feature,
+ bool compact)
+{
+ int i, idx;
+ size_t offs;
+ struct xsave_area_elm_descr *xep;
+
+ KASSERT(use_xsave, ("%s: XSAVE not supported", __func__));
+ xsave_extstate_bv_check(xstate_bv);
+ xsave_extfeature_check(feature);
+
+ idx = ilog2(feature);
+ if (!compact)
+ return (xsave_area_desc[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) {
+ xep = &xsave_area_desc[i];
+ if ((xep->flags & CPUID_EXTSTATE_ALIGNED) != 0)
+ offs = roundup2(offs, 64);
+ offs += xep->size;
+ xstate_bv &= ~((uint64_t)1 << i);
+ }
+
+ return (offs);
+}
+
+/*
+ * Returns the XSAVE area size for the requested feature bitmap
+ * 'xstate_bv' and extended region format ('compact').
+ */
+size_t
+xsave_area_size(uint64_t xstate_bv, bool compact)
+{
+ int last_idx;
+
+ KASSERT(use_xsave, ("%s: XSAVE not supported", __func__));
+ xsave_extstate_bv_check(xstate_bv);
+
+ last_idx = ilog2(xstate_bv);
+
+ return (xsave_area_offset(xstate_bv, (uint64_t)1 << last_idx, compact) +
+ xsave_area_desc[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
@@ -218,6 +218,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
Thu, Dec 26, 6:41 AM (11 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15602168
Default Alt Text
D47394.diff (4 KB)

Event Timeline