Supervisor state should be skipped b/c there is no slot in standard format XSAVE buffer for it. CET State is being migrated via MSRs and other supervisor state isn't currently migrated.
Fixes: 8612deb3f4 Signed-off-by: Magnus Kulke <[email protected]> --- target/i386/cpu.h | 2 ++ target/i386/xsave_helper.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index e6a197602d..fff701c6c4 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -655,9 +655,11 @@ typedef enum X86Seg { #define XSTATE_DYNAMIC_MASK (XSTATE_XTILE_DATA_MASK) +#define ESA_FEATURE_XSS_BIT 0 #define ESA_FEATURE_ALIGN64_BIT 1 #define ESA_FEATURE_XFD_BIT 2 +#define ESA_FEATURE_XSS_MASK (1U << ESA_FEATURE_XSS_BIT) #define ESA_FEATURE_ALIGN64_MASK (1U << ESA_FEATURE_ALIGN64_BIT) #define ESA_FEATURE_XFD_MASK (1U << ESA_FEATURE_XFD_BIT) diff --git a/target/i386/xsave_helper.c b/target/i386/xsave_helper.c index 625bae103a..1fa3133b1a 100644 --- a/target/i386/xsave_helper.c +++ b/target/i386/xsave_helper.c @@ -332,7 +332,7 @@ int decompact_xsave_area(const void *buf, size_t buflen, CPUX86State *env) size_t i; uint32_t eax, ebx, ecx, edx; uint32_t size, dst_off; - bool align64; + bool align64, supervisor; uint64_t guest_xcr0, *xstate_bv; compacted_xstate_bv = *(uint64_t *)(buf + XSAVE_XSTATE_BV_OFFSET); @@ -383,6 +383,7 @@ int decompact_xsave_area(const void *buf, size_t buflen, CPUX86State *env) size = eax; dst_off = ebx; align64 = (ecx & (1u << 1)) != 0; + supervisor = (ecx & ESA_FEATURE_XSS_MASK) != 0; /* Component is in the layout but unknown to the guest CPUID model */ if (size == 0) { @@ -433,8 +434,14 @@ int decompact_xsave_area(const void *buf, size_t buflen, CPUX86State *env) return -E2BIG; } - /* Copy components marked present in XSTATE_BV to guest model */ - if (((compacted_xstate_bv >> i) & 1) != 0) { + /* + * Copy components marked present in XSTATE_BV to guest model. + * + * NB: Supervisor state is skipped b/c there is no slot in the + * standard format XSAVE buffer (CET state is migrated via MSRs, + * others supervisor state isn't migrated). + */ + if (((compacted_xstate_bv >> i) & 1) != 0 && !supervisor) { memcpy(env->xsave_buf + dst_off, buf + xsave_offset, size); } -- 2.34.1
