mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
This is a follow-up of [0].
# Advantages
- This saves dozens of unneeded clone()s across the whole code base
- Makes it much easier to reason about how parameters are used
(often we passed owned Arc/Rc versions without actually needing
ownership)
# Exceptions
For certain code paths, the alternatives would require awkward or overly
complex code, and in some cases the functions are the logical owners of
the values they take. In those cases, I've added
#[allow(clippy::needless_pass_by_value)].
This does not mean that one should not improve this in the future.
[0] 6a86c157af
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
145 lines
4.4 KiB
Rust
145 lines
4.4 KiB
Rust
// Copyright © 2024 Institute of Software, CAS. All rights reserved.
|
|
// Copyright 2020, ARM Limited.
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
|
|
|
use std::result;
|
|
use std::sync::{Arc, Mutex};
|
|
|
|
use arch::layout;
|
|
use hypervisor::arch::riscv64::aia::{Vaia, VaiaConfig};
|
|
use hypervisor::{AiaState, CpuState};
|
|
use vm_device::interrupt::{
|
|
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
|
|
LegacyIrqSourceConfig, MsiIrqGroupConfig,
|
|
};
|
|
use vm_memory::address::Address;
|
|
use vm_migration::{Migratable, Pausable, Snapshottable, Transportable};
|
|
use vmm_sys_util::eventfd::EventFd;
|
|
|
|
use super::interrupt_controller::{Error, InterruptController};
|
|
|
|
type Result<T> = result::Result<T, Error>;
|
|
|
|
// Reserve 32 IRQs for legacy devices.
|
|
pub const IRQ_LEGACY_BASE: usize = layout::IRQ_BASE as usize;
|
|
pub const IRQ_LEGACY_COUNT: usize = 32;
|
|
// TODO: AIA snapshotting is not yet completed.
|
|
pub const _AIA_SNAPSHOT_ID: &str = "";
|
|
|
|
// Aia (Advance Interrupt Architecture) struct provides all the functionality of a
|
|
// AIA device. It wraps a hypervisor-emulated AIA device (Vaia) provided by the
|
|
// `hypervisor` crate.
|
|
// Aia struct also implements InterruptController to provide interrupt delivery
|
|
// service.
|
|
pub struct Aia {
|
|
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
|
|
// The hypervisor agnostic virtual AIA
|
|
vaia: Arc<Mutex<dyn Vaia>>,
|
|
}
|
|
|
|
impl Aia {
|
|
#[allow(clippy::needless_pass_by_value)]
|
|
pub fn new(
|
|
vcpu_count: u32,
|
|
interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>,
|
|
vm: Arc<dyn hypervisor::Vm>,
|
|
) -> Result<Aia> {
|
|
let interrupt_source_group = interrupt_manager
|
|
.create_group(MsiIrqGroupConfig {
|
|
base: IRQ_LEGACY_BASE as InterruptIndex,
|
|
count: IRQ_LEGACY_COUNT as InterruptIndex,
|
|
})
|
|
.map_err(Error::CreateInterruptSourceGroup)?;
|
|
|
|
let config = Aia::create_default_config(vcpu_count as u64);
|
|
let vaia = vm.create_vaia(&config).map_err(Error::CreateAia)?;
|
|
|
|
let aia = Aia {
|
|
interrupt_source_group,
|
|
vaia,
|
|
};
|
|
aia.enable()?;
|
|
|
|
Ok(aia)
|
|
}
|
|
|
|
pub fn restore_vaia(
|
|
&mut self,
|
|
state: Option<AiaState>,
|
|
_saved_vcpu_states: &[CpuState],
|
|
) -> Result<()> {
|
|
self.vaia
|
|
.clone()
|
|
.lock()
|
|
.unwrap()
|
|
.set_state(&state.unwrap())
|
|
.map_err(Error::RestoreAia)
|
|
}
|
|
|
|
fn enable(&self) -> Result<()> {
|
|
// Set irqfd for legacy interrupts
|
|
self.interrupt_source_group
|
|
.enable()
|
|
.map_err(Error::EnableInterrupt)?;
|
|
|
|
// Set irq_routing for legacy interrupts.
|
|
// irqchip: Hardcode to 0 as we support only 1 APLIC
|
|
// pin: Use irq number as pin
|
|
for i in IRQ_LEGACY_BASE..(IRQ_LEGACY_BASE + IRQ_LEGACY_COUNT) {
|
|
let config = LegacyIrqSourceConfig {
|
|
irqchip: 0,
|
|
pin: (i - IRQ_LEGACY_BASE) as u32,
|
|
};
|
|
self.interrupt_source_group
|
|
.update(
|
|
i as InterruptIndex,
|
|
InterruptSourceConfig::LegacyIrq(config),
|
|
false,
|
|
false,
|
|
)
|
|
.map_err(Error::EnableInterrupt)?;
|
|
}
|
|
|
|
self.interrupt_source_group
|
|
.set_gsi()
|
|
.map_err(Error::EnableInterrupt)?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Default config implied by arch::layout
|
|
pub fn create_default_config(vcpu_count: u64) -> VaiaConfig {
|
|
VaiaConfig {
|
|
vcpu_count: vcpu_count as u32,
|
|
aplic_addr: layout::APLIC_START.raw_value(),
|
|
imsic_addr: layout::IMSIC_START.raw_value(),
|
|
nr_irqs: layout::IRQ_NUM,
|
|
}
|
|
}
|
|
|
|
pub fn get_vaia(&mut self) -> Result<Arc<Mutex<dyn Vaia>>> {
|
|
Ok(self.vaia.clone())
|
|
}
|
|
}
|
|
|
|
impl InterruptController for Aia {
|
|
// This should be called anytime an interrupt needs to be injected into the
|
|
// running guest.
|
|
fn service_irq(&mut self, irq: usize) -> Result<()> {
|
|
self.interrupt_source_group
|
|
.trigger(irq as InterruptIndex)
|
|
.map_err(Error::TriggerInterrupt)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn notifier(&self, irq: usize) -> Option<EventFd> {
|
|
self.interrupt_source_group.notifier(irq as InterruptIndex)
|
|
}
|
|
}
|
|
|
|
impl Snapshottable for Aia {}
|
|
impl Pausable for Aia {}
|
|
impl Transportable for Aia {}
|
|
impl Migratable for Aia {}
|