Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions openhcl/virt_mshv_vtl/src/cvm_cpuid/masking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,24 +207,6 @@ impl CpuidResults {
.into(),
is_subleaf: true,
})
} else if subleaf == 1 {
Some(CpuidResultMask {
mask_eax: cpuid::ExtendedFeatureSubleaf1Eax::new()
.with_avx_vnni(true)
Copy link
Contributor

@jennagoddard jennagoddard Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.with_avx_vnni(true)

Do we still want to filter these out on AMD and ARM? #Closed

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah I see you moved this to TDX specifically

.with_avx512_bfloat16(true)
.with_fzlrep_movsb(true)
.with_fsrep_stosb(true)
.with_fsrep_cmpsb(true)
.with_avx_ifma(true)
.into(),
mask_ebx: 0,
mask_ecx: 0,
mask_edx: cpuid::ExtendedFeatureSubleaf1Edx::new()
.with_avx_vnni_int8(true)
.with_avx_ne_convert(true)
.into(),
is_subleaf: true,
})
} else {
None
}
Expand Down
117 changes: 117 additions & 0 deletions openhcl/virt_mshv_vtl/src/cvm_cpuid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ trait CpuidArchInitializer {

/// Returns the synthetic hypervisor cpuid leafs for the architecture.
fn hv_cpuid_leaves(&self) -> [(CpuidFunction, CpuidResult); 5];

/// Makes any architecture-specific updates to any cpuid leaves that have
/// dependencies on the extended state enumeration leaves.
fn update_xsave_dependencies(&self, xsave_support: u64, results: &mut CpuidResults);
}

/// Initialization parameters per isolation type for parsing cpuid results
Expand Down Expand Up @@ -537,6 +541,8 @@ impl CpuidResults {

self.max_extended_state = max_extended_state;

self.update_xsave_dependencies(arch_initializer);

Ok(())
}

Expand Down Expand Up @@ -631,6 +637,117 @@ impl CpuidResults {
extended_address_space_sizes.ebx = updated_sizes.into();
}

/// Suppress the availability of any feature that requires XSAVE support
/// if the corresponding XSAVE support is not enabled.
fn update_xsave_dependencies(&mut self, arch_initializer: &dyn CpuidArchInitializer) {
let mut clear_extended_features0_ebx = cpuid::ExtendedFeatureSubleaf0Ebx::new();
let mut clear_extended_features0_ecx = cpuid::ExtendedFeatureSubleaf0Ecx::new();
let mut clear_extended_features0_edx = cpuid::ExtendedFeatureSubleaf0Edx::new();

let mut clear_version_and_features0_ecx = cpuid::VersionAndFeaturesEcx::new();

let CpuidResult {
eax: xsave_low,
ebx: xsave_high,
ecx: _,
edx: _,
} = *self
.leaf_result_ref(CpuidFunction::ExtendedStateEnumeration, Some(0), true)
.expect("validated this subleaf exists");

let xsave_support = ((xsave_high as u64) << 32) | (xsave_low as u64);

let mut disable_avx_512 = false;

if (xsave_support & xsave::XFEATURE_YMM != xsave::XFEATURE_YMM)
|| (xsave_support & xsave::XFEATURE_SSE != xsave::XFEATURE_SSE)
{
clear_version_and_features0_ecx.set_avx(true);
clear_version_and_features0_ecx.set_fma(true);

clear_extended_features0_ebx.set_avx2(true);

clear_extended_features0_ecx.set_vaes(true);
clear_extended_features0_ecx.set_gfni(true);
clear_extended_features0_ecx.set_vpclmulqdq(true);

disable_avx_512 = true;
}

if disable_avx_512 || (xsave_support & xsave::XFEATURE_AVX512 != xsave::XFEATURE_AVX512) {
clear_extended_features0_ebx.set_avx512f(true);
clear_extended_features0_ebx.set_avx512dq(true);
clear_extended_features0_ebx.set_avx512_ifma(true);
clear_extended_features0_ebx.set_avx512cd(true);
clear_extended_features0_ebx.set_avx512bw(true);
clear_extended_features0_ebx.set_avx512vl(true);

clear_extended_features0_ecx.set_avx512_vbmi(true);
clear_extended_features0_ecx.set_avx512_vbmi2(true);
clear_extended_features0_ecx.set_avx512_vnni(true);
clear_extended_features0_ecx.set_avx512_bitalg(true);
clear_extended_features0_ecx.set_avx512_vpopcntdq(true);

clear_extended_features0_edx.set_avx512_vp2_intersect(true);
clear_extended_features0_edx.set_avx512_fp16(true);
}

let extended_features0_entry = self
.leaf_result_mut_ref(CpuidFunction::ExtendedFeatures, Some(0))
.expect("validated this leaf exists");

let clearing_ebx = cpuid::ExtendedFeatureSubleaf0Ebx::from(
extended_features0_entry.ebx & clear_extended_features0_ebx.into_bits(),
);

let clearing_ecx = cpuid::ExtendedFeatureSubleaf0Ecx::from(
extended_features0_entry.ecx & clear_extended_features0_ecx.into_bits(),
);

let clearing_edx = cpuid::ExtendedFeatureSubleaf0Edx::from(
extended_features0_entry.edx & clear_extended_features0_edx.into_bits(),
);

if (clearing_ebx.into_bits() != 0)
|| (clearing_ecx.into_bits() != 0)
|| (clearing_edx.into_bits() != 0)
{
tracing::warn!(
CVM_ALLOWED,
?clearing_ebx,
?clearing_ecx,
?clearing_edx,
?xsave_support,
"Disabling features in cpuid leaf 7.0 due to missing xsave support.",
);
}

extended_features0_entry.ebx &= !clear_extended_features0_ebx.into_bits();
extended_features0_entry.ecx &= !clear_extended_features0_ecx.into_bits();
extended_features0_entry.edx &= !clear_extended_features0_edx.into_bits();

let version_and_features = self
.leaf_result_mut_ref(CpuidFunction::VersionAndFeatures, None)
.expect("validated this leaf exists");

let clearing_ecx = cpuid::VersionAndFeaturesEcx::from(
version_and_features.ecx & clear_version_and_features0_ecx.into_bits(),
);

if clearing_ecx.into_bits() != 0 {
tracing::warn!(
CVM_ALLOWED,
?clearing_ecx,
?xsave_support,
"Disabling features in cpuid leaf 1.0 due to missing xsave support.",
);
}

version_and_features.ecx &= !clear_version_and_features0_ecx.into_bits();

arch_initializer.update_xsave_dependencies(xsave_support, self);
}

