virt\aarch64/
gic_software_device.rs1use crate::irqcon::ControlGic;
7use pci_core::msi::MsiControl;
8use pci_core::msi::MsiInterruptTarget;
9use std::ops::Range;
10use std::sync::Arc;
11use thiserror::Error;
12use vmcore::vpci_msi::MsiAddressData;
13use vmcore::vpci_msi::RegisterInterruptError;
14use vmcore::vpci_msi::VpciInterruptMapper;
15
16pub struct GicSoftwareDevice {
17 irqcon: Arc<dyn ControlGic>,
18}
19
20impl GicSoftwareDevice {
21 pub fn new(irqcon: Arc<dyn ControlGic>) -> Self {
22 Self { irqcon }
23 }
24}
25
26#[derive(Debug, Error)]
27enum GicInterruptError {
28 #[error("invalid vector count")]
29 InvalidVectorCount,
30 #[error("invalid vector")]
31 InvalidVector,
32}
33
34const SPI_RANGE: Range<u32> = 32..1020;
35
36impl VpciInterruptMapper for GicSoftwareDevice {
37 fn register_interrupt(
38 &self,
39 vector_count: u32,
40 params: &vmcore::vpci_msi::VpciInterruptParameters<'_>,
41 ) -> Result<MsiAddressData, RegisterInterruptError> {
42 if !vector_count.is_power_of_two() {
43 return Err(RegisterInterruptError::new(
44 GicInterruptError::InvalidVectorCount,
45 ));
46 }
47 if params.vector < SPI_RANGE.start
48 || params.vector.saturating_add(vector_count) > SPI_RANGE.end
49 {
50 return Err(RegisterInterruptError::new(
51 GicInterruptError::InvalidVector,
52 ));
53 }
54 Ok(MsiAddressData {
55 address: 0,
56 data: params.vector,
57 })
58 }
59
60 fn unregister_interrupt(&self, address: u64, data: u32) {
61 let _ = (address, data);
62 }
63}
64
65impl MsiInterruptTarget for GicSoftwareDevice {
66 fn new_interrupt(&self) -> Box<dyn MsiControl> {
67 let irqcon = self.irqcon.clone();
68 Box::new(move |_address, data| {
69 if SPI_RANGE.contains(&data) {
70 irqcon.set_spi_irq(data, true);
71 }
72 })
73 }
74}