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