devices/irqchip/kvm/
mod.rs1use std::sync::Arc;
6
7use base::error;
8use base::Error;
9use base::Event;
10use base::Result;
11#[cfg(target_arch = "x86_64")]
12use hypervisor::kvm::KvmCap;
13use hypervisor::IrqRoute;
14use hypervisor::MPState;
15use hypervisor::VcpuArch;
16use kvm_sys::kvm_mp_state;
17use resources::SystemAllocator;
18
19use crate::Bus;
20use crate::IrqEdgeEvent;
21use crate::IrqEventSource;
22use crate::IrqLevelEvent;
23
24#[cfg(target_arch = "x86_64")]
25mod x86_64;
26#[cfg(target_arch = "x86_64")]
27pub use x86_64::*;
28
29#[cfg(target_arch = "aarch64")]
30mod aarch64;
31#[cfg(target_arch = "aarch64")]
32pub use aarch64::*;
33
34#[cfg(target_arch = "riscv64")]
35mod riscv64;
36#[cfg(target_arch = "riscv64")]
37pub use riscv64::*;
38
39use crate::IrqChip;
40use crate::IrqChipCap;
41use crate::IrqEventIndex;
42use crate::VcpuRunState;
43
44impl IrqChip for KvmKernelIrqChip {
46 fn add_vcpu(&self, vcpu_id: usize, vcpu: Arc<dyn VcpuArch>) -> Result<()> {
48 let vcpu = Arc::downcast(vcpu)
49 .map_err(|_| ())
50 .expect("KvmKernelIrqChip::add_vcpu called with non-KvmVcpu");
51 self.vcpus.lock()[vcpu_id] = Some(vcpu);
52 Ok(())
53 }
54
55 fn register_edge_irq_event(
58 &self,
59 irq: u32,
60 irq_event: &IrqEdgeEvent,
61 _source: IrqEventSource,
62 ) -> Result<Option<IrqEventIndex>> {
63 self.vm.register_irqfd(irq, irq_event.get_trigger(), None)?;
64 Ok(None)
65 }
66
67 fn unregister_edge_irq_event(&self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()> {
69 self.vm.unregister_irqfd(irq, irq_event.get_trigger())
70 }
71
72 fn register_level_irq_event(
75 &self,
76 irq: u32,
77 irq_event: &IrqLevelEvent,
78 _source: IrqEventSource,
79 ) -> Result<Option<IrqEventIndex>> {
80 self.vm
81 .register_irqfd(irq, irq_event.get_trigger(), Some(irq_event.get_resample()))?;
82 Ok(None)
83 }
84
85 fn unregister_level_irq_event(&self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()> {
87 self.vm.unregister_irqfd(irq, irq_event.get_trigger())
88 }
89
90 fn route_irq(&self, route: IrqRoute) -> Result<()> {
92 let mut routes = self.routes.lock();
93 routes.retain(|r| r.gsi != route.gsi);
94
95 routes.push(route);
96
97 self.vm.set_gsi_routing(&routes)
98 }
99
100 fn set_irq_routes(&self, routes: &[IrqRoute]) -> Result<()> {
102 let mut current_routes = self.routes.lock();
103 *current_routes = routes.to_vec();
104
105 self.vm.set_gsi_routing(¤t_routes)
106 }
107
108 fn irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>> {
113 Ok(Vec::new())
114 }
115
116 fn service_irq(&self, irq: u32, level: bool) -> Result<()> {
120 self.vm.set_irq_line(irq, level)
121 }
122
123 fn service_irq_event(&self, _event_index: IrqEventIndex) -> Result<()> {
129 error!("service_irq_event should never be called for KvmKernelIrqChip");
130 Ok(())
131 }
132
133 fn broadcast_eoi(&self, _vector: u8) -> Result<()> {
137 error!("broadcast_eoi should never be called for KvmKernelIrqChip");
138 Ok(())
139 }
140
141 fn inject_interrupts(&self, _vcpu: &dyn VcpuArch) -> Result<()> {
145 Ok(())
146 }
147
148 fn halted(&self, _vcpu_id: usize) {}
151
152 fn wait_until_runnable(&self, _vcpu: &dyn VcpuArch) -> Result<VcpuRunState> {
158 Ok(VcpuRunState::Runnable)
159 }
160
161 fn kick_halted_vcpus(&self) {}
164
165 fn get_mp_state(&self, vcpu_id: usize) -> Result<MPState> {
167 match self.vcpus.lock().get(vcpu_id) {
168 Some(Some(vcpu)) => Ok(MPState::from(&vcpu.get_mp_state()?)),
169 _ => Err(Error::new(libc::ENOENT)),
170 }
171 }
172
173 fn set_mp_state(&self, vcpu_id: usize, state: &MPState) -> Result<()> {
175 match self.vcpus.lock().get(vcpu_id) {
176 Some(Some(vcpu)) => vcpu.set_mp_state(&kvm_mp_state::from(state)),
177 _ => Err(Error::new(libc::ENOENT)),
178 }
179 }
180
181 fn finalize_devices(
185 self: Arc<Self>,
186 _resources: &mut SystemAllocator,
187 _io_bus: &Bus,
188 _mmio_bus: &Bus,
189 ) -> Result<()> {
190 Ok(())
191 }
192
193 fn process_delayed_irq_events(&self) -> Result<()> {
195 Ok(())
196 }
197
198 fn irq_delayed_event_token(&self) -> Result<Option<Event>> {
199 Ok(None)
200 }
201
202 fn check_capability(&self, c: IrqChipCap) -> bool {
203 match c {
204 #[cfg(target_arch = "x86_64")]
205 IrqChipCap::TscDeadlineTimer => self.vm.check_raw_capability(KvmCap::TscDeadlineTimer),
206 #[cfg(target_arch = "x86_64")]
207 IrqChipCap::X2Apic => true,
208 IrqChipCap::MpStateGetSet => true,
209 }
210 }
211}