/// Returns a flag list of CPUID leaves.
///
/// The resulting sort order is unspecified.
Expand Down
4 changes: 4 additions & 0 deletions openhcl/virt_mshv_vtl/src/cvm_cpuid/snp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,10 @@ impl CpuidArchInitializer for SnpCpuidInitializer {

[l0, l1, l2, l3, l4]
}

fn update_xsave_dependencies(&self, _xsave_support: u64, _results: &mut CpuidResults) {
// No SNP-specific updates
}
}

pub struct SnpCpuidIterator<'a> {
Expand Down
94 changes: 94 additions & 0 deletions openhcl/virt_mshv_vtl/src/cvm_cpuid/tdx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,25 @@ impl CpuidArchInitializer for TdxCpuidInitializer<'_> {
.into(),
true,
))
} else if subleaf == 1 {
Some(CpuidResultMask::new(
cpuid::ExtendedFeatureSubleaf1Eax::new()
.with_avx_vnni(true)
.with_avx512_bfloat16(true)
.with_fzlrep_movsb(true)
.with_fsrep_stosb(true)
.with_fsrep_cmpsb(true)
.with_avx_ifma(true)
.into(),
0,
0,
cpuid::ExtendedFeatureSubleaf1Edx::new()
.with_avx_vnni_int8(true)
.with_avx_vnni_int16(true)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chris-oo avx_vnni_int16 is the new bit being filtered in. Lmk if you prefer we don't make this change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I still haven't tested yet that TDX boots)

.with_avx_ne_convert(true)
.into(),
true,
))
} else {
None
}
Expand Down Expand Up @@ -347,4 +366,79 @@ impl CpuidArchInitializer for TdxCpuidInitializer<'_> {

[l0, l1, l2, l3, l4]
}

fn update_xsave_dependencies(&self, xsave_support: u64, results: &mut CpuidResults) {
let mut clear_extended_features0_edx = cpuid::ExtendedFeatureSubleaf0Edx::new();
let mut clear_extended_features1_eax = cpuid::ExtendedFeatureSubleaf1Eax::new();
let mut clear_extended_features1_edx = cpuid::ExtendedFeatureSubleaf1Edx::new();

let mut disable_avx_512 = false;

if (xsave_support & xsave::XFEATURE_YMM != xsave::XFEATURE_YMM)
|| (xsave_support & xsave::XFEATURE_SSE != xsave::XFEATURE_SSE)
{
clear_extended_features1_eax.set_avx_vnni(true);
clear_extended_features1_eax.set_avx_ifma(true);

clear_extended_features1_edx.set_avx_vnni_int8(true);
clear_extended_features1_edx.set_avx_vnni_int16(true);
clear_extended_features1_edx.set_avx_ne_convert(true);

disable_avx_512 = true;
}

if disable_avx_512 || (xsave_support & xsave::XFEATURE_AVX512 != xsave::XFEATURE_AVX512) {
clear_extended_features1_eax.set_avx512_bfloat16(true);
}

if xsave_support & xsave::XFEATURE_AMX != xsave::XFEATURE_AMX {
clear_extended_features0_edx.set_amx_tile(true);
clear_extended_features0_edx.set_amx_int8(true);
clear_extended_features0_edx.set_amx_bf16(true);
}

let extended_features0_entry = results
.leaf_result_mut_ref(CpuidFunction::ExtendedFeatures, Some(0))
.expect("validated this leaf exists");

let clearing_edx = cpuid::ExtendedFeatureSubleaf0Edx::from(
extended_features0_entry.edx & clear_extended_features0_edx.into_bits(),
);

if clearing_edx.into_bits() != 0 {
tracing::warn!(
CVM_ALLOWED,
?clear_extended_features0_edx,
?xsave_support,
"Disabling features in cpuid leaf 7.0 due to missing xsave support.",
);
}

extended_features0_entry.edx &= !clear_extended_features0_edx.into_bits();

let extended_features1_entry = results
.leaf_result_mut_ref(CpuidFunction::ExtendedFeatures, Some(1))
.expect("validated this leaf exists");

let clearing_eax = cpuid::ExtendedFeatureSubleaf1Eax::from(
extended_features1_entry.eax & u32::from(clear_extended_features1_eax),
);

let clearing_edx = cpuid::ExtendedFeatureSubleaf1Edx::from(
extended_features1_entry.edx & u32::from(clear_extended_features1_edx),
);

if (clearing_eax.into_bits() != 0) || (clearing_edx.into_bits() != 0) {
tracing::warn!(
CVM_ALLOWED,
?clear_extended_features1_eax,
?clear_extended_features1_edx,
?xsave_support,
"Disabling features in cpuid leaf 7.1 due to missing xsave support.",
);
}

extended_features1_entry.eax &= !clear_extended_features1_eax.into_bits();
extended_features1_entry.edx &= !clear_extended_features1_edx.into_bits();
}
}
Loading