1use std::sync::Arc;
6
7use anyhow::anyhow;
8use anyhow::Context;
9use base::error;
10#[cfg(not(test))]
11use base::Clock;
12use base::Error;
13use base::Event;
14#[cfg(test)]
15use base::FakeClock as Clock;
16use base::Result;
17use base::Tube;
18use hypervisor::kvm::KvmCap;
19use hypervisor::kvm::KvmVcpu;
20use hypervisor::kvm::KvmVm;
21use hypervisor::IoapicState;
22use hypervisor::IrqRoute;
23use hypervisor::IrqSource;
24use hypervisor::IrqSourceChip;
25use hypervisor::LapicState;
26use hypervisor::MPState;
27use hypervisor::PicSelect;
28use hypervisor::PicState;
29use hypervisor::PitState;
30use hypervisor::Vcpu;
31use hypervisor::VcpuX86_64;
32use hypervisor::Vm;
33use kvm_sys::*;
34use resources::SystemAllocator;
35use serde::Deserialize;
36use serde::Serialize;
37use snapshot::AnySnapshot;
38use sync::Mutex;
39
40use crate::irqchip::Ioapic;
41use crate::irqchip::IrqEvent;
42use crate::irqchip::IrqEventIndex;
43use crate::irqchip::Pic;
44use crate::irqchip::VcpuRunState;
45use crate::irqchip::IOAPIC_BASE_ADDRESS;
46use crate::irqchip::IOAPIC_MEM_LENGTH_BYTES;
47use crate::Bus;
48use crate::IrqChip;
49use crate::IrqChipCap;
50use crate::IrqChipX86_64;
51use crate::IrqEdgeEvent;
52use crate::IrqEventSource;
53use crate::IrqLevelEvent;
54use crate::Pit;
55use crate::PitError;
56
57const PIT_CHANNEL0_IRQ: u32 = 0;
59
60fn kvm_default_irq_routing_table(ioapic_pins: usize) -> Vec<IrqRoute> {
63 let mut routes: Vec<IrqRoute> = Vec::new();
64
65 for i in 0..8 {
66 routes.push(IrqRoute::pic_irq_route(IrqSourceChip::PicPrimary, i));
67 routes.push(IrqRoute::ioapic_irq_route(i));
68 }
69 for i in 8..16 {
70 routes.push(IrqRoute::pic_irq_route(IrqSourceChip::PicSecondary, i));
71 routes.push(IrqRoute::ioapic_irq_route(i));
72 }
73 for i in 16..ioapic_pins as u32 {
74 routes.push(IrqRoute::ioapic_irq_route(i));
75 }
76
77 routes
78}
79
80pub struct KvmKernelIrqChip {
84 pub(super) vm: KvmVm,
85 pub(super) vcpus: Arc<Mutex<Vec<Option<KvmVcpu>>>>,
86 pub(super) routes: Arc<Mutex<Vec<IrqRoute>>>,
87}
88
89#[derive(Serialize, Deserialize)]
90struct KvmKernelIrqChipSnapshot {
91 routes: Vec<IrqRoute>,
92 apic_base: Vec<u64>,
96 interrupt_bitmap: Vec<[u64; 4usize]>,
97}
98
99impl KvmKernelIrqChip {
100 pub fn new(vm: KvmVm, num_vcpus: usize) -> Result<KvmKernelIrqChip> {
102 vm.create_irq_chip()?;
103 vm.create_pit()?;
104 let ioapic_pins = vm.get_ioapic_num_pins()?;
105
106 Ok(KvmKernelIrqChip {
107 vm,
108 vcpus: Arc::new(Mutex::new((0..num_vcpus).map(|_| None).collect())),
109 routes: Arc::new(Mutex::new(kvm_default_irq_routing_table(ioapic_pins))),
110 })
111 }
112 pub(super) fn arch_try_clone(&self) -> Result<Self> {
114 Ok(KvmKernelIrqChip {
115 vm: self.vm.try_clone()?,
116 vcpus: self.vcpus.clone(),
117 routes: self.routes.clone(),
118 })
119 }
120}
121
122impl IrqChipX86_64 for KvmKernelIrqChip {
123 fn try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>> {
124 Ok(Box::new(self.try_clone()?))
125 }
126
127 fn as_irq_chip(&self) -> &dyn IrqChip {
128 self
129 }
130
131 fn as_irq_chip_mut(&mut self) -> &mut dyn IrqChip {
132 self
133 }
134
135 fn get_pic_state(&self, select: PicSelect) -> Result<PicState> {
137 Ok(PicState::from(&self.vm.get_pic_state(select)?))
138 }
139
140 fn set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()> {
142 self.vm.set_pic_state(select, &kvm_pic_state::from(state))
143 }
144
145 fn get_ioapic_state(&self) -> Result<IoapicState> {
147 Ok(IoapicState::from(&self.vm.get_ioapic_state()?))
148 }
149
150 fn set_ioapic_state(&mut self, state: &IoapicState) -> Result<()> {
152 self.vm.set_ioapic_state(&kvm_ioapic_state::from(state))
153 }
154
155 fn get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState> {
157 match self.vcpus.lock().get(vcpu_id) {
158 Some(Some(vcpu)) => Ok(LapicState::from(&vcpu.get_lapic()?)),
159 _ => Err(Error::new(libc::ENOENT)),
160 }
161 }
162
163 fn set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()> {
165 match self.vcpus.lock().get(vcpu_id) {
166 Some(Some(vcpu)) => vcpu.set_lapic(&kvm_lapic_state::from(state)),
167 _ => Err(Error::new(libc::ENOENT)),
168 }
169 }
170
171 fn lapic_frequency(&self) -> u32 {
173 1_000_000_000
175 }
176
177 fn get_pit(&self) -> Result<PitState> {
179 Ok(PitState::from(&self.vm.get_pit_state()?))
180 }
181
182 fn set_pit(&mut self, state: &PitState) -> Result<()> {
184 self.vm.set_pit_state(&kvm_pit_state2::from(state))
185 }
186
187 fn pit_uses_speaker_port(&self) -> bool {
190 false
191 }
192
193 fn snapshot_chip_specific(&self) -> anyhow::Result<AnySnapshot> {
194 let mut apics: Vec<u64> = Vec::new();
195 let mut interrupt_bitmaps: Vec<[u64; 4usize]> = Vec::new();
196 {
197 let vcpus_lock = self.vcpus.lock();
198 for vcpu in (*vcpus_lock).iter().flatten() {
199 apics.push(vcpu.get_apic_base()?);
200 interrupt_bitmaps.push(vcpu.get_interrupt_bitmap()?);
201 }
202 }
203 AnySnapshot::to_any(KvmKernelIrqChipSnapshot {
204 routes: self.routes.lock().clone(),
205 apic_base: apics,
206 interrupt_bitmap: interrupt_bitmaps,
207 })
208 .context("failed to serialize KvmKernelIrqChip")
209 }
210
211 fn restore_chip_specific(&mut self, data: AnySnapshot) -> anyhow::Result<()> {
212 let deser: KvmKernelIrqChipSnapshot =
213 AnySnapshot::from_any(data).context("failed to deserialize data")?;
214 self.set_irq_routes(&deser.routes)?;
215 let vcpus_lock = self.vcpus.lock();
216 assert_eq!(deser.interrupt_bitmap.len(), vcpus_lock.len());
217 assert_eq!(deser.apic_base.len(), vcpus_lock.len());
218 for (i, vcpu) in vcpus_lock.iter().enumerate() {
219 if let Some(vcpu) = vcpu {
220 vcpu.set_apic_base(*deser.apic_base.get(i).unwrap())?;
221 vcpu.set_interrupt_bitmap(*deser.interrupt_bitmap.get(i).unwrap())?;
222 } else {
223 return Err(anyhow!(
224 "Received None instead of Vcpu while restoring apic_base and interrupt_bitmap"
225 ));
226 }
227 }
228 Ok(())
229 }
230}
231
232pub struct KvmSplitIrqChip {
237 vm: KvmVm,
238 vcpus: Arc<Mutex<Vec<Option<KvmVcpu>>>>,
239 routes: Arc<Mutex<Vec<IrqRoute>>>,
240 pit: Arc<Mutex<Pit>>,
241 pic: Arc<Mutex<Pic>>,
242 ioapic: Arc<Mutex<Ioapic>>,
243 ioapic_pins: usize,
244 delayed_ioapic_irq_events: Arc<Mutex<Vec<usize>>>,
249 delayed_ioapic_irq_trigger: Event,
251 irq_events: Arc<Mutex<Vec<Option<IrqEvent>>>>,
253}
254
255fn kvm_dummy_msi_routes(ioapic_pins: usize) -> Vec<IrqRoute> {
256 let mut routes: Vec<IrqRoute> = Vec::new();
257 for i in 0..ioapic_pins {
258 routes.push(
259 IrqRoute {
261 gsi: i as u32,
262 source: IrqSource::Msi {
263 address: 0,
264 data: 0,
265 },
266 },
267 );
268 }
269 routes
270}
271
272impl KvmSplitIrqChip {
273 pub fn new(
275 vm: KvmVm,
276 num_vcpus: usize,
277 irq_tube: Tube,
278 ioapic_pins: Option<usize>,
279 ) -> Result<Self> {
280 let ioapic_pins = ioapic_pins.unwrap_or(vm.get_ioapic_num_pins()?);
281 vm.enable_split_irqchip(ioapic_pins)?;
282 let pit_evt = IrqEdgeEvent::new()?;
283 let pit = Pit::new(pit_evt.try_clone()?, Arc::new(Mutex::new(Clock::new()))).map_err(
284 |e| match e {
285 PitError::CloneEvent(err) => err,
286 PitError::CreateEvent(err) => err,
287 PitError::CreateWaitContext(err) => err,
288 PitError::WaitError(err) => err,
289 PitError::TimerCreateError(err) => err,
290 PitError::SpawnThread(_) => Error::new(libc::EIO),
291 },
292 )?;
293
294 let pit_event_source = IrqEventSource::from_device(&pit);
295
296 let mut chip = KvmSplitIrqChip {
297 vm,
298 vcpus: Arc::new(Mutex::new((0..num_vcpus).map(|_| None).collect())),
299 routes: Arc::new(Mutex::new(Vec::new())),
300 pit: Arc::new(Mutex::new(pit)),
301 pic: Arc::new(Mutex::new(Pic::new())),
302 ioapic: Arc::new(Mutex::new(Ioapic::new(irq_tube, ioapic_pins)?)),
303 ioapic_pins,
304 delayed_ioapic_irq_events: Arc::new(Mutex::new(Vec::new())),
305 delayed_ioapic_irq_trigger: Event::new()?,
306 irq_events: Arc::new(Mutex::new(Default::default())),
307 };
308
309 let mut routes = kvm_default_irq_routing_table(ioapic_pins);
311 routes.append(&mut kvm_dummy_msi_routes(ioapic_pins));
313
314 chip.set_irq_routes(&routes)?;
316
317 chip.register_edge_irq_event(PIT_CHANNEL0_IRQ, &pit_evt, pit_event_source)?;
318 Ok(chip)
319 }
320}
321
322impl KvmSplitIrqChip {
323 fn routes_to_chips(&self, irq: u32) -> Vec<(IrqSourceChip, u32)> {
325 let mut chips = Vec::new();
326 for route in self.routes.lock().iter() {
327 match route {
328 IrqRoute {
329 gsi,
330 source: IrqSource::Irqchip { chip, pin },
331 } if *gsi == irq => match chip {
332 IrqSourceChip::PicPrimary
333 | IrqSourceChip::PicSecondary
334 | IrqSourceChip::Ioapic => chips.push((*chip, *pin)),
335 IrqSourceChip::Gic => {
336 error!("gic irq should not be possible on a KvmSplitIrqChip")
337 }
338 IrqSourceChip::Aia => {
339 error!("Aia irq should not be possible on x86_64")
340 }
341 },
342 _ => {}
344 }
345 }
346 chips
347 }
348
349 pub fn interrupt_requested(&self, vcpu_id: usize) -> bool {
352 if vcpu_id != 0 {
354 return false;
355 }
356 self.pic.lock().interrupt_requested()
357 }
358
359 pub fn get_external_interrupt(&self, vcpu_id: usize) -> Option<u8> {
363 if vcpu_id != 0 {
365 return None;
366 }
367 self.pic.lock().get_external_interrupt()
368 }
369
370 fn register_irq_event(
372 &mut self,
373 irq: u32,
374 irq_event: &Event,
375 resample_event: Option<&Event>,
376 source: IrqEventSource,
377 ) -> Result<Option<IrqEventIndex>> {
378 if irq < self.ioapic_pins as u32 {
379 let mut evt = IrqEvent {
380 gsi: irq,
381 event: irq_event.try_clone()?,
382 resample_event: None,
383 source,
384 };
385
386 if let Some(resample_event) = resample_event {
387 evt.resample_event = Some(resample_event.try_clone()?);
388 }
389
390 let mut irq_events = self.irq_events.lock();
391 let index = irq_events.len();
392 irq_events.push(Some(evt));
393 Ok(Some(index))
394 } else {
395 self.vm.register_irqfd(irq, irq_event, resample_event)?;
396 Ok(None)
397 }
398 }
399
400 fn unregister_irq_event(&mut self, irq: u32, irq_event: &Event) -> Result<()> {
402 if irq < self.ioapic_pins as u32 {
403 let mut irq_events = self.irq_events.lock();
404 for (index, evt) in irq_events.iter().enumerate() {
405 if let Some(evt) = evt {
406 if evt.gsi == irq && irq_event.eq(&evt.event) {
407 irq_events[index] = None;
408 break;
409 }
410 }
411 }
412 Ok(())
413 } else {
414 self.vm.unregister_irqfd(irq, irq_event)
415 }
416 }
417}
418
419fn routes_conflict(route: &IrqRoute, other: &IrqRoute) -> bool {
422 if route.gsi != other.gsi {
424 return false;
425 }
426
427 if let (IrqSource::Msi { .. }, IrqSource::Msi { .. }) = (route.source, other.source) {
429 return true;
430 }
431
432 if let (
434 IrqSource::Irqchip {
435 chip: route_chip, ..
436 },
437 IrqSource::Irqchip {
438 chip: other_chip, ..
439 },
440 ) = (route.source, other.source)
441 {
442 return route_chip == other_chip;
443 }
444
445 false
447}
448
449impl IrqChip for KvmSplitIrqChip {
451 fn add_vcpu(&mut self, vcpu_id: usize, vcpu: &dyn Vcpu) -> Result<()> {
453 let vcpu: &KvmVcpu = vcpu
454 .downcast_ref()
455 .expect("KvmSplitIrqChip::add_vcpu called with non-KvmVcpu");
456 self.vcpus.lock()[vcpu_id] = Some(vcpu.try_clone()?);
457 Ok(())
458 }
459
460 fn register_edge_irq_event(
462 &mut self,
463 irq: u32,
464 irq_event: &IrqEdgeEvent,
465 source: IrqEventSource,
466 ) -> Result<Option<IrqEventIndex>> {
467 self.register_irq_event(irq, irq_event.get_trigger(), None, source)
468 }
469
470 fn unregister_edge_irq_event(&mut self, irq: u32, irq_event: &IrqEdgeEvent) -> Result<()> {
471 self.unregister_irq_event(irq, irq_event.get_trigger())
472 }
473
474 fn register_level_irq_event(
475 &mut self,
476 irq: u32,
477 irq_event: &IrqLevelEvent,
478 source: IrqEventSource,
479 ) -> Result<Option<IrqEventIndex>> {
480 self.register_irq_event(
481 irq,
482 irq_event.get_trigger(),
483 Some(irq_event.get_resample()),
484 source,
485 )
486 }
487
488 fn unregister_level_irq_event(&mut self, irq: u32, irq_event: &IrqLevelEvent) -> Result<()> {
489 self.unregister_irq_event(irq, irq_event.get_trigger())
490 }
491
492 fn route_irq(&mut self, route: IrqRoute) -> Result<()> {
494 let mut routes = self.routes.lock();
495 routes.retain(|r| !routes_conflict(r, &route));
496
497 routes.push(route);
498
499 let mut msi_routes = routes.clone();
501 msi_routes.retain(|r| matches!(r.source, IrqSource::Msi { .. }));
502
503 self.vm.set_gsi_routing(&msi_routes)
504 }
505
506 fn set_irq_routes(&mut self, routes: &[IrqRoute]) -> Result<()> {
508 let mut current_routes = self.routes.lock();
509 *current_routes = routes.to_vec();
510
511 let mut msi_routes = routes.to_vec();
513 msi_routes.retain(|r| matches!(r.source, IrqSource::Msi { .. }));
514
515 self.vm.set_gsi_routing(&msi_routes)
516 }
517
518 fn irq_event_tokens(&self) -> Result<Vec<(IrqEventIndex, IrqEventSource, Event)>> {
521 let mut tokens = vec![];
522 for (index, evt) in self.irq_events.lock().iter().enumerate() {
523 if let Some(evt) = evt {
524 tokens.push((index, evt.source.clone(), evt.event.try_clone()?));
525 }
526 }
527 Ok(tokens)
528 }
529
530 fn service_irq(&mut self, irq: u32, level: bool) -> Result<()> {
533 let chips = self.routes_to_chips(irq);
534 for (chip, pin) in chips {
535 match chip {
536 IrqSourceChip::PicPrimary | IrqSourceChip::PicSecondary => {
537 self.pic.lock().service_irq(pin as u8, level);
538 }
539 IrqSourceChip::Ioapic => {
540 self.ioapic.lock().service_irq(pin as usize, level);
541 }
542 _ => {}
543 }
544 }
545 Ok(())
546 }
547
548 fn service_irq_event(&mut self, event_index: IrqEventIndex) -> Result<()> {
557 if let Some(evt) = &self.irq_events.lock()[event_index] {
558 evt.event.wait()?;
559 let chips = self.routes_to_chips(evt.gsi);
560
561 for (chip, pin) in chips {
562 match chip {
563 IrqSourceChip::PicPrimary | IrqSourceChip::PicSecondary => {
564 let mut pic = self.pic.lock();
565 pic.service_irq(pin as u8, true);
566 if evt.resample_event.is_none() {
567 pic.service_irq(pin as u8, false);
568 }
569 }
570 IrqSourceChip::Ioapic => {
571 if let Ok(mut ioapic) = self.ioapic.try_lock() {
572 ioapic.service_irq(pin as usize, true);
573 if evt.resample_event.is_none() {
574 ioapic.service_irq(pin as usize, false);
575 }
576 } else {
577 self.delayed_ioapic_irq_events.lock().push(event_index);
578 self.delayed_ioapic_irq_trigger.signal().unwrap();
579 }
580 }
581 _ => {}
582 }
583 }
584 }
585
586 Ok(())
587 }
588
589 fn broadcast_eoi(&self, vector: u8) -> Result<()> {
591 self.ioapic.lock().end_of_interrupt(vector);
592 Ok(())
593 }
594
595 fn inject_interrupts(&self, vcpu: &dyn Vcpu) -> Result<()> {
598 let vcpu: &KvmVcpu = vcpu
599 .downcast_ref()
600 .expect("KvmSplitIrqChip::add_vcpu called with non-KvmVcpu");
601
602 let vcpu_id = vcpu.id();
603 if !self.interrupt_requested(vcpu_id) || !vcpu.ready_for_interrupt() {
604 return Ok(());
605 }
606
607 if let Some(vector) = self.get_external_interrupt(vcpu_id) {
608 vcpu.interrupt(vector)?;
609 }
610
611 if self.interrupt_requested(vcpu_id) {
614 vcpu.set_interrupt_window_requested(true);
615 }
616 Ok(())
617 }
618
619 fn halted(&self, _vcpu_id: usize) {}
622
623 fn wait_until_runnable(&self, _vcpu: &dyn Vcpu) -> Result<VcpuRunState> {
629 Ok(VcpuRunState::Runnable)
630 }
631
632 fn kick_halted_vcpus(&self) {}
635
636 fn get_mp_state(&self, vcpu_id: usize) -> Result<MPState> {
638 match self.vcpus.lock().get(vcpu_id) {
639 Some(Some(vcpu)) => Ok(MPState::from(&vcpu.get_mp_state()?)),
640 _ => Err(Error::new(libc::ENOENT)),
641 }
642 }
643
644 fn set_mp_state(&mut self, vcpu_id: usize, state: &MPState) -> Result<()> {
646 match self.vcpus.lock().get(vcpu_id) {
647 Some(Some(vcpu)) => vcpu.set_mp_state(&kvm_mp_state::from(state)),
648 _ => Err(Error::new(libc::ENOENT)),
649 }
650 }
651
652 fn try_clone(&self) -> Result<Self> {
654 Ok(KvmSplitIrqChip {
655 vm: self.vm.try_clone()?,
656 vcpus: self.vcpus.clone(),
657 routes: self.routes.clone(),
658 pit: self.pit.clone(),
659 pic: self.pic.clone(),
660 ioapic: self.ioapic.clone(),
661 ioapic_pins: self.ioapic_pins,
662 delayed_ioapic_irq_events: self.delayed_ioapic_irq_events.clone(),
663 delayed_ioapic_irq_trigger: Event::new()?,
664 irq_events: self.irq_events.clone(),
665 })
666 }
667
668 fn finalize_devices(
671 &mut self,
672 resources: &mut SystemAllocator,
673 io_bus: &Bus,
674 mmio_bus: &Bus,
675 ) -> Result<()> {
676 io_bus.insert(self.pit.clone(), 0x040, 0x8).unwrap();
678 io_bus.insert(self.pit.clone(), 0x061, 0x1).unwrap();
679
680 io_bus.insert(self.pic.clone(), 0x20, 0x2).unwrap();
682 io_bus.insert(self.pic.clone(), 0xa0, 0x2).unwrap();
683 io_bus.insert(self.pic.clone(), 0x4d0, 0x2).unwrap();
684
685 mmio_bus
687 .insert(
688 self.ioapic.clone(),
689 IOAPIC_BASE_ADDRESS,
690 IOAPIC_MEM_LENGTH_BYTES,
691 )
692 .unwrap();
693
694 let mut ioapic_resample_events: Vec<Vec<Event>> =
697 (0..self.ioapic_pins).map(|_| Vec::new()).collect();
698 let mut pic_resample_events: Vec<Vec<Event>> =
699 (0..self.ioapic_pins).map(|_| Vec::new()).collect();
700
701 for evt in self.irq_events.lock().iter().flatten() {
702 if (evt.gsi as usize) >= self.ioapic_pins {
703 continue;
704 }
705 if let Some(resample_evt) = &evt.resample_event {
706 ioapic_resample_events[evt.gsi as usize].push(resample_evt.try_clone()?);
707 pic_resample_events[evt.gsi as usize].push(resample_evt.try_clone()?);
708 }
709 }
710
711 self.ioapic
713 .lock()
714 .register_resample_events(ioapic_resample_events);
715 self.pic
717 .lock()
718 .register_resample_events(pic_resample_events);
719
720 let mut irq_num = resources.allocate_irq().unwrap();
722 while irq_num < self.ioapic_pins as u32 {
723 irq_num = resources.allocate_irq().unwrap();
724 }
725
726 Ok(())
727 }
728
729 fn process_delayed_irq_events(&mut self) -> Result<()> {
737 self.delayed_ioapic_irq_events
738 .lock()
739 .retain(|&event_index| {
740 if let Some(evt) = &self.irq_events.lock()[event_index] {
741 if let Ok(mut ioapic) = self.ioapic.try_lock() {
742 ioapic.service_irq(evt.gsi as usize, true);
743 if evt.resample_event.is_none() {
744 ioapic.service_irq(evt.gsi as usize, false);
745 }
746
747 false
748 } else {
749 true
750 }
751 } else {
752 true
753 }
754 });
755
756 if self.delayed_ioapic_irq_events.lock().is_empty() {
757 self.delayed_ioapic_irq_trigger.wait()?;
758 }
759
760 Ok(())
761 }
762
763 fn irq_delayed_event_token(&self) -> Result<Option<Event>> {
764 Ok(Some(self.delayed_ioapic_irq_trigger.try_clone()?))
765 }
766
767 fn check_capability(&self, c: IrqChipCap) -> bool {
768 match c {
769 IrqChipCap::TscDeadlineTimer => self.vm.check_raw_capability(KvmCap::TscDeadlineTimer),
770 IrqChipCap::X2Apic => true,
771 IrqChipCap::MpStateGetSet => true,
772 }
773 }
774}
775
776#[derive(Serialize, Deserialize)]
777struct KvmSplitIrqChipSnapshot {
778 routes: Vec<IrqRoute>,
779}
780
781impl IrqChipX86_64 for KvmSplitIrqChip {
782 fn try_box_clone(&self) -> Result<Box<dyn IrqChipX86_64>> {
783 Ok(Box::new(self.try_clone()?))
784 }
785
786 fn as_irq_chip(&self) -> &dyn IrqChip {
787 self
788 }
789
790 fn as_irq_chip_mut(&mut self) -> &mut dyn IrqChip {
791 self
792 }
793
794 fn get_pic_state(&self, select: PicSelect) -> Result<PicState> {
796 Ok(self.pic.lock().get_pic_state(select))
797 }
798
799 fn set_pic_state(&mut self, select: PicSelect, state: &PicState) -> Result<()> {
801 self.pic.lock().set_pic_state(select, state);
802 Ok(())
803 }
804
805 fn get_ioapic_state(&self) -> Result<IoapicState> {
807 Ok(self.ioapic.lock().get_ioapic_state())
808 }
809
810 fn set_ioapic_state(&mut self, state: &IoapicState) -> Result<()> {
812 self.ioapic.lock().set_ioapic_state(state);
813 Ok(())
814 }
815
816 fn get_lapic_state(&self, vcpu_id: usize) -> Result<LapicState> {
818 match self.vcpus.lock().get(vcpu_id) {
819 Some(Some(vcpu)) => Ok(LapicState::from(&vcpu.get_lapic()?)),
820 _ => Err(Error::new(libc::ENOENT)),
821 }
822 }
823
824 fn set_lapic_state(&mut self, vcpu_id: usize, state: &LapicState) -> Result<()> {
826 match self.vcpus.lock().get(vcpu_id) {
827 Some(Some(vcpu)) => vcpu.set_lapic(&kvm_lapic_state::from(state)),
828 _ => Err(Error::new(libc::ENOENT)),
829 }
830 }
831
832 fn lapic_frequency(&self) -> u32 {
834 1_000_000_000
836 }
837
838 fn get_pit(&self) -> Result<PitState> {
840 Ok(self.pit.lock().get_pit_state())
841 }
842
843 fn set_pit(&mut self, state: &PitState) -> Result<()> {
845 self.pit.lock().set_pit_state(state);
846 Ok(())
847 }
848
849 fn pit_uses_speaker_port(&self) -> bool {
852 true
853 }
854
855 fn snapshot_chip_specific(&self) -> anyhow::Result<AnySnapshot> {
856 AnySnapshot::to_any(KvmSplitIrqChipSnapshot {
857 routes: self.routes.lock().clone(),
858 })
859 .context("failed to serialize KvmSplitIrqChip")
860 }
861
862 fn restore_chip_specific(&mut self, data: AnySnapshot) -> anyhow::Result<()> {
863 let deser: KvmSplitIrqChipSnapshot =
864 AnySnapshot::from_any(data).context("failed to deserialize KvmSplitIrqChip")?;
865 self.set_irq_routes(&deser.routes)?;
866 Ok(())
867 }
868}