1use std::marker::Send;
6use std::marker::Sized;
7
8use base::Event;
9use base::Result;
10use hypervisor::IrqRoute;
11use hypervisor::MPState;
12use hypervisor::Vcpu;
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 {
118 fn add_vcpu(&mut self, vcpu_id: usize, vcpu: &dyn Vcpu) -> Result<()>;
120
121 fn register_edge_irq_event(
124 &mut self,
125 irq: u32,
126 irq_event: &IrqEdgeEvent,
127 source: IrqEventSource,
128 ) -> Result<Option<IrqEventIndex>>;
129
130 fn unregister_edge_irq_event(&mut self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()>;
132
133 fn register_level_irq_event(
136 &mut self,
137 irq: u32,
138 irq_event: &IrqLevelEvent,
139 source: IrqEventSource,
140 ) -> Result<Option<IrqEventIndex>>;
141
142 fn unregister_level_irq_event(&mut self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()>;
144
145 fn route_irq(&mut self, route: IrqRoute) -> Result<()>;
147
148 fn set_irq_routes(&mut self, routes: &[IrqRoute]) -> Result<()>;
150
151 fn irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>>;
154
155 fn service_irq(&mut self, irq: u32, level: bool) -> Result<()>;
158
159 fn service_irq_event(&mut self, event_index: IrqEventIndex) -> Result<()>;
164
165 fn broadcast_eoi(&self, vector: u8) -> Result<()>;
167
168 fn inject_interrupts(&self, vcpu: &dyn Vcpu) -> Result<()>;
170
171 fn halted(&self, vcpu_id: usize);
173
174 fn wait_until_runnable(&self, vcpu: &dyn Vcpu) -> 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(&mut self, vcpu_id: usize, state: &MPState) -> Result<()>;
190
191 fn try_clone(&self) -> Result<Self>
193 where
194 Self: Sized;
195
196 fn finalize_devices(
199 &mut self,
200 resources: &mut SystemAllocator,
201 io_bus: &Bus,
202 mmio_bus: &Bus,
203 ) -> Result<()>;
204
205 fn process_delayed_irq_events(&mut self) -> Result<()>;
207
208 fn irq_delayed_event_token(&self) -> Result<Option<Event>>;
213
214 fn check_capability(&self, c: IrqChipCap) -> bool;
216}
217
218#[derive(Clone, Copy, Debug, PartialEq, Eq)]
220pub enum IrqChipCap {
221 #[cfg(target_arch = "x86_64")]
223 TscDeadlineTimer,
224 #[cfg(target_arch = "x86_64")]
226 X2Apic,
227 MpStateGetSet,
230}
231
232#[derive(Clone, Copy, Debug, PartialEq, Eq)]
234pub enum VcpuRunState {
235 Runnable,
236 Interrupted,
237}