Skip to content

Commit a602730

Browse files
zulinx86ShadowCurse
authored andcommitted
fix(vmm): disable IA32_ARCH_CAPABILITIES MSR on AMD
Disable IA32_ARCH_CAPABILITIES MSR on AMD by disabling CPUID.07H(ECX=0):EDX[bit 29]. This normalization was added in PR firecracker-microvm#1030, but was removed in PR firecracker-microvm#3076. Signed-off-by: Takahiro Itazuri <[email protected]>
1 parent 7f9d750 commit a602730

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

src/vmm/src/guest_config/cpuid/amd/normalize.rs

+72
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ pub enum NormalizeCpuidError {
1818
/// Failed to passthrough cache topology.
1919
#[error("Failed to passthrough cache topology: {0}")]
2020
PassthroughCacheTopology(#[from] PassthroughCacheTopologyError),
21+
/// Missing leaf 0x7 / subleaf 0.
22+
#[error("Missing leaf 0x7 / subleaf 0.")]
23+
MissingLeaf0x7Subleaf0,
2124
/// Missing leaf 0x80000000.
2225
#[error("Missing leaf 0x80000000.")]
2326
MissingLeaf0x80000000,
@@ -119,6 +122,7 @@ impl super::AmdCpuid {
119122
cpus_per_core: u8,
120123
) -> Result<(), NormalizeCpuidError> {
121124
self.passthrough_cache_topology()?;
125+
self.update_structured_extended_entry()?;
122126
self.update_largest_extended_fn_entry()?;
123127
self.update_extended_feature_fn_entry()?;
124128
self.update_amd_feature_entry(cpu_count)?;
@@ -227,6 +231,20 @@ impl super::AmdCpuid {
227231
Ok(())
228232
}
229233

234+
// Update structured extended feature entry.
235+
fn update_structured_extended_entry(&mut self) -> Result<(), NormalizeCpuidError> {
236+
let leaf_7_subleaf_0 = self
237+
.get_mut(&CpuidKey::subleaf(0x7, 0x0))
238+
.ok_or(NormalizeCpuidError::MissingLeaf0x7Subleaf0)?;
239+
240+
// According to AMD64 Architecture Programmer’s Manual, IA32_ARCH_CAPABILITIES MSR is not
241+
// available on AMD. The availability of IA32_ARCH_CAPABILITIES MSR is controlled via
242+
// CPUID.07H(ECX=0):EDX[bit 29]. KVM sets this bit no matter what but this feature is not
243+
// supported by hardware.
244+
set_bit(&mut leaf_7_subleaf_0.result.edx, 29, false);
245+
Ok(())
246+
}
247+
230248
/// Update AMD feature entry.
231249
#[allow(clippy::unwrap_used, clippy::unwrap_in_result)]
232250
fn update_amd_feature_entry(&mut self, cpu_count: u8) -> Result<(), FeatureEntryError> {
@@ -408,3 +426,57 @@ impl super::AmdCpuid {
408426
Ok(())
409427
}
410428
}
429+
430+
#[cfg(test)]
431+
mod tests {
432+
433+
use std::collections::BTreeMap;
434+
435+
use super::*;
436+
use crate::guest_config::cpuid::AmdCpuid;
437+
438+
#[test]
439+
fn test_update_structured_extended_entry_invalid() {
440+
// `update_structured_extended_entry()` should exit with MissingLeaf0x7Subleaf0 error for
441+
// CPUID lacking leaf 0x7 / subleaf 0.
442+
let mut cpuid = AmdCpuid(BTreeMap::new());
443+
assert_eq!(
444+
cpuid.update_structured_extended_entry().unwrap_err(),
445+
NormalizeCpuidError::MissingLeaf0x7Subleaf0
446+
);
447+
}
448+
449+
#[test]
450+
fn test_update_structured_extended_entry_valid() {
451+
// `update_structured_extended_entry()` should succeed for CPUID having leaf 0x7 / subleaf
452+
// 0, and bit 29 of EDX (IA32_ARCH_CAPABILITIES MSR enumeration) should be disabled.
453+
let mut cpuid = AmdCpuid(BTreeMap::from([(
454+
CpuidKey {
455+
leaf: 0x7,
456+
subleaf: 0x0,
457+
},
458+
CpuidEntry {
459+
flags: KvmCpuidFlags::SIGNIFICANT_INDEX,
460+
result: CpuidRegisters {
461+
eax: 0,
462+
ebx: 0,
463+
ecx: 0,
464+
edx: u32::MAX,
465+
},
466+
},
467+
)]));
468+
assert!(cpuid.update_structured_extended_entry().is_ok());
469+
assert_eq!(
470+
cpuid
471+
.get(&CpuidKey {
472+
leaf: 0x7,
473+
subleaf: 0x0
474+
})
475+
.unwrap()
476+
.result
477+
.edx
478+
& (1 << 29),
479+
0
480+
);
481+
}
482+
}

0 commit comments

Comments
 (0)