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