xref: /aosp_15_r20/external/crosvm/devices/tests/irqchip/userspace.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2022 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 #![cfg(target_arch = "x86_64")]
6 
7 use std::collections::BTreeMap;
8 use std::sync::Arc;
9 use std::thread;
10 use std::time::Duration;
11 use std::time::Instant;
12 
13 use base::Clock;
14 use base::EventWaitResult;
15 use base::Result;
16 use base::Tube;
17 use devices::Bus;
18 use devices::BusAccessInfo;
19 use devices::BusDeviceSync;
20 use devices::BusType;
21 use devices::CrosvmDeviceId;
22 use devices::DestinationShorthand;
23 use devices::DeviceId;
24 use devices::Interrupt;
25 use devices::InterruptData;
26 use devices::InterruptDestination;
27 use devices::IrqChip;
28 use devices::IrqChipX86_64;
29 use devices::IrqEdgeEvent;
30 use devices::IrqEventSource;
31 use devices::IrqLevelEvent;
32 use devices::UserspaceIrqChip;
33 use devices::VcpuRunState;
34 use devices::APIC_BASE_ADDRESS;
35 use devices::IOAPIC_BASE_ADDRESS;
36 use hypervisor::CpuId;
37 use hypervisor::CpuIdEntry;
38 use hypervisor::DebugRegs;
39 use hypervisor::DeliveryMode;
40 use hypervisor::DestinationMode;
41 use hypervisor::Fpu;
42 use hypervisor::IoParams;
43 use hypervisor::IoapicRedirectionTableEntry;
44 use hypervisor::IrqRoute;
45 use hypervisor::IrqSource;
46 use hypervisor::Level;
47 use hypervisor::PicSelect;
48 use hypervisor::PitRWMode;
49 use hypervisor::Regs;
50 use hypervisor::Sregs;
51 use hypervisor::TriggerMode;
52 use hypervisor::Vcpu;
53 use hypervisor::VcpuExit;
54 use hypervisor::VcpuSnapshot;
55 use hypervisor::VcpuX86_64;
56 use hypervisor::Xsave;
57 use resources::AddressRange;
58 use resources::SystemAllocator;
59 use resources::SystemAllocatorConfig;
60 use sync::Mutex;
61 use vm_memory::GuestAddress;
62 
63 use crate::x86_64::test_get_ioapic;
64 use crate::x86_64::test_get_pit;
65 use crate::x86_64::test_route_irq;
66 use crate::x86_64::test_set_ioapic;
67 use crate::x86_64::test_set_pic;
68 use crate::x86_64::test_set_pit;
69 
70 const APIC_ID: u64 = 0x20;
71 const TPR: u64 = 0x80;
72 const EOI: u64 = 0xB0;
73 const TEST_SLEEP_DURATION: Duration = Duration::from_millis(50);
74 
75 /// Helper function for setting up a UserspaceIrqChip.
get_chip(num_vcpus: usize) -> UserspaceIrqChip<FakeVcpu>76 fn get_chip(num_vcpus: usize) -> UserspaceIrqChip<FakeVcpu> {
77     get_chip_with_clock(num_vcpus, Arc::new(Mutex::new(Clock::new())))
78 }
79 
get_chip_with_clock(num_vcpus: usize, clock: Arc<Mutex<Clock>>) -> UserspaceIrqChip<FakeVcpu>80 fn get_chip_with_clock(num_vcpus: usize, clock: Arc<Mutex<Clock>>) -> UserspaceIrqChip<FakeVcpu> {
81     let (_, irq_tube) = Tube::pair().unwrap();
82     let mut chip = UserspaceIrqChip::<FakeVcpu>::new_with_clock(num_vcpus, irq_tube, None, clock)
83         .expect("failed to instantiate UserspaceIrqChip");
84 
85     for i in 0..num_vcpus {
86         let vcpu = FakeVcpu {
87             id: i,
88             requested: Arc::new(Mutex::new(false)),
89             ready: Arc::new(Mutex::new(true)),
90             injected: Arc::new(Mutex::new(None)),
91         };
92         chip.add_vcpu(i, &vcpu).expect("failed to add vcpu");
93         chip.apics[i].lock().set_enabled(true);
94     }
95 
96     chip
97 }
98 
99 /// Helper function for cloning vcpus from a UserspaceIrqChip.
get_vcpus(chip: &UserspaceIrqChip<FakeVcpu>) -> Vec<FakeVcpu>100 fn get_vcpus(chip: &UserspaceIrqChip<FakeVcpu>) -> Vec<FakeVcpu> {
101     chip.vcpus
102         .lock()
103         .iter()
104         .map(|v| v.as_ref().unwrap().try_clone().unwrap())
105         .collect()
106 }
107 
108 #[test]
set_pic()109 fn set_pic() {
110     test_set_pic(get_chip(1));
111 }
112 
113 #[test]
get_ioapic()114 fn get_ioapic() {
115     test_get_ioapic(get_chip(1));
116 }
117 
118 #[test]
set_ioapic()119 fn set_ioapic() {
120     test_set_ioapic(get_chip(1));
121 }
122 
123 #[test]
get_pit()124 fn get_pit() {
125     test_get_pit(get_chip(1));
126 }
127 
128 #[test]
set_pit()129 fn set_pit() {
130     test_set_pit(get_chip(1));
131 }
132 
133 #[test]
route_irq()134 fn route_irq() {
135     test_route_irq(get_chip(1));
136 }
137 
138 #[test]
pit_uses_speaker_port()139 fn pit_uses_speaker_port() {
140     let chip = get_chip(1);
141     assert!(chip.pit_uses_speaker_port());
142 }
143 
144 #[test]
routes_conflict()145 fn routes_conflict() {
146     let mut chip = get_chip(1);
147     chip.route_irq(IrqRoute {
148         gsi: 32,
149         source: IrqSource::Msi {
150             address: 4276092928,
151             data: 0,
152         },
153     })
154     .expect("failed to set msi rout");
155     // this second route should replace the first
156     chip.route_irq(IrqRoute {
157         gsi: 32,
158         source: IrqSource::Msi {
159             address: 4276092928,
160             data: 32801,
161         },
162     })
163     .expect("failed to set msi rout");
164 }
165 
166 #[test]
irq_event_tokens()167 fn irq_event_tokens() {
168     let mut chip = get_chip(1);
169     let tokens = chip
170         .irq_event_tokens()
171         .expect("could not get irq_event_tokens");
172 
173     // there should be one token on a fresh split irqchip, for the pit
174     assert_eq!(tokens.len(), 1);
175     assert_eq!(tokens[0].1.device_name, "userspace PIT");
176 
177     // register another irq event
178     let evt = IrqEdgeEvent::new().expect("failed to create eventfd");
179     let source = IrqEventSource {
180         device_id: CrosvmDeviceId::Cmos.into(),
181         queue_id: 0,
182         device_name: "test".to_owned(),
183     };
184     chip.register_edge_irq_event(6, &evt, source)
185         .expect("failed to register irq event");
186 
187     let tokens = chip
188         .irq_event_tokens()
189         .expect("could not get irq_event_tokens");
190 
191     // now there should be two tokens
192     assert_eq!(tokens.len(), 2);
193     assert_eq!(tokens[0].1.device_name, "userspace PIT");
194     assert_eq!(
195         tokens[1].1.device_id,
196         DeviceId::PlatformDeviceId(CrosvmDeviceId::Cmos)
197     );
198     assert_eq!(tokens[1].2, evt.get_trigger().try_clone().unwrap());
199 }
200 
201 // TODO(srichman): Factor out of UserspaceIrqChip and KvmSplitIrqChip.
202 #[test]
finalize_devices()203 fn finalize_devices() {
204     let mut chip = get_chip(1);
205 
206     let mmio_bus = Bus::new(BusType::Mmio);
207     let io_bus = Bus::new(BusType::Io);
208     let mut resources = SystemAllocator::new(
209         SystemAllocatorConfig {
210             io: Some(AddressRange {
211                 start: 0xc000,
212                 end: 0xFFFF,
213             }),
214             low_mmio: AddressRange {
215                 start: 0,
216                 end: 2047,
217             },
218             high_mmio: AddressRange {
219                 start: 2048,
220                 end: 6143,
221             },
222             platform_mmio: None,
223             first_irq: 5,
224         },
225         None,
226         &[],
227     )
228     .expect("failed to create SystemAllocator");
229 
230     // Setup an event and a resample event for irq line 1.
231     let evt = IrqLevelEvent::new().expect("failed to create event");
232 
233     let source = IrqEventSource {
234         device_id: CrosvmDeviceId::Cmos.into(),
235         device_name: "test".to_owned(),
236         queue_id: 0,
237     };
238 
239     let evt_index = chip
240         .register_level_irq_event(1, &evt, source)
241         .expect("failed to register_level_irq_event")
242         .expect("register_level_irq_event should not return None");
243 
244     // Once we finalize devices, the pic/pit/ioapic should be attached to io and mmio busses.
245     chip.finalize_devices(&mut resources, &io_bus, &mmio_bus)
246         .expect("failed to finalize devices");
247 
248     // Should not be able to allocate an irq < 24 now.
249     assert!(resources.allocate_irq().expect("failed to allocate irq") >= 24);
250 
251     // Set PIT counter 2 to "SquareWaveGen" (aka 3) mode and "Both" access mode.
252     io_bus.write(0x43, &[0b10110110]);
253 
254     let state = chip.get_pit().expect("failed to get pit state");
255     assert_eq!(state.channels[2].mode, 3);
256     assert_eq!(state.channels[2].rw_mode, PitRWMode::Both);
257 
258     // ICW1 0x11: Edge trigger, cascade mode, ICW4 needed.
259     // ICW2 0x08: Interrupt vector base address 0x08.
260     // ICW3 0xff: Value written does not matter.
261     // ICW4 0x13: Special fully nested mode, auto EOI.
262     io_bus.write(0x20, &[0x11]);
263     io_bus.write(0x21, &[0x08]);
264     io_bus.write(0x21, &[0xff]);
265     io_bus.write(0x21, &[0x13]);
266 
267     let state = chip
268         .get_pic_state(PicSelect::Primary)
269         .expect("failed to get pic state");
270 
271     // Auto eoi and special fully nested mode should be turned on.
272     assert!(state.auto_eoi);
273     assert!(state.special_fully_nested_mode);
274 
275     // Need to write to the irq event before servicing it.
276     evt.trigger().expect("failed to write to eventfd");
277 
278     // If we assert irq line one, and then get the resulting interrupt, an auto-eoi should occur
279     // and cause the resample_event to be written to.
280     chip.service_irq_event(evt_index)
281         .expect("failed to service irq");
282 
283     let vcpu = get_vcpus(&chip).remove(0);
284     chip.inject_interrupts(&vcpu).unwrap();
285     assert_eq!(
286         vcpu.clear_injected(),
287         // Vector is 9 because the interrupt vector base address is 0x08 and this is irq line 1
288         // and 8+1 = 9.
289         Some(0x9)
290     );
291 
292     assert_eq!(
293         evt.get_resample()
294             .wait_timeout(std::time::Duration::from_secs(1))
295             .expect("failed to read_timeout"),
296         EventWaitResult::Signaled
297     );
298 
299     // Setup a ioapic redirection table entry 14.
300     let mut entry = IoapicRedirectionTableEntry::default();
301     entry.set_vector(44);
302 
303     let irq_14_offset = 0x10 + 14 * 2;
304     mmio_bus.write(IOAPIC_BASE_ADDRESS, &[irq_14_offset]);
305     mmio_bus.write(
306         IOAPIC_BASE_ADDRESS + 0x10,
307         &(entry.get(0, 32) as u32).to_ne_bytes(),
308     );
309     mmio_bus.write(IOAPIC_BASE_ADDRESS, &[irq_14_offset + 1]);
310     mmio_bus.write(
311         IOAPIC_BASE_ADDRESS + 0x10,
312         &(entry.get(32, 32) as u32).to_ne_bytes(),
313     );
314 
315     let state = chip.get_ioapic_state().expect("failed to get ioapic state");
316 
317     // Redirection table entry 14 should have a vector of 44.
318     assert_eq!(state.redirect_table[14].get_vector(), 44);
319 }
320 
321 #[test]
inject_pic_interrupt()322 fn inject_pic_interrupt() {
323     let mut chip = get_chip(2);
324     let vcpus = get_vcpus(&chip);
325 
326     assert_eq!(vcpus[0].clear_injected(), None);
327     assert_eq!(vcpus[1].clear_injected(), None);
328 
329     chip.service_irq(0, true).expect("failed to service irq");
330 
331     // Should not inject PIC interrupt for vcpu_id != 0.
332     chip.inject_interrupts(&vcpus[1]).unwrap();
333     assert_eq!(vcpus[1].clear_injected(), None);
334 
335     // Should inject Some interrupt.
336     chip.inject_interrupts(&vcpus[0]).unwrap();
337     assert_eq!(vcpus[0].clear_injected(), Some(0));
338 
339     // Interrupt is not injected twice.
340     chip.inject_interrupts(&vcpus[0]).unwrap();
341     assert_eq!(vcpus[0].clear_injected(), None);
342 }
343 
344 #[test]
inject_msi()345 fn inject_msi() {
346     let mut chip = get_chip(2);
347     let vcpus = get_vcpus(&chip);
348 
349     let evt = IrqEdgeEvent::new().unwrap();
350     let source = IrqEventSource {
351         device_id: CrosvmDeviceId::Cmos.into(),
352         device_name: "test".to_owned(),
353         queue_id: 0,
354     };
355     let event_idx = chip
356         .register_edge_irq_event(30, &evt, source)
357         .unwrap()
358         .unwrap();
359     chip.route_irq(IrqRoute {
360         gsi: 30,
361         source: IrqSource::Msi {
362             address: 0xFEE01000, // physical addressing, send to apic 1
363             data: 0x000000F1,    // edge-triggered, fixed interrupt, vector 0xF1
364         },
365     })
366     .unwrap();
367     evt.trigger().unwrap();
368 
369     assert!(!vcpus[0].window_requested());
370     assert!(!vcpus[1].window_requested());
371     chip.service_irq_event(event_idx).unwrap();
372     assert!(!vcpus[0].window_requested());
373     assert!(vcpus[1].window_requested());
374 
375     chip.inject_interrupts(&vcpus[0]).unwrap();
376     assert_eq!(vcpus[0].clear_injected(), None);
377 
378     vcpus[1].set_ready(false);
379     chip.inject_interrupts(&vcpus[1]).unwrap();
380     assert_eq!(vcpus[1].clear_injected(), None);
381     vcpus[1].set_ready(true);
382     chip.inject_interrupts(&vcpus[1]).unwrap();
383     assert_eq!(vcpus[1].clear_injected(), Some(0xF1));
384     assert!(!vcpus[1].window_requested());
385 }
386 
387 #[test]
lowest_priority_destination()388 fn lowest_priority_destination() {
389     let chip = get_chip(2);
390     let vcpus = get_vcpus(&chip);
391 
392     // Make vcpu 0 higher priority.
393     chip.write(
394         BusAccessInfo {
395             id: 0,
396             address: APIC_BASE_ADDRESS + TPR,
397             offset: TPR,
398         },
399         &[0x10, 0, 0, 0],
400     );
401     chip.send_irq_to_apics(&Interrupt {
402         dest: InterruptDestination {
403             source_id: 0,
404             dest_id: 0,
405             shorthand: DestinationShorthand::All,
406             mode: DestinationMode::Physical,
407         },
408         data: InterruptData {
409             vector: 111,
410             delivery: DeliveryMode::Lowest,
411             trigger: TriggerMode::Edge,
412             level: Level::Deassert,
413         },
414     });
415     chip.inject_interrupts(&vcpus[0]).unwrap();
416     chip.inject_interrupts(&vcpus[1]).unwrap();
417     assert_eq!(vcpus[0].clear_injected(), None);
418     assert_eq!(vcpus[1].clear_injected(), Some(111));
419     chip.write(
420         BusAccessInfo {
421             id: 1,
422             address: APIC_BASE_ADDRESS + EOI,
423             offset: EOI,
424         },
425         &[0, 0, 0, 0],
426     );
427 
428     // Make vcpu 1 higher priority.
429     chip.write(
430         BusAccessInfo {
431             id: 1,
432             address: APIC_BASE_ADDRESS + TPR,
433             offset: TPR,
434         },
435         &[0x20, 0, 0, 0],
436     );
437     chip.send_irq_to_apics(&Interrupt {
438         dest: InterruptDestination {
439             source_id: 0,
440             dest_id: 0,
441             shorthand: DestinationShorthand::All,
442             mode: DestinationMode::Physical,
443         },
444         data: InterruptData {
445             vector: 222,
446             delivery: DeliveryMode::Lowest,
447             trigger: TriggerMode::Edge,
448             level: Level::Deassert,
449         },
450     });
451     chip.inject_interrupts(&vcpus[0]).unwrap();
452     chip.inject_interrupts(&vcpus[1]).unwrap();
453     assert_eq!(vcpus[0].clear_injected(), Some(222));
454     assert_eq!(vcpus[1].clear_injected(), None);
455 }
456 
457 // TODO(srichman): Factor out of UserspaceIrqChip and KvmSplitIrqChip.
458 #[test]
broadcast_eoi()459 fn broadcast_eoi() {
460     let mut chip = get_chip(1);
461 
462     let mmio_bus = Bus::new(BusType::Mmio);
463     let io_bus = Bus::new(BusType::Io);
464     let mut resources = SystemAllocator::new(
465         SystemAllocatorConfig {
466             io: Some(AddressRange {
467                 start: 0xc000,
468                 end: 0xFFFF,
469             }),
470             low_mmio: AddressRange {
471                 start: 0,
472                 end: 2047,
473             },
474             high_mmio: AddressRange {
475                 start: 2048,
476                 end: 6143,
477             },
478             platform_mmio: None,
479             first_irq: 5,
480         },
481         None,
482         &[],
483     )
484     .expect("failed to create SystemAllocator");
485 
486     // setup an event for irq line 1
487     let evt = IrqLevelEvent::new().expect("failed to create event");
488 
489     let source = IrqEventSource {
490         device_id: CrosvmDeviceId::Cmos.into(),
491         device_name: "test".to_owned(),
492         queue_id: 0,
493     };
494 
495     chip.register_level_irq_event(1, &evt, source)
496         .expect("failed to register_level_irq_event");
497 
498     // Once we finalize devices, the pic/pit/ioapic should be attached to io and mmio busses
499     chip.finalize_devices(&mut resources, &io_bus, &mmio_bus)
500         .expect("failed to finalize devices");
501 
502     // setup a ioapic redirection table entry 1 with a vector of 123
503     let mut entry = IoapicRedirectionTableEntry::default();
504     entry.set_vector(123);
505     entry.set_trigger_mode(TriggerMode::Level);
506 
507     let irq_write_offset = 0x10 + 1 * 2;
508     mmio_bus.write(IOAPIC_BASE_ADDRESS, &[irq_write_offset]);
509     mmio_bus.write(
510         IOAPIC_BASE_ADDRESS + 0x10,
511         &(entry.get(0, 32) as u32).to_ne_bytes(),
512     );
513     mmio_bus.write(IOAPIC_BASE_ADDRESS, &[irq_write_offset + 1]);
514     mmio_bus.write(
515         IOAPIC_BASE_ADDRESS + 0x10,
516         &(entry.get(32, 32) as u32).to_ne_bytes(),
517     );
518 
519     // Assert line 1
520     chip.service_irq(1, true).expect("failed to service irq");
521 
522     // resample event should not be written to
523     assert_eq!(
524         evt.get_resample()
525             .wait_timeout(std::time::Duration::from_millis(10))
526             .expect("failed to read_timeout"),
527         EventWaitResult::TimedOut
528     );
529 
530     // irq line 1 should be asserted
531     let state = chip.get_ioapic_state().expect("failed to get ioapic state");
532     assert_eq!(state.current_interrupt_level_bitmap, 1 << 1);
533 
534     // Now broadcast an eoi for vector 123
535     chip.broadcast_eoi(123).expect("failed to broadcast eoi");
536 
537     // irq line 1 should be deasserted
538     let state = chip.get_ioapic_state().expect("failed to get ioapic state");
539     assert_eq!(state.current_interrupt_level_bitmap, 0);
540 
541     // resample event should be written to by ioapic
542     assert_eq!(
543         evt.get_resample()
544             .wait_timeout(std::time::Duration::from_millis(10))
545             .expect("failed to read_timeout"),
546         EventWaitResult::Signaled
547     );
548 }
549 
550 #[test]
apic_mmio()551 fn apic_mmio() {
552     let chip = get_chip(2);
553     let mut data = [0u8; 4];
554     chip.read(
555         BusAccessInfo {
556             id: 0,
557             address: APIC_BASE_ADDRESS + APIC_ID,
558             offset: APIC_ID,
559         },
560         &mut data,
561     );
562     assert_eq!(data, [0, 0, 0, 0]);
563     chip.read(
564         BusAccessInfo {
565             id: 1,
566             address: APIC_BASE_ADDRESS + APIC_ID,
567             offset: APIC_ID,
568         },
569         &mut data,
570     );
571     assert_eq!(data, [0, 0, 0, 1]);
572 }
573 
574 #[test]
575 #[ignore = "TODO(b/237977699): remove reliance on sleep"]
runnable_vcpu_unhalts()576 fn runnable_vcpu_unhalts() {
577     let chip = get_chip(1);
578     let vcpu = get_vcpus(&chip).remove(0);
579     let chip_copy = chip.try_clone().unwrap();
580     // BSP starts runnable.
581     assert_eq!(chip.wait_until_runnable(&vcpu), Ok(VcpuRunState::Runnable));
582     let start = Instant::now();
583     let handle = thread::spawn(move || {
584         thread::sleep(TEST_SLEEP_DURATION);
585         chip_copy.send_irq_to_apic(
586             0,
587             &InterruptData {
588                 vector: 123,
589                 delivery: DeliveryMode::Fixed,
590                 trigger: TriggerMode::Level,
591                 level: Level::Assert,
592             },
593         );
594     });
595     chip.halted(0);
596     assert_eq!(chip.wait_until_runnable(&vcpu), Ok(VcpuRunState::Runnable));
597     assert!(Instant::now() - start > Duration::from_millis(5));
598     handle.join().unwrap();
599 }
600 
601 #[test]
602 #[ignore = "TODO(b/237977699): remove reliance on sleep"]
kicked_vcpu_unhalts()603 fn kicked_vcpu_unhalts() {
604     let chip = get_chip(1);
605     let vcpu = get_vcpus(&chip).remove(0);
606     let chip_copy = chip.try_clone().unwrap();
607     // BSP starts runnable.
608     assert_eq!(chip.wait_until_runnable(&vcpu), Ok(VcpuRunState::Runnable));
609     let start = Instant::now();
610     let handle = thread::spawn(move || {
611         thread::sleep(TEST_SLEEP_DURATION);
612         chip_copy.kick_halted_vcpus();
613     });
614     chip.halted(0);
615     assert_eq!(
616         chip.wait_until_runnable(&vcpu),
617         Ok(VcpuRunState::Interrupted)
618     );
619     assert!(Instant::now() - start > Duration::from_millis(5));
620     handle.join().unwrap();
621 }
622 
623 /// Mock vcpu for testing interrupt injection.
624 struct FakeVcpu {
625     id: usize,
626     requested: Arc<Mutex<bool>>,
627     ready: Arc<Mutex<bool>>,
628     injected: Arc<Mutex<Option<u8>>>,
629 }
630 
631 impl FakeVcpu {
632     /// Returns and clears the last interrupt set by `interrupt`.
clear_injected(&self) -> Option<u8>633     fn clear_injected(&self) -> Option<u8> {
634         self.injected.lock().take()
635     }
636 
637     /// Returns true if an interrupt window was requested with `set_interrupt_window_requested`.
window_requested(&self) -> bool638     fn window_requested(&self) -> bool {
639         *self.requested.lock()
640     }
641 
642     /// Sets the value to be returned by `ready_for_interrupt`.
set_ready(&self, val: bool)643     fn set_ready(&self, val: bool) {
644         *self.ready.lock() = val;
645     }
646 }
647 
648 impl Vcpu for FakeVcpu {
try_clone(&self) -> Result<Self>649     fn try_clone(&self) -> Result<Self> {
650         Ok(FakeVcpu {
651             id: self.id,
652             requested: self.requested.clone(),
653             ready: self.ready.clone(),
654             injected: self.injected.clone(),
655         })
656     }
657 
id(&self) -> usize658     fn id(&self) -> usize {
659         self.id
660     }
661 
as_vcpu(&self) -> &dyn Vcpu662     fn as_vcpu(&self) -> &dyn Vcpu {
663         self
664     }
665 
run(&mut self) -> Result<VcpuExit>666     fn run(&mut self) -> Result<VcpuExit> {
667         unimplemented!()
668     }
669 
set_immediate_exit(&self, _exit: bool)670     fn set_immediate_exit(&self, _exit: bool) {}
671 
672     #[cfg(any(target_os = "android", target_os = "linux"))]
signal_handle(&self) -> hypervisor::VcpuSignalHandle673     fn signal_handle(&self) -> hypervisor::VcpuSignalHandle {
674         unimplemented!()
675     }
676 
handle_mmio(&self, _handle_fn: &mut dyn FnMut(IoParams) -> Result<()>) -> Result<()>677     fn handle_mmio(&self, _handle_fn: &mut dyn FnMut(IoParams) -> Result<()>) -> Result<()> {
678         unimplemented!()
679     }
handle_io(&self, _handle_fn: &mut dyn FnMut(IoParams)) -> Result<()>680     fn handle_io(&self, _handle_fn: &mut dyn FnMut(IoParams)) -> Result<()> {
681         unimplemented!()
682     }
on_suspend(&self) -> Result<()>683     fn on_suspend(&self) -> Result<()> {
684         unimplemented!()
685     }
enable_raw_capability(&self, _cap: u32, _args: &[u64; 4]) -> Result<()>686     unsafe fn enable_raw_capability(&self, _cap: u32, _args: &[u64; 4]) -> Result<()> {
687         unimplemented!()
688     }
689 }
690 
691 impl VcpuX86_64 for FakeVcpu {
set_interrupt_window_requested(&self, requested: bool)692     fn set_interrupt_window_requested(&self, requested: bool) {
693         *self.requested.lock() = requested;
694     }
695 
ready_for_interrupt(&self) -> bool696     fn ready_for_interrupt(&self) -> bool {
697         *self.ready.lock()
698     }
699 
interrupt(&self, irq: u8) -> Result<()>700     fn interrupt(&self, irq: u8) -> Result<()> {
701         *self.injected.lock() = Some(irq);
702         Ok(())
703     }
704 
inject_nmi(&self) -> Result<()>705     fn inject_nmi(&self) -> Result<()> {
706         Ok(())
707     }
708 
get_regs(&self) -> Result<Regs>709     fn get_regs(&self) -> Result<Regs> {
710         unimplemented!()
711     }
set_regs(&self, _regs: &Regs) -> Result<()>712     fn set_regs(&self, _regs: &Regs) -> Result<()> {
713         unimplemented!()
714     }
get_sregs(&self) -> Result<Sregs>715     fn get_sregs(&self) -> Result<Sregs> {
716         unimplemented!()
717     }
set_sregs(&self, _sregs: &Sregs) -> Result<()>718     fn set_sregs(&self, _sregs: &Sregs) -> Result<()> {
719         unimplemented!()
720     }
get_fpu(&self) -> Result<Fpu>721     fn get_fpu(&self) -> Result<Fpu> {
722         unimplemented!()
723     }
set_fpu(&self, _fpu: &Fpu) -> Result<()>724     fn set_fpu(&self, _fpu: &Fpu) -> Result<()> {
725         unimplemented!()
726     }
get_xsave(&self) -> Result<Xsave>727     fn get_xsave(&self) -> Result<Xsave> {
728         unimplemented!()
729     }
set_xsave(&self, _xsave: &Xsave) -> Result<()>730     fn set_xsave(&self, _xsave: &Xsave) -> Result<()> {
731         unimplemented!()
732     }
get_interrupt_state(&self) -> Result<serde_json::Value>733     fn get_interrupt_state(&self) -> Result<serde_json::Value> {
734         unimplemented!()
735     }
set_interrupt_state(&self, _data: serde_json::Value) -> Result<()>736     fn set_interrupt_state(&self, _data: serde_json::Value) -> Result<()> {
737         unimplemented!()
738     }
get_debugregs(&self) -> Result<DebugRegs>739     fn get_debugregs(&self) -> Result<DebugRegs> {
740         unimplemented!()
741     }
set_debugregs(&self, _debugregs: &DebugRegs) -> Result<()>742     fn set_debugregs(&self, _debugregs: &DebugRegs) -> Result<()> {
743         unimplemented!()
744     }
get_xcrs(&self) -> Result<BTreeMap<u32, u64>>745     fn get_xcrs(&self) -> Result<BTreeMap<u32, u64>> {
746         unimplemented!()
747     }
set_xcr(&self, _xcr_index: u32, _value: u64) -> Result<()>748     fn set_xcr(&self, _xcr_index: u32, _value: u64) -> Result<()> {
749         unimplemented!()
750     }
get_msr(&self, _msr_index: u32) -> Result<u64>751     fn get_msr(&self, _msr_index: u32) -> Result<u64> {
752         unimplemented!()
753     }
get_all_msrs(&self) -> Result<BTreeMap<u32, u64>>754     fn get_all_msrs(&self) -> Result<BTreeMap<u32, u64>> {
755         unimplemented!()
756     }
set_msr(&self, _msr_index: u32, _value: u64) -> Result<()>757     fn set_msr(&self, _msr_index: u32, _value: u64) -> Result<()> {
758         unimplemented!()
759     }
set_cpuid(&self, _cpuid: &CpuId) -> Result<()>760     fn set_cpuid(&self, _cpuid: &CpuId) -> Result<()> {
761         unimplemented!()
762     }
handle_cpuid(&mut self, _entry: &CpuIdEntry) -> Result<()>763     fn handle_cpuid(&mut self, _entry: &CpuIdEntry) -> Result<()> {
764         unimplemented!()
765     }
set_guest_debug(&self, _addrs: &[GuestAddress], _enable_singlestep: bool) -> Result<()>766     fn set_guest_debug(&self, _addrs: &[GuestAddress], _enable_singlestep: bool) -> Result<()> {
767         unimplemented!()
768     }
snapshot(&self) -> anyhow::Result<VcpuSnapshot>769     fn snapshot(&self) -> anyhow::Result<VcpuSnapshot> {
770         unimplemented!()
771     }
restore( &mut self, _snapshot: &VcpuSnapshot, _host_tsc_reference_moment: u64, ) -> anyhow::Result<()>772     fn restore(
773         &mut self,
774         _snapshot: &VcpuSnapshot,
775         _host_tsc_reference_moment: u64,
776     ) -> anyhow::Result<()> {
777         unimplemented!()
778     }
restore_timekeeping(&self, _host_tsc_reference_moment: u64, _tsc_offset: u64) -> Result<()>779     fn restore_timekeeping(&self, _host_tsc_reference_moment: u64, _tsc_offset: u64) -> Result<()> {
780         unimplemented!()
781     }
782 }
783