Skip to content

Commit 5eaf2eb

Browse files
committed
refactor: Split VmError enum into arch specific versions
Introduce `enum ArchVmError` which contains architecture specific variants for VM operations (mostly related to snapshot creation/restore). Do this by adapting exiting architecture specific enums that were used for snapshot restoration (x86_64)/GIC creation (aarch64). While we're at it, remove unused/duplicated enum variants, and on x86 use the SetIrqChip enum variant for failures inside `setup_irq_chip` instead of producing some generic `VmError`. Admittedly, there's a lot more cleanup that can be done here, but for now this is enough to attain my goals (separating architecture specific code). No functional change intended (apart from error messages changing). Signed-off-by: Patrick Roy <[email protected]>
1 parent 9af26f1 commit 5eaf2eb

File tree

5 files changed

+56
-69
lines changed

5 files changed

+56
-69
lines changed

src/vmm/src/builder.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError};
7171
use crate::vstate::kvm::Kvm;
7272
use crate::vstate::memory::{GuestAddress, GuestMemory, GuestMemoryMmap};
7373
use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuError};
74-
use crate::vstate::vm::Vm;
74+
use crate::vstate::vm::{Vm, VmError};
7575
use crate::{device_manager, EventManager, Vmm, VmmError};
7676

7777
/// Errors associated with starting the instance.
@@ -436,7 +436,7 @@ pub enum BuildMicrovmFromSnapshotError {
436436
/// Could not set TSC scaling within the snapshot: {0}
437437
SetTsc(#[from] crate::vstate::vcpu::SetTscError),
438438
/// Failed to restore microVM state: {0}
439-
RestoreState(#[from] crate::vstate::vm::RestoreStateError),
439+
RestoreState(#[from] crate::vstate::vm::ArchVmError),
440440
/// Failed to update microVM configuration: {0}
441441
VmUpdateConfig(#[from] MachineConfigError),
442442
/// Failed to restore MMIO device: {0}
@@ -675,6 +675,7 @@ where
675675
#[cfg(target_arch = "x86_64")]
676676
pub fn setup_interrupt_controller(vm: &mut Vm) -> Result<(), StartMicrovmError> {
677677
vm.setup_irqchip()
678+
.map_err(VmError::Arch)
678679
.map_err(VmmError::Vm)
679680
.map_err(StartMicrovmError::Internal)
680681
}
@@ -683,6 +684,7 @@ pub fn setup_interrupt_controller(vm: &mut Vm) -> Result<(), StartMicrovmError>
683684
#[cfg(target_arch = "aarch64")]
684685
pub fn setup_interrupt_controller(vm: &mut Vm, vcpu_count: u8) -> Result<(), StartMicrovmError> {
685686
vm.setup_irqchip(vcpu_count)
687+
.map_err(VmError::Arch)
686688
.map_err(VmmError::Vm)
687689
.map_err(StartMicrovmError::Internal)
688690
}

src/vmm/src/persist.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ pub enum MicrovmStateError {
129129
/// Cannot save Vcpu state: {0}
130130
SaveVcpuState(vstate::vcpu::VcpuError),
131131
/// Cannot save Vm state: {0}
132-
SaveVmState(vstate::vm::VmError),
132+
SaveVmState(vstate::vm::ArchVmError),
133133
/// Cannot signal Vcpu: {0}
134134
SignalVcpu(VcpuSendEventError),
135135
/// Vcpu is in unexpected state.

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

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,25 @@
44
use serde::{Deserialize, Serialize};
55

66
use crate::arch::aarch64::gic::GicState;
7-
use crate::vstate::vm::VmError;
87
use crate::Vm;
98

109
/// Error type for [`Vm::restore_state`]
11-
#[derive(Debug, thiserror::Error, displaydoc::Display)]
12-
pub enum RestoreStateError {
13-
/// {0}
14-
GicError(crate::arch::aarch64::gic::GicError),
15-
/// {0}
16-
VmError(VmError),
10+
#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)]
11+
pub enum ArchVmError {
12+
/// Error creating the global interrupt controller: {0}
13+
VmCreateGIC(crate::arch::aarch64::gic::GicError),
14+
/// Failed to save the VM's GIC state: {0}
15+
SaveGic(crate::arch::aarch64::gic::GicError),
16+
/// Failed to restore the VM's GIC state: {0}
17+
RestoreGic(crate::arch::aarch64::gic::GicError),
1718
}
1819

1920
impl Vm {
2021
/// Creates the GIC (Global Interrupt Controller).
21-
pub fn setup_irqchip(&mut self, vcpu_count: u8) -> Result<(), VmError> {
22+
pub fn setup_irqchip(&mut self, vcpu_count: u8) -> Result<(), ArchVmError> {
2223
self.irqchip_handle = Some(
2324
crate::arch::aarch64::gic::create_gic(&self.fd, vcpu_count.into(), None)
24-
.map_err(VmError::VmCreateGIC)?,
25+
.map_err(ArchVmError::VmCreateGIC)?,
2526
);
2627
Ok(())
2728
}
@@ -32,12 +33,12 @@ impl Vm {
3233
}
3334

3435
/// Saves and returns the Kvm Vm state.
35-
pub fn save_state(&self, mpidrs: &[u64]) -> Result<crate::vstate::vm::VmState, VmError> {
36-
Ok(crate::vstate::vm::VmState {
36+
pub fn save_state(&self, mpidrs: &[u64]) -> Result<VmState, ArchVmError> {
37+
Ok(VmState {
3738
gic: self
3839
.get_irqchip()
3940
.save_device(mpidrs)
40-
.map_err(VmError::SaveGic)?,
41+
.map_err(ArchVmError::SaveGic)?,
4142
})
4243
}
4344

@@ -46,14 +47,10 @@ impl Vm {
4647
/// # Errors
4748
///
4849
/// When [`crate::arch::aarch64::gic::GICDevice::restore_device`] errors.
49-
pub fn restore_state(
50-
&mut self,
51-
mpidrs: &[u64],
52-
state: &crate::vstate::vm::VmState,
53-
) -> Result<(), RestoreStateError> {
50+
pub fn restore_state(&mut self, mpidrs: &[u64], state: &VmState) -> Result<(), ArchVmError> {
5451
self.get_irqchip()
5552
.restore_device(mpidrs, &state.gic)
56-
.map_err(RestoreStateError::GicError)?;
53+
.map_err(ArchVmError::RestoreGic)?;
5754
Ok(())
5855
}
5956
}

src/vmm/src/vstate/vm/mod.rs

Lines changed: 3 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ mod arch;
2222
#[path = "aarch64.rs"]
2323
mod arch;
2424

25-
pub use arch::{RestoreStateError, VmState};
25+
pub use arch::{ArchVmError, VmState};
2626

2727
/// Errors associated with the wrappers over KVM ioctls.
2828
/// Needs `rustfmt::skip` to make multiline comments work
@@ -31,37 +31,12 @@ pub use arch::{RestoreStateError, VmState};
3131
pub enum VmError {
3232
/// Cannot set the memory regions: {0}
3333
SetUserMemoryRegion(kvm_ioctls::Error),
34-
#[cfg(target_arch = "aarch64")]
35-
/// Error creating the global interrupt controller: {0}
36-
VmCreateGIC(crate::arch::aarch64::gic::GicError),
3734
/// Cannot open the VM file descriptor: {0}
3835
VmFd(kvm_ioctls::Error),
39-
#[cfg(target_arch = "x86_64")]
40-
/// Failed to get KVM vm pit state: {0}
41-
VmGetPit2(kvm_ioctls::Error),
42-
#[cfg(target_arch = "x86_64")]
43-
/// Failed to get KVM vm clock: {0}
44-
VmGetClock(kvm_ioctls::Error),
45-
#[cfg(target_arch = "x86_64")]
46-
/// Failed to get KVM vm irqchip: {0}
47-
VmGetIrqChip(kvm_ioctls::Error),
48-
#[cfg(target_arch = "x86_64")]
49-
/// Failed to set KVM vm pit state: {0}
50-
VmSetPit2(kvm_ioctls::Error),
51-
#[cfg(target_arch = "x86_64")]
52-
/// Failed to set KVM vm clock: {0}
53-
VmSetClock(kvm_ioctls::Error),
54-
#[cfg(target_arch = "x86_64")]
55-
/// Failed to set KVM vm irqchip: {0}
56-
VmSetIrqChip(kvm_ioctls::Error),
5736
/// Cannot configure the microvm: {0}
5837
VmSetup(kvm_ioctls::Error),
59-
#[cfg(target_arch = "aarch64")]
60-
/// Failed to save the VM's GIC state: {0}
61-
SaveGic(crate::arch::aarch64::gic::GicError),
62-
#[cfg(target_arch = "aarch64")]
63-
/// Failed to restore the VM's GIC state: {0}
64-
RestoreGic(crate::arch::aarch64::gic::GicError),
38+
/// {0}
39+
Arch(#[from] ArchVmError),
6540
}
6641

6742
/// A wrapper around creating and using a VM.

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

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,13 @@ use kvm_bindings::{
99
};
1010
use serde::{Deserialize, Serialize};
1111

12-
use crate::vstate::vm::VmError;
1312
use crate::Vm;
1413

1514
/// Error type for [`Vm::restore_state`]
1615
#[allow(missing_docs)]
1716
#[cfg(target_arch = "x86_64")]
18-
#[derive(Debug, thiserror::Error, displaydoc::Display, PartialEq, Eq)]
19-
pub enum RestoreStateError {
17+
#[derive(Debug, PartialEq, Eq, thiserror::Error, displaydoc::Display)]
18+
pub enum ArchVmError {
2019
/// Set PIT2 error: {0}
2120
SetPit2(kvm_ioctls::Error),
2221
/// Set clock error: {0}
@@ -27,8 +26,18 @@ pub enum RestoreStateError {
2726
SetIrqChipPicSlave(kvm_ioctls::Error),
2827
/// Set IrqChipIoAPIC error: {0}
2928
SetIrqChipIoAPIC(kvm_ioctls::Error),
30-
/// VM error: {0}
31-
VmError(VmError),
29+
/// Failed to get KVM vm pit state: {0}
30+
VmGetPit2(kvm_ioctls::Error),
31+
/// Failed to get KVM vm clock: {0}
32+
VmGetClock(kvm_ioctls::Error),
33+
/// Failed to get KVM vm irqchip: {0}
34+
VmGetIrqChip(kvm_ioctls::Error),
35+
/// Failed to set KVM vm pit state: {0}
36+
VmSetPit2(kvm_ioctls::Error),
37+
/// Failed to set KVM vm clock: {0}
38+
VmSetClock(kvm_ioctls::Error),
39+
/// Failed to set KVM vm irqchip: {0}
40+
VmSetIrqChip(kvm_ioctls::Error),
3241
}
3342

3443
impl Vm {
@@ -42,42 +51,46 @@ impl Vm {
4251
/// - [`kvm_ioctls::VmFd::set_irqchip`] errors.
4352
/// - [`kvm_ioctls::VmFd::set_irqchip`] errors.
4453
/// - [`kvm_ioctls::VmFd::set_irqchip`] errors.
45-
pub fn restore_state(&mut self, state: &VmState) -> Result<(), RestoreStateError> {
54+
pub fn restore_state(&mut self, state: &VmState) -> Result<(), ArchVmError> {
4655
self.fd
4756
.set_pit2(&state.pitstate)
48-
.map_err(RestoreStateError::SetPit2)?;
57+
.map_err(ArchVmError::SetPit2)?;
4958
self.fd
5059
.set_clock(&state.clock)
51-
.map_err(RestoreStateError::SetClock)?;
60+
.map_err(ArchVmError::SetClock)?;
5261
self.fd
5362
.set_irqchip(&state.pic_master)
54-
.map_err(RestoreStateError::SetIrqChipPicMaster)?;
63+
.map_err(ArchVmError::SetIrqChipPicMaster)?;
5564
self.fd
5665
.set_irqchip(&state.pic_slave)
57-
.map_err(RestoreStateError::SetIrqChipPicSlave)?;
66+
.map_err(ArchVmError::SetIrqChipPicSlave)?;
5867
self.fd
5968
.set_irqchip(&state.ioapic)
60-
.map_err(RestoreStateError::SetIrqChipIoAPIC)?;
69+
.map_err(ArchVmError::SetIrqChipIoAPIC)?;
6170
Ok(())
6271
}
6372

6473
/// Creates the irq chip and an in-kernel device model for the PIT.
65-
pub fn setup_irqchip(&self) -> Result<(), VmError> {
66-
self.fd.create_irq_chip().map_err(VmError::VmSetup)?;
74+
pub fn setup_irqchip(&self) -> Result<(), ArchVmError> {
75+
self.fd
76+
.create_irq_chip()
77+
.map_err(ArchVmError::VmSetIrqChip)?;
6778
// We need to enable the emulation of a dummy speaker port stub so that writing to port 0x61
6879
// (i.e. KVM_SPEAKER_BASE_ADDRESS) does not trigger an exit to user space.
6980
let pit_config = kvm_pit_config {
7081
flags: KVM_PIT_SPEAKER_DUMMY,
7182
..Default::default()
7283
};
73-
self.fd.create_pit2(pit_config).map_err(VmError::VmSetup)
84+
self.fd
85+
.create_pit2(pit_config)
86+
.map_err(ArchVmError::VmSetIrqChip)
7487
}
7588

7689
/// Saves and returns the Kvm Vm state.
77-
pub fn save_state(&self) -> Result<VmState, VmError> {
78-
let pitstate = self.fd.get_pit2().map_err(VmError::VmGetPit2)?;
90+
pub fn save_state(&self) -> Result<VmState, ArchVmError> {
91+
let pitstate = self.fd.get_pit2().map_err(ArchVmError::VmGetPit2)?;
7992

80-
let mut clock = self.fd.get_clock().map_err(VmError::VmGetClock)?;
93+
let mut clock = self.fd.get_clock().map_err(ArchVmError::VmGetClock)?;
8194
// This bit is not accepted in SET_CLOCK, clear it.
8295
clock.flags &= !KVM_CLOCK_TSC_STABLE;
8396

@@ -87,23 +100,23 @@ impl Vm {
87100
};
88101
self.fd
89102
.get_irqchip(&mut pic_master)
90-
.map_err(VmError::VmGetIrqChip)?;
103+
.map_err(ArchVmError::VmGetIrqChip)?;
91104

92105
let mut pic_slave = kvm_irqchip {
93106
chip_id: KVM_IRQCHIP_PIC_SLAVE,
94107
..Default::default()
95108
};
96109
self.fd
97110
.get_irqchip(&mut pic_slave)
98-
.map_err(VmError::VmGetIrqChip)?;
111+
.map_err(ArchVmError::VmGetIrqChip)?;
99112

100113
let mut ioapic = kvm_irqchip {
101114
chip_id: KVM_IRQCHIP_IOAPIC,
102115
..Default::default()
103116
};
104117
self.fd
105118
.get_irqchip(&mut ioapic)
106-
.map_err(VmError::VmGetIrqChip)?;
119+
.map_err(ArchVmError::VmGetIrqChip)?;
107120

108121
Ok(VmState {
109122
pitstate,

0 commit comments

Comments
 (0)