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