hypervisor: Ensure required feature MSRs are successfully restored

Feature MSRs must have consistent values across snapshot and restore,
otherwise we risk subtle time of check to time of use errors.

We thus adapt `Vcpu::set_state` to return a hard error if any feature
MSR cannot be restored.

It is enough to check that each MSR failing to be set does not have
an address corresponding to any of the feature MSRs stored in the
`KvmVcpu`. This is because the `msrs` in the `VcpuKvmState` contain all
the feature MSRs required by the selected CPU profile by construction.

Signed-off-by: Oliver Anderson <oliver.anderson@cyberus-technology.de>
On-behalf-of: SAP oliver.anderson@sap.com
This commit is contained in:
Oliver Anderson
2026-07-23 07:28:33 +02:00
committed by Rob Bradford
parent 30063eff7e
commit 2eb64a2b4f
2 changed files with 19 additions and 5 deletions

View File

@@ -101,6 +101,11 @@ pub enum HypervisorCpuError {
#[error("Failed to set Msr entries")]
SetMsrEntries(#[source] anyhow::Error),
///
/// Restoring required feature MSR
///
#[error("Failed to restore required feature MSR")]
RestoreFeatureMsr,
///
/// Getting Msr entries error
///
#[error("Failed to get Msr entries")]

View File

@@ -3394,12 +3394,18 @@ impl cpu::Vcpu for KvmVcpu {
let num_msrs = self.set_msrs(&state.msrs)?;
if num_msrs != expected_num_msrs {
let mut faulty_msr_index = num_msrs;
let mut required_feature_msr_not_set = false;
loop {
warn!(
"Detected faulty MSR 0x{:x} while setting MSRs",
state.msrs[faulty_msr_index].index
);
let msr_address = state.msrs[faulty_msr_index].index;
warn!("Detected faulty MSR {msr_address:#x} while setting MSRs");
if self.feature_msrs.iter().any(|msr| msr.index == msr_address) {
error!(
"Unable to set feature MSR {msr_address:#x}, MSR value={}",
state.msrs[faulty_msr_index].data
);
required_feature_msr_not_set = true;
}
// Skip the first bad MSR
let start_pos = faulty_msr_index + 1;
@@ -3414,6 +3420,9 @@ impl cpu::Vcpu for KvmVcpu {
faulty_msr_index = start_pos + num_msrs;
}
if required_feature_msr_not_set {
return Err(cpu::HypervisorCpuError::RestoreFeatureMsr);
}
}
self.set_vcpu_events(&state.vcpu_events)?;