git: b9951017bab3 - main - amd64/fpu: Track supervisor state XSAVE components
Date: Wed, 22 Jan 2025 12:59:12 UTC
The branch main has been updated by bnovkov: URL: https://cgit.FreeBSD.org/src/commit/?id=b9951017bab396e24042e85632e2cc34ee0329ff commit b9951017bab396e24042e85632e2cc34ee0329ff Author: Bojan Novković <bnovkov@FreeBSD.org> AuthorDate: 2025-01-15 16:41:24 +0000 Commit: Bojan Novković <bnovkov@FreeBSD.org> CommitDate: 2025-01-22 12:58:34 +0000 amd64/fpu: Track supervisor state XSAVE components The amd64/fpu.c xsave_* routines track supported XSAVE components and features. However, they only track supported user state components, and there is currently no way for a consumer to check whether the CPU supports a supervisor state component. Fix this by saving the supported supervisor state components, enumerated by CPUID function 0DH, sub-function 1, in a separate mask. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D48466 --- sys/amd64/amd64/fpu.c | 38 ++++++++++++++++++++++++-------------- sys/x86/include/fpu.h | 5 +++-- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c index 591bd196ca7d..79d1722268b7 100644 --- a/sys/amd64/amd64/fpu.c +++ b/sys/amd64/amd64/fpu.c @@ -164,6 +164,7 @@ SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD, int use_xsave; /* non-static for cpu_switch.S */ uint64_t xsave_mask; /* the same */ +static uint64_t xsave_mask_supervisor; static uint64_t xsave_extensions; static uma_zone_t fpu_save_area_zone; static struct savefpu *fpu_initialstate; @@ -324,6 +325,7 @@ fpuinit_bsp1(void) ctx_switch_xsave[3] |= 0x10; restore_wp(old_wp); } + xsave_mask_supervisor = ((uint64_t)cp[3] << 32) | cp[2]; } /* @@ -421,7 +423,7 @@ fpuinitstate(void *arg __unused) XSAVE_AREA_ALIGN - 1, 0); fpu_initialstate = uma_zalloc(fpu_save_area_zone, M_WAITOK | M_ZERO); if (use_xsave) { - max_ext_n = flsl(xsave_mask); + max_ext_n = flsl(xsave_mask | xsave_mask_supervisor); xsave_area_desc = malloc(max_ext_n * sizeof(struct xsave_area_elm_descr), M_DEVBUF, M_WAITOK | M_ZERO); } @@ -1293,19 +1295,25 @@ fpu_save_area_reset(struct savefpu *fsa) } static __inline void -xsave_extfeature_check(uint64_t feature) +xsave_extfeature_check(uint64_t feature, bool supervisor) { + uint64_t mask; + mask = supervisor ? xsave_mask_supervisor : xsave_mask; KASSERT((feature & (feature - 1)) == 0, ("%s: invalid XFEATURE 0x%lx", __func__, feature)); - KASSERT(feature < flsl(xsave_mask), - ("%s: unsupported XFEATURE 0x%lx", __func__, feature)); + KASSERT(ilog2(feature) <= ilog2(mask), + ("%s: unsupported %s XFEATURE 0x%lx", __func__, + supervisor ? "supervisor" : "user", feature)); } static __inline void -xsave_extstate_bv_check(uint64_t xstate_bv) +xsave_extstate_bv_check(uint64_t xstate_bv, bool supervisor) { - KASSERT(xstate_bv != 0 && ilog2(xstate_bv) < flsl(xsave_mask), + uint64_t mask; + + mask = supervisor ? xsave_mask_supervisor : xsave_mask; + KASSERT(xstate_bv != 0 && ilog2(xstate_bv) <= ilog2(mask), ("%s: invalid XSTATE_BV 0x%lx", __func__, xstate_bv)); } @@ -1317,11 +1325,13 @@ bool xsave_extfeature_supported(uint64_t feature, bool supervisor) { int idx; + uint64_t mask; KASSERT(use_xsave, ("%s: XSAVE not supported", __func__)); - xsave_extfeature_check(feature); + xsave_extfeature_check(feature, supervisor); - if ((xsave_mask & feature) == 0) + mask = supervisor ? xsave_mask_supervisor : xsave_mask; + if ((mask & feature) == 0) return (false); idx = ilog2(feature); return (((xsave_area_desc[idx].flags & CPUID_EXTSTATE_SUPERVISOR) != 0) == @@ -1345,15 +1355,15 @@ xsave_extension_supported(uint64_t extension) */ size_t xsave_area_offset(uint64_t xstate_bv, uint64_t feature, - bool compact) + bool compact, bool supervisor) { 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); + xsave_extstate_bv_check(xstate_bv, supervisor); + xsave_extfeature_check(feature, supervisor); idx = ilog2(feature); if (!compact) @@ -1376,16 +1386,16 @@ xsave_area_offset(uint64_t xstate_bv, uint64_t feature, * 'xstate_bv' and extended region format ('compact'). */ size_t -xsave_area_size(uint64_t xstate_bv, bool compact) +xsave_area_size(uint64_t xstate_bv, bool compact, bool supervisor) { int last_idx; KASSERT(use_xsave, ("%s: XSAVE not supported", __func__)); - xsave_extstate_bv_check(xstate_bv); + xsave_extstate_bv_check(xstate_bv, supervisor); last_idx = ilog2(xstate_bv); - return (xsave_area_offset(xstate_bv, (uint64_t)1 << last_idx, compact) + + return (xsave_area_offset(xstate_bv, (uint64_t)1 << last_idx, compact, supervisor) + xsave_area_desc[last_idx].size); } diff --git a/sys/x86/include/fpu.h b/sys/x86/include/fpu.h index 9d2e43f6386e..c94e058498f6 100644 --- a/sys/x86/include/fpu.h +++ b/sys/x86/include/fpu.h @@ -222,8 +222,9 @@ struct savefpu_ymm { 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); +size_t xsave_area_offset(uint64_t xstate_bv, uint64_t feature, bool compact, + bool supervisor); +size_t xsave_area_size(uint64_t xstate_bv, bool compact, bool supervisor); #endif #endif /* !_X86_FPU_H_ */