1use std::marker::Send;
6use std::sync::Arc;
7
8use base::Event;
9use base::Result;
10use hypervisor::IrqRoute;
11use hypervisor::MPState;
12use hypervisor::VcpuArch;
13use resources::SystemAllocator;
14use serde::Deserialize;
15use serde::Serialize;
16use vm_control::DeviceId;
17
18use crate::Bus;
19use crate::BusDevice;
20use crate::IrqEdgeEvent;
21use crate::IrqLevelEvent;
22
23cfg_if::cfg_if! {
24 if #[cfg(any(target_os = "android", target_os = "linux"))] {
25 mod kvm;
26 pub use self::kvm::KvmKernelIrqChip;
27 #[cfg(target_arch = "x86_64")]
28 pub use self::kvm::KvmSplitIrqChip;
29 #[cfg(target_arch = "aarch64")]
30 pub use self::kvm::{AARCH64_GIC_NR_IRQS, AARCH64_GIC_NR_SPIS};
31
32 #[cfg(all(target_arch = "aarch64", feature = "gunyah"))]
33 mod gunyah;
34 #[cfg(all(target_arch = "aarch64", feature = "gunyah"))]
35 pub use self::gunyah::GunyahIrqChip;
36
37 #[cfg(all(target_arch = "aarch64", feature = "geniezone"))]
38 mod geniezone;
39 #[cfg(all(target_arch = "aarch64", feature = "geniezone"))]
40 pub use self::geniezone::GeniezoneKernelIrqChip;
41 } else if #[cfg(all(windows, feature = "whpx"))] {
42 mod whpx;
43 pub use self::whpx::WhpxSplitIrqChip;
44 }
45}
46
47cfg_if::cfg_if! {
48 if #[cfg(target_arch = "x86_64")] {
49 mod x86_64;
50 pub use x86_64::*;
51 mod pic;
52 pub use pic::*;
53 mod ioapic;
54 pub use ioapic::*;
55 mod apic;
56 pub use apic::*;
57 mod userspace;
58 pub use userspace::*;
59 } else if #[cfg(target_arch = "aarch64")] {
60 mod aarch64;
61 pub use aarch64::*;
62 } else if #[cfg(target_arch = "riscv64")] {
63 mod riscv64;
64 pub use riscv64::*;
65 pub use self::kvm::aia_addr_imsic;
66 pub use self::kvm::aia_aplic_addr;
67 pub use self::kvm::aia_imsic_addr;
68 pub use self::kvm::aia_imsic_size;
69 pub use self::kvm::AIA_APLIC_SIZE;
70 pub use self::kvm::AIA_IMSIC_BASE;
71 pub use self::kvm::IMSIC_MAX_INT_IDS;
72 }
73
74}
75
76#[cfg(all(target_arch = "aarch64", feature = "halla"))]
77mod halla;
78#[cfg(all(target_arch = "aarch64", feature = "halla"))]
79pub use self::halla::HallaKernelIrqChip;
80
81pub type IrqEventIndex = usize;
82
83#[cfg(target_arch = "x86_64")]
84struct IrqEvent {
85 event: Event,
86 gsi: u32,
87 resample_event: Option<Event>,
88 source: IrqEventSource,
89}
90
91#[derive(Clone, Serialize, Deserialize)]
93pub struct IrqEventSource {
94 pub device_id: DeviceId,
95 pub queue_id: usize,
96 pub device_name: String,
97}
98
99impl IrqEventSource {
100 pub fn from_device(device: &dyn BusDevice) -> Self {
101 Self {
102 device_id: device.device_id(),
103 queue_id: 0,
104 device_name: device.debug_label(),
105 }
106 }
107}
108
109pub trait IrqChip: Send + Sync {
118 fn add_vcpu(&self, vcpu_id: usize, vcpu: Arc<dyn VcpuArch>) -> Result<()>;
120
121 fn register_edge_irq_event(
124 &self,
125 irq: u32,
126 irq_event: &IrqEdgeEvent,
127 source: IrqEventSource,
128 ) -> Result<Option<IrqEventIndex>>;
129
130 fn unregister_edge_irq_event(&self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()>;
132
133 fn register_level_irq_event(
136 &self,
137 irq: u32,
138 irq_event: &IrqLevelEvent,
139 source: IrqEventSource,
140 ) -> Result<Option<IrqEventIndex>>;
141
142 fn unregister_level_irq_event(&self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()>;
144
145 fn route_irq(&self, route: IrqRoute) -> Result<()>;
147
148 fn set_irq_routes(&self, routes: &[IrqRoute]) -> Result<()>;
150
151 fn irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>>;
154
155 fn service_irq(&self, irq: u32, level: bool) -> Result<()>;
158
159 fn service_irq_event(&self, event_index: IrqEventIndex) -> Result<()>;
164
165 fn broadcast_eoi(&self, vector: u8) -> Result<()>;
167
168 fn inject_interrupts(&self, vcpu: &dyn VcpuArch) -> Result<()>;
170
171 fn halted(&self, vcpu_id: usize);
173
174 fn wait_until_runnable(&self, vcpu: &dyn VcpuArch) -> Result<VcpuRunState>;
178
179 fn kick_halted_vcpus(&self);
184
185 fn get_mp_state(&self, vcpu_id: usize) -> Result<MPState>;
187
188 fn set_mp_state(&self, vcpu_id: usize, state: &MPState) -> Result<()>;
190
191 fn finalize_devices(
194 self: Arc<Self>,
195 resources: &mut SystemAllocator,
196 io_bus: &Bus,
197 mmio_bus: &Bus,
198 ) -> Result<()>;
199
200 fn process_delayed_irq_events(&self) -> Result<()>;
202
203 fn irq_delayed_event_token(&self) -> Result<Option<Event>>;
208
209 fn check_capability(&self, c: IrqChipCap) -> bool;
211}
212
213#[derive(Clone, Copy, Debug, PartialEq, Eq)]
215pub enum IrqChipCap {
216 #[cfg(target_arch = "x86_64")]
218 TscDeadlineTimer,
219 #[cfg(target_arch = "x86_64")]
221 X2Apic,
222 MpStateGetSet,
225}
226
227#[derive(Clone, Copy, Debug, PartialEq, Eq)]
229pub enum VcpuRunState {
230 Runnable,
231 Interrupted,
232}