Skip to content

Commit f7f9895

Browse files
Coffeerilikebreath
authored andcommitted
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>
1 parent 676c0d3 commit f7f9895

3 files changed

Lines changed: 62 additions & 3 deletions

File tree

hypervisor/src/arch/x86/mod.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,36 @@ pub mod msr_index;
2828
// MTRR constants
2929
pub const MTRR_ENABLE: u64 = 0x800; // IA32_MTRR_DEF_TYPE MSR: E (MTRRs enabled) flag, bit 11
3030
pub const MTRR_MEM_TYPE_WB: u64 = 0x6;
31+
pub const MTRR_MSR_INDICES: [u32; 28] = [
32+
msr_index::MSR_MTRRdefType,
33+
msr_index::MSR_IA32_MTRR_PHYSBASE0,
34+
msr_index::MSR_IA32_MTRR_PHYSMASK0,
35+
msr_index::MSR_IA32_MTRR_PHYSBASE1,
36+
msr_index::MSR_IA32_MTRR_PHYSMASK1,
37+
msr_index::MSR_IA32_MTRR_PHYSBASE2,
38+
msr_index::MSR_IA32_MTRR_PHYSMASK2,
39+
msr_index::MSR_IA32_MTRR_PHYSBASE3,
40+
msr_index::MSR_IA32_MTRR_PHYSMASK3,
41+
msr_index::MSR_IA32_MTRR_PHYSBASE4,
42+
msr_index::MSR_IA32_MTRR_PHYSMASK4,
43+
msr_index::MSR_IA32_MTRR_PHYSBASE5,
44+
msr_index::MSR_IA32_MTRR_PHYSMASK5,
45+
msr_index::MSR_IA32_MTRR_PHYSBASE6,
46+
msr_index::MSR_IA32_MTRR_PHYSMASK6,
47+
msr_index::MSR_IA32_MTRR_PHYSBASE7,
48+
msr_index::MSR_IA32_MTRR_PHYSMASK7,
49+
msr_index::MSR_MTRRfix64K_00000,
50+
msr_index::MSR_MTRRfix16K_80000,
51+
msr_index::MSR_MTRRfix16K_A0000,
52+
msr_index::MSR_MTRRfix4K_C0000,
53+
msr_index::MSR_MTRRfix4K_C8000,
54+
msr_index::MSR_MTRRfix4K_D0000,
55+
msr_index::MSR_MTRRfix4K_D8000,
56+
msr_index::MSR_MTRRfix4K_E0000,
57+
msr_index::MSR_MTRRfix4K_E8000,
58+
msr_index::MSR_MTRRfix4K_F0000,
59+
msr_index::MSR_MTRRfix4K_F8000,
60+
];
3161

3262
// IOAPIC pins
3363
pub const NUM_IOAPIC_PINS: usize = 24;

hypervisor/src/arch/x86/msr_index.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,22 @@ pub const MSR_IA32_RTIT_ADDR3_B: ::std::os::raw::c_uint = 0x00000587;
8585
pub const MSR_IA32_RTIT_CR3_MATCH: ::std::os::raw::c_uint = 0x00000572;
8686
pub const MSR_IA32_RTIT_OUTPUT_BASE: ::std::os::raw::c_uint = 0x00000560;
8787
pub const MSR_IA32_RTIT_OUTPUT_MASK: ::std::os::raw::c_uint = 0x00000561;
88+
pub const MSR_IA32_MTRR_PHYSBASE0: ::std::os::raw::c_uint = 0x00000200;
89+
pub const MSR_IA32_MTRR_PHYSMASK0: ::std::os::raw::c_uint = 0x00000201;
90+
pub const MSR_IA32_MTRR_PHYSBASE1: ::std::os::raw::c_uint = 0x00000202;
91+
pub const MSR_IA32_MTRR_PHYSMASK1: ::std::os::raw::c_uint = 0x00000203;
92+
pub const MSR_IA32_MTRR_PHYSBASE2: ::std::os::raw::c_uint = 0x00000204;
93+
pub const MSR_IA32_MTRR_PHYSMASK2: ::std::os::raw::c_uint = 0x00000205;
94+
pub const MSR_IA32_MTRR_PHYSBASE3: ::std::os::raw::c_uint = 0x00000206;
95+
pub const MSR_IA32_MTRR_PHYSMASK3: ::std::os::raw::c_uint = 0x00000207;
96+
pub const MSR_IA32_MTRR_PHYSBASE4: ::std::os::raw::c_uint = 0x00000208;
97+
pub const MSR_IA32_MTRR_PHYSMASK4: ::std::os::raw::c_uint = 0x00000209;
98+
pub const MSR_IA32_MTRR_PHYSBASE5: ::std::os::raw::c_uint = 0x0000020a;
99+
pub const MSR_IA32_MTRR_PHYSMASK5: ::std::os::raw::c_uint = 0x0000020b;
100+
pub const MSR_IA32_MTRR_PHYSBASE6: ::std::os::raw::c_uint = 0x0000020c;
101+
pub const MSR_IA32_MTRR_PHYSMASK6: ::std::os::raw::c_uint = 0x0000020d;
102+
pub const MSR_IA32_MTRR_PHYSBASE7: ::std::os::raw::c_uint = 0x0000020e;
103+
pub const MSR_IA32_MTRR_PHYSMASK7: ::std::os::raw::c_uint = 0x0000020f;
88104
pub const MSR_MTRRfix64K_00000: ::std::os::raw::c_uint = 0x00000250;
89105
pub const MSR_MTRRfix16K_80000: ::std::os::raw::c_uint = 0x00000258;
90106
pub const MSR_MTRRfix16K_A0000: ::std::os::raw::c_uint = 0x00000259;

hypervisor/src/kvm/mod.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ pub use x86_64::{CpuId, ExtendedControlRegisters, MsrEntries, VcpuKvmState};
7070
use crate::ClockData;
7171
#[cfg(target_arch = "x86_64")]
7272
use crate::arch::x86::{
73-
CpuIdEntry, FpuState, LapicState, MsrEntry, NUM_IOAPIC_PINS, SpecialRegisters, XsaveState,
73+
CpuIdEntry, FpuState, LapicState, MTRR_MSR_INDICES, MsrEntry, NUM_IOAPIC_PINS,
74+
SpecialRegisters, XsaveState,
7475
};
7576
use crate::{CpuState, IoEventAddress, IrqRoutingEntry, MpState, StandardRegisters};
7677
// aarch64 dependencies
@@ -1128,9 +1129,21 @@ impl KvmHypervisor {
11281129
/// Retrieve the list of MSRs supported by the hypervisor.
11291130
///
11301131
fn get_msr_list(&self) -> hypervisor::Result<MsrList> {
1131-
self.kvm
1132+
let mut indices = self
1133+
.kvm
11321134
.get_msr_index_list()
1133-
.map_err(|e| hypervisor::HypervisorError::GetMsrList(e.into()))
1135+
.map_err(|e| hypervisor::HypervisorError::GetMsrList(e.into()))?
1136+
.as_slice()
1137+
.to_vec();
1138+
1139+
// KVM_GET_MSR_INDEX_LIST does not include MTRR MSRs, but firmware may update them before an early boot snapshot.
1140+
indices.extend(MTRR_MSR_INDICES);
1141+
1142+
let mut msr_list = MsrList::new(indices.len())
1143+
.map_err(|e| hypervisor::HypervisorError::GetMsrList(e.into()))?;
1144+
msr_list.as_mut_slice().copy_from_slice(&indices);
1145+
1146+
Ok(msr_list)
11341147
}
11351148
}
11361149

0 commit comments

Comments
 (0)