mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-01 17:35:19 +00:00
pci: msi: Implement Snapshot for MsiConfig
Adding support for snapshot and restore to the MsiConfig structure, as it will be needed part of VFIO migration. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
3c8e280bf1
commit
f076819d81
@ -3,11 +3,17 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
|
||||
//
|
||||
|
||||
use anyhow::anyhow;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use std::io;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::{
|
||||
InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig,
|
||||
};
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
||||
|
||||
// MSI control masks
|
||||
const MSI_CTL_ENABLE: u16 = 0x1;
|
||||
@ -32,7 +38,15 @@ pub fn msi_num_enabled_vectors(msg_ctl: u16) -> usize {
|
||||
1 << field
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default)]
|
||||
#[derive(Error, Debug)]
|
||||
enum Error {
|
||||
#[error("Failed enabling the interrupt route: {0}")]
|
||||
EnableInterruptRoute(io::Error),
|
||||
#[error("Failed updating the interrupt route: {0}")]
|
||||
UpdateInterruptRoute(io::Error),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default, Versionize)]
|
||||
pub struct MsiCap {
|
||||
// Message Control Register
|
||||
// 0: MSI enable.
|
||||
@ -157,6 +171,13 @@ impl MsiCap {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Versionize)]
|
||||
struct MsiConfigState {
|
||||
cap: MsiCap,
|
||||
}
|
||||
|
||||
impl VersionMapped for MsiConfigState {}
|
||||
|
||||
pub struct MsiConfig {
|
||||
cap: MsiCap,
|
||||
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
|
||||
@ -175,6 +196,39 @@ impl MsiConfig {
|
||||
}
|
||||
}
|
||||
|
||||
fn state(&self) -> MsiConfigState {
|
||||
MsiConfigState { cap: self.cap }
|
||||
}
|
||||
|
||||
fn set_state(&mut self, state: &MsiConfigState) -> Result<(), Error> {
|
||||
self.cap = state.cap;
|
||||
|
||||
if self.enabled() {
|
||||
for idx in 0..self.num_enabled_vectors() {
|
||||
let config = MsiIrqSourceConfig {
|
||||
high_addr: self.cap.msg_addr_hi,
|
||||
low_addr: self.cap.msg_addr_lo,
|
||||
data: self.cap.msg_data as u32,
|
||||
devid: 0,
|
||||
};
|
||||
|
||||
self.interrupt_source_group
|
||||
.update(
|
||||
idx as InterruptIndex,
|
||||
InterruptSourceConfig::MsiIrq(config),
|
||||
self.cap.vector_masked(idx),
|
||||
)
|
||||
.map_err(Error::UpdateInterruptRoute)?;
|
||||
}
|
||||
|
||||
self.interrupt_source_group
|
||||
.enable()
|
||||
.map_err(Error::EnableInterruptRoute)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn enabled(&self) -> bool {
|
||||
self.cap.enabled()
|
||||
}
|
||||
@ -222,3 +276,26 @@ impl MsiConfig {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pausable for MsiConfig {}
|
||||
|
||||
impl Snapshottable for MsiConfig {
|
||||
fn id(&self) -> String {
|
||||
String::from("msi_config")
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_versioned_state(&self.id(), &self.state())
|
||||
}
|
||||
|
||||
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
|
||||
self.set_state(&snapshot.to_versioned_state(&self.id())?)
|
||||
.map_err(|e| {
|
||||
MigratableError::Restore(anyhow!(
|
||||
"Could not restore state for {}: {:?}",
|
||||
self.id(),
|
||||
e
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user