From 780f431a9731a3c0dd91114166d801e8de0c284d Mon Sep 17 00:00:00 2001 From: Oliver Anderson Date: Tue, 24 Mar 2026 16:20:17 +0100 Subject: [PATCH 1/8] arch: Disable HDC state components for CPU profiles Hardware duty cycling (HDC) does not make sense in the virtualization setting and should thus not be displayed as available to guests. We have already disabled certain HDC aspects via CPUID 0x6 ECX[13], but we forgot to disable the state components which is what we do in this commit. Signed-off-by: Oliver Anderson On-behalf-of: SAP oliver.anderson@sap.com --- .../cpu_profiles/sapphire-rapids.cpuid.json | 16 ++++- .../x86_64/cpu_profiles/skylake.cpuid.json | 14 +++++ arch/src/x86_64/cpuid_definitions/intel.rs | 60 +++++++++---------- 3 files changed, 59 insertions(+), 31 deletions(-) diff --git a/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json b/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json index b3389bf947..2f8ce47814 100644 --- a/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json +++ b/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json @@ -1542,6 +1542,20 @@ "mask": "0x00000000" } ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0xd", + "end": "0xd" + }, + "register": "EDX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], [ { "leaf": "0xd", @@ -3251,4 +3265,4 @@ } ] ] -} \ No newline at end of file +} diff --git a/arch/src/x86_64/cpu_profiles/skylake.cpuid.json b/arch/src/x86_64/cpu_profiles/skylake.cpuid.json index 48c3f94ccd..9aaa83a1de 100644 --- a/arch/src/x86_64/cpu_profiles/skylake.cpuid.json +++ b/arch/src/x86_64/cpu_profiles/skylake.cpuid.json @@ -1542,6 +1542,20 @@ "mask": "0x00000000" } ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0xd", + "end": "0xd" + }, + "register": "EDX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], [ { "leaf": "0xd", diff --git a/arch/src/x86_64/cpuid_definitions/intel.rs b/arch/src/x86_64/cpuid_definitions/intel.rs index ee944bbf9d..7c173b9c16 100644 --- a/arch/src/x86_64/cpuid_definitions/intel.rs +++ b/arch/src/x86_64/cpuid_definitions/intel.rs @@ -39,7 +39,7 @@ use super::{ /// a few of the short names and descriptions to be more inline with what is written in the /// aforementioned Intel manual. Finally we decided on a [`ProfilePolicy`] to be set for every /// single [`ValueDefinition`] and manually appended those. -pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<167> = const { +pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<168> = const { CpuidDefinitions([ // ========================================================================================= // Basic CPUID Information @@ -2409,10 +2409,10 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<167> = const { policy: ProfilePolicy::Static(0), }, ValueDefinition { - short: "xcr0_ia32_xss_bits", + short: "xcr0_ia32_xss_hdc", description: "XCR0.IA32_XSS (bit 13) used for IA32_XSS", bits_range: (13, 13), - policy: ProfilePolicy::Inherit, + policy: ProfilePolicy::Static(0), }, ValueDefinition { short: "xcr0_ia32_xss_UINTR", @@ -2592,7 +2592,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<167> = const { short: "xss_hdc", description: "HDC state, supported", bits_range: (13, 13), - policy: ProfilePolicy::Inherit, + policy: ProfilePolicy::Static(0), }, ValueDefinition { short: "xss_uintr", @@ -2855,6 +2855,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<167> = const { policy: ProfilePolicy::Static(0), }]), ), + // Disable HDC for CPU profiles ( Parameters { leaf: 0xd, @@ -2862,10 +2863,10 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<167> = const { register: CpuidReg::EAX, }, ValueDefinitions::new(&[ValueDefinition { - short: "xsave_sz", - description: "Size of save area for subleaf-N feature, in bytes", + short: "0xd-13-eax-edc-zero", + description: "This leaf has been zeroed out because CET state components are disabled", bits_range: (0, 31), - policy: ProfilePolicy::Inherit, + policy: ProfilePolicy::Static(0), }]), ), ( @@ -2875,10 +2876,10 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<167> = const { register: CpuidReg::EBX, }, ValueDefinitions::new(&[ValueDefinition { - short: "xsave_offset", - description: "Offset of save area for subleaf-N feature, in bytes", + short: "0xd-13-ebx-hdc-zero", + description: "This leaf has been zeroed out because CET state components are disabled", bits_range: (0, 31), - policy: ProfilePolicy::Inherit, + policy: ProfilePolicy::Static(0), }]), ), ( @@ -2887,26 +2888,25 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<167> = const { sub_leaf: RangeInclusive::new(13, 13), register: CpuidReg::ECX, }, - ValueDefinitions::new(&[ - ValueDefinition { - short: "is_xss_bit", - description: "Subleaf N describes an XSS bit, otherwise XCR0 bit", - bits_range: (0, 0), - policy: ProfilePolicy::Inherit, - }, - ValueDefinition { - short: "compacted_xsave_64byte_aligned", - description: "When compacted, subleaf-N feature XSAVE area is 64-byte aligned", - bits_range: (1, 1), - policy: ProfilePolicy::Inherit, - }, - ValueDefinition { - short: "xfd_faulting", - description: "Indicates support for xfd faulting", - bits_range: (2, 2), - policy: ProfilePolicy::Inherit, - }, - ]), + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-13-ecx-hdc-zero", + description: "This leaf has been zeroed out because CET state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(13, 13), + register: CpuidReg::EDX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-13-edx-hdc-zero", + description: "This leaf has been zeroed out because CET state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), ), // We decided to disable UINTR for CPU profiles, hence we zero out these sub-leaves ( From de1d3de948751d6ecda14bc79490bbd95e6fe2bb Mon Sep 17 00:00:00 2001 From: Oliver Anderson Date: Tue, 24 Mar 2026 16:52:05 +0100 Subject: [PATCH 2/8] arch: Disable LBR state components We have already disabled architectural LBR (last branch record) for CPU profiles, but we forgot to disable the corresponding state components. Signed-off-by: Oliver Anderson On-behalf-of: SAP oliver.anderson@sap.com --- .../cpu_profiles/sapphire-rapids.cpuid.json | 62 +++++++++++++++- .../x86_64/cpu_profiles/skylake.cpuid.json | 60 +++++++++++++++- arch/src/x86_64/cpuid_definitions/intel.rs | 71 +++++++++++++++++-- 3 files changed, 182 insertions(+), 11 deletions(-) diff --git a/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json b/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json index 2f8ce47814..4ea61cfa91 100644 --- a/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json +++ b/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json @@ -1617,6 +1617,62 @@ "leaf": "0xd", "sub_leaf": { "start": "0xf", + "end": "0xf" + }, + "register": "EAX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0xf", + "end": "0xf" + }, + "register": "EBX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0xf", + "end": "0xf" + }, + "register": "ECX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0xf", + "end": "0xf" + }, + "register": "EDX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0x10", "end": "0x10" }, "register": "EAX" @@ -1672,7 +1728,7 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0xf", + "start": "0x10", "end": "0x10" }, "register": "EBX" @@ -1728,7 +1784,7 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0xf", + "start": "0x10", "end": "0x10" }, "register": "ECX" @@ -3265,4 +3321,4 @@ } ] ] -} +} \ No newline at end of file diff --git a/arch/src/x86_64/cpu_profiles/skylake.cpuid.json b/arch/src/x86_64/cpu_profiles/skylake.cpuid.json index 9aaa83a1de..da9f6b967e 100644 --- a/arch/src/x86_64/cpu_profiles/skylake.cpuid.json +++ b/arch/src/x86_64/cpu_profiles/skylake.cpuid.json @@ -1617,7 +1617,7 @@ "leaf": "0xd", "sub_leaf": { "start": "0xf", - "end": "0x3f" + "end": "0xf" }, "register": "EAX" }, @@ -1631,7 +1631,7 @@ "leaf": "0xd", "sub_leaf": { "start": "0xf", - "end": "0x3f" + "end": "0xf" }, "register": "EBX" }, @@ -1645,6 +1645,62 @@ "leaf": "0xd", "sub_leaf": { "start": "0xf", + "end": "0xf" + }, + "register": "ECX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0xf", + "end": "0xf" + }, + "register": "EDX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0x10", + "end": "0x3f" + }, + "register": "EAX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0x10", + "end": "0x3f" + }, + "register": "EBX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0x10", "end": "0x3f" }, "register": "ECX" diff --git a/arch/src/x86_64/cpuid_definitions/intel.rs b/arch/src/x86_64/cpuid_definitions/intel.rs index 7c173b9c16..e2502cb565 100644 --- a/arch/src/x86_64/cpuid_definitions/intel.rs +++ b/arch/src/x86_64/cpuid_definitions/intel.rs @@ -39,7 +39,7 @@ use super::{ /// a few of the short names and descriptions to be more inline with what is written in the /// aforementioned Intel manual. Finally we decided on a [`ProfilePolicy`] to be set for every /// single [`ValueDefinition`] and manually appended those. -pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<168> = const { +pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<172> = const { CpuidDefinitions([ // ========================================================================================= // Basic CPUID Information @@ -2420,10 +2420,16 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<168> = const { bits_range: (14, 14), policy: ProfilePolicy::Static(0), }, + ValueDefinition { + short: "xcr0_ia32_xss_LBR", + description: "XCR0.IA32_XSS (bit 15) used for LBR in IA32_XSS", + bits_range: (15, 15), + policy: ProfilePolicy::Static(0), + }, ValueDefinition { short: "xcr0_ia32_xss_bits_15_16", description: "XCR0.IA32_XSS (bit 15 - 16) used for IA32_XSS", - bits_range: (15, 16), + bits_range: (16, 16), policy: ProfilePolicy::Inherit, }, // NOTE: AMX currently requires opt-in, even for the host CPU profile. We still inherit this value for profiles and modify this value at runtime if AMX is not enabled by the user. @@ -2604,7 +2610,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<168> = const { short: "xss_lbr", description: "LBR state, supported", bits_range: (15, 15), - policy: ProfilePolicy::Inherit, + policy: ProfilePolicy::Static(0), }, ValueDefinition { short: "xss_hwp", @@ -2961,12 +2967,65 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<168> = const { policy: ProfilePolicy::Static(0), }]), ), + // Disable LBR for CPU Profiles + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(15, 15), + register: CpuidReg::EAX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-eax-lbr-zero", + description: "This leaf has been zeroed out because LBR state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(15, 15), + register: CpuidReg::EBX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-ebx-lbr-zero", + description: "This leaf has been zeroed out because LBR state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(15, 15), + register: CpuidReg::ECX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-ecx-lbr-zero", + description: "This leaf has been zeroed out because LBR state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(15, 15), + register: CpuidReg::EDX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-edx-lbr-zero", + description: "This leaf has been zeroed out because LBR state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), // NOTE: Sub-leaves 17 & 18 are AMX related and we will alter the adjustments corresponding to // the policy declared here at runtime for those values. ( Parameters { leaf: 0xd, - sub_leaf: RangeInclusive::new(15, 63), + sub_leaf: RangeInclusive::new(16, 63), register: CpuidReg::EAX, }, ValueDefinitions::new(&[ValueDefinition { @@ -2979,7 +3038,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<168> = const { ( Parameters { leaf: 0xd, - sub_leaf: RangeInclusive::new(15, 63), + sub_leaf: RangeInclusive::new(16, 63), register: CpuidReg::EBX, }, ValueDefinitions::new(&[ValueDefinition { @@ -2992,7 +3051,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<168> = const { ( Parameters { leaf: 0xd, - sub_leaf: RangeInclusive::new(15, 63), + sub_leaf: RangeInclusive::new(16, 63), register: CpuidReg::ECX, }, ValueDefinitions::new(&[ From 24f67f7e36a4724f1d298b04780ea08c3c546942 Mon Sep 17 00:00:00 2001 From: Oliver Anderson Date: Tue, 24 Mar 2026 17:13:29 +0100 Subject: [PATCH 3/8] arch: Disable HWP state components Hardware P-states (HWP) is already disabled for non-host CPU profiles, but we forgot to also disable the associated state components. Signed-off-by: Oliver Anderson On-behalf-of: SAP oliver.anderson@sap.com --- .../cpu_profiles/sapphire-rapids.cpuid.json | 68 ++++++++++-------- .../x86_64/cpu_profiles/skylake.cpuid.json | 60 +++++++++++++++- arch/src/x86_64/cpuid_definitions/intel.rs | 69 ++++++++++++++++--- 3 files changed, 160 insertions(+), 37 deletions(-) diff --git a/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json b/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json index 4ea61cfa91..522c5ce33c 100644 --- a/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json +++ b/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json @@ -1686,13 +1686,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x11", - "end": "0x11" + "start": "0x10", + "end": "0x10" }, - "register": "EAX" + "register": "EBX" }, { - "replacements": "0x00000040", + "replacements": "0x00000000", "mask": "0x00000000" } ], @@ -1700,13 +1700,41 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x12", - "end": "0x12" + "start": "0x10", + "end": "0x10" + }, + "register": "ECX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0x10", + "end": "0x10" + }, + "register": "EDX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0x11", + "end": "0x11" }, "register": "EAX" }, { - "replacements": "0x00002000", + "replacements": "0x00000040", "mask": "0x00000000" } ], @@ -1714,13 +1742,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x13", - "end": "0x3f" + "start": "0x12", + "end": "0x12" }, "register": "EAX" }, { - "replacements": "0x00000000", + "replacements": "0x00002000", "mask": "0x00000000" } ], @@ -1728,10 +1756,10 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x10", - "end": "0x10" + "start": "0x13", + "end": "0x3f" }, - "register": "EBX" + "register": "EAX" }, { "replacements": "0x00000000", @@ -1780,20 +1808,6 @@ "mask": "0x00000000" } ], - [ - { - "leaf": "0xd", - "sub_leaf": { - "start": "0x10", - "end": "0x10" - }, - "register": "ECX" - }, - { - "replacements": "0x00000000", - "mask": "0x00000000" - } - ], [ { "leaf": "0xd", diff --git a/arch/src/x86_64/cpu_profiles/skylake.cpuid.json b/arch/src/x86_64/cpu_profiles/skylake.cpuid.json index da9f6b967e..4c08a64595 100644 --- a/arch/src/x86_64/cpu_profiles/skylake.cpuid.json +++ b/arch/src/x86_64/cpu_profiles/skylake.cpuid.json @@ -1673,7 +1673,7 @@ "leaf": "0xd", "sub_leaf": { "start": "0x10", - "end": "0x3f" + "end": "0x10" }, "register": "EAX" }, @@ -1687,7 +1687,7 @@ "leaf": "0xd", "sub_leaf": { "start": "0x10", - "end": "0x3f" + "end": "0x10" }, "register": "EBX" }, @@ -1701,6 +1701,62 @@ "leaf": "0xd", "sub_leaf": { "start": "0x10", + "end": "0x10" + }, + "register": "ECX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0x10", + "end": "0x10" + }, + "register": "EDX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0x11", + "end": "0x3f" + }, + "register": "EAX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0x11", + "end": "0x3f" + }, + "register": "EBX" + }, + { + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0x11", "end": "0x3f" }, "register": "ECX" diff --git a/arch/src/x86_64/cpuid_definitions/intel.rs b/arch/src/x86_64/cpuid_definitions/intel.rs index e2502cb565..2fd575d252 100644 --- a/arch/src/x86_64/cpuid_definitions/intel.rs +++ b/arch/src/x86_64/cpuid_definitions/intel.rs @@ -39,7 +39,7 @@ use super::{ /// a few of the short names and descriptions to be more inline with what is written in the /// aforementioned Intel manual. Finally we decided on a [`ProfilePolicy`] to be set for every /// single [`ValueDefinition`] and manually appended those. -pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<172> = const { +pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<176> = const { CpuidDefinitions([ // ========================================================================================= // Basic CPUID Information @@ -2427,10 +2427,10 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<172> = const { policy: ProfilePolicy::Static(0), }, ValueDefinition { - short: "xcr0_ia32_xss_bits_15_16", - description: "XCR0.IA32_XSS (bit 15 - 16) used for IA32_XSS", + short: "xcr0_ia32_xss_bits_hwp", + description: "XCR0.IA32_XSS (bit 16) used for HWP in IA32_XSS", bits_range: (16, 16), - policy: ProfilePolicy::Inherit, + policy: ProfilePolicy::Static(0), }, // NOTE: AMX currently requires opt-in, even for the host CPU profile. We still inherit this value for profiles and modify this value at runtime if AMX is not enabled by the user. ValueDefinition { @@ -2616,7 +2616,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<172> = const { short: "xss_hwp", description: "HWP state, supported", bits_range: (16, 16), - policy: ProfilePolicy::Inherit, + policy: ProfilePolicy::Static(0), }, ValueDefinition { short: "xcr0_bits", @@ -3020,12 +3020,65 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<172> = const { policy: ProfilePolicy::Static(0), }]), ), + // Disable HWP for CPU profiles + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(16, 16), + register: CpuidReg::EAX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-eax-hwp-zero", + description: "This leaf has been zeroed out because HWP state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(16, 16), + register: CpuidReg::EBX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-ebx-hwp-zero", + description: "This leaf has been zeroed out because HWP state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(16, 16), + register: CpuidReg::ECX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-ecx-hwp-zero", + description: "This leaf has been zeroed out because HWP state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(16, 16), + register: CpuidReg::EDX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-edx-hwp-zero", + description: "This leaf has been zeroed out because HWP state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), // NOTE: Sub-leaves 17 & 18 are AMX related and we will alter the adjustments corresponding to // the policy declared here at runtime for those values. ( Parameters { leaf: 0xd, - sub_leaf: RangeInclusive::new(16, 63), + sub_leaf: RangeInclusive::new(17, 63), register: CpuidReg::EAX, }, ValueDefinitions::new(&[ValueDefinition { @@ -3038,7 +3091,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<172> = const { ( Parameters { leaf: 0xd, - sub_leaf: RangeInclusive::new(16, 63), + sub_leaf: RangeInclusive::new(17, 63), register: CpuidReg::EBX, }, ValueDefinitions::new(&[ValueDefinition { @@ -3051,7 +3104,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<172> = const { ( Parameters { leaf: 0xd, - sub_leaf: RangeInclusive::new(16, 63), + sub_leaf: RangeInclusive::new(17, 63), register: CpuidReg::ECX, }, ValueDefinitions::new(&[ From e0bb0dd74b6316ffc2877d61860deae95e95b743 Mon Sep 17 00:00:00 2001 From: Oliver Anderson Date: Tue, 24 Mar 2026 17:28:28 +0100 Subject: [PATCH 4/8] arch: Disable PT state components We already disabled Processor Trace (PT) for CPU profiles, but forgot to disable the associated state components. Signed-off-by: Oliver Anderson On-behalf-of: SAP oliver.anderson@sap.com --- .../cpu_profiles/sapphire-rapids.cpuid.json | 90 +++++++------ .../x86_64/cpu_profiles/skylake.cpuid.json | 90 +++++++------ arch/src/x86_64/cpuid_definitions/intel.rs | 121 ++++++++++++++++-- 3 files changed, 217 insertions(+), 84 deletions(-) diff --git a/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json b/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json index 522c5ce33c..fc024bfe7e 100644 --- a/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json +++ b/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json @@ -1182,13 +1182,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x8", - "end": "0x8" + "start": "0x5", + "end": "0x5" }, - "register": "EAX" + "register": "EBX" }, { - "replacements": "0x00000000", + "replacements": "0x00000440", "mask": "0x00000000" } ], @@ -1196,13 +1196,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x9", - "end": "0x9" + "start": "0x6", + "end": "0x6" }, - "register": "EAX" + "register": "EBX" }, { - "replacements": "0x00000008", + "replacements": "0x00000480", "mask": "0x00000000" } ], @@ -1210,13 +1210,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0xa", - "end": "0xa" + "start": "0x7", + "end": "0x7" }, - "register": "EAX" + "register": "EBX" }, { - "replacements": "0x00000000", + "replacements": "0x00000680", "mask": "0x00000000" } ], @@ -1227,10 +1227,10 @@ "start": "0x5", "end": "0x5" }, - "register": "EBX" + "register": "ECX" }, { - "replacements": "0x00000440", + "replacements": "0x00000000", "mask": "0x00000000" } ], @@ -1241,10 +1241,10 @@ "start": "0x6", "end": "0x6" }, - "register": "EBX" + "register": "ECX" }, { - "replacements": "0x00000480", + "replacements": "0x00000000", "mask": "0x00000000" } ], @@ -1255,10 +1255,10 @@ "start": "0x7", "end": "0x7" }, - "register": "EBX" + "register": "ECX" }, { - "replacements": "0x00000680", + "replacements": "0x00000000", "mask": "0x00000000" } ], @@ -1269,7 +1269,7 @@ "start": "0x8", "end": "0x8" }, - "register": "EBX" + "register": "EAX" }, { "replacements": "0x00000000", @@ -1280,13 +1280,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x9", - "end": "0x9" + "start": "0x8", + "end": "0x8" }, "register": "EBX" }, { - "replacements": "0x00000a80", + "replacements": "0x00000000", "mask": "0x00000000" } ], @@ -1294,10 +1294,10 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0xa", - "end": "0xa" + "start": "0x8", + "end": "0x8" }, - "register": "EBX" + "register": "ECX" }, { "replacements": "0x00000000", @@ -1308,10 +1308,10 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x5", - "end": "0x5" + "start": "0x8", + "end": "0x8" }, - "register": "ECX" + "register": "EDX" }, { "replacements": "0x00000000", @@ -1322,13 +1322,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x6", - "end": "0x6" + "start": "0x9", + "end": "0x9" }, - "register": "ECX" + "register": "EAX" }, { - "replacements": "0x00000000", + "replacements": "0x00000008", "mask": "0x00000000" } ], @@ -1336,10 +1336,10 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x7", - "end": "0x7" + "start": "0xa", + "end": "0xa" }, - "register": "ECX" + "register": "EAX" }, { "replacements": "0x00000000", @@ -1350,10 +1350,24 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x8", - "end": "0x8" + "start": "0x9", + "end": "0x9" }, - "register": "ECX" + "register": "EBX" + }, + { + "replacements": "0x00000a80", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0xa", + "end": "0xa" + }, + "register": "EBX" }, { "replacements": "0x00000000", diff --git a/arch/src/x86_64/cpu_profiles/skylake.cpuid.json b/arch/src/x86_64/cpu_profiles/skylake.cpuid.json index 4c08a64595..4e2e58232a 100644 --- a/arch/src/x86_64/cpu_profiles/skylake.cpuid.json +++ b/arch/src/x86_64/cpu_profiles/skylake.cpuid.json @@ -1238,13 +1238,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x8", - "end": "0x8" + "start": "0x5", + "end": "0x5" }, - "register": "EAX" + "register": "EBX" }, { - "replacements": "0x00000000", + "replacements": "0x00000440", "mask": "0x00000000" } ], @@ -1252,13 +1252,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x9", - "end": "0x9" + "start": "0x6", + "end": "0x6" }, - "register": "EAX" + "register": "EBX" }, { - "replacements": "0x00000008", + "replacements": "0x00000480", "mask": "0x00000000" } ], @@ -1266,13 +1266,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0xa", - "end": "0xa" + "start": "0x7", + "end": "0x7" }, - "register": "EAX" + "register": "EBX" }, { - "replacements": "0x00000000", + "replacements": "0x00000680", "mask": "0x00000000" } ], @@ -1283,10 +1283,10 @@ "start": "0x5", "end": "0x5" }, - "register": "EBX" + "register": "ECX" }, { - "replacements": "0x00000440", + "replacements": "0x00000000", "mask": "0x00000000" } ], @@ -1297,10 +1297,10 @@ "start": "0x6", "end": "0x6" }, - "register": "EBX" + "register": "ECX" }, { - "replacements": "0x00000480", + "replacements": "0x00000000", "mask": "0x00000000" } ], @@ -1311,10 +1311,10 @@ "start": "0x7", "end": "0x7" }, - "register": "EBX" + "register": "ECX" }, { - "replacements": "0x00000680", + "replacements": "0x00000000", "mask": "0x00000000" } ], @@ -1325,7 +1325,7 @@ "start": "0x8", "end": "0x8" }, - "register": "EBX" + "register": "EAX" }, { "replacements": "0x00000000", @@ -1336,13 +1336,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x9", - "end": "0x9" + "start": "0x8", + "end": "0x8" }, "register": "EBX" }, { - "replacements": "0x00000a80", + "replacements": "0x00000000", "mask": "0x00000000" } ], @@ -1350,10 +1350,10 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0xa", - "end": "0xa" + "start": "0x8", + "end": "0x8" }, - "register": "EBX" + "register": "ECX" }, { "replacements": "0x00000000", @@ -1364,10 +1364,10 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x5", - "end": "0x5" + "start": "0x8", + "end": "0x8" }, - "register": "ECX" + "register": "EDX" }, { "replacements": "0x00000000", @@ -1378,13 +1378,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x6", - "end": "0x6" + "start": "0x9", + "end": "0x9" }, - "register": "ECX" + "register": "EAX" }, { - "replacements": "0x00000000", + "replacements": "0x00000008", "mask": "0x00000000" } ], @@ -1392,10 +1392,10 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x7", - "end": "0x7" + "start": "0xa", + "end": "0xa" }, - "register": "ECX" + "register": "EAX" }, { "replacements": "0x00000000", @@ -1406,10 +1406,24 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x8", - "end": "0x8" + "start": "0x9", + "end": "0x9" }, - "register": "ECX" + "register": "EBX" + }, + { + "replacements": "0x00000a80", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0xa", + "end": "0xa" + }, + "register": "EBX" }, { "replacements": "0x00000000", diff --git a/arch/src/x86_64/cpuid_definitions/intel.rs b/arch/src/x86_64/cpuid_definitions/intel.rs index 2fd575d252..2c5f97b386 100644 --- a/arch/src/x86_64/cpuid_definitions/intel.rs +++ b/arch/src/x86_64/cpuid_definitions/intel.rs @@ -39,7 +39,7 @@ use super::{ /// a few of the short names and descriptions to be more inline with what is written in the /// aforementioned Intel manual. Finally we decided on a [`ProfilePolicy`] to be set for every /// single [`ValueDefinition`] and manually appended those. -pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<176> = const { +pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<183> = const { CpuidDefinitions([ // ========================================================================================= // Basic CPUID Information @@ -2386,9 +2386,9 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<176> = const { // MSR related ValueDefinition { short: "xcr0_ia32_xss", - description: "XCR0.IA32_XSS (bit 8) used for IA32_XSS", + description: "XCR0.IA32_XSS (bit 8) used for PT in IA32_XSS", bits_range: (8, 8), - policy: ProfilePolicy::Inherit, + policy: ProfilePolicy::Static(0), }, ValueDefinition { short: "xcr0_pkru", @@ -2568,7 +2568,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<176> = const { short: "xss_pt", description: "PT state, supported", bits_range: (8, 8), - policy: ProfilePolicy::Inherit, + policy: ProfilePolicy::Static(0), }, ValueDefinition { short: "xcr0_bit9", @@ -2758,7 +2758,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<176> = const { ( Parameters { leaf: 0xd, - sub_leaf: RangeInclusive::new(5, 10), + sub_leaf: RangeInclusive::new(5, 7), register: CpuidReg::EAX, }, ValueDefinitions::new(&[ValueDefinition { @@ -2771,7 +2771,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<176> = const { ( Parameters { leaf: 0xd, - sub_leaf: RangeInclusive::new(5, 10), + sub_leaf: RangeInclusive::new(5, 7), register: CpuidReg::EBX, }, ValueDefinitions::new(&[ValueDefinition { @@ -2784,7 +2784,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<176> = const { ( Parameters { leaf: 0xd, - sub_leaf: RangeInclusive::new(5, 10), + sub_leaf: RangeInclusive::new(5, 7), register: CpuidReg::ECX, }, ValueDefinitions::new(&[ @@ -2808,7 +2808,112 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<176> = const { }, ]), ), - // We leave CET out of CPU profiles for the time being + // Disable PT for CPU profiles + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(8, 8), + register: CpuidReg::EAX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-8-eax-pt-zero", + description: "This leaf has been zeroed out because PT state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(8, 8), + register: CpuidReg::EBX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-8-ebx-pt-zero", + description: "This leaf has been zeroed out because PT state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(8, 8), + register: CpuidReg::ECX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-8-ecx-pt-zero", + description: "This leaf has been zeroed out because PT state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(8, 8), + register: CpuidReg::EDX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-8-edx-pt-zero", + description: "This leaf has been zeroed out because PT state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(9, 10), + register: CpuidReg::EAX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "xsave_sz", + description: "Size of save area for subleaf-N feature, in bytes", + bits_range: (0, 31), + policy: ProfilePolicy::Inherit, + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(9, 10), + register: CpuidReg::EBX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "xsave_offset", + description: "Offset of save area for subleaf-N feature, in bytes", + bits_range: (0, 31), + policy: ProfilePolicy::Inherit, + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(9, 10), + register: CpuidReg::ECX, + }, + ValueDefinitions::new(&[ + ValueDefinition { + short: "is_xss_bit", + description: "Subleaf N describes an XSS bit, otherwise XCR0 bit", + bits_range: (0, 0), + policy: ProfilePolicy::Inherit, + }, + ValueDefinition { + short: "compacted_xsave_64byte_aligned", + description: "When compacted, subleaf-N feature XSAVE area is 64-byte aligned", + bits_range: (1, 1), + policy: ProfilePolicy::Inherit, + }, + ValueDefinition { + short: "xfd_faulting", + description: "Indicates support for xfd faulting", + bits_range: (2, 2), + policy: ProfilePolicy::Inherit, + }, + ]), + ), // We leave CET out of CPU profiles for the time being ( Parameters { leaf: 0xd, From 94fa6dab87e9b8d3062d2f1c12742405cd44ad7b Mon Sep 17 00:00:00 2001 From: Oliver Anderson Date: Tue, 24 Mar 2026 17:39:24 +0100 Subject: [PATCH 5/8] arch: Disable PASID state components We have already forbidden IA32_PASID, an MSR related to process address space identifiers (PASID), but we forgot to disable the associated state components. Signed-off-by: Oliver Anderson On-behalf-of: SAP oliver.anderson@sap.com --- .../cpu_profiles/sapphire-rapids.cpuid.json | 32 ++++++--- .../x86_64/cpu_profiles/skylake.cpuid.json | 32 ++++++--- arch/src/x86_64/cpuid_definitions/intel.rs | 72 ++++++++++++++++--- 3 files changed, 109 insertions(+), 27 deletions(-) diff --git a/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json b/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json index fc024bfe7e..b0790bb426 100644 --- a/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json +++ b/arch/src/x86_64/cpu_profiles/sapphire-rapids.cpuid.json @@ -1336,13 +1336,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0xa", - "end": "0xa" + "start": "0x9", + "end": "0x9" }, - "register": "EAX" + "register": "EBX" }, { - "replacements": "0x00000000", + "replacements": "0x00000a80", "mask": "0x00000000" } ], @@ -1353,10 +1353,24 @@ "start": "0x9", "end": "0x9" }, - "register": "EBX" + "register": "ECX" }, { - "replacements": "0x00000a80", + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0xa", + "end": "0xa" + }, + "register": "EAX" + }, + { + "replacements": "0x00000000", "mask": "0x00000000" } ], @@ -1378,8 +1392,8 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x9", - "end": "0x9" + "start": "0xa", + "end": "0xa" }, "register": "ECX" }, @@ -1395,7 +1409,7 @@ "start": "0xa", "end": "0xa" }, - "register": "ECX" + "register": "EDX" }, { "replacements": "0x00000000", diff --git a/arch/src/x86_64/cpu_profiles/skylake.cpuid.json b/arch/src/x86_64/cpu_profiles/skylake.cpuid.json index 4e2e58232a..bbe3ec73a8 100644 --- a/arch/src/x86_64/cpu_profiles/skylake.cpuid.json +++ b/arch/src/x86_64/cpu_profiles/skylake.cpuid.json @@ -1392,13 +1392,13 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0xa", - "end": "0xa" + "start": "0x9", + "end": "0x9" }, - "register": "EAX" + "register": "EBX" }, { - "replacements": "0x00000000", + "replacements": "0x00000a80", "mask": "0x00000000" } ], @@ -1409,10 +1409,24 @@ "start": "0x9", "end": "0x9" }, - "register": "EBX" + "register": "ECX" }, { - "replacements": "0x00000a80", + "replacements": "0x00000000", + "mask": "0x00000000" + } + ], + [ + { + "leaf": "0xd", + "sub_leaf": { + "start": "0xa", + "end": "0xa" + }, + "register": "EAX" + }, + { + "replacements": "0x00000000", "mask": "0x00000000" } ], @@ -1434,8 +1448,8 @@ { "leaf": "0xd", "sub_leaf": { - "start": "0x9", - "end": "0x9" + "start": "0xa", + "end": "0xa" }, "register": "ECX" }, @@ -1451,7 +1465,7 @@ "start": "0xa", "end": "0xa" }, - "register": "ECX" + "register": "EDX" }, { "replacements": "0x00000000", diff --git a/arch/src/x86_64/cpuid_definitions/intel.rs b/arch/src/x86_64/cpuid_definitions/intel.rs index 2c5f97b386..61517e7e1b 100644 --- a/arch/src/x86_64/cpuid_definitions/intel.rs +++ b/arch/src/x86_64/cpuid_definitions/intel.rs @@ -39,7 +39,7 @@ use super::{ /// a few of the short names and descriptions to be more inline with what is written in the /// aforementioned Intel manual. Finally we decided on a [`ProfilePolicy`] to be set for every /// single [`ValueDefinition`] and manually appended those. -pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<183> = const { +pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<187> = const { CpuidDefinitions([ // ========================================================================================= // Basic CPUID Information @@ -2397,10 +2397,10 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<183> = const { policy: ProfilePolicy::Inherit, }, ValueDefinition { - short: "xcr0_ia32_xss_bits", - description: "XCR0.IA32_XSS (bit 10) used for IA32_XSS", + short: "xcr0_ia32_xss_pasid", + description: "XCR0.IA32_XSS (bit 10) used for PASID in IA32_XSS", bits_range: (10, 10), - policy: ProfilePolicy::Inherit, + policy: ProfilePolicy::Static(0), }, ValueDefinition { short: "xcr0_ia32_xss_cet", @@ -2580,7 +2580,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<183> = const { short: "xss_pasid", description: "PASID state, supported", bits_range: (10, 10), - policy: ProfilePolicy::Inherit, + policy: ProfilePolicy::Static(0), }, ValueDefinition { short: "xss_cet_u", @@ -2864,7 +2864,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<183> = const { ( Parameters { leaf: 0xd, - sub_leaf: RangeInclusive::new(9, 10), + sub_leaf: RangeInclusive::new(9, 9), register: CpuidReg::EAX, }, ValueDefinitions::new(&[ValueDefinition { @@ -2877,7 +2877,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<183> = const { ( Parameters { leaf: 0xd, - sub_leaf: RangeInclusive::new(9, 10), + sub_leaf: RangeInclusive::new(9, 9), register: CpuidReg::EBX, }, ValueDefinitions::new(&[ValueDefinition { @@ -2890,7 +2890,7 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<183> = const { ( Parameters { leaf: 0xd, - sub_leaf: RangeInclusive::new(9, 10), + sub_leaf: RangeInclusive::new(9, 9), register: CpuidReg::ECX, }, ValueDefinitions::new(&[ @@ -2913,7 +2913,61 @@ pub static INTEL_CPUID_DEFINITIONS: CpuidDefinitions<183> = const { policy: ProfilePolicy::Inherit, }, ]), - ), // We leave CET out of CPU profiles for the time being + ), + // Disable PASID for CPU profiles + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(10, 10), + register: CpuidReg::EAX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-10-eax-pasid-zero", + description: "This leaf has been zeroed out because PASID state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(10, 10), + register: CpuidReg::EBX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-10-ebx-pasid-zero", + description: "This leaf has been zeroed out because PASID state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(10, 10), + register: CpuidReg::ECX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-10-ecx-pasid-zero", + description: "This leaf has been zeroed out because PASID state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + ( + Parameters { + leaf: 0xd, + sub_leaf: RangeInclusive::new(10, 10), + register: CpuidReg::EDX, + }, + ValueDefinitions::new(&[ValueDefinition { + short: "0xd-10-edx-pasid-zero", + description: "This leaf has been zeroed out because PASID state components are disabled", + bits_range: (0, 31), + policy: ProfilePolicy::Static(0), + }]), + ), + // We leave CET out of CPU profiles for the time being ( Parameters { leaf: 0xd, From fbd695b2a7614d4e01a3532379f2fd802e252c2c Mon Sep 17 00:00:00 2001 From: Oliver Anderson Date: Tue, 24 Mar 2026 18:49:13 +0100 Subject: [PATCH 6/8] arch: Disable VM_ENTRY_HARDWARE_EXCEPTIONS for CPU profiles Bit 56 of VM_ENTRY_HARDWARE_EXCEPTIONS in IA32_VMX_BASIC is only set on rather recent KVM versions. Thus whenever a CPU profile is generated on a machine with a recent Linux kernel, the current inherit policy will lead to the CPU profile being incompatible on deplyoments with older Linux kernels. This may not be the intention of the person generating the CPU profile, thus we change the policy to `Static(0)` for the time being. Signed-off-by: Oliver Anderson On-behalf-of: SAP oliver.anderson@sap.com --- arch/src/x86_64/msr_definitions/intel/msr_based_features.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/src/x86_64/msr_definitions/intel/msr_based_features.rs b/arch/src/x86_64/msr_definitions/intel/msr_based_features.rs index bc36eb8581..c268229677 100644 --- a/arch/src/x86_64/msr_definitions/intel/msr_based_features.rs +++ b/arch/src/x86_64/msr_definitions/intel/msr_based_features.rs @@ -370,11 +370,13 @@ pub static INTEL_MSR_FEATURE_DEFINITIONS: MsrDefinitions<24> = const { bits_range: (55,55), policy: ProfilePolicy::Inherit }, + // This is only available for relatively recent kernels + // TODO: Revisit this policy ValueDefinition { short: "VM_ENTRY_HARDWARE_EXCEPTIONS", description: "If 1, then software can use VM entry to deliver a hardware exception", bits_range: (56, 56), - policy: ProfilePolicy::Inherit + policy: ProfilePolicy::Static(0) } ]) ), From 16ff02ab7ab8713e0f47d97f15a3da8487a89881 Mon Sep 17 00:00:00 2001 From: Oliver Anderson Date: Tue, 24 Mar 2026 19:18:28 +0100 Subject: [PATCH 7/8] arch: Forbid IA32_XSS for non-host CPU profiles IA32_XSS (Extended Supervisor State Mask) is only reported via KVM_GET_MSR_INDEX_LIST on rather recent kernels. This can lead to CPU profiles that are generated on a machine with the latest Linux kernel, not work with deployments where the hosts use a bit older kernels which may be unintentional. We thus decide to forbid this MSR for now, even though CPUID 0xd.0x1.EAX[3] can inform the guest that the MSR is available. We do not want to force the aforementioned feature bit to 0 because it is also used to report support for XSAVES/XRSTORS. Although not ideal, we consider denying access to IA32_XSS to be acceptable because the 0xd CPUID leaves report all IA32_XSS related state components to be unsupported. There is thus no reason for the guest to be interested in using this MSR. Signed-off-by: Oliver Anderson On-behalf-of: SAP oliver.anderson@sap.com --- .../intel/architectural_msrs.rs | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/arch/src/x86_64/msr_definitions/intel/architectural_msrs.rs b/arch/src/x86_64/msr_definitions/intel/architectural_msrs.rs index 6fd61cc3d2..af7b4e7cc0 100644 --- a/arch/src/x86_64/msr_definitions/intel/architectural_msrs.rs +++ b/arch/src/x86_64/msr_definitions/intel/architectural_msrs.rs @@ -429,13 +429,6 @@ mod permitted_architectural_msrs { const IA32_X2APIC_INIT_COUNT: u32 = 0x838; const IA32_X2APIC_DIV_CONF: u32 = 0x83e; - const IA32_XSS: u32 = 0xda0; - const _IA32_XSS_CPUID_CHECK: () = assert_not_denied_cpuid_feature::<3>(&Parameters { - leaf: 0xd, - sub_leaf: 1..=1, - register: CpuidReg::EAX, - }); - /// Extended Feature Enable const IA32_EFER: u32 = 0xc0000080; @@ -461,7 +454,7 @@ mod permitted_architectural_msrs { register: CpuidReg::ECX, }); - pub(super) const READ_WRITE_IA32_MSRS: [u32; 200] = [ + pub(super) const READ_WRITE_IA32_MSRS: [u32; 199] = [ IA32_TIME_STAMP_COUNTER, IA32_APIC_BASE, IA32_FEATURE_CONTROL, @@ -652,7 +645,6 @@ mod permitted_architectural_msrs { IA32_X2APIC_LVT_ERROR, IA32_X2APIC_INIT_COUNT, IA32_X2APIC_DIV_CONF, - IA32_XSS, IA32_EFER, IA32_STAR, IA32_LSTAR, @@ -705,8 +697,8 @@ mod permitted_architectural_msrs { /// /// The MSRs listed here can be studied further in Table 2.2 in Section 2.1 of the Intel SDM /// Vol. 4 from October 2025 - pub(in crate::x86_64) const PERMITTED_IA32_MSRS: [u32; 243] = const { - let mut permitted = [0u32; 243]; + pub(in crate::x86_64) const PERMITTED_IA32_MSRS: [u32; 242] = const { + let mut permitted = [0u32; 242]; let read_only_len = READ_ONLY_IA32_MSRS.len(); let write_only_len = WRITE_ONLY_IA32_MSRS.len(); let read_write_len = READ_WRITE_IA32_MSRS.len(); @@ -1105,6 +1097,21 @@ mod forbidden_architectural_msrs { const IA32_COPY_PLATFORM_TO_LOCAL: (u32, u32) = (0xd92, 0xd92); const IA32_PASID: (u32, u32) = (0xd93, 0xd93); + + /* + IA32_XSS is a bit problematic: Only never kernels will report it via + KVM_GET_MSR_INDEX_LIST, but CPUID 0xd.0x1.EAX[3] reports that this MSR + exists. + + In order for CPU profiles generated with recent kernels to work with + deployments operating with older kernels, we decide to forbid this MSR + for now even though CPUID indicates that it is available to the guest. + + We consider this OK because we have disabled every single IA32_XSS + related state component in the 0xd CPUID leaves, hence there is no + reason for the guest to want to use this. + */ + const IA32_XSS: (u32, u32) = (0xda0, 0xda0); // Disabled via CPUID for non-host CPU profiles const IA32_PKG_HDC_CTL: (u32, u32) = (0xdb0, 0xdb0); @@ -1270,7 +1277,7 @@ mod forbidden_architectural_msrs { const IA32_UARCH_MISC_CTL: (u32, u32) = (0x1b01, 0x1b01); /// A list of ARCHITECTURAL MSR register addresses that are forbidden for all non-host CPU profiles and also not /// considered MSR-based FEATURE indices by KVM. - pub(in crate::x86_64) const FORBIDDEN_IA32_MSR_RANGES: [(u32, u32); 228] = [ + pub(in crate::x86_64) const FORBIDDEN_IA32_MSR_RANGES: [(u32, u32); 229] = [ IA32_P5_MC_ADDR, IA32_P5_MC_TYPE, // TODO: Not sure about IA32_P5_MC_ADDR & IA32_P5_MC_TYPE @@ -1520,6 +1527,7 @@ mod forbidden_architectural_msrs { // Disabled via CPUID for non-host CPU profiles IA32_COPY_PLATFORM_TO_LOCAL, IA32_PASID, + IA32_XSS, // Disabled via CPUID for non-host CPU profiles IA32_PKG_HDC_CTL, // Disabled via CPUID for non-host CPU profiles From ea9c534ff1c005bf13fd67de3e15b34cfc957341 Mon Sep 17 00:00:00 2001 From: Oliver Anderson Date: Tue, 24 Mar 2026 19:43:44 +0100 Subject: [PATCH 8/8] arch: Clear LBR related bits in the VM-Exit and VM-Entry CTL MSRs We have disabled LBR for non-host CPU profiles, but forgot to also do so in the VM-Exit and VM-Entry control MSRs. Signed-off-by: Oliver Anderson On-behalf-of: SAP oliver.anderson@sap.com --- .../x86_64/cpu_profiles/sapphire-rapids.msr.json | 2 +- arch/src/x86_64/cpu_profiles/skylake.msr.json | 2 +- .../msr_definitions/intel/msr_based_features.rs | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/arch/src/x86_64/cpu_profiles/sapphire-rapids.msr.json b/arch/src/x86_64/cpu_profiles/sapphire-rapids.msr.json index cd2b7a5a97..c9b5d42089 100644 --- a/arch/src/x86_64/cpu_profiles/sapphire-rapids.msr.json +++ b/arch/src/x86_64/cpu_profiles/sapphire-rapids.msr.json @@ -203,4 +203,4 @@ "0xc0000102", "0xc0000103" ] -} +} \ No newline at end of file diff --git a/arch/src/x86_64/cpu_profiles/skylake.msr.json b/arch/src/x86_64/cpu_profiles/skylake.msr.json index 5cc3398dc1..eceb91fcda 100644 --- a/arch/src/x86_64/cpu_profiles/skylake.msr.json +++ b/arch/src/x86_64/cpu_profiles/skylake.msr.json @@ -201,4 +201,4 @@ "0xc0000102", "0xc0000103" ] -} +} \ No newline at end of file diff --git a/arch/src/x86_64/msr_definitions/intel/msr_based_features.rs b/arch/src/x86_64/msr_definitions/intel/msr_based_features.rs index c268229677..e5cb7b214d 100644 --- a/arch/src/x86_64/msr_definitions/intel/msr_based_features.rs +++ b/arch/src/x86_64/msr_definitions/intel/msr_based_features.rs @@ -941,7 +941,7 @@ pub static INTEL_MSR_FEATURE_DEFINITIONS: MsrDefinitions<24> = const { short:"ALLOWED_ZERO_CLEAR_IA32_LBR_CTL", description: "See Intel SDM Vol.3C Section 26.7.1 Table 26-14 (Definitions of Primary VM-Exit Controls)", bits_range: (26, 26), - policy: ProfilePolicy::Inherit + policy: ProfilePolicy::Static(0) }, ValueDefinition { short:"ALLOWED_ZERO_CLEAR_UINV", @@ -1082,7 +1082,7 @@ pub static INTEL_MSR_FEATURE_DEFINITIONS: MsrDefinitions<24> = const { short:"ALLOWED_ONE_CLEAR_IA32_LBR_CTL", description: "See Intel SDM Vol.3C Section 26.7.1 Table 26-14 (Definitions of Primary VM-Exit Controls)", bits_range: (58, 58), - policy: ProfilePolicy::Inherit + policy: ProfilePolicy::Static(0) }, ValueDefinition { short:"ALLOWED_ONE_CLEAR_UINV", @@ -1215,7 +1215,7 @@ pub static INTEL_MSR_FEATURE_DEFINITIONS: MsrDefinitions<24> = const { short:"ALLOWED_ZERO_LOAD_GUEST_IA32_LBR_CTL", description: "See Intel SDM Vol.3C Section 26.8.1 Table 26-17. (Definitions of VM-Entry Controls)", bits_range: (21, 21), - policy: ProfilePolicy::Inherit + policy: ProfilePolicy::Static(0) }, ValueDefinition { short:"ALLOWED_ZERO_LOAD_PKRS", @@ -1335,7 +1335,7 @@ pub static INTEL_MSR_FEATURE_DEFINITIONS: MsrDefinitions<24> = const { short:"ALLOWED_ONE_LOAD_GUEST_IA32_LBR_CTL", description: "See Intel SDM Vol.3C Section 26.8.1 Table 26-17. (Definitions of VM-Entry Controls)", bits_range: (53, 53), - policy: ProfilePolicy::Inherit + policy: ProfilePolicy::Static(0) }, ValueDefinition { short:"ALLOWED_ONE_LOAD_PKRS", @@ -3126,7 +3126,7 @@ pub static INTEL_MSR_FEATURE_DEFINITIONS: MsrDefinitions<24> = const { short:"ALLOWED_ZERO_CLEAR_IA32_LBR_CTL", description: "See Intel SDM Vol.3C Section 26.7.1 Table 26-14 (Definitions of Primary VM-Exit Controls)", bits_range: (26, 26), - policy: ProfilePolicy::Inherit + policy: ProfilePolicy::Static(0) }, ValueDefinition { short:"ALLOWED_ZERO_CLEAR_UINV", @@ -3266,7 +3266,7 @@ pub static INTEL_MSR_FEATURE_DEFINITIONS: MsrDefinitions<24> = const { short:"ALLOWED_ONE_CLEAR_IA32_LBR_CTL", description: "See Intel SDM Vol.3C Section 26.7.1 Table 26-14 (Definitions of Primary VM-Exit Controls)", bits_range: (58, 58), - policy: ProfilePolicy::Inherit + policy: ProfilePolicy::Static(0) }, ValueDefinition { short:"ALLOWED_ONE_CLEAR_UINV", @@ -3398,7 +3398,7 @@ pub static INTEL_MSR_FEATURE_DEFINITIONS: MsrDefinitions<24> = const { short:"ALLOWED_ZERO_LOAD_GUEST_IA32_LBR_CTL", description: "See Intel SDM Vol.3C Section 26.8.1 Table 26-17. (Definitions of VM-Entry Controls)", bits_range: (21, 21), - policy: ProfilePolicy::Inherit + policy: ProfilePolicy::Static(0) }, ValueDefinition { short:"ALLOWED_ZERO_LOAD_PKRS", @@ -3518,7 +3518,7 @@ pub static INTEL_MSR_FEATURE_DEFINITIONS: MsrDefinitions<24> = const { short:"ALLOWED_ONE_LOAD_GUEST_IA32_LBR_CTL", description: "See Intel SDM Vol.3C Section 26.8.1 Table 26-17. (Definitions of VM-Entry Controls)", bits_range: (53, 53), - policy: ProfilePolicy::Inherit + policy: ProfilePolicy::Static(0) }, ValueDefinition { short:"ALLOWED_ONE_LOAD_PKRS",