• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::sync::Arc;
6 
7 use anyhow::anyhow;
8 use anyhow::Context;
9 use base::error;
10 #[cfg(not(test))]
11 use base::Clock;
12 use base::Error;
13 use base::Event;
14 #[cfg(test)]
15 use base::FakeClock as Clock;
16 use base::Result;
17 use base::Tube;
18 use hypervisor::kvm::KvmVcpu;
19 use hypervisor::kvm::KvmVm;
20 use hypervisor::HypervisorCap;
21 use hypervisor::IoapicState;
22 use hypervisor::IrqRoute;
23 use hypervisor::IrqSource;
24 use hypervisor::IrqSourceChip;
25 use hypervisor::LapicState;
26 use hypervisor::MPState;
27 use hypervisor::PicSelect;
28 use hypervisor::PicState;
29 use hypervisor::PitState;
30 use hypervisor::Vcpu;
31 use hypervisor::VcpuX86_64;
32 use hypervisor::Vm;
33 use hypervisor::VmX86_64;
34 use kvm_sys::*;
35 use resources::SystemAllocator;
36 use serde::Deserialize;
37 use serde::Serialize;
38 use snapshot::AnySnapshot;
39 use sync::Mutex;
40 
41 use crate::irqchip::Ioapic;
42 use crate::irqchip::IrqEvent;
43 use crate::irqchip::IrqEventIndex;
44 use crate::irqchip::Pic;
45 use crate::irqchip::VcpuRunState;
46 use crate::irqchip::IOAPIC_BASE_ADDRESS;
47 use crate::irqchip::IOAPIC_MEM_LENGTH_BYTES;
48 use crate::Bus;
49 use crate::IrqChip;
50 use crate::IrqChipCap;
51 use crate::IrqChipX86_64;
52 use crate::IrqEdgeEvent;
53 use crate::IrqEventSource;
54 use crate::IrqLevelEvent;
55 use crate::Pit;
56 use crate::PitError;
57 
58 /// PIT tube 0 timer is connected to IRQ 0
59 const PIT_CHANNEL0_IRQ: u32 = 0;
60 
61 /// Default x86 routing table.  Pins 0-7 go to primary pic and ioapic, pins 8-15 go to secondary
62 /// pic and ioapic, and pins 16-23 go only to the ioapic.
kvm_default_irq_routing_table(ioapic_pins: usize) -> Vec<IrqRoute>63 fn kvm_default_irq_routing_table(ioapic_pins: usize) -> Vec<IrqRoute> {
64     let mut routes: Vec<IrqRoute> = Vec::new();
65 
66     for i in 0..8 {
67         routes.push(IrqRoute::pic_irq_route(IrqSourceChip::PicPrimary, i));
68         routes.push(IrqRoute::ioapic_irq_route(i));
69     }
70     for i in 8..16 {
71         routes.push(IrqRoute::pic_irq_route(IrqSourceChip::PicSecondary, i));
72         routes.push(IrqRoute::ioapic_irq_route(i));
73     }
74     for i in 16..ioapic_pins as u32 {
75         routes.push(IrqRoute::ioapic_irq_route(i));
76     }
77 
78     routes
79 }
80 
81 /// IrqChip implementation where the entire IrqChip is emulated by KVM.
82 ///
83 /// This implementation will use the KVM API to create and configure the in-kernel irqchip.
84 pub struct KvmKernelIrqChip {
85     pub(super) vm: KvmVm,
86     pub(super) vcpus: Arc<Mutex<Vec<Option<KvmVcpu>>>>,
87     pub(super) routes: Arc<Mutex<Vec<IrqRoute>>>,
88 }
89 
90 #[derive(Serialize, Deserialize)]
91 struct KvmKernelIrqChipSnapshot {
92     routes: Vec<IrqRoute>,
93     // apic_base and interrupt_bitmap are part of the IrqChip, despite the
94     // fact that we get the values from the Vcpu ioctl "KVM_GET_SREGS".
95     // Contains 1 entry per Vcpu.
96     apic_base: Vec<u64>,
97     interrupt_bitmap: Vec<[u64; 4usize]>,
98 }
99 
100 impl KvmKernelIrqChip {
101     /// Construct a new KvmKernelIrqchip.
new(vm: KvmVm, num_vcpus: usize) -> Result<KvmKernelIrqChip>102     pub fn new(vm: KvmVm, num_vcpus: usize) -> Result<KvmKernelIrqChip> {
103         vm.create_irq_chip()?;
104         vm.create_pit()?;
105         let ioapic_pins = vm.get_ioapic_num_pins()?;
106 
107         Ok(KvmKernelIrqChip {
108             vm,
109             vcpus: Arc::new(Mutex::new((0..num_vcpus).map(|_| None).collect())),
110             routes: Arc::new(Mutex::new(kvm_default_irq_routing_table(ioapic_pins))),
111         })
112     }
113     /// Attempt to create a shallow clone of this x86_64 KvmKernelIrqChip instance.
arch_try_clone(&self) -> Result<Self>114     pub(super) fn arch_try_clone(&self) -> Result<Self> {
115         Ok(KvmKernelIrqChip {
116             vm: self.vm.try_clone()?,
117             vcpus: self.vcpus.clone(),
118             routes: self.routes.clone(),
119         })
120     }
121 }
122 
123 impl IrqChipX86_64 for KvmKernelIrqChip {
try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>>124     fn try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>> {
125         Ok(Box::new(self.try_clone()?))
126     }
127 
as_irq_chip(&self) -> &dyn IrqChip128     fn as_irq_chip(&self) -> &dyn IrqChip {
129         self
130     }
131 
as_irq_chip_mut(&mut self) -> &mut dyn IrqChip132     fn as_irq_chip_mut(&mut self) -> &mut dyn IrqChip {
133         self
134     }
135 
136     /// Get the current state of the PIC
get_pic_state(&self, select: PicSelect) -> Result<PicState>137     fn get_pic_state(&self, select: PicSelect) -> Result<PicState> {
138         Ok(PicState::from(&self.vm.get_pic_state(select)?))
139     }
140 
141     /// Set the current state of the PIC
set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()>142     fn set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()> {
143         self.vm.set_pic_state(select, &kvm_pic_state::from(state))
144     }
145 
146     /// Get the current state of the IOAPIC
get_ioapic_state(&self) -> Result<IoapicState>147     fn get_ioapic_state(&self) -> Result<IoapicState> {
148         Ok(IoapicState::from(&self.vm.get_ioapic_state()?))
149     }
150 
151     /// Set the current state of the IOAPIC
set_ioapic_state(&mut self, state: &IoapicState) -> Result<()>152     fn set_ioapic_state(&mut self, state: &IoapicState) -> Result<()> {
153         self.vm.set_ioapic_state(&kvm_ioapic_state::from(state))
154     }
155 
156     /// Get the current state of the specified VCPU's local APIC
get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState>157     fn get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState> {
158         match self.vcpus.lock().get(vcpu_id) {
159             Some(Some(vcpu)) => Ok(LapicState::from(&vcpu.get_lapic()?)),
160             _ => Err(Error::new(libc::ENOENT)),
161         }
162     }
163 
164     /// Set the current state of the specified VCPU's local APIC
set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()>165     fn set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()> {
166         match self.vcpus.lock().get(vcpu_id) {
167             Some(Some(vcpu)) => vcpu.set_lapic(&kvm_lapic_state::from(state)),
168             _ => Err(Error::new(libc::ENOENT)),
169         }
170     }
171 
172     /// Get the lapic frequency in Hz
lapic_frequency(&self) -> u32173     fn lapic_frequency(&self) -> u32 {
174         // KVM emulates the lapic to have a bus frequency of 1GHz
175         1_000_000_000
176     }
177 
178     /// Retrieves the state of the PIT. Gets the pit state via the KVM API.
get_pit(&self) -> Result<PitState>179     fn get_pit(&self) -> Result<PitState> {
180         Ok(PitState::from(&self.vm.get_pit_state()?))
181     }
182 
183     /// Sets the state of the PIT. Sets the pit state via the KVM API.
set_pit(&mut self, state: &PitState) -> Result<()>184     fn set_pit(&mut self, state: &PitState) -> Result<()> {
185         self.vm.set_pit_state(&kvm_pit_state2::from(state))
186     }
187 
188     /// Returns true if the PIT uses port 0x61 for the PC speaker, false if 0x61 is unused.
189     /// KVM's kernel PIT doesn't use 0x61.
pit_uses_speaker_port(&self) -> bool190     fn pit_uses_speaker_port(&self) -> bool {
191         false
192     }
193 
snapshot_chip_specific(&self) -> anyhow::Result<AnySnapshot>194     fn snapshot_chip_specific(&self) -> anyhow::Result<AnySnapshot> {
195         let mut apics: Vec<u64> = Vec::new();
196         let mut interrupt_bitmaps: Vec<[u64; 4usize]> = Vec::new();
197         {
198             let vcpus_lock = self.vcpus.lock();
199             for vcpu in (*vcpus_lock).iter().flatten() {
200                 apics.push(vcpu.get_apic_base()?);
201                 interrupt_bitmaps.push(vcpu.get_interrupt_bitmap()?);
202             }
203         }
204         AnySnapshot::to_any(KvmKernelIrqChipSnapshot {
205             routes: self.routes.lock().clone(),
206             apic_base: apics,
207             interrupt_bitmap: interrupt_bitmaps,
208         })
209         .context("failed to serialize KvmKernelIrqChip")
210     }
211 
restore_chip_specific(&mut self, data: AnySnapshot) -> anyhow::Result<()>212     fn restore_chip_specific(&mut self, data: AnySnapshot) -> anyhow::Result<()> {
213         let deser: KvmKernelIrqChipSnapshot =
214             AnySnapshot::from_any(data).context("failed to deserialize data")?;
215         self.set_irq_routes(&deser.routes)?;
216         let vcpus_lock = self.vcpus.lock();
217         assert_eq!(deser.interrupt_bitmap.len(), vcpus_lock.len());
218         assert_eq!(deser.apic_base.len(), vcpus_lock.len());
219         for (i, vcpu) in vcpus_lock.iter().enumerate() {
220             if let Some(vcpu) = vcpu {
221                 vcpu.set_apic_base(*deser.apic_base.get(i).unwrap())?;
222                 vcpu.set_interrupt_bitmap(*deser.interrupt_bitmap.get(i).unwrap())?;
223             } else {
224                 return Err(anyhow!(
225                     "Received None instead of Vcpu while restoring apic_base and interrupt_bitmap"
226                 ));
227             }
228         }
229         Ok(())
230     }
231 }
232 
233 /// The KvmSplitIrqsChip supports KVM's SPLIT_IRQCHIP feature, where the PIC and IOAPIC
234 /// are emulated in userspace, while the local APICs are emulated in the kernel.
235 /// The SPLIT_IRQCHIP feature only supports x86/x86_64 so we only define this IrqChip in crosvm
236 /// for x86/x86_64.
237 pub struct KvmSplitIrqChip {
238     vm: KvmVm,
239     vcpus: Arc<Mutex<Vec<Option<KvmVcpu>>>>,
240     routes: Arc<Mutex<Vec<IrqRoute>>>,
241     pit: Arc<Mutex<Pit>>,
242     pic: Arc<Mutex<Pic>>,
243     ioapic: Arc<Mutex<Ioapic>>,
244     ioapic_pins: usize,
245     /// Vec of ioapic irq events that have been delayed because the ioapic was locked when
246     /// service_irq was called on the irqchip. This prevents deadlocks when a Vcpu thread has
247     /// locked the ioapic and the ioapic sends a AddMsiRoute signal to the main thread (which
248     /// itself may be busy trying to call service_irq).
249     delayed_ioapic_irq_events: Arc<Mutex<Vec<usize>>>,
250     /// Event which is meant to trigger process of any irqs events that were delayed.
251     delayed_ioapic_irq_trigger: Event,
252     /// Array of Events that devices will use to assert ioapic pins.
253     irq_events: Arc<Mutex<Vec<Option<IrqEvent>>>>,
254 }
255 
kvm_dummy_msi_routes(ioapic_pins: usize) -> Vec<IrqRoute>256 fn kvm_dummy_msi_routes(ioapic_pins: usize) -> Vec<IrqRoute> {
257     let mut routes: Vec<IrqRoute> = Vec::new();
258     for i in 0..ioapic_pins {
259         routes.push(
260             // Add dummy MSI routes to replace the default IRQChip routes.
261             IrqRoute {
262                 gsi: i as u32,
263                 source: IrqSource::Msi {
264                     address: 0,
265                     data: 0,
266                 },
267             },
268         );
269     }
270     routes
271 }
272 
273 impl KvmSplitIrqChip {
274     /// Construct a new KvmSplitIrqChip.
new( vm: KvmVm, num_vcpus: usize, irq_tube: Tube, ioapic_pins: Option<usize>, ) -> Result<Self>275     pub fn new(
276         vm: KvmVm,
277         num_vcpus: usize,
278         irq_tube: Tube,
279         ioapic_pins: Option<usize>,
280     ) -> Result<Self> {
281         let ioapic_pins = ioapic_pins.unwrap_or(vm.get_ioapic_num_pins()?);
282         vm.enable_split_irqchip(ioapic_pins)?;
283         let pit_evt = IrqEdgeEvent::new()?;
284         let pit = Pit::new(pit_evt.try_clone()?, Arc::new(Mutex::new(Clock::new()))).map_err(
285             |e| match e {
286                 PitError::CloneEvent(err) => err,
287                 PitError::CreateEvent(err) => err,
288                 PitError::CreateWaitContext(err) => err,
289                 PitError::WaitError(err) => err,
290                 PitError::TimerCreateError(err) => err,
291                 PitError::SpawnThread(_) => Error::new(libc::EIO),
292             },
293         )?;
294 
295         let pit_event_source = IrqEventSource::from_device(&pit);
296 
297         let mut chip = KvmSplitIrqChip {
298             vm,
299             vcpus: Arc::new(Mutex::new((0..num_vcpus).map(|_| None).collect())),
300             routes: Arc::new(Mutex::new(Vec::new())),
301             pit: Arc::new(Mutex::new(pit)),
302             pic: Arc::new(Mutex::new(Pic::new())),
303             ioapic: Arc::new(Mutex::new(Ioapic::new(irq_tube, ioapic_pins)?)),
304             ioapic_pins,
305             delayed_ioapic_irq_events: Arc::new(Mutex::new(Vec::new())),
306             delayed_ioapic_irq_trigger: Event::new()?,
307             irq_events: Arc::new(Mutex::new(Default::default())),
308         };
309 
310         // Setup standard x86 irq routes
311         let mut routes = kvm_default_irq_routing_table(ioapic_pins);
312         // Add dummy MSI routes for the first ioapic_pins GSIs
313         routes.append(&mut kvm_dummy_msi_routes(ioapic_pins));
314 
315         // Set the routes so they get sent to KVM
316         chip.set_irq_routes(&routes)?;
317 
318         chip.register_edge_irq_event(PIT_CHANNEL0_IRQ, &pit_evt, pit_event_source)?;
319         Ok(chip)
320     }
321 }
322 
323 impl KvmSplitIrqChip {
324     /// Convenience function for determining which chips the supplied irq routes to.
routes_to_chips(&self, irq: u32) -> Vec<(IrqSourceChip, u32)>325     fn routes_to_chips(&self, irq: u32) -> Vec<(IrqSourceChip, u32)> {
326         let mut chips = Vec::new();
327         for route in self.routes.lock().iter() {
328             match route {
329                 IrqRoute {
330                     gsi,
331                     source: IrqSource::Irqchip { chip, pin },
332                 } if *gsi == irq => match chip {
333                     IrqSourceChip::PicPrimary
334                     | IrqSourceChip::PicSecondary
335                     | IrqSourceChip::Ioapic => chips.push((*chip, *pin)),
336                     IrqSourceChip::Gic => {
337                         error!("gic irq should not be possible on a KvmSplitIrqChip")
338                     }
339                     IrqSourceChip::Aia => {
340                         error!("Aia irq should not be possible on x86_64")
341                     }
342                 },
343                 // Ignore MSIs and other routes
344                 _ => {}
345             }
346         }
347         chips
348     }
349 
350     /// Return true if there is a pending interrupt for the specified vcpu. For KvmSplitIrqChip
351     /// this calls interrupt_requested on the pic.
interrupt_requested(&self, vcpu_id: usize) -> bool352     pub fn interrupt_requested(&self, vcpu_id: usize) -> bool {
353         // Pic interrupts for the split irqchip only go to vcpu 0
354         if vcpu_id != 0 {
355             return false;
356         }
357         self.pic.lock().interrupt_requested()
358     }
359 
360     /// Check if the specified vcpu has any pending interrupts. Returns [`None`] for no interrupts,
361     /// otherwise [`Some::<u8>`] should be the injected interrupt vector. For [`KvmSplitIrqChip`]
362     /// this calls `get_external_interrupt` on the pic.
get_external_interrupt(&self, vcpu_id: usize) -> Option<u8>363     pub fn get_external_interrupt(&self, vcpu_id: usize) -> Option<u8> {
364         // Pic interrupts for the split irqchip only go to vcpu 0
365         if vcpu_id != 0 {
366             return None;
367         }
368         self.pic.lock().get_external_interrupt()
369     }
370 
371     /// Register an event that can trigger an interrupt for a particular GSI.
register_irq_event( &mut self, irq: u32, irq_event: &Event, resample_event: Option<&Event>, source: IrqEventSource, ) -> Result<Option<IrqEventIndex>>372     fn register_irq_event(
373         &mut self,
374         irq: u32,
375         irq_event: &Event,
376         resample_event: Option<&Event>,
377         source: IrqEventSource,
378     ) -> Result<Option<IrqEventIndex>> {
379         if irq < self.ioapic_pins as u32 {
380             let mut evt = IrqEvent {
381                 gsi: irq,
382                 event: irq_event.try_clone()?,
383                 resample_event: None,
384                 source,
385             };
386 
387             if let Some(resample_event) = resample_event {
388                 evt.resample_event = Some(resample_event.try_clone()?);
389             }
390 
391             let mut irq_events = self.irq_events.lock();
392             let index = irq_events.len();
393             irq_events.push(Some(evt));
394             Ok(Some(index))
395         } else {
396             self.vm.register_irqfd(irq, irq_event, resample_event)?;
397             Ok(None)
398         }
399     }
400 
401     /// Unregister an event for a particular GSI.
unregister_irq_event(&mut self, irq: u32, irq_event: &Event) -> Result<()>402     fn unregister_irq_event(&mut self, irq: u32, irq_event: &Event) -> Result<()> {
403         if irq < self.ioapic_pins as u32 {
404             let mut irq_events = self.irq_events.lock();
405             for (index, evt) in irq_events.iter().enumerate() {
406                 if let Some(evt) = evt {
407                     if evt.gsi == irq && irq_event.eq(&evt.event) {
408                         irq_events[index] = None;
409                         break;
410                     }
411                 }
412             }
413             Ok(())
414         } else {
415             self.vm.unregister_irqfd(irq, irq_event)
416         }
417     }
418 }
419 
420 /// Convenience function for determining whether or not two irq routes conflict.
421 /// Returns true if they conflict.
routes_conflict(route: &IrqRoute, other: &IrqRoute) -> bool422 fn routes_conflict(route: &IrqRoute, other: &IrqRoute) -> bool {
423     // They don't conflict if they have different GSIs.
424     if route.gsi != other.gsi {
425         return false;
426     }
427 
428     // If they're both MSI with the same GSI then they conflict.
429     if let (IrqSource::Msi { .. }, IrqSource::Msi { .. }) = (route.source, other.source) {
430         return true;
431     }
432 
433     // If the route chips match and they have the same GSI then they conflict.
434     if let (
435         IrqSource::Irqchip {
436             chip: route_chip, ..
437         },
438         IrqSource::Irqchip {
439             chip: other_chip, ..
440         },
441     ) = (route.source, other.source)
442     {
443         return route_chip == other_chip;
444     }
445 
446     // Otherwise they do not conflict.
447     false
448 }
449 
450 /// This IrqChip only works with Kvm so we only implement it for KvmVcpu.
451 impl IrqChip for KvmSplitIrqChip {
452     /// Add a vcpu to the irq chip.
add_vcpu(&mut self, vcpu_id: usize, vcpu: &dyn Vcpu) -> Result<()>453     fn add_vcpu(&mut self, vcpu_id: usize, vcpu: &dyn Vcpu) -> Result<()> {
454         let vcpu: &KvmVcpu = vcpu
455             .downcast_ref()
456             .expect("KvmSplitIrqChip::add_vcpu called with non-KvmVcpu");
457         self.vcpus.lock()[vcpu_id] = Some(vcpu.try_clone()?);
458         Ok(())
459     }
460 
461     /// Register an event that can trigger an interrupt for a particular GSI.
register_edge_irq_event( &mut self, irq: u32, irq_event: &IrqEdgeEvent, source: IrqEventSource, ) -> Result<Option<IrqEventIndex>>462     fn register_edge_irq_event(
463         &mut self,
464         irq: u32,
465         irq_event: &IrqEdgeEvent,
466         source: IrqEventSource,
467     ) -> Result<Option<IrqEventIndex>> {
468         self.register_irq_event(irq, irq_event.get_trigger(), None, source)
469     }
470 
unregister_edge_irq_event(&mut self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()>471     fn unregister_edge_irq_event(&mut self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()> {
472         self.unregister_irq_event(irq, irq_event.get_trigger())
473     }
474 
register_level_irq_event( &mut self, irq: u32, irq_event: &IrqLevelEvent, source: IrqEventSource, ) -> Result<Option<IrqEventIndex>>475     fn register_level_irq_event(
476         &mut self,
477         irq: u32,
478         irq_event: &IrqLevelEvent,
479         source: IrqEventSource,
480     ) -> Result<Option<IrqEventIndex>> {
481         self.register_irq_event(
482             irq,
483             irq_event.get_trigger(),
484             Some(irq_event.get_resample()),
485             source,
486         )
487     }
488 
unregister_level_irq_event(&mut self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()>489     fn unregister_level_irq_event(&mut self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()> {
490         self.unregister_irq_event(irq, irq_event.get_trigger())
491     }
492 
493     /// Route an IRQ line to an interrupt controller, or to a particular MSI vector.
route_irq(&mut self, route: IrqRoute) -> Result<()>494     fn route_irq(&mut self, route: IrqRoute) -> Result<()> {
495         let mut routes = self.routes.lock();
496         routes.retain(|r| !routes_conflict(r, &route));
497 
498         routes.push(route);
499 
500         // We only call set_gsi_routing with the msi routes
501         let mut msi_routes = routes.clone();
502         msi_routes.retain(|r| matches!(r.source, IrqSource::Msi { .. }));
503 
504         self.vm.set_gsi_routing(&msi_routes)
505     }
506 
507     /// Replace all irq routes with the supplied routes
set_irq_routes(&mut self, routes: &[IrqRoute]) -> Result<()>508     fn set_irq_routes(&mut self, routes: &[IrqRoute]) -> Result<()> {
509         let mut current_routes = self.routes.lock();
510         *current_routes = routes.to_vec();
511 
512         // We only call set_gsi_routing with the msi routes
513         let mut msi_routes = routes.to_vec();
514         msi_routes.retain(|r| matches!(r.source, IrqSource::Msi { .. }));
515 
516         self.vm.set_gsi_routing(&msi_routes)
517     }
518 
519     /// Return a vector of all registered irq numbers and their associated events and event
520     /// indices. These should be used by the main thread to wait for irq events.
irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>>521     fn irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>> {
522         let mut tokens = vec![];
523         for (index, evt) in self.irq_events.lock().iter().enumerate() {
524             if let Some(evt) = evt {
525                 tokens.push((index, evt.source.clone(), evt.event.try_clone()?));
526             }
527         }
528         Ok(tokens)
529     }
530 
531     /// Either assert or deassert an IRQ line.  Sends to either an interrupt controller, or does
532     /// a send_msi if the irq is associated with an MSI.
service_irq(&mut self, irq: u32, level: bool) -> Result<()>533     fn service_irq(&mut self, irq: u32, level: bool) -> Result<()> {
534         let chips = self.routes_to_chips(irq);
535         for (chip, pin) in chips {
536             match chip {
537                 IrqSourceChip::PicPrimary | IrqSourceChip::PicSecondary => {
538                     self.pic.lock().service_irq(pin as u8, level);
539                 }
540                 IrqSourceChip::Ioapic => {
541                     self.ioapic.lock().service_irq(pin as usize, level);
542                 }
543                 _ => {}
544             }
545         }
546         Ok(())
547     }
548 
549     /// Service an IRQ event by asserting then deasserting an IRQ line. The associated Event
550     /// that triggered the irq event will be read from. If the irq is associated with a resample
551     /// Event, then the deassert will only happen after an EOI is broadcast for a vector
552     /// associated with the irq line.
553     /// For the KvmSplitIrqChip, this function identifies which chips the irq routes to, then
554     /// attempts to call service_irq on those chips. If the ioapic is unable to be immediately
555     /// locked, we add the irq to the delayed_ioapic_irq_events Vec (though we still read
556     /// from the Event that triggered the irq event).
service_irq_event(&mut self, event_index: IrqEventIndex) -> Result<()>557     fn service_irq_event(&mut self, event_index: IrqEventIndex) -> Result<()> {
558         if let Some(evt) = &self.irq_events.lock()[event_index] {
559             evt.event.wait()?;
560             let chips = self.routes_to_chips(evt.gsi);
561 
562             for (chip, pin) in chips {
563                 match chip {
564                     IrqSourceChip::PicPrimary | IrqSourceChip::PicSecondary => {
565                         let mut pic = self.pic.lock();
566                         pic.service_irq(pin as u8, true);
567                         if evt.resample_event.is_none() {
568                             pic.service_irq(pin as u8, false);
569                         }
570                     }
571                     IrqSourceChip::Ioapic => {
572                         if let Ok(mut ioapic) = self.ioapic.try_lock() {
573                             ioapic.service_irq(pin as usize, true);
574                             if evt.resample_event.is_none() {
575                                 ioapic.service_irq(pin as usize, false);
576                             }
577                         } else {
578                             self.delayed_ioapic_irq_events.lock().push(event_index);
579                             self.delayed_ioapic_irq_trigger.signal().unwrap();
580                         }
581                     }
582                     _ => {}
583                 }
584             }
585         }
586 
587         Ok(())
588     }
589 
590     /// Broadcast an end of interrupt. For KvmSplitIrqChip this sends the EOI to the ioapic
broadcast_eoi(&self, vector: u8) -> Result<()>591     fn broadcast_eoi(&self, vector: u8) -> Result<()> {
592         self.ioapic.lock().end_of_interrupt(vector);
593         Ok(())
594     }
595 
596     /// Injects any pending interrupts for `vcpu`.
597     /// For KvmSplitIrqChip this injects any PIC interrupts on vcpu_id 0.
inject_interrupts(&self, vcpu: &dyn Vcpu) -> Result<()>598     fn inject_interrupts(&self, vcpu: &dyn Vcpu) -> Result<()> {
599         let vcpu: &KvmVcpu = vcpu
600             .downcast_ref()
601             .expect("KvmSplitIrqChip::add_vcpu called with non-KvmVcpu");
602 
603         let vcpu_id = vcpu.id();
604         if !self.interrupt_requested(vcpu_id) || !vcpu.ready_for_interrupt() {
605             return Ok(());
606         }
607 
608         if let Some(vector) = self.get_external_interrupt(vcpu_id) {
609             vcpu.interrupt(vector)?;
610         }
611 
612         // The second interrupt request should be handled immediately, so ask vCPU to exit as soon
613         // as possible.
614         if self.interrupt_requested(vcpu_id) {
615             vcpu.set_interrupt_window_requested(true);
616         }
617         Ok(())
618     }
619 
620     /// Notifies the irq chip that the specified VCPU has executed a halt instruction.
621     /// For KvmSplitIrqChip this is a no-op because KVM handles VCPU blocking.
halted(&self, _vcpu_id: usize)622     fn halted(&self, _vcpu_id: usize) {}
623 
624     /// Blocks until `vcpu` is in a runnable state or until interrupted by
625     /// `IrqChip::kick_halted_vcpus`.  Returns `VcpuRunState::Runnable if vcpu is runnable, or
626     /// `VcpuRunState::Interrupted` if the wait was interrupted.
627     /// For KvmSplitIrqChip this is a no-op and always returns Runnable because KVM handles VCPU
628     /// blocking.
wait_until_runnable(&self, _vcpu: &dyn Vcpu) -> Result<VcpuRunState>629     fn wait_until_runnable(&self, _vcpu: &dyn Vcpu) -> Result<VcpuRunState> {
630         Ok(VcpuRunState::Runnable)
631     }
632 
633     /// Makes unrunnable VCPUs return immediately from `wait_until_runnable`.
634     /// For KvmSplitIrqChip this is a no-op because KVM handles VCPU blocking.
kick_halted_vcpus(&self)635     fn kick_halted_vcpus(&self) {}
636 
637     /// Get the current MP state of the specified VCPU.
get_mp_state(&self, vcpu_id: usize) -> Result<MPState>638     fn get_mp_state(&self, vcpu_id: usize) -> Result<MPState> {
639         match self.vcpus.lock().get(vcpu_id) {
640             Some(Some(vcpu)) => Ok(MPState::from(&vcpu.get_mp_state()?)),
641             _ => Err(Error::new(libc::ENOENT)),
642         }
643     }
644 
645     /// Set the current MP state of the specified VCPU.
set_mp_state(&mut self, vcpu_id: usize, state: &MPState) -> Result<()>646     fn set_mp_state(&mut self, vcpu_id: usize, state: &MPState) -> Result<()> {
647         match self.vcpus.lock().get(vcpu_id) {
648             Some(Some(vcpu)) => vcpu.set_mp_state(&kvm_mp_state::from(state)),
649             _ => Err(Error::new(libc::ENOENT)),
650         }
651     }
652 
653     /// Attempt to clone this IrqChip instance.
try_clone(&self) -> Result<Self>654     fn try_clone(&self) -> Result<Self> {
655         Ok(KvmSplitIrqChip {
656             vm: self.vm.try_clone()?,
657             vcpus: self.vcpus.clone(),
658             routes: self.routes.clone(),
659             pit: self.pit.clone(),
660             pic: self.pic.clone(),
661             ioapic: self.ioapic.clone(),
662             ioapic_pins: self.ioapic_pins,
663             delayed_ioapic_irq_events: self.delayed_ioapic_irq_events.clone(),
664             delayed_ioapic_irq_trigger: Event::new()?,
665             irq_events: self.irq_events.clone(),
666         })
667     }
668 
669     /// Finalize irqchip setup. Should be called once all devices have registered irq events and
670     /// been added to the io_bus and mmio_bus.
finalize_devices( &mut self, resources: &mut SystemAllocator, io_bus: &Bus, mmio_bus: &Bus, ) -> Result<()>671     fn finalize_devices(
672         &mut self,
673         resources: &mut SystemAllocator,
674         io_bus: &Bus,
675         mmio_bus: &Bus,
676     ) -> Result<()> {
677         // Insert pit into io_bus
678         io_bus.insert(self.pit.clone(), 0x040, 0x8).unwrap();
679         io_bus.insert(self.pit.clone(), 0x061, 0x1).unwrap();
680 
681         // Insert pic into io_bus
682         io_bus.insert(self.pic.clone(), 0x20, 0x2).unwrap();
683         io_bus.insert(self.pic.clone(), 0xa0, 0x2).unwrap();
684         io_bus.insert(self.pic.clone(), 0x4d0, 0x2).unwrap();
685 
686         // Insert ioapic into mmio_bus
687         mmio_bus
688             .insert(
689                 self.ioapic.clone(),
690                 IOAPIC_BASE_ADDRESS,
691                 IOAPIC_MEM_LENGTH_BYTES,
692             )
693             .unwrap();
694 
695         // At this point, all of our devices have been created and they have registered their
696         // irq events, so we can clone our resample events
697         let mut ioapic_resample_events: Vec<Vec<Event>> =
698             (0..self.ioapic_pins).map(|_| Vec::new()).collect();
699         let mut pic_resample_events: Vec<Vec<Event>> =
700             (0..self.ioapic_pins).map(|_| Vec::new()).collect();
701 
702         for evt in self.irq_events.lock().iter().flatten() {
703             if (evt.gsi as usize) >= self.ioapic_pins {
704                 continue;
705             }
706             if let Some(resample_evt) = &evt.resample_event {
707                 ioapic_resample_events[evt.gsi as usize].push(resample_evt.try_clone()?);
708                 pic_resample_events[evt.gsi as usize].push(resample_evt.try_clone()?);
709             }
710         }
711 
712         // Register resample events with the ioapic
713         self.ioapic
714             .lock()
715             .register_resample_events(ioapic_resample_events);
716         // Register resample events with the pic
717         self.pic
718             .lock()
719             .register_resample_events(pic_resample_events);
720 
721         // Make sure all future irq numbers are beyond IO-APIC range.
722         let mut irq_num = resources.allocate_irq().unwrap();
723         while irq_num < self.ioapic_pins as u32 {
724             irq_num = resources.allocate_irq().unwrap();
725         }
726 
727         Ok(())
728     }
729 
730     /// The KvmSplitIrqChip's ioapic may be locked because a vcpu thread is currently writing to
731     /// the ioapic, and the ioapic may be blocking on adding MSI routes, which requires blocking
732     /// socket communication back to the main thread.  Thus, we do not want the main thread to
733     /// block on a locked ioapic, so any irqs that could not be serviced because the ioapic could
734     /// not be immediately locked are added to the delayed_ioapic_irq_events Vec. This function
735     /// processes each delayed event in the vec each time it's called. If the ioapic is still
736     /// locked, we keep the queued irqs for the next time this function is called.
process_delayed_irq_events(&mut self) -> Result<()>737     fn process_delayed_irq_events(&mut self) -> Result<()> {
738         self.delayed_ioapic_irq_events
739             .lock()
740             .retain(|&event_index| {
741                 if let Some(evt) = &self.irq_events.lock()[event_index] {
742                     if let Ok(mut ioapic) = self.ioapic.try_lock() {
743                         ioapic.service_irq(evt.gsi as usize, true);
744                         if evt.resample_event.is_none() {
745                             ioapic.service_irq(evt.gsi as usize, false);
746                         }
747 
748                         false
749                     } else {
750                         true
751                     }
752                 } else {
753                     true
754                 }
755             });
756 
757         if self.delayed_ioapic_irq_events.lock().is_empty() {
758             self.delayed_ioapic_irq_trigger.wait()?;
759         }
760 
761         Ok(())
762     }
763 
irq_delayed_event_token(&self) -> Result<Option<Event>>764     fn irq_delayed_event_token(&self) -> Result<Option<Event>> {
765         Ok(Some(self.delayed_ioapic_irq_trigger.try_clone()?))
766     }
767 
check_capability(&self, c: IrqChipCap) -> bool768     fn check_capability(&self, c: IrqChipCap) -> bool {
769         match c {
770             IrqChipCap::TscDeadlineTimer => self
771                 .vm
772                 .get_hypervisor()
773                 .check_capability(HypervisorCap::TscDeadlineTimer),
774             IrqChipCap::X2Apic => true,
775             IrqChipCap::MpStateGetSet => true,
776         }
777     }
778 }
779 
780 #[derive(Serialize, Deserialize)]
781 struct KvmSplitIrqChipSnapshot {
782     routes: Vec<IrqRoute>,
783 }
784 
785 impl IrqChipX86_64 for KvmSplitIrqChip {
try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>>786     fn try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>> {
787         Ok(Box::new(self.try_clone()?))
788     }
789 
as_irq_chip(&self) -> &dyn IrqChip790     fn as_irq_chip(&self) -> &dyn IrqChip {
791         self
792     }
793 
as_irq_chip_mut(&mut self) -> &mut dyn IrqChip794     fn as_irq_chip_mut(&mut self) -> &mut dyn IrqChip {
795         self
796     }
797 
798     /// Get the current state of the PIC
get_pic_state(&self, select: PicSelect) -> Result<PicState>799     fn get_pic_state(&self, select: PicSelect) -> Result<PicState> {
800         Ok(self.pic.lock().get_pic_state(select))
801     }
802 
803     /// Set the current state of the PIC
set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()>804     fn set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()> {
805         self.pic.lock().set_pic_state(select, state);
806         Ok(())
807     }
808 
809     /// Get the current state of the IOAPIC
get_ioapic_state(&self) -> Result<IoapicState>810     fn get_ioapic_state(&self) -> Result<IoapicState> {
811         Ok(self.ioapic.lock().get_ioapic_state())
812     }
813 
814     /// Set the current state of the IOAPIC
set_ioapic_state(&mut self, state: &IoapicState) -> Result<()>815     fn set_ioapic_state(&mut self, state: &IoapicState) -> Result<()> {
816         self.ioapic.lock().set_ioapic_state(state);
817         Ok(())
818     }
819 
820     /// Get the current state of the specified VCPU's local APIC
get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState>821     fn get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState> {
822         match self.vcpus.lock().get(vcpu_id) {
823             Some(Some(vcpu)) => Ok(LapicState::from(&vcpu.get_lapic()?)),
824             _ => Err(Error::new(libc::ENOENT)),
825         }
826     }
827 
828     /// Set the current state of the specified VCPU's local APIC
set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()>829     fn set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()> {
830         match self.vcpus.lock().get(vcpu_id) {
831             Some(Some(vcpu)) => vcpu.set_lapic(&kvm_lapic_state::from(state)),
832             _ => Err(Error::new(libc::ENOENT)),
833         }
834     }
835 
836     /// Get the lapic frequency in Hz
lapic_frequency(&self) -> u32837     fn lapic_frequency(&self) -> u32 {
838         // KVM emulates the lapic to have a bus frequency of 1GHz
839         1_000_000_000
840     }
841 
842     /// Retrieves the state of the PIT. Gets the pit state via the KVM API.
get_pit(&self) -> Result<PitState>843     fn get_pit(&self) -> Result<PitState> {
844         Ok(self.pit.lock().get_pit_state())
845     }
846 
847     /// Sets the state of the PIT. Sets the pit state via the KVM API.
set_pit(&mut self, state: &PitState) -> Result<()>848     fn set_pit(&mut self, state: &PitState) -> Result<()> {
849         self.pit.lock().set_pit_state(state);
850         Ok(())
851     }
852 
853     /// Returns true if the PIT uses port 0x61 for the PC speaker, false if 0x61 is unused.
854     /// devices::Pit uses 0x61.
pit_uses_speaker_port(&self) -> bool855     fn pit_uses_speaker_port(&self) -> bool {
856         true
857     }
858 
snapshot_chip_specific(&self) -> anyhow::Result<AnySnapshot>859     fn snapshot_chip_specific(&self) -> anyhow::Result<AnySnapshot> {
860         AnySnapshot::to_any(KvmSplitIrqChipSnapshot {
861             routes: self.routes.lock().clone(),
862         })
863         .context("failed to serialize KvmSplitIrqChip")
864     }
865 
restore_chip_specific(&mut self, data: AnySnapshot) -> anyhow::Result<()>866     fn restore_chip_specific(&mut self, data: AnySnapshot) -> anyhow::Result<()> {
867         let deser: KvmSplitIrqChipSnapshot =
868             AnySnapshot::from_any(data).context("failed to deserialize KvmSplitIrqChip")?;
869         self.set_irq_routes(&deser.routes)?;
870         Ok(())
871     }
872 }
873