hypervisor: kvm: preserve guest MTRR MSRs

KVM_GET_MSR_INDEX_LIST does not consistently include all
guest-programmable MTRR MSRs.

During save/restore while booting, the VMM initially sets only
MSR_MTRRdefType, then guest firmware or other early boot code can
program additional MTRR state before the snapshot is taken. If those
MSRs are missing from the vCPU MSR buffer, snapshot omits part of the
guest's MTRR configuration and restore resumes with an incomplete
MTRR map.

Add the guest-programmable MTRR MSRs to the KVM MSR index list used
to build the vCPU MSR buffer so the existing snapshot/restore path
preserves the guest's MTRR state.

On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
This commit is contained in:
Leander Kohler
2026-03-20 13:07:10 +01:00
committed by Bo Chen
parent 676c0d320b
commit f7f9895d57
3 changed files with 62 additions and 3 deletions

View File

@@ -28,6 +28,36 @@ pub mod msr_index;
// MTRR constants
pub const MTRR_ENABLE: u64 = 0x800; // IA32_MTRR_DEF_TYPE MSR: E (MTRRs enabled) flag, bit 11
pub const MTRR_MEM_TYPE_WB: u64 = 0x6;
pub const MTRR_MSR_INDICES: [u32; 28] = [
msr_index::MSR_MTRRdefType,
msr_index::MSR_IA32_MTRR_PHYSBASE0,
msr_index::MSR_IA32_MTRR_PHYSMASK0,
msr_index::MSR_IA32_MTRR_PHYSBASE1,
msr_index::MSR_IA32_MTRR_PHYSMASK1,
msr_index::MSR_IA32_MTRR_PHYSBASE2,
msr_index::MSR_IA32_MTRR_PHYSMASK2,
msr_index::MSR_IA32_MTRR_PHYSBASE3,
msr_index::MSR_IA32_MTRR_PHYSMASK3,
msr_index::MSR_IA32_MTRR_PHYSBASE4,
msr_index::MSR_IA32_MTRR_PHYSMASK4,
msr_index::MSR_IA32_MTRR_PHYSBASE5,
msr_index::MSR_IA32_MTRR_PHYSMASK5,
msr_index::MSR_IA32_MTRR_PHYSBASE6,
msr_index::MSR_IA32_MTRR_PHYSMASK6,
msr_index::MSR_IA32_MTRR_PHYSBASE7,
msr_index::MSR_IA32_MTRR_PHYSMASK7,
msr_index::MSR_MTRRfix64K_00000,
msr_index::MSR_MTRRfix16K_80000,
msr_index::MSR_MTRRfix16K_A0000,
msr_index::MSR_MTRRfix4K_C0000,
msr_index::MSR_MTRRfix4K_C8000,
msr_index::MSR_MTRRfix4K_D0000,
msr_index::MSR_MTRRfix4K_D8000,
msr_index::MSR_MTRRfix4K_E0000,
msr_index::MSR_MTRRfix4K_E8000,
msr_index::MSR_MTRRfix4K_F0000,
msr_index::MSR_MTRRfix4K_F8000,
];
// IOAPIC pins
pub const NUM_IOAPIC_PINS: usize = 24;

View File

@@ -85,6 +85,22 @@ pub const MSR_IA32_RTIT_ADDR3_B: ::std::os::raw::c_uint = 0x00000587;
pub const MSR_IA32_RTIT_CR3_MATCH: ::std::os::raw::c_uint = 0x00000572;
pub const MSR_IA32_RTIT_OUTPUT_BASE: ::std::os::raw::c_uint = 0x00000560;
pub const MSR_IA32_RTIT_OUTPUT_MASK: ::std::os::raw::c_uint = 0x00000561;
pub const MSR_IA32_MTRR_PHYSBASE0: ::std::os::raw::c_uint = 0x00000200;
pub const MSR_IA32_MTRR_PHYSMASK0: ::std::os::raw::c_uint = 0x00000201;
pub const MSR_IA32_MTRR_PHYSBASE1: ::std::os::raw::c_uint = 0x00000202;
pub const MSR_IA32_MTRR_PHYSMASK1: ::std::os::raw::c_uint = 0x00000203;
pub const MSR_IA32_MTRR_PHYSBASE2: ::std::os::raw::c_uint = 0x00000204;
pub const MSR_IA32_MTRR_PHYSMASK2: ::std::os::raw::c_uint = 0x00000205;
pub const MSR_IA32_MTRR_PHYSBASE3: ::std::os::raw::c_uint = 0x00000206;
pub const MSR_IA32_MTRR_PHYSMASK3: ::std::os::raw::c_uint = 0x00000207;
pub const MSR_IA32_MTRR_PHYSBASE4: ::std::os::raw::c_uint = 0x00000208;
pub const MSR_IA32_MTRR_PHYSMASK4: ::std::os::raw::c_uint = 0x00000209;
pub const MSR_IA32_MTRR_PHYSBASE5: ::std::os::raw::c_uint = 0x0000020a;
pub const MSR_IA32_MTRR_PHYSMASK5: ::std::os::raw::c_uint = 0x0000020b;
pub const MSR_IA32_MTRR_PHYSBASE6: ::std::os::raw::c_uint = 0x0000020c;
pub const MSR_IA32_MTRR_PHYSMASK6: ::std::os::raw::c_uint = 0x0000020d;
pub const MSR_IA32_MTRR_PHYSBASE7: ::std::os::raw::c_uint = 0x0000020e;
pub const MSR_IA32_MTRR_PHYSMASK7: ::std::os::raw::c_uint = 0x0000020f;
pub const MSR_MTRRfix64K_00000: ::std::os::raw::c_uint = 0x00000250;
pub const MSR_MTRRfix16K_80000: ::std::os::raw::c_uint = 0x00000258;
pub const MSR_MTRRfix16K_A0000: ::std::os::raw::c_uint = 0x00000259;

View File

@@ -70,7 +70,8 @@ pub use x86_64::{CpuId, ExtendedControlRegisters, MsrEntries, VcpuKvmState};
use crate::ClockData;
#[cfg(target_arch = "x86_64")]
use crate::arch::x86::{
CpuIdEntry, FpuState, LapicState, MsrEntry, NUM_IOAPIC_PINS, SpecialRegisters, XsaveState,
CpuIdEntry, FpuState, LapicState, MTRR_MSR_INDICES, MsrEntry, NUM_IOAPIC_PINS,
SpecialRegisters, XsaveState,
};
use crate::{CpuState, IoEventAddress, IrqRoutingEntry, MpState, StandardRegisters};
// aarch64 dependencies
@@ -1128,9 +1129,21 @@ impl KvmHypervisor {
/// Retrieve the list of MSRs supported by the hypervisor.
///
fn get_msr_list(&self) -> hypervisor::Result<MsrList> {
self.kvm
let mut indices = self
.kvm
.get_msr_index_list()
.map_err(|e| hypervisor::HypervisorError::GetMsrList(e.into()))
.map_err(|e| hypervisor::HypervisorError::GetMsrList(e.into()))?
.as_slice()
.to_vec();
// KVM_GET_MSR_INDEX_LIST does not include MTRR MSRs, but firmware may update them before an early boot snapshot.
indices.extend(MTRR_MSR_INDICES);
let mut msr_list = MsrList::new(indices.len())
.map_err(|e| hypervisor::HypervisorError::GetMsrList(e.into()))?;
msr_list.as_mut_slice().copy_from_slice(&indices);
Ok(msr_list)
}
}