Skip to content

Commit f9bfe0c

Browse files
committed
vstate: support serializing interrupts to snapshots
Vm object is now maintaining information about the interrupts (both traditional IRQs and MSI-X vectors) that are being used by microVM devices. Derive Serialize/Deserialize add logic for recreating objects for relevant types. Signed-off-by: Babis Chalios <[email protected]>
1 parent 5092382 commit f9bfe0c

File tree

1 file changed

+58
-2
lines changed

1 file changed

+58
-2
lines changed

src/vmm/src/vstate/vm.rs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use kvm_bindings::{
2020
};
2121
use kvm_ioctls::VmFd;
2222
use log::debug;
23+
use serde::{Deserialize, Serialize};
2324
use vm_device::interrupt::{InterruptSourceGroup, MsiIrqSourceConfig};
2425
use vmm_sys_util::errno;
2526
use vmm_sys_util::eventfd::EventFd;
@@ -28,6 +29,7 @@ pub use crate::arch::{ArchVm as Vm, ArchVmError, VmState};
2829
use crate::device_manager::resources::ResourceAllocator;
2930
use crate::logger::info;
3031
use crate::persist::CreateSnapshotError;
32+
use crate::snapshot::Persist;
3133
use crate::utils::u64_to_usize;
3234
use crate::vmm_config::snapshot::SnapshotType;
3335
use crate::vstate::memory::{
@@ -49,7 +51,7 @@ pub enum InterruptError {
4951
Kvm(#[from] kvm_ioctls::Error),
5052
}
5153

52-
#[derive(Debug)]
54+
#[derive(Debug, Serialize, Deserialize)]
5355
/// A struct representing an interrupt line used by some device of the microVM
5456
pub struct RoutingEntry {
5557
entry: kvm_irq_routing_entry,
@@ -114,6 +116,38 @@ impl MsiVectorGroup {
114116
}
115117
}
116118

119+
impl<'a> Persist<'a> for MsiVectorGroup {
120+
type State = HashMap<u32, u32>;
121+
type ConstructorArgs = Arc<Vm>;
122+
type Error = InterruptError;
123+
124+
fn save(&self) -> Self::State {
125+
// We don't save the "enabled" state of the MSI interrupt. PCI devices store the MSI-X
126+
// configuration and make sure that the vector is enabled during the restore path if it was
127+
// initially enabled
128+
self.irq_routes
129+
.iter()
130+
.map(|(id, route)| (*id, route.gsi))
131+
.collect()
132+
}
133+
134+
fn restore(
135+
constructor_args: Self::ConstructorArgs,
136+
state: &Self::State,
137+
) -> std::result::Result<Self, Self::Error> {
138+
let mut irq_routes = HashMap::new();
139+
140+
for (id, gsi) in state {
141+
irq_routes.insert(*id, MsiVector::new(*gsi, false)?);
142+
}
143+
144+
Ok(MsiVectorGroup {
145+
vm: constructor_args,
146+
irq_routes,
147+
})
148+
}
149+
}
150+
117151
impl InterruptSourceGroup for MsiVectorGroup {
118152
fn enable(&self) -> vm_device::interrupt::Result<()> {
119153
for (_, route) in self.irq_routes.iter() {
@@ -210,7 +244,7 @@ pub struct VmCommon {
210244
/// The guest memory of this Vm.
211245
pub guest_memory: GuestMemoryMmap,
212246
/// Interrupts used by Vm's devices
213-
interrupts: Arc<Mutex<HashMap<u32, RoutingEntry>>>,
247+
pub interrupts: Arc<Mutex<HashMap<u32, RoutingEntry>>>,
214248
}
215249

216250
/// Errors associated with the wrappers over KVM ioctls.
@@ -891,4 +925,26 @@ pub(crate) mod tests {
891925

892926
msix_group.set_gsi().unwrap();
893927
}
928+
929+
#[test]
930+
fn test_msi_vector_group_persistence() {
931+
let (_, mut vm) = setup_vm_with_memory(mib_to_bytes(128));
932+
enable_irqchip(&mut vm);
933+
let vm = Arc::new(vm);
934+
let msix_group = create_msix_group(&vm);
935+
936+
msix_group.enable().unwrap();
937+
let state = msix_group.save();
938+
let restored_group = MsiVectorGroup::restore(vm, &state).unwrap();
939+
940+
assert_eq!(msix_group.num_vectors(), restored_group.num_vectors());
941+
// Even if an MSI group is enabled, we don't save it as such. During restoration, the PCI
942+
// transport will make sure the correct config is set for the vectors and enable them
943+
// accordingly.
944+
for (id, vector) in msix_group.irq_routes {
945+
let new_vector = restored_group.irq_routes.get(&id).unwrap();
946+
assert_eq!(vector.gsi, new_vector.gsi);
947+
assert!(!new_vector.enabled.load(Ordering::Acquire));
948+
}
949+
}
894950
}

0 commit comments

Comments
 (0)