Skip to content

Commit 05d11e8

Browse files
committed
x86: pass through cpuid leaves 15h and 16h
These leaves communicate TSC and CPU frequencies to the guest, and are used by the guest as a preferred means of calibration. This is especially important in secret-free contexts, where kvm-clock is not available (so guest cannot get TSC frequency from there), and calibration against PIT is unreliable. Signed-off-by: Patrick Roy <[email protected]>
1 parent 9fc405b commit 05d11e8

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

src/vmm/src/cpu_config/x86_64/cpuid/intel/normalize.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::cpu_config::x86_64::cpuid::normalize::{
55
CheckedAssignError, get_range, set_bit, set_range,
66
};
77
use crate::cpu_config::x86_64::cpuid::{
8-
BRAND_STRING_LENGTH, CpuidKey, CpuidRegisters, CpuidTrait, MissingBrandStringLeaves,
8+
BRAND_STRING_LENGTH, CpuidKey, CpuidRegisters, CpuidTrait, MissingBrandStringLeaves, cpuid,
99
host_brand_string,
1010
};
1111

@@ -71,10 +71,41 @@ impl super::IntelCpuid {
7171
self.update_performance_monitoring_entry()?;
7272
self.update_extended_topology_v2_entry();
7373
self.update_brand_string_entry()?;
74+
self.update_frequency_information();
7475

7576
Ok(())
7677
}
7778

79+
/// Passes through the host value of cpuid leaves 15h and 16h if they
80+
/// are not already configured via cpu template.
81+
fn update_frequency_information(&mut self) {
82+
let Some(leaf_15h) = self.get_mut(&CpuidKey::leaf(0x15)) else {
83+
return;
84+
};
85+
86+
if leaf_15h.result == CpuidRegisters::default() {
87+
let host_leaf_15 = cpuid(0x15);
88+
89+
leaf_15h.result.eax = host_leaf_15.eax;
90+
leaf_15h.result.ebx = host_leaf_15.ebx;
91+
leaf_15h.result.ecx = host_leaf_15.ecx;
92+
// edx is reserved
93+
}
94+
95+
let Some(leaf_16h) = self.get_mut(&CpuidKey::leaf(0x16)) else {
96+
return;
97+
};
98+
99+
if leaf_16h.result == CpuidRegisters::default() {
100+
let host_leaf_16 = cpuid(0x16);
101+
102+
leaf_16h.result.eax = host_leaf_16.eax;
103+
leaf_16h.result.ebx = host_leaf_16.ebx;
104+
leaf_16h.result.ecx = host_leaf_16.ecx;
105+
// edx is reserved
106+
}
107+
}
108+
78109
/// Update deterministic cache entry
79110
#[allow(clippy::unwrap_in_result)]
80111
fn update_deterministic_cache_entry(

0 commit comments

Comments
 (0)