mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
devices: Refactor IOAPIC to cover other architectures
IOAPIC, a X86 specific interrupt controller, is referenced by device manager and CPU manager. To work with more architectures, a common type for all architectures is needed. This commit introduces trait InterruptController to provide architecture agnostic functions. Device manager and CPU manager can use it without caring what the underlying device is. Signed-off-by: Michael Zhao <michael.zhao@arm.com>
This commit is contained in:
committed by
Samuel Ortiz
parent
d588418053
commit
b32d3025f3
+14
-11
@@ -20,7 +20,7 @@ use anyhow::anyhow;
|
||||
#[cfg(feature = "acpi")]
|
||||
use arch::layout;
|
||||
use arch::EntryPoint;
|
||||
use devices::{ioapic, BusDevice};
|
||||
use devices::{interrupt_controller::InterruptController, BusDevice};
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use kvm_bindings::{
|
||||
kvm_fpu, kvm_lapic_state, kvm_mp_state, kvm_regs, kvm_sregs, kvm_vcpu_events, kvm_xcrs,
|
||||
@@ -329,7 +329,7 @@ pub struct Vcpu {
|
||||
io_bus: Arc<devices::Bus>,
|
||||
mmio_bus: Arc<devices::Bus>,
|
||||
#[cfg_attr(target_arch = "aarch64", allow(dead_code))]
|
||||
ioapic: Option<Arc<Mutex<ioapic::Ioapic>>>,
|
||||
interrupt_controller: Option<Arc<Mutex<dyn InterruptController>>>,
|
||||
#[cfg_attr(target_arch = "aarch64", allow(dead_code))]
|
||||
vm_ts: std::time::Instant,
|
||||
}
|
||||
@@ -364,7 +364,7 @@ impl Vcpu {
|
||||
fd: &Arc<VmFd>,
|
||||
io_bus: Arc<devices::Bus>,
|
||||
mmio_bus: Arc<devices::Bus>,
|
||||
ioapic: Option<Arc<Mutex<ioapic::Ioapic>>>,
|
||||
interrupt_controller: Option<Arc<Mutex<dyn InterruptController>>>,
|
||||
creation_ts: std::time::Instant,
|
||||
) -> Result<Arc<Mutex<Self>>> {
|
||||
let kvm_vcpu = fd.create_vcpu(id).map_err(Error::VcpuFd)?;
|
||||
@@ -374,7 +374,7 @@ impl Vcpu {
|
||||
id,
|
||||
io_bus,
|
||||
mmio_bus,
|
||||
ioapic,
|
||||
interrupt_controller,
|
||||
vm_ts: creation_ts,
|
||||
})))
|
||||
}
|
||||
@@ -452,8 +452,11 @@ impl Vcpu {
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
VcpuExit::IoapicEoi(vector) => {
|
||||
if let Some(ioapic) = &self.ioapic {
|
||||
ioapic.lock().unwrap().end_of_interrupt(vector);
|
||||
if let Some(interrupt_controller) = &self.interrupt_controller {
|
||||
interrupt_controller
|
||||
.lock()
|
||||
.unwrap()
|
||||
.end_of_interrupt(vector);
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
@@ -618,7 +621,7 @@ pub struct CpuManager {
|
||||
#[cfg_attr(target_arch = "aarch64", allow(dead_code))]
|
||||
mmio_bus: Arc<devices::Bus>,
|
||||
#[cfg_attr(target_arch = "aarch64", allow(dead_code))]
|
||||
ioapic: Option<Arc<Mutex<ioapic::Ioapic>>>,
|
||||
interrupt_controller: Option<Arc<Mutex<dyn InterruptController>>>,
|
||||
#[cfg_attr(target_arch = "aarch64", allow(dead_code))]
|
||||
vm_memory: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -769,7 +772,7 @@ impl CpuManager {
|
||||
max_vcpus: config.max_vcpus,
|
||||
io_bus: device_manager.io_bus().clone(),
|
||||
mmio_bus: device_manager.mmio_bus().clone(),
|
||||
ioapic: device_manager.ioapic().clone(),
|
||||
interrupt_controller: device_manager.interrupt_controller().clone(),
|
||||
vm_memory: guest_memory,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
cpuid,
|
||||
@@ -858,8 +861,8 @@ impl CpuManager {
|
||||
inserting: bool,
|
||||
snapshot: Option<Snapshot>,
|
||||
) -> Result<()> {
|
||||
let ioapic = if let Some(ioapic) = &self.ioapic {
|
||||
Some(ioapic.clone())
|
||||
let interrupt_controller = if let Some(interrupt_controller) = &self.interrupt_controller {
|
||||
Some(interrupt_controller.clone())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -869,7 +872,7 @@ impl CpuManager {
|
||||
&self.fd,
|
||||
self.io_bus.clone(),
|
||||
self.mmio_bus.clone(),
|
||||
ioapic,
|
||||
interrupt_controller,
|
||||
creation_ts,
|
||||
)?;
|
||||
|
||||
|
||||
+32
-19
@@ -26,7 +26,10 @@ use anyhow::anyhow;
|
||||
use arch::layout;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use arch::layout::{APIC_START, IOAPIC_SIZE, IOAPIC_START};
|
||||
use devices::{ioapic, BusDevice, HotPlugNotificationFlags};
|
||||
use devices::{
|
||||
interrupt_controller, interrupt_controller::InterruptController, ioapic, BusDevice,
|
||||
HotPlugNotificationFlags,
|
||||
};
|
||||
use kvm_ioctls::*;
|
||||
use libc::TIOCGWINSZ;
|
||||
use libc::{MAP_NORESERVE, MAP_PRIVATE, MAP_SHARED, O_TMPFILE, PROT_READ, PROT_WRITE};
|
||||
@@ -235,8 +238,8 @@ pub enum DeviceManagerError {
|
||||
/// Failed to update interrupt source group.
|
||||
UpdateInterruptGroup(io::Error),
|
||||
|
||||
/// Failed creating IOAPIC.
|
||||
CreateIoapic(ioapic::Error),
|
||||
/// Failed creating interrupt controller.
|
||||
CreateInterruptController(interrupt_controller::Error),
|
||||
|
||||
/// Failed creating a new MmapRegion instance.
|
||||
NewMmapRegion(vm_memory::mmap::MmapRegionError),
|
||||
@@ -626,8 +629,8 @@ pub struct DeviceManager {
|
||||
// Console abstraction
|
||||
console: Arc<Console>,
|
||||
|
||||
// IOAPIC
|
||||
ioapic: Option<Arc<Mutex<ioapic::Ioapic>>>,
|
||||
// Interrupt controller
|
||||
interrupt_controller: Option<Arc<Mutex<ioapic::Ioapic>>>,
|
||||
|
||||
// Things to be added to the commandline (i.e. for virtio-mmio)
|
||||
cmdline_additions: Vec<String>,
|
||||
@@ -746,7 +749,7 @@ impl DeviceManager {
|
||||
let device_manager = DeviceManager {
|
||||
address_manager: Arc::clone(&address_manager),
|
||||
console: Arc::new(Console::default()),
|
||||
ioapic: None,
|
||||
interrupt_controller: None,
|
||||
cmdline_additions: Vec::new(),
|
||||
#[cfg(feature = "acpi")]
|
||||
ged_notification_device: None,
|
||||
@@ -804,13 +807,15 @@ impl DeviceManager {
|
||||
pub fn create_devices(&mut self) -> DeviceManagerResult<()> {
|
||||
let mut virtio_devices: Vec<(VirtioDeviceArc, bool, String)> = Vec::new();
|
||||
|
||||
let ioapic = self.add_ioapic()?;
|
||||
let interrupt_controller = self.add_interrupt_controller()?;
|
||||
|
||||
// Now we can create the legacy interrupt manager, which needs the freshly
|
||||
// formed IOAPIC device.
|
||||
let legacy_interrupt_manager: Arc<
|
||||
dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>,
|
||||
> = Arc::new(KvmLegacyUserspaceInterruptManager::new(ioapic));
|
||||
> = Arc::new(KvmLegacyUserspaceInterruptManager::new(Arc::clone(
|
||||
&interrupt_controller,
|
||||
)));
|
||||
|
||||
#[cfg(feature = "acpi")]
|
||||
self.address_manager
|
||||
@@ -1003,33 +1008,37 @@ impl DeviceManager {
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn add_ioapic(&mut self) -> DeviceManagerResult<Arc<Mutex<ioapic::Ioapic>>> {
|
||||
fn add_interrupt_controller(
|
||||
&mut self,
|
||||
) -> DeviceManagerResult<Arc<Mutex<dyn InterruptController>>> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
fn add_ioapic(&mut self) -> DeviceManagerResult<Arc<Mutex<ioapic::Ioapic>>> {
|
||||
fn add_interrupt_controller(
|
||||
&mut self,
|
||||
) -> DeviceManagerResult<Arc<Mutex<dyn InterruptController>>> {
|
||||
let id = String::from(IOAPIC_DEVICE_NAME);
|
||||
|
||||
// Create IOAPIC
|
||||
let ioapic = Arc::new(Mutex::new(
|
||||
let interrupt_controller = Arc::new(Mutex::new(
|
||||
ioapic::Ioapic::new(
|
||||
id.clone(),
|
||||
APIC_START,
|
||||
Arc::clone(&self.msi_interrupt_manager),
|
||||
)
|
||||
.map_err(DeviceManagerError::CreateIoapic)?,
|
||||
.map_err(DeviceManagerError::CreateInterruptController)?,
|
||||
));
|
||||
|
||||
self.ioapic = Some(ioapic.clone());
|
||||
self.interrupt_controller = Some(interrupt_controller.clone());
|
||||
|
||||
self.address_manager
|
||||
.mmio_bus
|
||||
.insert(ioapic.clone(), IOAPIC_START.0, IOAPIC_SIZE)
|
||||
.insert(interrupt_controller.clone(), IOAPIC_START.0, IOAPIC_SIZE)
|
||||
.map_err(DeviceManagerError::BusError)?;
|
||||
|
||||
self.bus_devices
|
||||
.push(Arc::clone(&ioapic) as Arc<Mutex<dyn BusDevice>>);
|
||||
.push(Arc::clone(&interrupt_controller) as Arc<Mutex<dyn BusDevice>>);
|
||||
|
||||
// Fill the device tree with a new node. In case of restore, we
|
||||
// know there is nothing to do, so we can simply override the
|
||||
@@ -1037,9 +1046,9 @@ impl DeviceManager {
|
||||
self.device_tree
|
||||
.lock()
|
||||
.unwrap()
|
||||
.insert(id.clone(), device_node!(id, ioapic));
|
||||
.insert(id.clone(), device_node!(id, interrupt_controller));
|
||||
|
||||
Ok(ioapic)
|
||||
Ok(interrupt_controller)
|
||||
}
|
||||
|
||||
#[cfg(feature = "acpi")]
|
||||
@@ -2550,8 +2559,12 @@ impl DeviceManager {
|
||||
&self.address_manager.allocator
|
||||
}
|
||||
|
||||
pub fn ioapic(&self) -> &Option<Arc<Mutex<ioapic::Ioapic>>> {
|
||||
&self.ioapic
|
||||
pub fn interrupt_controller(&self) -> Option<Arc<Mutex<dyn InterruptController>>> {
|
||||
if let Some(interrupt_controller) = &self.interrupt_controller {
|
||||
Some(interrupt_controller.clone() as Arc<Mutex<dyn InterruptController>>)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn console(&self) -> &Arc<Console> {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
//
|
||||
|
||||
use devices::ioapic;
|
||||
use devices::interrupt_controller::InterruptController;
|
||||
use kvm_bindings::{kvm_irq_routing, kvm_irq_routing_entry, KVM_IRQ_ROUTING_MSI};
|
||||
use kvm_ioctls::VmFd;
|
||||
use std::collections::HashMap;
|
||||
@@ -281,12 +281,12 @@ impl InterruptSourceGroup for MsiInterruptGroup {
|
||||
}
|
||||
|
||||
pub struct LegacyUserspaceInterruptGroup {
|
||||
ioapic: Arc<Mutex<ioapic::Ioapic>>,
|
||||
ioapic: Arc<Mutex<dyn InterruptController>>,
|
||||
irq: u32,
|
||||
}
|
||||
|
||||
impl LegacyUserspaceInterruptGroup {
|
||||
fn new(ioapic: Arc<Mutex<ioapic::Ioapic>>, irq: u32) -> Self {
|
||||
fn new(ioapic: Arc<Mutex<dyn InterruptController>>, irq: u32) -> Self {
|
||||
LegacyUserspaceInterruptGroup { ioapic, irq }
|
||||
}
|
||||
}
|
||||
@@ -311,7 +311,7 @@ impl InterruptSourceGroup for LegacyUserspaceInterruptGroup {
|
||||
}
|
||||
|
||||
pub struct KvmLegacyUserspaceInterruptManager {
|
||||
ioapic: Arc<Mutex<ioapic::Ioapic>>,
|
||||
ioapic: Arc<Mutex<dyn InterruptController>>,
|
||||
}
|
||||
|
||||
pub struct KvmMsiInterruptManager {
|
||||
@@ -321,7 +321,7 @@ pub struct KvmMsiInterruptManager {
|
||||
}
|
||||
|
||||
impl KvmLegacyUserspaceInterruptManager {
|
||||
pub fn new(ioapic: Arc<Mutex<ioapic::Ioapic>>) -> Self {
|
||||
pub fn new(ioapic: Arc<Mutex<dyn InterruptController>>) -> Self {
|
||||
KvmLegacyUserspaceInterruptManager { ioapic }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user