Skip to content

Commit add1d52

Browse files
committed
refactor: Store msrs_to_save in struct Vm instead of Kvm
This allows us to not need to feed `struct Kvm` all the way down to Vcpu creation. While we're at it, abstract away the `MsrList` type, and just have a helper that returns a slice of u32 (as every call site converts the MsrList to this anyway). Signed-off-by: Patrick Roy <[email protected]>
1 parent de011a0 commit add1d52

File tree

7 files changed

+53
-53
lines changed

7 files changed

+53
-53
lines changed

src/vmm/src/builder.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ fn create_vmm_and_vcpus(
192192
#[cfg(target_arch = "x86_64")]
193193
let (vcpus, pio_device_manager) = {
194194
setup_interrupt_controller(&mut vm)?;
195-
let vcpus = create_vcpus(&kvm, &vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?;
195+
let vcpus = create_vcpus(&vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?;
196196

197197
// Make stdout non blocking.
198198
set_stdout_nonblocking();
@@ -224,7 +224,7 @@ fn create_vmm_and_vcpus(
224224
// Search for `kvm_arch_vcpu_create` in arch/arm/kvm/arm.c.
225225
#[cfg(target_arch = "aarch64")]
226226
let vcpus = {
227-
let vcpus = create_vcpus(&kvm, &vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?;
227+
let vcpus = create_vcpus(&vm, vcpu_count, &vcpus_exit_evt).map_err(Internal)?;
228228
setup_interrupt_controller(&mut vm, vcpu_count)?;
229229
vcpus
230230
};
@@ -746,16 +746,11 @@ fn attach_legacy_devices_aarch64(
746746
.map_err(VmmError::RegisterMMIODevice)
747747
}
748748

749-
fn create_vcpus(
750-
kvm: &Kvm,
751-
vm: &Vm,
752-
vcpu_count: u8,
753-
exit_evt: &EventFd,
754-
) -> Result<Vec<Vcpu>, VmmError> {
749+
fn create_vcpus(vm: &Vm, vcpu_count: u8, exit_evt: &EventFd) -> Result<Vec<Vcpu>, VmmError> {
755750
let mut vcpus = Vec::with_capacity(vcpu_count as usize);
756751
for cpu_idx in 0..vcpu_count {
757752
let exit_evt = exit_evt.try_clone().map_err(VmmError::EventFd)?;
758-
let vcpu = Vcpu::new(cpu_idx, vm, kvm, exit_evt).map_err(VmmError::VcpuCreate)?;
753+
let vcpu = Vcpu::new(cpu_idx, vm, exit_evt).map_err(VmmError::VcpuCreate)?;
759754
vcpus.push(vcpu);
760755
}
761756
Ok(vcpus)
@@ -1164,7 +1159,7 @@ pub(crate) mod tests {
11641159
#[cfg(target_arch = "aarch64")]
11651160
{
11661161
let exit_evt = EventFd::new(libc::EFD_NONBLOCK).unwrap();
1167-
let _vcpu = Vcpu::new(1, &vm, &kvm, exit_evt).unwrap();
1162+
let _vcpu = Vcpu::new(1, &vm, exit_evt).unwrap();
11681163
setup_interrupt_controller(&mut vm, 1).unwrap();
11691164
}
11701165

@@ -1399,7 +1394,7 @@ pub(crate) mod tests {
13991394
#[cfg(target_arch = "x86_64")]
14001395
setup_interrupt_controller(&mut vm).unwrap();
14011396

1402-
let vcpu_vec = create_vcpus(&kvm, &vm, vcpu_count, &evfd).unwrap();
1397+
let vcpu_vec = create_vcpus(&vm, vcpu_count, &evfd).unwrap();
14031398
assert_eq!(vcpu_vec.len(), vcpu_count as usize);
14041399
}
14051400

src/vmm/src/vstate/kvm.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ pub enum KvmError {
2323
configured on the /dev/kvm file's ACL. */
2424
Kvm(kvm_ioctls::Error),
2525
#[cfg(target_arch = "x86_64")]
26-
/// Failed to get MSR index list to save into snapshots: {0}
27-
GetMsrsToSave(crate::arch::x86_64::msr::MsrError),
28-
#[cfg(target_arch = "x86_64")]
2926
/// Failed to get supported cpuid: {0}
3027
GetSupportedCpuId(kvm_ioctls::Error),
3128
/// The number of configured slots is bigger than the maximum reported by KVM
@@ -45,9 +42,6 @@ pub struct Kvm {
4542
#[cfg(target_arch = "x86_64")]
4643
/// Supported CpuIds.
4744
pub supported_cpuid: CpuId,
48-
#[cfg(target_arch = "x86_64")]
49-
/// Msrs needed to be saved on snapshot creation.
50-
pub msrs_to_save: MsrList,
5145
}
5246

5347
impl Kvm {
@@ -82,19 +76,22 @@ impl Kvm {
8276
let supported_cpuid = kvm_fd
8377
.get_supported_cpuid(KVM_MAX_CPUID_ENTRIES)
8478
.map_err(KvmError::GetSupportedCpuId)?;
85-
let msrs_to_save = crate::arch::x86_64::msr::get_msrs_to_save(&kvm_fd)
86-
.map_err(KvmError::GetMsrsToSave)?;
8779

8880
Ok(Kvm {
8981
fd: kvm_fd,
9082
max_memslots,
9183
kvm_cap_modifiers,
9284
supported_cpuid,
93-
msrs_to_save,
9485
})
9586
}
9687
}
9788

89+
/// Msrs needed to be saved on snapshot creation.
90+
#[cfg(target_arch = "x86_64")]
91+
pub fn msrs_to_save(&self) -> Result<MsrList, crate::arch::x86_64::msr::MsrError> {
92+
crate::arch::x86_64::msr::get_msrs_to_save(&self.fd)
93+
}
94+
9895
/// Check guest memory does not have more regions than kvm allows.
9996
pub fn check_memory(&self, guest_mem: &GuestMemoryMmap) -> Result<(), KvmError> {
10097
if guest_mem.num_regions() > self.max_memslots {

src/vmm/src/vstate/vcpu/aarch64.rs

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::cpu_config::aarch64::custom_cpu_template::VcpuFeatures;
2222
use crate::cpu_config::templates::CpuConfiguration;
2323
use crate::logger::{error, IncMetric, METRICS};
2424
use crate::vcpu::{VcpuConfig, VcpuError};
25-
use crate::vstate::kvm::{Kvm, OptionalCapabilities};
25+
use crate::vstate::kvm::OptionalCapabilities;
2626
use crate::vstate::memory::{Address, GuestAddress, GuestMemoryMmap};
2727
use crate::vstate::vcpu::VcpuEmulation;
2828
use crate::vstate::vm::Vm;
@@ -78,7 +78,7 @@ impl KvmVcpu {
7878
///
7979
/// * `index` - Represents the 0-based CPU index between [0, max vcpus).
8080
/// * `vm` - The vm to which this vcpu will get attached.
81-
pub fn new(index: u8, vm: &Vm, _: &Kvm) -> Result<Self, KvmVcpuError> {
81+
pub fn new(index: u8, vm: &Vm) -> Result<Self, KvmVcpuError> {
8282
let kvm_vcpu = vm
8383
.fd()
8484
.create_vcpu(index.into())
@@ -315,7 +315,7 @@ mod tests {
315315

316316
fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) {
317317
let (kvm, mut vm, vm_mem) = setup_vm_with_memory(mem_size);
318-
let mut vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap();
318+
let mut vcpu = KvmVcpu::new(0, &vm).unwrap();
319319
vcpu.init(&[]).unwrap();
320320
vm.setup_irqchip(1).unwrap();
321321

@@ -324,11 +324,11 @@ mod tests {
324324

325325
#[test]
326326
fn test_create_vcpu() {
327-
let (kvm, vm, _) = setup_vm_with_memory(0x1000);
327+
let (_, vm, _) = setup_vm_with_memory(0x1000);
328328

329329
unsafe { libc::close(vm.fd().as_raw_fd()) };
330330

331-
let err = KvmVcpu::new(0, &vm, &kvm);
331+
let err = KvmVcpu::new(0, &vm);
332332
assert_eq!(
333333
err.err().unwrap().to_string(),
334334
"Error creating vcpu: Bad file descriptor (os error 9)".to_string()
@@ -378,8 +378,8 @@ mod tests {
378378

379379
#[test]
380380
fn test_init_vcpu() {
381-
let (kvm, mut vm, _) = setup_vm_with_memory(0x1000);
382-
let mut vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap();
381+
let (_, mut vm, _) = setup_vm_with_memory(0x1000);
382+
let mut vcpu = KvmVcpu::new(0, &vm).unwrap();
383383
vm.setup_irqchip(1).unwrap();
384384

385385
// KVM_ARM_VCPU_PSCI_0_2 is set by default.
@@ -397,8 +397,8 @@ mod tests {
397397

398398
#[test]
399399
fn test_vcpu_save_restore_state() {
400-
let (kvm, mut vm, _) = setup_vm_with_memory(0x1000);
401-
let mut vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap();
400+
let (_, mut vm, _) = setup_vm_with_memory(0x1000);
401+
let mut vcpu = KvmVcpu::new(0, &vm).unwrap();
402402
vm.setup_irqchip(1).unwrap();
403403

404404
// Calling KVM_GET_REGLIST before KVM_VCPU_INIT will result in error.
@@ -441,8 +441,8 @@ mod tests {
441441
//
442442
// This should fail with ENOEXEC.
443443
// https://elixir.bootlin.com/linux/v5.10.176/source/arch/arm64/kvm/arm.c#L1165
444-
let (kvm, mut vm, _) = setup_vm_with_memory(0x1000);
445-
let vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap();
444+
let (_, mut vm, _) = setup_vm_with_memory(0x1000);
445+
let vcpu = KvmVcpu::new(0, &vm).unwrap();
446446
vm.setup_irqchip(1).unwrap();
447447

448448
vcpu.dump_cpu_config().unwrap_err();
@@ -451,8 +451,8 @@ mod tests {
451451
#[test]
452452
fn test_dump_cpu_config_after_init() {
453453
// Test `dump_cpu_config()` after `KVM_VCPU_INIT`.
454-
let (kvm, mut vm, _) = setup_vm_with_memory(0x1000);
455-
let mut vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap();
454+
let (_, mut vm, _) = setup_vm_with_memory(0x1000);
455+
let mut vcpu = KvmVcpu::new(0, &vm).unwrap();
456456
vm.setup_irqchip(1).unwrap();
457457
vcpu.init(&[]).unwrap();
458458

@@ -461,10 +461,10 @@ mod tests {
461461

462462
#[test]
463463
fn test_setup_non_boot_vcpu() {
464-
let (kvm, vm, _) = setup_vm_with_memory(0x1000);
465-
let mut vcpu1 = KvmVcpu::new(0, &vm, &kvm).unwrap();
464+
let (_, vm, _) = setup_vm_with_memory(0x1000);
465+
let mut vcpu1 = KvmVcpu::new(0, &vm).unwrap();
466466
vcpu1.init(&[]).unwrap();
467-
let mut vcpu2 = KvmVcpu::new(1, &vm, &kvm).unwrap();
467+
let mut vcpu2 = KvmVcpu::new(1, &vm).unwrap();
468468
vcpu2.init(&[]).unwrap();
469469
}
470470

src/vmm/src/vstate/vcpu/mod.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ pub use aarch64::{KvmVcpuError, *};
4444
#[cfg(target_arch = "x86_64")]
4545
pub use x86_64::{KvmVcpuError, *};
4646

47-
use super::kvm::Kvm;
48-
4947
/// Signal number (SIGRTMIN) used to kick Vcpus.
5048
pub const VCPU_RTSIG_OFFSET: i32 = 0;
5149

@@ -214,10 +212,10 @@ impl Vcpu {
214212
/// * `index` - Represents the 0-based CPU index between [0, max vcpus).
215213
/// * `vm` - The vm to which this vcpu will get attached.
216214
/// * `exit_evt` - An `EventFd` that will be written into when this vcpu exits.
217-
pub fn new(index: u8, vm: &Vm, kvm: &Kvm, exit_evt: EventFd) -> Result<Self, VcpuError> {
215+
pub fn new(index: u8, vm: &Vm, exit_evt: EventFd) -> Result<Self, VcpuError> {
218216
let (event_sender, event_receiver) = channel();
219217
let (response_sender, response_receiver) = channel();
220-
let kvm_vcpu = KvmVcpu::new(index, vm, kvm).unwrap();
218+
let kvm_vcpu = KvmVcpu::new(index, vm).unwrap();
221219

222220
Ok(Vcpu {
223221
exit_evt,
@@ -787,6 +785,7 @@ pub(crate) mod tests {
787785
use crate::devices::BusDevice;
788786
use crate::seccomp::get_empty_filters;
789787
use crate::utils::signal::validate_signal_num;
788+
use crate::vstate::kvm::Kvm;
790789
use crate::vstate::memory::{GuestAddress, GuestMemoryMmap};
791790
use crate::vstate::vcpu::VcpuError as EmulationError;
792791
use crate::vstate::vm::tests::setup_vm_with_memory;
@@ -937,15 +936,15 @@ pub(crate) mod tests {
937936

938937
#[cfg(target_arch = "aarch64")]
939938
let vcpu = {
940-
let mut vcpu = Vcpu::new(1, &vm, &kvm, exit_evt).unwrap();
939+
let mut vcpu = Vcpu::new(1, &vm, exit_evt).unwrap();
941940
vcpu.kvm_vcpu.init(&[]).unwrap();
942941
vm.setup_irqchip(1).unwrap();
943942
vcpu
944943
};
945944
#[cfg(target_arch = "x86_64")]
946945
let vcpu = {
947946
vm.setup_irqchip().unwrap();
948-
Vcpu::new(1, &vm, &kvm, exit_evt).unwrap()
947+
Vcpu::new(1, &vm, exit_evt).unwrap()
949948
};
950949
(kvm, vm, vcpu, gm)
951950
}

src/vmm/src/vstate/vcpu/x86_64.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use crate::arch::x86_64::msr::{create_boot_msr_entries, MsrError};
2323
use crate::arch::x86_64::regs::{SetupFpuError, SetupRegistersError, SetupSpecialRegistersError};
2424
use crate::cpu_config::x86_64::{cpuid, CpuConfiguration};
2525
use crate::logger::{IncMetric, METRICS};
26-
use crate::vstate::kvm::Kvm;
2726
use crate::vstate::memory::{Address, GuestAddress, GuestMemoryMmap};
2827
use crate::vstate::vcpu::{VcpuConfig, VcpuEmulation};
2928
use crate::vstate::vm::Vm;
@@ -165,7 +164,7 @@ impl KvmVcpu {
165164
///
166165
/// * `index` - Represents the 0-based CPU index between [0, max vcpus).
167166
/// * `vm` - The vm to which this vcpu will get attached.
168-
pub fn new(index: u8, vm: &Vm, kvm: &Kvm) -> Result<Self, KvmVcpuError> {
167+
pub fn new(index: u8, vm: &Vm) -> Result<Self, KvmVcpuError> {
169168
let kvm_vcpu = vm
170169
.fd()
171170
.create_vcpu(index.into())
@@ -175,7 +174,7 @@ impl KvmVcpu {
175174
index,
176175
fd: kvm_vcpu,
177176
peripherals: Default::default(),
178-
msrs_to_save: kvm.msrs_to_save.as_slice().to_vec(),
177+
msrs_to_save: vm.msrs_to_save().to_vec(),
179178
})
180179
}
181180

@@ -726,6 +725,7 @@ mod tests {
726725
StaticCpuTemplate,
727726
};
728727
use crate::cpu_config::x86_64::cpuid::{Cpuid, CpuidEntry, CpuidKey};
728+
use crate::vstate::kvm::Kvm;
729729
use crate::vstate::vm::tests::{setup_vm, setup_vm_with_memory};
730730
use crate::vstate::vm::Vm;
731731

@@ -750,7 +750,7 @@ mod tests {
750750
fn setup_vcpu(mem_size: usize) -> (Kvm, Vm, KvmVcpu, GuestMemoryMmap) {
751751
let (kvm, vm, vm_mem) = setup_vm_with_memory(mem_size);
752752
vm.setup_irqchip().unwrap();
753-
let vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap();
753+
let vcpu = KvmVcpu::new(0, &vm).unwrap();
754754
(kvm, vm, vcpu, vm_mem)
755755
}
756756

@@ -1168,11 +1168,11 @@ mod tests {
11681168
#[test]
11691169
fn test_get_msr_chunks_preserved_order() {
11701170
// Regression test for #4666
1171-
let (kvm, vm) = setup_vm();
1172-
let vcpu = KvmVcpu::new(0, &vm, &kvm).unwrap();
1171+
let (_, vm) = setup_vm();
1172+
let vcpu = KvmVcpu::new(0, &vm).unwrap();
11731173

11741174
// The list of supported MSR indices, in the order they were returned by KVM
1175-
let msrs_to_save = kvm.msrs_to_save;
1175+
let msrs_to_save = vm.msrs_to_save();
11761176
// The MSRs after processing. The order should be identical to the one returned by KVM, with
11771177
// the exception of deferred MSRs, which should be moved to the end (but show up in the same
11781178
// order as they are listed in [`DEFERRED_MSRS`].
@@ -1185,7 +1185,6 @@ mod tests {
11851185
.flat_map(|chunk| chunk.as_slice().iter())
11861186
.zip(
11871187
msrs_to_save
1188-
.as_slice()
11891188
.iter()
11901189
.filter(|&idx| !DEFERRED_MSRS.contains(idx))
11911190
.chain(DEFERRED_MSRS.iter()),

src/vmm/src/vstate/vm/aarch64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
66

77
use super::VmError;
88
use crate::arch::aarch64::gic::GicState;
9-
use crate::vstate::kvm::Kvm;
9+
use crate::Kvm;
1010

1111
/// Structure representing the current architecture's understand of what a "virtual machine" is.
1212
#[derive(Debug)]

src/vmm/src/vstate/vm/x86_64.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
use std::fmt;
55

66
use kvm_bindings::{
7-
kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, KVM_CLOCK_TSC_STABLE,
7+
kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2, MsrList, KVM_CLOCK_TSC_STABLE,
88
KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE, KVM_PIT_SPEAKER_DUMMY,
99
};
1010
use kvm_ioctls::VmFd;
1111
use serde::{Deserialize, Serialize};
1212

13+
use crate::arch::x86_64::msr::MsrError;
1314
use crate::vstate::vm::VmError;
1415

1516
/// Error type for [`Vm::restore_state`]
@@ -39,19 +40,23 @@ pub enum ArchVmError {
3940
VmSetClock(kvm_ioctls::Error),
4041
/// Failed to set KVM vm irqchip: {0}
4142
VmSetIrqChip(kvm_ioctls::Error),
43+
/// Failed to get MSR index list to save into snapshots: {0}
44+
GetMsrsToSave(MsrError),
4245
}
4346

4447
/// Structure representing the current architecture's understand of what a "virtual machine" is.
4548
#[derive(Debug)]
4649
pub struct ArchVm {
4750
pub(super) fd: VmFd,
51+
msrs_to_save: MsrList,
4852
}
4953

5054
impl ArchVm {
5155
/// Create a new `Vm` struct.
5256
pub fn new(kvm: &crate::vstate::kvm::Kvm) -> Result<ArchVm, VmError> {
5357
let fd = kvm.fd.create_vm().map_err(VmError::VmFd)?;
54-
Ok(ArchVm { fd })
58+
let msrs_to_save = kvm.msrs_to_save().map_err(ArchVmError::GetMsrsToSave)?;
59+
Ok(ArchVm { fd, msrs_to_save })
5560
}
5661

5762
/// Restores the KVM VM state.
@@ -139,6 +144,11 @@ impl ArchVm {
139144
ioapic,
140145
})
141146
}
147+
148+
/// Gets the list of MSRs to save when creating snapshots
149+
pub fn msrs_to_save(&self) -> &[u32] {
150+
self.msrs_to_save.as_slice()
151+
}
142152
}
143153

144154
#[derive(Default, Deserialize, Serialize)]

0 commit comments

Comments
 (0)