arch: Switch to new GIC interface

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
Michael Zhao 2022-05-31 19:53:22 +08:00 committed by Xin Wang
parent b8dbb26647
commit 04949755c0
6 changed files with 41 additions and 81 deletions

View File

@ -8,6 +8,7 @@
use crate::{NumaNodes, PciSpaceInfo}; use crate::{NumaNodes, PciSpaceInfo};
use byteorder::{BigEndian, ByteOrder}; use byteorder::{BigEndian, ByteOrder};
use hypervisor::arch::aarch64::gic::Vgic;
use std::cmp; use std::cmp;
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::CStr; use std::ffi::CStr;
@ -18,7 +19,6 @@ use std::str;
use super::super::DeviceType; use super::super::DeviceType;
use super::super::GuestMemoryMmap; use super::super::GuestMemoryMmap;
use super::super::InitramfsConfig; use super::super::InitramfsConfig;
use super::gic::GicDevice;
use super::layout::{ use super::layout::{
IRQ_BASE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, MEM_PCI_IO_SIZE, MEM_PCI_IO_START, IRQ_BASE, MEM_32BIT_DEVICES_SIZE, MEM_32BIT_DEVICES_START, MEM_PCI_IO_SIZE, MEM_PCI_IO_START,
PCI_HIGH_BASE, PCI_MMIO_CONFIG_SIZE_PER_SEGMENT, PCI_HIGH_BASE, PCI_MMIO_CONFIG_SIZE_PER_SEGMENT,
@ -90,7 +90,7 @@ pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHash
vcpu_mpidr: Vec<u64>, vcpu_mpidr: Vec<u64>,
vcpu_topology: Option<(u8, u8, u8)>, vcpu_topology: Option<(u8, u8, u8)>,
device_info: &HashMap<(DeviceType, String), T, S>, device_info: &HashMap<(DeviceType, String), T, S>,
gic_device: &dyn GicDevice, gic_device: &dyn Vgic,
initrd: &Option<InitramfsConfig>, initrd: &Option<InitramfsConfig>,
pci_space_info: &[PciSpaceInfo], pci_space_info: &[PciSpaceInfo],
numa_nodes: &NumaNodes, numa_nodes: &NumaNodes,
@ -315,7 +315,7 @@ fn create_chosen_node(
Ok(()) Ok(())
} }
fn create_gic_node(fdt: &mut FdtWriter, gic_device: &dyn GicDevice) -> FdtWriterResult<()> { fn create_gic_node(fdt: &mut FdtWriter, gic_device: &dyn Vgic) -> FdtWriterResult<()> {
let gic_reg_prop = gic_device.device_properties(); let gic_reg_prop = gic_device.device_properties();
let intc_node = fdt.begin_node("intc")?; let intc_node = fdt.begin_node("intc")?;

View File

@ -1,11 +1,12 @@
// Copyright 2021 Arm Limited (or its affiliates). All rights reserved. // Copyright 2021 Arm Limited (or its affiliates). All rights reserved.
use crate::layout;
use anyhow::anyhow;
use hypervisor::{arch::aarch64::gic::Vgic, CpuState}; use hypervisor::{arch::aarch64::gic::Vgic, CpuState};
use std::result; use std::result;
use std::sync::Arc; use std::sync::Arc;
use vm_migration::{ use vm_memory::Address;
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped, use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
};
/// Errors thrown while setting up the GIC. /// Errors thrown while setting up the GIC.
#[derive(Debug)] #[derive(Debug)]
@ -35,7 +36,9 @@ impl GicDevice {
Ok(GicDevice { vgic }) Ok(GicDevice { vgic })
} }
pub fn set_gicr_typers(&mut self, vcpu_states: &[CpuState]) {} pub fn set_gicr_typers(&mut self, vcpu_states: &[CpuState]) {
self.vgic.set_gicr_typers(vcpu_states)
}
pub fn get_vgic(&self) -> &dyn Vgic { pub fn get_vgic(&self) -> &dyn Vgic {
&*self.vgic &*self.vgic
@ -54,30 +57,23 @@ impl Snapshottable for GicDevice {
} }
fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> { fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> {
self.vgic.set_state(&snapshot.to_state(&self.id())?) self.vgic
.set_state(&snapshot.to_state(&self.id())?)
.map_err(|e| { .map_err(|e| {
MigratableError::Restore(anyhow!("Could not restore GICv3ITS state {:?}", e)) MigratableError::Restore(anyhow!("Could not restore GICv3ITS state {:?}", e))
}) })
Ok(())
} }
} }
impl Pausable for GicDevice { impl Pausable for GicDevice {
fn pause(&mut self) -> std::result::Result<(), MigratableError> { fn pause(&mut self) -> std::result::Result<(), MigratableError> {
/* // Flush tables to guest RAM
// Flush redistributors pending tables to guest RAM. self.vgic.save_data_tables().map_err(|e| {
KvmGicDevice::save_pending_tables(self.device()).map_err(|e| { MigratableError::Pause(anyhow!(
MigratableError::Pause(anyhow!( "Could not save GICv3ITS GIC pending tables {:?}",
"Could not save GICv3ITS GIC pending tables {:?}", e
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 GicDevice {} impl Transportable for GicDevice {}

View File

@ -15,7 +15,6 @@ pub mod uefi;
pub use self::fdt::DeviceInfoForFdt; pub use self::fdt::DeviceInfoForFdt;
use crate::{DeviceType, GuestMemoryMmap, NumaNodes, PciSpaceInfo, RegionType}; use crate::{DeviceType, GuestMemoryMmap, NumaNodes, PciSpaceInfo, RegionType};
use gic::GicDevice;
use log::{log_enabled, Level}; use log::{log_enabled, Level};
use std::collections::HashMap; use std::collections::HashMap;
use std::convert::TryInto; use std::convert::TryInto;
@ -143,7 +142,7 @@ pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Bui
initrd: &Option<super::InitramfsConfig>, initrd: &Option<super::InitramfsConfig>,
pci_space_info: &[PciSpaceInfo], pci_space_info: &[PciSpaceInfo],
virtio_iommu_bdf: Option<u32>, virtio_iommu_bdf: Option<u32>,
gic_device: &dyn GicDevice, gic_device: &gic::GicDevice,
numa_nodes: &NumaNodes, numa_nodes: &NumaNodes,
pmu_supported: bool, pmu_supported: bool,
) -> super::Result<()> { ) -> super::Result<()> {
@ -153,7 +152,7 @@ pub fn configure_system<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::Bui
vcpu_mpidr, vcpu_mpidr,
vcpu_topology, vcpu_topology,
device_info, device_info,
gic_device, gic_device.get_vgic(),
initrd, initrd,
pci_space_info, pci_space_info,
numa_nodes, numa_nodes,

View File

@ -27,7 +27,7 @@ pub const IRQ_LEGACY_COUNT: usize = 32;
// 2. Move this file and ioapic.rs to arch/, as they are architecture specific. // 2. Move this file and ioapic.rs to arch/, as they are architecture specific.
pub struct Gic { pub struct Gic {
interrupt_source_group: Arc<dyn InterruptSourceGroup>, interrupt_source_group: Arc<dyn InterruptSourceGroup>,
gic_device: Option<Arc<Mutex<Box<dyn GicDevice>>>>, gic_device: Option<Arc<Mutex<GicDevice>>>,
} }
impl Gic { impl Gic {
@ -48,11 +48,11 @@ impl Gic {
}) })
} }
pub fn set_gic_device(&mut self, gic_device: Arc<Mutex<Box<dyn GicDevice>>>) { pub fn set_gic_device(&mut self, gic_device: Arc<Mutex<GicDevice>>) {
self.gic_device = Some(gic_device); self.gic_device = Some(gic_device);
} }
pub fn get_gic_device(&self) -> Option<&Arc<Mutex<Box<dyn GicDevice>>>> { pub fn get_gic_device(&self) -> Option<&Arc<Mutex<GicDevice>>> {
self.gic_device.as_ref() self.gic_device.as_ref()
} }
} }

View File

@ -29,8 +29,6 @@ use crate::PciDeviceInfo;
use crate::{device_node, DEVICE_MANAGER_SNAPSHOT_ID}; use crate::{device_node, DEVICE_MANAGER_SNAPSHOT_ID};
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::kvm::KvmGicV3Its;
use arch::layout; use arch::layout;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use arch::layout::{APIC_START, IOAPIC_SIZE, IOAPIC_START}; use arch::layout::{APIC_START, IOAPIC_SIZE, IOAPIC_START};
@ -4327,26 +4325,15 @@ impl Pausable for DeviceManager {
// and ITS tables to guest RAM. // and ITS tables to guest RAM.
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
{ {
let gic_device = Arc::clone( self.get_interrupt_controller()
self.get_interrupt_controller() .unwrap()
.unwrap()
.lock()
.unwrap()
.get_gic_device()
.unwrap(),
);
if let Some(gicv3_its) = gic_device
.lock() .lock()
.unwrap() .unwrap()
.as_any_concrete_mut() .get_gic_device()
.downcast_mut::<KvmGicV3Its>() .unwrap()
{ .lock()
gicv3_its.pause()?; .unwrap()
} else { .pause()?;
return Err(MigratableError::Pause(anyhow!(
"GicDevice downcast to KvmGicV3Its failed when pausing device manager!"
)));
};
}; };
Ok(()) Ok(())

View File

@ -38,9 +38,7 @@ use crate::{
}; };
use anyhow::anyhow; use anyhow::anyhow;
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
use arch::aarch64::gic::kvm::create_gic; use arch::aarch64::gic::{GicDevice, GIC_V3_ITS_SNAPSHOT_ID};
#[cfg(target_arch = "aarch64")]
use arch::aarch64::gic::kvm::{KvmGicV3Its, GIC_V3_ITS_SNAPSHOT_ID};
use arch::get_host_cpu_phys_bits; use arch::get_host_cpu_phys_bits;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use arch::layout::{KVM_IDENTITY_MAP_START, KVM_TSS_START}; use arch::layout::{KVM_IDENTITY_MAP_START, KVM_TSS_START};
@ -1184,7 +1182,7 @@ impl Vm {
.as_ref() .as_ref()
.map(|(v, _)| *v); .map(|(v, _)| *v);
let gic_device = create_gic( let gic_device = GicDevice::new(
&self.memory_manager.lock().as_ref().unwrap().vm, &self.memory_manager.lock().as_ref().unwrap().vm,
self.cpu_manager.lock().unwrap().boot_vcpus() as u64, self.cpu_manager.lock().unwrap().boot_vcpus() as u64,
) )
@ -1215,13 +1213,14 @@ impl Vm {
&initramfs_config, &initramfs_config,
&pci_space_info, &pci_space_info,
virtio_iommu_bdf.map(|bdf| bdf.into()), virtio_iommu_bdf.map(|bdf| bdf.into()),
&*gic_device, &gic_device,
&self.numa_nodes, &self.numa_nodes,
pmu_supported, pmu_supported,
) )
.map_err(Error::ConfigureSystem)?; .map_err(Error::ConfigureSystem)?;
// Update the GIC entity in device manager // Update the GIC entity in device manager
let gic_device = Arc::new(Mutex::new(gic_device));
self.device_manager self.device_manager
.lock() .lock()
.unwrap() .unwrap()
@ -1229,7 +1228,7 @@ impl Vm {
.unwrap() .unwrap()
.lock() .lock()
.unwrap() .unwrap()
.set_gic_device(Arc::new(Mutex::new(gic_device))); .set_gic_device(gic_device);
// Activate gic device // Activate gic device
self.device_manager self.device_manager
@ -2237,20 +2236,7 @@ impl Vm {
.unwrap() .unwrap()
.set_gicr_typers(&saved_vcpu_states); .set_gicr_typers(&saved_vcpu_states);
vm_snapshot.add_snapshot( vm_snapshot.add_snapshot(gic_device.lock().unwrap().snapshot()?);
if let Some(gicv3_its) = gic_device
.lock()
.unwrap()
.as_any_concrete_mut()
.downcast_mut::<KvmGicV3Its>()
{
gicv3_its.snapshot()?
} else {
return Err(MigratableError::Snapshot(anyhow!(
"GicDevice downcast to KvmGicV3Its failed when snapshotting VM!"
)));
},
);
Ok(()) Ok(())
} }
@ -2268,7 +2254,7 @@ impl Vm {
// Creating a GIC device here, as the GIC will not be created when // Creating a GIC device here, as the GIC will not be created when
// restoring the device manager. Note that currently only the bare GICv3 // restoring the device manager. Note that currently only the bare GICv3
// without ITS is supported. // without ITS is supported.
let mut gic_device = create_gic(&self.vm, vcpu_numbers.try_into().unwrap()) let mut gic_device = GicDevice::new(&self.vm, vcpu_numbers.try_into().unwrap())
.map_err(|e| MigratableError::Restore(anyhow!("Could not create GIC: {:#?}", e)))?; .map_err(|e| MigratableError::Restore(anyhow!("Could not create GIC: {:#?}", e)))?;
// PMU interrupt sticks to PPI, so need to be added by 16 to get real irq number. // PMU interrupt sticks to PPI, so need to be added by 16 to get real irq number.
@ -2290,22 +2276,14 @@ impl Vm {
.unwrap() .unwrap()
.lock() .lock()
.unwrap() .unwrap()
.set_gic_device(Arc::clone(&gic_device)); .set_gic_device(gic_device.clone());
// Restore GIC states. // Restore GIC states.
if let Some(gicv3_its_snapshot) = vm_snapshot.snapshots.get(GIC_V3_ITS_SNAPSHOT_ID) { if let Some(gicv3_its_snapshot) = vm_snapshot.snapshots.get(GIC_V3_ITS_SNAPSHOT_ID) {
if let Some(gicv3_its) = gic_device gic_device
.lock() .lock()
.unwrap() .unwrap()
.as_any_concrete_mut() .restore(*gicv3_its_snapshot.clone())?;
.downcast_mut::<KvmGicV3Its>()
{
gicv3_its.restore(*gicv3_its_snapshot.clone())?;
} else {
return Err(MigratableError::Restore(anyhow!(
"GicDevice downcast to KvmGicV3Its failed when restoring VM!"
)));
};
} else { } else {
return Err(MigratableError::Restore(anyhow!( return Err(MigratableError::Restore(anyhow!(
"Missing GicV3Its snapshot" "Missing GicV3Its snapshot"