mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-02 11:35:46 +00:00
arch, vmm: Implement GIC Pausable trait
This commit implements the GIC (including both GICv3 and GICv3ITS) Pausable trait. The pause of device manager will trigger a "pause" of GIC, where we flush GIC pending tables and ITS tables to the guest RAM. Signed-off-by: Henry Wang <Henry.Wang@arm.com>
This commit is contained in:
parent
7b80709595
commit
46c60183cd
@ -109,9 +109,6 @@ pub mod kvm {
|
|||||||
|
|
||||||
/// Save the state of GIC.
|
/// Save the state of GIC.
|
||||||
fn state(&self, gicr_typers: &[u64]) -> Result<Gicv3State> {
|
fn state(&self, gicr_typers: &[u64]) -> Result<Gicv3State> {
|
||||||
// Flush redistributors pending tables to guest RAM.
|
|
||||||
save_pending_tables(self.device()).map_err(Error::SavePendingTables)?;
|
|
||||||
|
|
||||||
let gicd_ctlr =
|
let gicd_ctlr =
|
||||||
read_ctlr(self.device()).map_err(Error::SaveDistributorCtrlRegisters)?;
|
read_ctlr(self.device()).map_err(Error::SaveDistributorCtrlRegisters)?;
|
||||||
|
|
||||||
@ -255,7 +252,16 @@ pub mod kvm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pausable for KvmGicV3 {}
|
impl Pausable for KvmGicV3 {
|
||||||
|
fn pause(&mut self) -> std::result::Result<(), MigratableError> {
|
||||||
|
// Flush redistributors pending tables to guest RAM.
|
||||||
|
save_pending_tables(self.device()).map_err(|e| {
|
||||||
|
MigratableError::Pause(anyhow!("Could not save GICv3 GIC pending tables {:?}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
impl Transportable for KvmGicV3 {}
|
impl Transportable for KvmGicV3 {}
|
||||||
impl Migratable for KvmGicV3 {}
|
impl Migratable for KvmGicV3 {}
|
||||||
}
|
}
|
||||||
|
@ -191,9 +191,6 @@ pub mod kvm {
|
|||||||
|
|
||||||
/// Save the state of GICv3ITS.
|
/// Save the state of GICv3ITS.
|
||||||
fn state(&self, gicr_typers: &[u64]) -> Result<Gicv3ItsState> {
|
fn state(&self, gicr_typers: &[u64]) -> Result<Gicv3ItsState> {
|
||||||
// Flush redistributors pending tables to guest RAM.
|
|
||||||
save_pending_tables(self.device()).map_err(Error::SavePendingTables)?;
|
|
||||||
|
|
||||||
let gicd_ctlr =
|
let gicd_ctlr =
|
||||||
read_ctlr(self.device()).map_err(Error::SaveDistributorCtrlRegisters)?;
|
read_ctlr(self.device()).map_err(Error::SaveDistributorCtrlRegisters)?;
|
||||||
|
|
||||||
@ -206,10 +203,6 @@ pub mod kvm {
|
|||||||
let icc_state =
|
let icc_state =
|
||||||
get_icc_regs(self.device(), gicr_typers).map_err(Error::SaveIccRegisters)?;
|
get_icc_regs(self.device(), gicr_typers).map_err(Error::SaveIccRegisters)?;
|
||||||
|
|
||||||
// Save GICv3ITS registers
|
|
||||||
gicv3_its_tables_access(self.its_device().unwrap(), true)
|
|
||||||
.map_err(Error::SaveITSTables)?;
|
|
||||||
|
|
||||||
let its_baser_state: [u64; 8] = [0; 8];
|
let its_baser_state: [u64; 8] = [0; 8];
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
gicv3_its_attr_access(
|
gicv3_its_attr_access(
|
||||||
@ -501,7 +494,23 @@ pub mod kvm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pausable for KvmGicV3Its {}
|
impl Pausable for KvmGicV3Its {
|
||||||
|
fn pause(&mut self) -> std::result::Result<(), MigratableError> {
|
||||||
|
// Flush redistributors pending tables to guest RAM.
|
||||||
|
save_pending_tables(self.device()).map_err(|e| {
|
||||||
|
MigratableError::Pause(anyhow!(
|
||||||
|
"Could not save GICv3ITS GIC pending tables {:?}",
|
||||||
|
e
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
// Flush ITS tables to guest RAM.
|
||||||
|
gicv3_its_tables_access(self.its_device().unwrap(), true).map_err(|e| {
|
||||||
|
MigratableError::Pause(anyhow!("Could not save GICv3ITS ITS tables {:?}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
impl Transportable for KvmGicV3Its {}
|
impl Transportable for KvmGicV3Its {}
|
||||||
impl Migratable for KvmGicV3Its {}
|
impl Migratable for KvmGicV3Its {}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,8 @@ use crate::{device_node, DEVICE_MANAGER_SNAPSHOT_ID};
|
|||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
use acpi_tables::{aml, aml::Aml};
|
use acpi_tables::{aml, aml::Aml};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
use arch::aarch64::gic::gicv3_its::kvm::KvmGicV3Its;
|
||||||
#[cfg(feature = "acpi")]
|
#[cfg(feature = "acpi")]
|
||||||
use arch::layout;
|
use arch::layout;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
@ -4132,6 +4134,27 @@ impl Pausable for DeviceManager {
|
|||||||
migratable.lock().unwrap().pause()?;
|
migratable.lock().unwrap().pause()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// On AArch64, the pause of device manager needs to trigger
|
||||||
|
// a "pause" of GIC, which will flush the GIC pending tables
|
||||||
|
// and ITS tables to guest RAM.
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
{
|
||||||
|
let gic_device = Arc::clone(
|
||||||
|
self.get_interrupt_controller()
|
||||||
|
.unwrap()
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.get_gic_device()
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
gic_device
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.as_any_concrete_mut()
|
||||||
|
.downcast_mut::<KvmGicV3Its>()
|
||||||
|
.unwrap()
|
||||||
|
.pause()?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user