CET Shadow Stack(SHSTK) and Indirect Branch Tracking(IBT) are enumerated via CPUID.(EAX=07H,ECX=0H):ECX[bit 7] and EDX[bit 20] respectively. Two CET bits (bit 11 and 12) are defined in MSR_IA32_XSS for XSAVES. They correspond to CET states in user and supervisor mode respectively. Signed-off-by: Yang Weijiang <weijiang.yang@xxxxxxxxx> --- target/i386/cpu.c | 35 +++++++++++++++++++++++++++++++++++ target/i386/cpu.h | 23 ++++++++++++++++++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index f3923988ed..ef786b920e 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1060,6 +1060,16 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { }, [FEAT_XSAVE_XSS_LO] = { .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "cet-u", + "cet-s", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, .cpuid = { .eax = 0xD, .needs_ecx = true, @@ -1486,6 +1496,14 @@ static const ExtSaveArea x86_ext_save_areas[] = { { .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU, .offset = offsetof(X86XSaveArea, pkru_state), .size = sizeof(XSavePKRU) }, + [XSTATE_CET_U_BIT] = { + .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_CET_SHSTK, + .offset = 0, + .size = sizeof(XSavesCETU) }, + [XSTATE_CET_S_BIT] = { + .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_CET_SHSTK, + .offset = 0, + .size = sizeof(XSavesCETS) }, }; static uint32_t xsave_area_size(uint64_t mask) @@ -6329,6 +6347,23 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu) if (env->features[esa->feature] & esa->bits) { mask |= (1ULL << i); } + + /* + * Both CET SHSTK and IBT feature requires XSAVES support, but two + * features can be controlled independently by kernel, and we only + * have one correlated bit set in x86_ext_save_areas, so if either + * of two features is enabled, we set the XSAVES support bit to make + * the enabled feature work. + */ + if (i == XSTATE_CET_U_BIT || i == XSTATE_CET_S_BIT) { + uint64_t ecx = env->features[FEAT_7_0_ECX]; + uint64_t edx = env->features[FEAT_7_0_EDX]; + + if ((ecx & CPUID_7_0_ECX_CET_SHSTK) || + (edx & CPUID_7_0_EDX_CET_IBT)) { + mask |= (1ULL << i); + } + } } env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK; diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 8aeaa8869a..a43fb6d597 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -493,6 +493,8 @@ typedef enum X86Seg { #define XSTATE_ZMM_Hi256_BIT 6 #define XSTATE_Hi16_ZMM_BIT 7 #define XSTATE_PKRU_BIT 9 +#define XSTATE_CET_U_BIT 11 +#define XSTATE_CET_S_BIT 12 #define XSTATE_FP_MASK (1ULL << XSTATE_FP_BIT) #define XSTATE_SSE_MASK (1ULL << XSTATE_SSE_BIT) @@ -503,6 +505,8 @@ typedef enum X86Seg { #define XSTATE_ZMM_Hi256_MASK (1ULL << XSTATE_ZMM_Hi256_BIT) #define XSTATE_Hi16_ZMM_MASK (1ULL << XSTATE_Hi16_ZMM_BIT) #define XSTATE_PKRU_MASK (1ULL << XSTATE_PKRU_BIT) +#define XSTATE_CET_U_MASK (1ULL << XSTATE_CET_U_BIT) +#define XSTATE_CET_S_MASK (1ULL << XSTATE_CET_S_BIT) /* CPUID feature bits available in XCR0 */ #define CPUID_XSTATE_XCR0_MASK (XSTATE_FP_MASK | XSTATE_SSE_MASK | \ @@ -512,7 +516,7 @@ typedef enum X86Seg { XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK) /* CPUID feature bits available in XSS */ -#define CPUID_XSTATE_XSS_MASK 0 +#define CPUID_XSTATE_XSS_MASK (XSTATE_CET_U_MASK) /* CPUID feature words */ typedef enum FeatureWord { @@ -760,6 +764,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; #define CPUID_7_0_ECX_WAITPKG (1U << 5) /* Additional AVX-512 Vector Byte Manipulation Instruction */ #define CPUID_7_0_ECX_AVX512_VBMI2 (1U << 6) +/* CET SHSTK feature */ +#define CPUID_7_0_ECX_CET_SHSTK (1U << 7) /* Galois Field New Instructions */ #define CPUID_7_0_ECX_GFNI (1U << 8) /* Vector AES Instructions */ @@ -795,6 +801,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; #define CPUID_7_0_EDX_SERIALIZE (1U << 14) /* TSX Suspend Load Address Tracking instruction */ #define CPUID_7_0_EDX_TSX_LDTRK (1U << 16) +/* CET IBT feature */ +#define CPUID_7_0_EDX_CET_IBT (1U << 20) /* Speculation Control */ #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Single Thread Indirect Branch Predictors */ @@ -1285,6 +1293,19 @@ typedef struct XSavePKRU { uint32_t padding; } XSavePKRU; +/* Ext. save area 11: User mode CET state */ +typedef struct XSavesCETU { + uint64_t u_cet; + uint64_t user_ssp; +} XSavesCETU; + +/* Ext. save area 12: Supervisor mode CET state */ +typedef struct XSavesCETS { + uint64_t kernel_ssp; + uint64_t pl1_ssp; + uint64_t pl2_ssp; +} XSavesCETS; + typedef struct X86XSaveArea { X86LegacyXSaveArea legacy; X86XSaveHeader header; -- 2.26.2