1use std::arch::x86_64::CpuidResult;
6use std::collections::BTreeMap;
7use std::sync::Arc;
8
9use base::errno_result;
10use base::error;
11use base::ioctl;
12use base::ioctl_with_mut_ptr;
13use base::ioctl_with_mut_ref;
14use base::ioctl_with_ptr;
15use base::ioctl_with_ref;
16use base::ioctl_with_val;
17use base::AsRawDescriptor;
18use base::Error;
19use base::IoctlNr;
20use base::MappedRegion;
21use base::Result;
22use kvm_sys::*;
23use libc::E2BIG;
24use libc::EAGAIN;
25use libc::EINVAL;
26use libc::EIO;
27use libc::ENOMEM;
28use libc::ENXIO;
29use serde::Deserialize;
30use serde::Serialize;
31use snapshot::AnySnapshot;
32use vm_memory::GuestAddress;
33use zerocopy::FromZeros;
34
35use super::Config;
36use super::Kvm;
37use super::KvmCap;
38use super::KvmVcpu;
39use super::KvmVm;
40use crate::host_phys_addr_bits;
41use crate::ClockState;
42use crate::CpuId;
43use crate::CpuIdEntry;
44use crate::DebugRegs;
45use crate::DescriptorTable;
46use crate::DeviceKind;
47use crate::Fpu;
48use crate::FpuReg;
49use crate::HypervisorX86_64;
50use crate::IoapicRedirectionTableEntry;
51use crate::IoapicState;
52use crate::IrqSourceChip;
53use crate::LapicState;
54use crate::PicSelect;
55use crate::PicState;
56use crate::PitChannelState;
57use crate::PitState;
58use crate::ProtectionType;
59use crate::Regs;
60use crate::Segment;
61use crate::Sregs;
62use crate::VcpuExit;
63use crate::VcpuX86_64;
64use crate::VmCap;
65use crate::VmX86_64;
66use crate::Xsave;
67use crate::NUM_IOAPIC_PINS;
68
69const KVM_XSAVE_MAX_SIZE: usize = 4096;
70const MSR_IA32_APICBASE: u32 = 0x0000001b;
71
72#[derive(Debug, Clone, Serialize, Deserialize)]
73pub struct VcpuEvents {
74 pub exception: VcpuExceptionState,
75 pub interrupt: VcpuInterruptState,
76 pub nmi: VcpuNmiState,
77 pub sipi_vector: Option<u32>,
78 pub smi: VcpuSmiState,
79 pub triple_fault: VcpuTripleFaultState,
80 pub exception_payload: Option<u64>,
81}
82
83#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct VcpuExceptionState {
85 pub injected: bool,
86 pub nr: u8,
87 pub has_error_code: bool,
88 pub pending: Option<bool>,
89 pub error_code: u32,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize)]
93pub struct VcpuInterruptState {
94 pub injected: bool,
95 pub nr: u8,
96 pub soft: bool,
97 pub shadow: Option<u8>,
98}
99
100#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct VcpuNmiState {
102 pub injected: bool,
103 pub pending: Option<bool>,
104 pub masked: bool,
105}
106
107#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct VcpuSmiState {
109 pub smm: Option<bool>,
110 pub pending: bool,
111 pub smm_inside_nmi: bool,
112 pub latched_init: u8,
113}
114
115#[derive(Debug, Clone, Serialize, Deserialize)]
116pub struct VcpuTripleFaultState {
117 pub pending: Option<bool>,
118}
119
120pub fn get_cpuid_with_initial_capacity<T: AsRawDescriptor>(
121 descriptor: &T,
122 kind: IoctlNr,
123 initial_capacity: usize,
124) -> Result<CpuId> {
125 let mut entries: usize = initial_capacity;
126
127 loop {
128 let mut kvm_cpuid =
129 kvm_cpuid2::<[kvm_cpuid_entry2]>::new_box_zeroed_with_elems(entries).unwrap();
130 kvm_cpuid.nent = entries.try_into().unwrap();
131
132 let ret = {
133 unsafe { ioctl_with_mut_ref(descriptor, kind, &mut *kvm_cpuid) }
138 };
139 if ret < 0 {
140 let err = Error::last();
141 match err.errno() {
142 E2BIG => {
143 if let Some(val) = entries.checked_mul(2) {
145 entries = val;
146 } else {
147 return Err(err);
148 }
149 }
150 _ => return Err(err),
151 }
152 } else {
153 return Ok(CpuId::from(&*kvm_cpuid));
154 }
155 }
156}
157
158impl Kvm {
159 pub fn get_cpuid(&self, kind: IoctlNr) -> Result<CpuId> {
160 const KVM_MAX_ENTRIES: usize = 256;
161 get_cpuid_with_initial_capacity(self, kind, KVM_MAX_ENTRIES)
162 }
163
164 pub fn get_vm_type(&self, protection_type: ProtectionType) -> Result<u32> {
165 if protection_type.isolates_memory() {
166 Ok(KVM_X86_PKVM_PROTECTED_VM)
167 } else {
168 Ok(KVM_X86_DEFAULT_VM)
169 }
170 }
171
172 pub fn get_guest_phys_addr_bits(&self) -> u8 {
174 host_phys_addr_bits()
176 }
177}
178
179impl HypervisorX86_64 for Kvm {
180 fn get_supported_cpuid(&self) -> Result<CpuId> {
181 self.get_cpuid(KVM_GET_SUPPORTED_CPUID)
182 }
183
184 fn get_msr_index_list(&self) -> Result<Vec<u32>> {
185 const MAX_KVM_MSR_ENTRIES: usize = 256;
186
187 let mut msr_list = kvm_msr_list::<[u32; MAX_KVM_MSR_ENTRIES]>::new_zeroed();
188 msr_list.nmsrs = MAX_KVM_MSR_ENTRIES as u32;
189
190 let ret = {
191 unsafe { ioctl_with_mut_ref(self, KVM_GET_MSR_INDEX_LIST, &mut msr_list) }
196 };
197 if ret < 0 {
198 return errno_result();
199 }
200
201 let mut nmsrs = msr_list.nmsrs;
202 if nmsrs > MAX_KVM_MSR_ENTRIES as u32 {
203 nmsrs = MAX_KVM_MSR_ENTRIES as u32;
204 }
205
206 Ok(msr_list.indices[..nmsrs as usize].to_vec())
207 }
208}
209
210impl KvmVm {
211 pub fn init_arch(&self, _cfg: &Config) -> Result<()> {
213 Ok(())
214 }
215
216 pub fn check_capability_arch(&self, c: VmCap) -> Option<bool> {
219 match c {
220 VmCap::PvClock => Some(true),
221 _ => None,
222 }
223 }
224
225 pub fn get_device_params_arch(&self, _kind: DeviceKind) -> Option<kvm_create_device> {
228 None
229 }
230
231 pub fn get_pvclock_arch(&self) -> Result<ClockState> {
233 let mut clock_data: kvm_clock_data = Default::default();
234 let ret =
235 unsafe { ioctl_with_mut_ref(self, KVM_GET_CLOCK, &mut clock_data) };
239 if ret == 0 {
240 Ok(ClockState::from(&clock_data))
241 } else {
242 errno_result()
243 }
244 }
245
246 pub fn set_pvclock_arch(&self, state: &ClockState) -> Result<()> {
248 let clock_data = kvm_clock_data::from(state);
249 let ret = unsafe { ioctl_with_ref(self, KVM_SET_CLOCK, &clock_data) };
253 if ret == 0 {
254 Ok(())
255 } else {
256 errno_result()
257 }
258 }
259
260 pub fn signal_msi_to_lapic(&self, apic_id: u32, vector: u8) -> Result<()> {
262 let msi = kvm_msi {
263 address_lo: 0xFEE0_0000 | ((apic_id & 0xFF) << 12),
264 address_hi: 0,
265 data: vector as u32,
266 flags: 0,
267 ..Default::default()
268 };
269 self.signal_msi(&msi)
270 }
271
272 pub fn get_pic_state(&self, id: PicSelect) -> Result<kvm_pic_state> {
276 let mut irqchip_state = kvm_irqchip {
277 chip_id: id as u32,
278 ..Default::default()
279 };
280 let ret = {
281 unsafe { ioctl_with_mut_ref(self, KVM_GET_IRQCHIP, &mut irqchip_state) }
285 };
286 if ret == 0 {
287 Ok(
288 unsafe { irqchip_state.chip.pic },
292 )
293 } else {
294 errno_result()
295 }
296 }
297
298 pub fn set_pic_state(&self, id: PicSelect, state: &kvm_pic_state) -> Result<()> {
302 let mut irqchip_state = kvm_irqchip {
303 chip_id: id as u32,
304 ..Default::default()
305 };
306 irqchip_state.chip.pic = *state;
307 let ret = unsafe { ioctl_with_ref(self, KVM_SET_IRQCHIP, &irqchip_state) };
311 if ret == 0 {
312 Ok(())
313 } else {
314 errno_result()
315 }
316 }
317
318 pub fn get_ioapic_num_pins(&self) -> Result<usize> {
320 Ok(NUM_IOAPIC_PINS)
321 }
322
323 pub fn get_ioapic_state(&self) -> Result<kvm_ioapic_state> {
327 let mut irqchip_state = kvm_irqchip {
328 chip_id: 2,
329 ..Default::default()
330 };
331 let ret = {
332 unsafe { ioctl_with_mut_ref(self, KVM_GET_IRQCHIP, &mut irqchip_state) }
336 };
337 if ret == 0 {
338 Ok(
339 unsafe { irqchip_state.chip.ioapic },
343 )
344 } else {
345 errno_result()
346 }
347 }
348
349 pub fn set_ioapic_state(&self, state: &kvm_ioapic_state) -> Result<()> {
353 let mut irqchip_state = kvm_irqchip {
354 chip_id: 2,
355 ..Default::default()
356 };
357 irqchip_state.chip.ioapic = *state;
358 let ret = unsafe { ioctl_with_ref(self, KVM_SET_IRQCHIP, &irqchip_state) };
362 if ret == 0 {
363 Ok(())
364 } else {
365 errno_result()
366 }
367 }
368
369 pub fn create_pit(&self) -> Result<()> {
373 let pit_config = kvm_pit_config::default();
374 let ret = unsafe { ioctl_with_ref(self, KVM_CREATE_PIT2, &pit_config) };
378 if ret == 0 {
379 Ok(())
380 } else {
381 errno_result()
382 }
383 }
384
385 pub fn get_pit_state(&self) -> Result<kvm_pit_state2> {
389 let mut pit_state = Default::default();
390 let ret = unsafe { ioctl_with_mut_ref(self, KVM_GET_PIT2, &mut pit_state) };
394 if ret == 0 {
395 Ok(pit_state)
396 } else {
397 errno_result()
398 }
399 }
400
401 pub fn set_pit_state(&self, pit_state: &kvm_pit_state2) -> Result<()> {
405 let ret = unsafe { ioctl_with_ref(self, KVM_SET_PIT2, pit_state) };
409 if ret == 0 {
410 Ok(())
411 } else {
412 errno_result()
413 }
414 }
415
416 pub fn set_platform_info_read_access(&self, allow_read: bool) -> Result<()> {
418 let mut cap = kvm_enable_cap {
419 cap: KVM_CAP_MSR_PLATFORM_INFO,
420 ..Default::default()
421 };
422 cap.args[0] = allow_read as u64;
423
424 let ret = unsafe { ioctl_with_ref(self, KVM_ENABLE_CAP, &cap) };
429 if ret < 0 {
430 errno_result()
431 } else {
432 Ok(())
433 }
434 }
435
436 pub fn enable_split_irqchip(&self, ioapic_pins: usize) -> Result<()> {
438 let mut cap = kvm_enable_cap {
439 cap: KVM_CAP_SPLIT_IRQCHIP,
440 ..Default::default()
441 };
442 cap.args[0] = ioapic_pins as u64;
443 let ret = unsafe { ioctl_with_ref(self, KVM_ENABLE_CAP, &cap) };
447 if ret < 0 {
448 errno_result()
449 } else {
450 Ok(())
451 }
452 }
453
454 fn get_protected_vm_info(&self) -> Result<KvmProtectedVmInfo> {
461 let mut info = KvmProtectedVmInfo {
462 firmware_size: 0,
463 reserved: [0; 7],
464 };
465 unsafe {
469 self.enable_raw_capability(
470 KvmCap::X86ProtectedVm,
471 KVM_CAP_X86_PROTECTED_VM_FLAGS_INFO,
472 &[&mut info as *mut KvmProtectedVmInfo as u64, 0, 0, 0],
473 )
474 }?;
475 Ok(info)
476 }
477
478 fn set_protected_vm_firmware_gpa(&self, fw_addr: GuestAddress) -> Result<()> {
479 unsafe {
482 self.enable_raw_capability(
483 KvmCap::X86ProtectedVm,
484 KVM_CAP_X86_PROTECTED_VM_FLAGS_SET_FW_GPA,
485 &[fw_addr.0, 0, 0, 0],
486 )
487 }
488 }
489}
490
491#[repr(C)]
492struct KvmProtectedVmInfo {
493 firmware_size: u64,
494 reserved: [u64; 7],
495}
496
497impl VmX86_64 for KvmVm {
498 fn get_hypervisor(&self) -> &dyn HypervisorX86_64 {
499 &self.kvm
500 }
501
502 fn load_protected_vm_firmware(&self, fw_addr: GuestAddress, fw_max_size: u64) -> Result<()> {
503 let info = self.get_protected_vm_info()?;
504 if info.firmware_size == 0 {
505 Err(Error::new(EINVAL))
506 } else {
507 if info.firmware_size > fw_max_size {
508 return Err(Error::new(ENOMEM));
509 }
510 self.set_protected_vm_firmware_gpa(fw_addr)
511 }
512 }
513
514 fn create_vcpu(&self, id: usize) -> Result<Arc<dyn VcpuX86_64>> {
515 Ok(Arc::new(KvmVm::create_kvm_vcpu(self, id)?))
518 }
519
520 fn set_tss_addr(&self, addr: GuestAddress) -> Result<()> {
524 let ret = unsafe { ioctl_with_val(self, KVM_SET_TSS_ADDR, addr.offset()) };
527 if ret == 0 {
528 Ok(())
529 } else {
530 errno_result()
531 }
532 }
533
534 fn set_identity_map_addr(&self, addr: GuestAddress) -> Result<()> {
538 let ret = unsafe { ioctl_with_ref(self, KVM_SET_IDENTITY_MAP_ADDR, &addr.offset()) };
541 if ret == 0 {
542 Ok(())
543 } else {
544 errno_result()
545 }
546 }
547}
548
549impl KvmVcpu {
550 pub fn system_event_reset(&self, _event_flags: u64) -> Result<VcpuExit> {
553 Ok(VcpuExit::SystemEventReset)
554 }
555
556 fn xsave_size(&self) -> Result<usize> {
563 let size = {
564 unsafe { ioctl_with_val(&self.vm, KVM_CHECK_EXTENSION, KVM_CAP_XSAVE2 as u64) }
567 };
568 if size < 0 {
569 return errno_result();
570 }
571 let size: usize = size.try_into().unwrap();
573 Ok(size.max(KVM_XSAVE_MAX_SIZE))
574 }
575
576 #[inline]
577 pub(crate) fn handle_vm_exit_arch(&self, run: &mut kvm_run) -> Option<VcpuExit> {
578 match run.exit_reason {
579 KVM_EXIT_IO => Some(VcpuExit::Io),
580 KVM_EXIT_IOAPIC_EOI => {
581 let vector = unsafe { run.__bindgen_anon_1.eoi.vector };
585 Some(VcpuExit::IoapicEoi { vector })
586 }
587 KVM_EXIT_HLT => Some(VcpuExit::Hlt),
588 KVM_EXIT_SET_TPR => Some(VcpuExit::SetTpr),
589 KVM_EXIT_TPR_ACCESS => Some(VcpuExit::TprAccess),
590 KVM_EXIT_X86_BUS_LOCK => Some(VcpuExit::BusLock),
591 _ => None,
592 }
593 }
594}
595
596#[derive(Debug, Serialize, Deserialize)]
597struct HypervisorState {
598 interrupts: VcpuEvents,
599 nested_state: Vec<u8>,
600}
601
602impl VcpuX86_64 for KvmVcpu {
603 #[allow(clippy::cast_ptr_alignment)]
604 fn set_interrupt_window_requested(&self, requested: bool) {
605 let run = unsafe { &mut *(self.run_mmap.as_ptr() as *mut kvm_run) };
610 run.request_interrupt_window = requested.into();
611 }
612
613 #[allow(clippy::cast_ptr_alignment)]
614 fn ready_for_interrupt(&self) -> bool {
615 let run = unsafe { &mut *(self.run_mmap.as_ptr() as *mut kvm_run) };
620 run.ready_for_interrupt_injection != 0 && run.if_flag != 0
621 }
622
623 fn interrupt(&self, irq: u8) -> Result<()> {
628 if !self.ready_for_interrupt() {
629 return Err(Error::new(EAGAIN));
630 }
631
632 let interrupt = kvm_interrupt { irq: irq.into() };
633 let ret = unsafe { ioctl_with_ref(self, KVM_INTERRUPT, &interrupt) };
637 if ret == 0 {
638 Ok(())
639 } else {
640 errno_result()
641 }
642 }
643
644 fn inject_nmi(&self) -> Result<()> {
645 let ret = unsafe { ioctl(self, KVM_NMI) };
648 if ret == 0 {
649 Ok(())
650 } else {
651 errno_result()
652 }
653 }
654
655 fn get_regs(&self) -> Result<Regs> {
656 let mut regs: kvm_regs = Default::default();
657 let ret = {
658 unsafe { ioctl_with_mut_ref(self, KVM_GET_REGS, &mut regs) }
663 };
664 if ret == 0 {
665 Ok(Regs::from(®s))
666 } else {
667 errno_result()
668 }
669 }
670
671 fn set_regs(&self, regs: &Regs) -> Result<()> {
672 let regs = kvm_regs::from(regs);
673 let ret = {
674 unsafe { ioctl_with_ref(self, KVM_SET_REGS, ®s) }
679 };
680 if ret == 0 {
681 Ok(())
682 } else {
683 errno_result()
684 }
685 }
686
687 fn get_sregs(&self) -> Result<Sregs> {
688 let mut regs: kvm_sregs = Default::default();
689 let ret = {
690 unsafe { ioctl_with_mut_ref(self, KVM_GET_SREGS, &mut regs) }
695 };
696 if ret == 0 {
697 Ok(Sregs::from(®s))
698 } else {
699 errno_result()
700 }
701 }
702
703 fn set_sregs(&self, sregs: &Sregs) -> Result<()> {
704 let mut kvm_sregs: kvm_sregs = Default::default();
707 let ret = unsafe { ioctl_with_mut_ref(self, KVM_GET_SREGS, &mut kvm_sregs) };
711 if ret != 0 {
712 return errno_result();
713 }
714
715 kvm_sregs.cs = kvm_segment::from(&sregs.cs);
716 kvm_sregs.ds = kvm_segment::from(&sregs.ds);
717 kvm_sregs.es = kvm_segment::from(&sregs.es);
718 kvm_sregs.fs = kvm_segment::from(&sregs.fs);
719 kvm_sregs.gs = kvm_segment::from(&sregs.gs);
720 kvm_sregs.ss = kvm_segment::from(&sregs.ss);
721 kvm_sregs.tr = kvm_segment::from(&sregs.tr);
722 kvm_sregs.ldt = kvm_segment::from(&sregs.ldt);
723 kvm_sregs.gdt = kvm_dtable::from(&sregs.gdt);
724 kvm_sregs.idt = kvm_dtable::from(&sregs.idt);
725 kvm_sregs.cr0 = sregs.cr0;
726 kvm_sregs.cr2 = sregs.cr2;
727 kvm_sregs.cr3 = sregs.cr3;
728 kvm_sregs.cr4 = sregs.cr4;
729 kvm_sregs.cr8 = sregs.cr8;
730 kvm_sregs.efer = sregs.efer;
731
732 let ret = unsafe { ioctl_with_ref(self, KVM_SET_SREGS, &kvm_sregs) };
736 if ret == 0 {
737 Ok(())
738 } else {
739 errno_result()
740 }
741 }
742
743 fn get_fpu(&self) -> Result<Fpu> {
744 let mut fpu: kvm_fpu = Default::default();
745 let ret = unsafe { ioctl_with_mut_ref(self, KVM_GET_FPU, &mut fpu) };
749 if ret == 0 {
750 Ok(Fpu::from(&fpu))
751 } else {
752 errno_result()
753 }
754 }
755
756 fn set_fpu(&self, fpu: &Fpu) -> Result<()> {
757 let fpu = kvm_fpu::from(fpu);
758 let ret = {
759 unsafe { ioctl_with_ref(self, KVM_SET_FPU, &fpu) }
762 };
763 if ret == 0 {
764 Ok(())
765 } else {
766 errno_result()
767 }
768 }
769
770 fn get_xsave(&self) -> Result<Xsave> {
772 let size = self.xsave_size()?;
773 let ioctl_nr = if size > KVM_XSAVE_MAX_SIZE {
774 KVM_GET_XSAVE2
775 } else {
776 KVM_GET_XSAVE
777 };
778 let mut xsave = Xsave::new(size);
779
780 let ret = unsafe { ioctl_with_mut_ptr(self, ioctl_nr, xsave.as_mut_ptr()) };
784 if ret == 0 {
785 Ok(xsave)
786 } else {
787 errno_result()
788 }
789 }
790
791 fn set_xsave(&self, xsave: &Xsave) -> Result<()> {
792 let size = self.xsave_size()?;
793 if xsave.len() != size {
796 return Err(Error::new(EIO));
797 }
798
799 let ret = unsafe { ioctl_with_ptr(self, KVM_SET_XSAVE, xsave.as_ptr()) };
805 if ret == 0 {
806 Ok(())
807 } else {
808 errno_result()
809 }
810 }
811
812 fn get_hypervisor_specific_state(&self) -> Result<AnySnapshot> {
813 let mut vcpu_evts: kvm_vcpu_events = Default::default();
814 let ret = { unsafe { ioctl_with_mut_ref(self, KVM_GET_VCPU_EVENTS, &mut vcpu_evts) } };
819 if ret != 0 {
820 return errno_result();
821 }
822 let interrupts = VcpuEvents::from(&vcpu_evts);
823 let ret =
824 unsafe { ioctl_with_val(&self.vm, KVM_CHECK_EXTENSION, KVM_CAP_NESTED_STATE as u64) };
827 if ret < 0 {
828 return errno_result();
829 }
830 let nested_state = if ret == 0 {
832 Vec::new()
833 } else {
834 let mut nested_state: Vec<u8> = vec![0; ret as usize];
835 let nested_state_ptr = nested_state.as_ptr() as *mut kvm_nested_state;
836 assert!(nested_state_ptr.is_aligned());
837 unsafe {
845 (*nested_state_ptr).size = ret as u32;
846 }
847 assert!(nested_state.as_ptr().is_aligned());
848 let ret = unsafe {
852 ioctl_with_mut_ptr(self, KVM_GET_NESTED_STATE, nested_state.as_mut_ptr())
853 };
854 if ret < 0 {
855 return errno_result();
856 }
857 nested_state
858 };
859 AnySnapshot::to_any(HypervisorState {
860 interrupts,
861 nested_state,
862 })
863 .map_err(|e| {
864 error!("failed to serialize hypervisor state: {:?}", e);
865 Error::new(EIO)
866 })
867 }
868
869 fn set_hypervisor_specific_state(&self, data: AnySnapshot) -> Result<()> {
870 let hypervisor_state = AnySnapshot::from_any::<HypervisorState>(data).map_err(|e| {
871 error!("failed to deserialize hypervisor_state: {:?}", e);
872 Error::new(EIO)
873 })?;
874 let vcpu_events = kvm_vcpu_events::from(&hypervisor_state.interrupts);
875 let ret = {
876 unsafe { ioctl_with_ref(self, KVM_SET_VCPU_EVENTS, &vcpu_events) }
881 };
882 if ret != 0 {
883 return errno_result();
884 }
885 if hypervisor_state.nested_state.is_empty() {
886 return Ok(());
887 }
888 unsafe {
897 let vec_len = hypervisor_state.nested_state.len();
898 assert!(
899 (hypervisor_state.nested_state.as_ptr() as *const kvm_nested_state).is_aligned()
900 );
901 if (*(hypervisor_state.nested_state.as_ptr() as *const kvm_nested_state)).size
902 > vec_len as u32
903 {
904 error!("Invalued nested state data, size larger than vec allocated.");
905 return Err(Error::new(EINVAL));
906 }
907 }
908 let ret = unsafe {
913 ioctl_with_ptr(
914 self,
915 KVM_SET_NESTED_STATE,
916 hypervisor_state.nested_state.as_ptr(),
917 )
918 };
919 if ret == 0 {
920 Ok(())
921 } else {
922 errno_result()
923 }
924 }
925
926 fn get_debugregs(&self) -> Result<DebugRegs> {
927 let mut regs: kvm_debugregs = Default::default();
928 let ret = unsafe { ioctl_with_mut_ref(self, KVM_GET_DEBUGREGS, &mut regs) };
932 if ret == 0 {
933 Ok(DebugRegs::from(®s))
934 } else {
935 errno_result()
936 }
937 }
938
939 fn set_debugregs(&self, dregs: &DebugRegs) -> Result<()> {
940 let dregs = kvm_debugregs::from(dregs);
941 let ret = {
942 unsafe { ioctl_with_ref(self, KVM_SET_DEBUGREGS, &dregs) }
945 };
946 if ret == 0 {
947 Ok(())
948 } else {
949 errno_result()
950 }
951 }
952
953 fn get_xcrs(&self) -> Result<BTreeMap<u32, u64>> {
954 let mut regs: kvm_xcrs = Default::default();
955 let ret = unsafe { ioctl_with_mut_ref(self, KVM_GET_XCRS, &mut regs) };
959 if ret < 0 {
960 return errno_result();
961 }
962
963 Ok(regs
964 .xcrs
965 .iter()
966 .take(regs.nr_xcrs as usize)
967 .map(|kvm_xcr| (kvm_xcr.xcr, kvm_xcr.value))
968 .collect())
969 }
970
971 fn set_xcr(&self, xcr_index: u32, value: u64) -> Result<()> {
972 let mut kvm_xcr = kvm_xcrs {
973 nr_xcrs: 1,
974 ..Default::default()
975 };
976 kvm_xcr.xcrs[0].xcr = xcr_index;
977 kvm_xcr.xcrs[0].value = value;
978
979 let ret = {
980 unsafe { ioctl_with_ref(self, KVM_SET_XCRS, &kvm_xcr) }
983 };
984 if ret == 0 {
985 Ok(())
986 } else {
987 errno_result()
988 }
989 }
990
991 fn get_msr(&self, msr_index: u32) -> Result<u64> {
992 let mut msrs = kvm_msrs::<[kvm_msr_entry; 1]>::new_zeroed();
993 msrs.nmsrs = 1;
994 msrs.entries[0].index = msr_index;
995
996 let ret = {
997 unsafe { ioctl_with_mut_ref(self, KVM_GET_MSRS, &mut msrs) }
1000 };
1001 if ret < 0 {
1002 return errno_result();
1003 }
1004
1005 if ret != 1 {
1007 return Err(base::Error::new(libc::ENOENT));
1008 }
1009
1010 Ok(msrs.entries[0].data)
1011 }
1012
1013 fn get_all_msrs(&self) -> Result<BTreeMap<u32, u64>> {
1014 let msr_index_list = self.kvm.get_msr_index_list()?;
1015
1016 let mut kvm_msrs =
1017 kvm_msrs::<[kvm_msr_entry]>::new_box_zeroed_with_elems(msr_index_list.len()).unwrap();
1018 kvm_msrs.nmsrs = msr_index_list.len() as u32;
1019 kvm_msrs
1020 .entries
1021 .iter_mut()
1022 .zip(msr_index_list.iter())
1023 .for_each(|(msr_entry, msr_index)| msr_entry.index = *msr_index);
1024
1025 let ret = {
1026 unsafe { ioctl_with_mut_ref(self, KVM_GET_MSRS, &mut *kvm_msrs) }
1029 };
1030 if ret < 0 {
1031 return errno_result();
1032 }
1033
1034 let count = ret as usize;
1036 if count != msr_index_list.len() {
1037 error!(
1038 "failed to get all MSRs: requested {}, got {}",
1039 msr_index_list.len(),
1040 count,
1041 );
1042 return Err(base::Error::new(libc::EPERM));
1043 }
1044
1045 let msrs = BTreeMap::from_iter(
1046 kvm_msrs
1047 .entries
1048 .iter()
1049 .map(|kvm_msr| (kvm_msr.index, kvm_msr.data)),
1050 );
1051
1052 Ok(msrs)
1053 }
1054
1055 fn set_msr(&self, msr_index: u32, value: u64) -> Result<()> {
1056 let mut kvm_msrs = kvm_msrs::<[kvm_msr_entry; 1]>::new_zeroed();
1057 kvm_msrs.nmsrs = 1;
1058 kvm_msrs.entries[0].index = msr_index;
1059 kvm_msrs.entries[0].data = value;
1060
1061 let ret = {
1062 unsafe { ioctl_with_ref(self, KVM_SET_MSRS, &kvm_msrs) }
1065 };
1066 if ret < 0 {
1067 return errno_result();
1068 }
1069
1070 if ret != 1 {
1072 error!("failed to set MSR {:#x} to {:#x}", msr_index, value);
1073 return Err(base::Error::new(libc::EPERM));
1074 }
1075
1076 Ok(())
1077 }
1078
1079 fn set_cpuid(&self, cpuid: &CpuId) -> Result<()> {
1080 let cpuid = Box::<kvm_cpuid2<[kvm_cpuid_entry2]>>::from(cpuid);
1081 let ret = {
1082 unsafe { ioctl_with_ref(self, KVM_SET_CPUID2, &*cpuid) }
1085 };
1086 if ret == 0 {
1087 Ok(())
1088 } else {
1089 errno_result()
1090 }
1091 }
1092
1093 fn set_guest_debug(&self, addrs: &[GuestAddress], enable_singlestep: bool) -> Result<()> {
1094 use kvm_sys::*;
1095 let mut dbg: kvm_guest_debug = Default::default();
1096
1097 if addrs.len() > 4 {
1098 error!(
1099 "Support 4 breakpoints at most but {} addresses are passed",
1100 addrs.len()
1101 );
1102 return Err(base::Error::new(libc::EINVAL));
1103 }
1104
1105 dbg.control = KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
1106 if enable_singlestep {
1107 dbg.control |= KVM_GUESTDBG_SINGLESTEP;
1108 }
1109
1110 dbg.arch.debugreg[7] = 0x0600;
1114
1115 for (i, addr) in addrs.iter().enumerate() {
1116 dbg.arch.debugreg[i] = addr.0;
1117 dbg.arch.debugreg[7] |= 2 << (i * 2);
1119 }
1120
1121 let ret = {
1122 unsafe { ioctl_with_ref(self, KVM_SET_GUEST_DEBUG, &dbg) }
1125 };
1126 if ret == 0 {
1127 Ok(())
1128 } else {
1129 errno_result()
1130 }
1131 }
1132
1133 fn handle_cpuid(&self, _entry: &CpuIdEntry) -> Result<()> {
1135 Err(Error::new(ENXIO))
1136 }
1137
1138 fn restore_timekeeping(&self, _host_tsc_reference_moment: u64, _tsc_offset: u64) -> Result<()> {
1139 Ok(())
1141 }
1142}
1143
1144impl KvmVcpu {
1145 pub fn get_lapic(&self) -> Result<kvm_lapic_state> {
1150 let mut klapic: kvm_lapic_state = Default::default();
1151
1152 let ret = {
1153 unsafe { ioctl_with_mut_ref(self, KVM_GET_LAPIC, &mut klapic) }
1157 };
1158 if ret < 0 {
1159 return errno_result();
1160 }
1161 Ok(klapic)
1162 }
1163
1164 pub fn set_lapic(&self, klapic: &kvm_lapic_state) -> Result<()> {
1169 let ret = {
1170 unsafe { ioctl_with_ref(self, KVM_SET_LAPIC, klapic) }
1173 };
1174 if ret < 0 {
1175 return errno_result();
1176 }
1177 Ok(())
1178 }
1179
1180 pub fn get_apic_base(&self) -> Result<u64> {
1184 self.get_msr(MSR_IA32_APICBASE)
1185 }
1186
1187 pub fn set_apic_base(&self, apic_base: u64) -> Result<()> {
1191 self.set_msr(MSR_IA32_APICBASE, apic_base)
1192 }
1193
1194 pub fn get_interrupt_bitmap(&self) -> Result<[u64; 4usize]> {
1198 let mut regs: kvm_sregs = Default::default();
1199 let ret = unsafe { ioctl_with_mut_ref(self, KVM_GET_SREGS, &mut regs) };
1203 if ret >= 0 {
1204 Ok(regs.interrupt_bitmap)
1205 } else {
1206 errno_result()
1207 }
1208 }
1209
1210 pub fn set_interrupt_bitmap(&self, interrupt_bitmap: [u64; 4usize]) -> Result<()> {
1214 let mut regs: kvm_sregs = Default::default();
1218 let ret = unsafe { ioctl_with_mut_ref(self, KVM_GET_SREGS, &mut regs) };
1222 if ret >= 0 {
1223 regs.interrupt_bitmap = interrupt_bitmap;
1224 let ret = unsafe { ioctl_with_ref(self, KVM_SET_SREGS, ®s) };
1229 if ret >= 0 {
1230 Ok(())
1231 } else {
1232 errno_result()
1233 }
1234 } else {
1235 errno_result()
1236 }
1237 }
1238}
1239
1240impl<'a> From<&'a kvm_cpuid2<[kvm_cpuid_entry2]>> for CpuId {
1241 fn from(kvm_cpuid: &'a kvm_cpuid2<[kvm_cpuid_entry2]>) -> CpuId {
1242 let kvm_entries = &kvm_cpuid.entries[..kvm_cpuid.nent as usize];
1243 let mut cpu_id_entries = Vec::with_capacity(kvm_entries.len());
1244
1245 for entry in kvm_entries {
1246 let cpu_id_entry = CpuIdEntry {
1247 function: entry.function,
1248 index: entry.index,
1249 flags: entry.flags,
1250 cpuid: CpuidResult {
1251 eax: entry.eax,
1252 ebx: entry.ebx,
1253 ecx: entry.ecx,
1254 edx: entry.edx,
1255 },
1256 };
1257 cpu_id_entries.push(cpu_id_entry)
1258 }
1259 CpuId { cpu_id_entries }
1260 }
1261}
1262
1263impl From<&CpuId> for Box<kvm_cpuid2<[kvm_cpuid_entry2]>> {
1264 fn from(cpuid: &CpuId) -> Box<kvm_cpuid2<[kvm_cpuid_entry2]>> {
1265 let mut kvm =
1266 kvm_cpuid2::<[kvm_cpuid_entry2]>::new_box_zeroed_with_elems(cpuid.cpu_id_entries.len())
1267 .unwrap();
1268 kvm.nent = cpuid.cpu_id_entries.len().try_into().unwrap();
1269 for (i, &e) in cpuid.cpu_id_entries.iter().enumerate() {
1270 kvm.entries[i] = kvm_cpuid_entry2 {
1271 function: e.function,
1272 index: e.index,
1273 flags: e.flags,
1274 eax: e.cpuid.eax,
1275 ebx: e.cpuid.ebx,
1276 ecx: e.cpuid.ecx,
1277 edx: e.cpuid.edx,
1278 ..Default::default()
1279 };
1280 }
1281 kvm
1282 }
1283}
1284
1285impl From<&ClockState> for kvm_clock_data {
1286 fn from(state: &ClockState) -> Self {
1287 kvm_clock_data {
1288 clock: state.clock,
1289 ..Default::default()
1290 }
1291 }
1292}
1293
1294impl From<&kvm_clock_data> for ClockState {
1295 fn from(clock_data: &kvm_clock_data) -> Self {
1296 ClockState {
1297 clock: clock_data.clock,
1298 }
1299 }
1300}
1301
1302impl From<&kvm_pic_state> for PicState {
1303 fn from(item: &kvm_pic_state) -> Self {
1304 PicState {
1305 last_irr: item.last_irr,
1306 irr: item.irr,
1307 imr: item.imr,
1308 isr: item.isr,
1309 priority_add: item.priority_add,
1310 irq_base: item.irq_base,
1311 read_reg_select: item.read_reg_select != 0,
1312 poll: item.poll != 0,
1313 special_mask: item.special_mask != 0,
1314 init_state: item.init_state.into(),
1315 auto_eoi: item.auto_eoi != 0,
1316 rotate_on_auto_eoi: item.rotate_on_auto_eoi != 0,
1317 special_fully_nested_mode: item.special_fully_nested_mode != 0,
1318 use_4_byte_icw: item.init4 != 0,
1319 elcr: item.elcr,
1320 elcr_mask: item.elcr_mask,
1321 }
1322 }
1323}
1324
1325impl From<&PicState> for kvm_pic_state {
1326 fn from(item: &PicState) -> Self {
1327 kvm_pic_state {
1328 last_irr: item.last_irr,
1329 irr: item.irr,
1330 imr: item.imr,
1331 isr: item.isr,
1332 priority_add: item.priority_add,
1333 irq_base: item.irq_base,
1334 read_reg_select: item.read_reg_select as u8,
1335 poll: item.poll as u8,
1336 special_mask: item.special_mask as u8,
1337 init_state: item.init_state as u8,
1338 auto_eoi: item.auto_eoi as u8,
1339 rotate_on_auto_eoi: item.rotate_on_auto_eoi as u8,
1340 special_fully_nested_mode: item.special_fully_nested_mode as u8,
1341 init4: item.use_4_byte_icw as u8,
1342 elcr: item.elcr,
1343 elcr_mask: item.elcr_mask,
1344 }
1345 }
1346}
1347
1348impl From<&kvm_ioapic_state> for IoapicState {
1349 fn from(item: &kvm_ioapic_state) -> Self {
1350 let mut state = IoapicState {
1351 base_address: item.base_address,
1352 ioregsel: item.ioregsel as u8,
1353 ioapicid: item.id,
1354 current_interrupt_level_bitmap: item.irr,
1355 redirect_table: [IoapicRedirectionTableEntry::default(); NUM_IOAPIC_PINS],
1356 };
1357 for (in_state, out_state) in item.redirtbl.iter().zip(state.redirect_table.iter_mut()) {
1358 *out_state = in_state.into();
1359 }
1360 state
1361 }
1362}
1363
1364impl From<&IoapicRedirectionTableEntry> for kvm_ioapic_state__bindgen_ty_1 {
1365 fn from(item: &IoapicRedirectionTableEntry) -> Self {
1366 kvm_ioapic_state__bindgen_ty_1 {
1367 bits: item.get(0, 64),
1370 }
1371 }
1372}
1373
1374impl From<&kvm_ioapic_state__bindgen_ty_1> for IoapicRedirectionTableEntry {
1375 fn from(item: &kvm_ioapic_state__bindgen_ty_1) -> Self {
1376 let mut entry = IoapicRedirectionTableEntry::default();
1377 entry.set(0, 64, unsafe { item.bits });
1381 entry
1382 }
1383}
1384
1385impl From<&IoapicState> for kvm_ioapic_state {
1386 fn from(item: &IoapicState) -> Self {
1387 let mut state = kvm_ioapic_state {
1388 base_address: item.base_address,
1389 ioregsel: item.ioregsel as u32,
1390 id: item.ioapicid,
1391 irr: item.current_interrupt_level_bitmap,
1392 ..Default::default()
1393 };
1394 for (in_state, out_state) in item.redirect_table.iter().zip(state.redirtbl.iter_mut()) {
1395 *out_state = in_state.into();
1396 }
1397 state
1398 }
1399}
1400
1401impl From<&LapicState> for kvm_lapic_state {
1402 fn from(item: &LapicState) -> Self {
1403 let mut state = kvm_lapic_state::default();
1404 for (reg, value) in item.regs.iter().enumerate() {
1406 let reg_offset = 16 * reg;
1408 let regs_slice = &mut state.regs[reg_offset..reg_offset + 4];
1409
1410 for (i, v) in value.to_le_bytes().iter().enumerate() {
1413 regs_slice[i] = *v as i8;
1414 }
1415 }
1416 state
1417 }
1418}
1419
1420impl From<&kvm_lapic_state> for LapicState {
1421 fn from(item: &kvm_lapic_state) -> Self {
1422 let mut state = LapicState { regs: [0; 64] };
1423 for reg in 0..64 {
1425 let reg_offset = 16 * reg;
1427
1428 let reg_slice = &item.regs[reg_offset..reg_offset + 4];
1430 let mut bytes = [0u8; 4];
1431 for i in 0..4 {
1432 bytes[i] = reg_slice[i] as u8;
1433 }
1434 state.regs[reg] = u32::from_le_bytes(bytes);
1435 }
1436 state
1437 }
1438}
1439
1440impl From<&PitState> for kvm_pit_state2 {
1441 fn from(item: &PitState) -> Self {
1442 kvm_pit_state2 {
1443 channels: [
1444 kvm_pit_channel_state::from(&item.channels[0]),
1445 kvm_pit_channel_state::from(&item.channels[1]),
1446 kvm_pit_channel_state::from(&item.channels[2]),
1447 ],
1448 flags: item.flags,
1449 ..Default::default()
1450 }
1451 }
1452}
1453
1454impl From<&kvm_pit_state2> for PitState {
1455 fn from(item: &kvm_pit_state2) -> Self {
1456 PitState {
1457 channels: [
1458 PitChannelState::from(&item.channels[0]),
1459 PitChannelState::from(&item.channels[1]),
1460 PitChannelState::from(&item.channels[2]),
1461 ],
1462 flags: item.flags,
1463 }
1464 }
1465}
1466
1467impl From<&PitChannelState> for kvm_pit_channel_state {
1468 fn from(item: &PitChannelState) -> Self {
1469 kvm_pit_channel_state {
1470 count: item.count,
1471 latched_count: item.latched_count,
1472 count_latched: item.count_latched as u8,
1473 status_latched: item.status_latched as u8,
1474 status: item.status,
1475 read_state: item.read_state as u8,
1476 write_state: item.write_state as u8,
1477 write_latch: item.reload_value as u8,
1479 rw_mode: item.rw_mode as u8,
1480 mode: item.mode,
1481 bcd: item.bcd as u8,
1482 gate: item.gate as u8,
1483 count_load_time: item.count_load_time as i64,
1484 }
1485 }
1486}
1487
1488impl From<&kvm_pit_channel_state> for PitChannelState {
1489 fn from(item: &kvm_pit_channel_state) -> Self {
1490 PitChannelState {
1491 count: item.count,
1492 latched_count: item.latched_count,
1493 count_latched: item.count_latched.into(),
1494 status_latched: item.status_latched != 0,
1495 status: item.status,
1496 read_state: item.read_state.into(),
1497 write_state: item.write_state.into(),
1498 reload_value: item.write_latch as u16,
1500 rw_mode: item.rw_mode.into(),
1501 mode: item.mode,
1502 bcd: item.bcd != 0,
1503 gate: item.gate != 0,
1504 count_load_time: item.count_load_time as u64,
1505 }
1506 }
1507}
1508
1509pub(super) fn chip_to_kvm_chip(chip: IrqSourceChip) -> u32 {
1513 match chip {
1514 IrqSourceChip::PicPrimary => KVM_IRQCHIP_PIC_MASTER,
1515 IrqSourceChip::PicSecondary => KVM_IRQCHIP_PIC_SLAVE,
1516 IrqSourceChip::Ioapic => KVM_IRQCHIP_IOAPIC,
1517 _ => {
1518 error!("Invalid IrqChipSource for X86 {:?}", chip);
1519 0
1520 }
1521 }
1522}
1523
1524impl From<&kvm_regs> for Regs {
1525 fn from(r: &kvm_regs) -> Self {
1526 Regs {
1527 rax: r.rax,
1528 rbx: r.rbx,
1529 rcx: r.rcx,
1530 rdx: r.rdx,
1531 rsi: r.rsi,
1532 rdi: r.rdi,
1533 rsp: r.rsp,
1534 rbp: r.rbp,
1535 r8: r.r8,
1536 r9: r.r9,
1537 r10: r.r10,
1538 r11: r.r11,
1539 r12: r.r12,
1540 r13: r.r13,
1541 r14: r.r14,
1542 r15: r.r15,
1543 rip: r.rip,
1544 rflags: r.rflags,
1545 }
1546 }
1547}
1548
1549impl From<&Regs> for kvm_regs {
1550 fn from(r: &Regs) -> Self {
1551 kvm_regs {
1552 rax: r.rax,
1553 rbx: r.rbx,
1554 rcx: r.rcx,
1555 rdx: r.rdx,
1556 rsi: r.rsi,
1557 rdi: r.rdi,
1558 rsp: r.rsp,
1559 rbp: r.rbp,
1560 r8: r.r8,
1561 r9: r.r9,
1562 r10: r.r10,
1563 r11: r.r11,
1564 r12: r.r12,
1565 r13: r.r13,
1566 r14: r.r14,
1567 r15: r.r15,
1568 rip: r.rip,
1569 rflags: r.rflags,
1570 }
1571 }
1572}
1573
1574impl From<&VcpuEvents> for kvm_vcpu_events {
1575 fn from(ve: &VcpuEvents) -> Self {
1576 let mut kvm_ve: kvm_vcpu_events = Default::default();
1577
1578 kvm_ve.exception.injected = ve.exception.injected as u8;
1579 kvm_ve.exception.nr = ve.exception.nr;
1580 kvm_ve.exception.has_error_code = ve.exception.has_error_code as u8;
1581 if let Some(pending) = ve.exception.pending {
1582 kvm_ve.exception.pending = pending as u8;
1583 if ve.exception_payload.is_some() {
1584 kvm_ve.exception_has_payload = true as u8;
1585 }
1586 kvm_ve.exception_payload = ve.exception_payload.unwrap_or(0);
1587 kvm_ve.flags |= KVM_VCPUEVENT_VALID_PAYLOAD;
1588 }
1589 kvm_ve.exception.error_code = ve.exception.error_code;
1590
1591 kvm_ve.interrupt.injected = ve.interrupt.injected as u8;
1592 kvm_ve.interrupt.nr = ve.interrupt.nr;
1593 kvm_ve.interrupt.soft = ve.interrupt.soft as u8;
1594 if let Some(shadow) = ve.interrupt.shadow {
1595 kvm_ve.interrupt.shadow = shadow;
1596 kvm_ve.flags |= KVM_VCPUEVENT_VALID_SHADOW;
1597 }
1598
1599 kvm_ve.nmi.injected = ve.nmi.injected as u8;
1600 if let Some(pending) = ve.nmi.pending {
1601 kvm_ve.nmi.pending = pending as u8;
1602 kvm_ve.flags |= KVM_VCPUEVENT_VALID_NMI_PENDING;
1603 }
1604 kvm_ve.nmi.masked = ve.nmi.masked as u8;
1605
1606 if let Some(sipi_vector) = ve.sipi_vector {
1607 kvm_ve.sipi_vector = sipi_vector;
1608 kvm_ve.flags |= KVM_VCPUEVENT_VALID_SIPI_VECTOR;
1609 }
1610
1611 if let Some(smm) = ve.smi.smm {
1612 kvm_ve.smi.smm = smm as u8;
1613 kvm_ve.flags |= KVM_VCPUEVENT_VALID_SMM;
1614 }
1615 kvm_ve.smi.pending = ve.smi.pending as u8;
1616 kvm_ve.smi.smm_inside_nmi = ve.smi.smm_inside_nmi as u8;
1617 kvm_ve.smi.latched_init = ve.smi.latched_init;
1618
1619 if let Some(pending) = ve.triple_fault.pending {
1620 kvm_ve.triple_fault.pending = pending as u8;
1621 kvm_ve.flags |= KVM_VCPUEVENT_VALID_TRIPLE_FAULT;
1622 }
1623 kvm_ve
1624 }
1625}
1626
1627impl From<&kvm_vcpu_events> for VcpuEvents {
1628 fn from(ve: &kvm_vcpu_events) -> Self {
1629 let exception = VcpuExceptionState {
1630 injected: ve.exception.injected != 0,
1631 nr: ve.exception.nr,
1632 has_error_code: ve.exception.has_error_code != 0,
1633 pending: if ve.flags & KVM_VCPUEVENT_VALID_PAYLOAD != 0 {
1634 Some(ve.exception.pending != 0)
1635 } else {
1636 None
1637 },
1638 error_code: ve.exception.error_code,
1639 };
1640
1641 let interrupt = VcpuInterruptState {
1642 injected: ve.interrupt.injected != 0,
1643 nr: ve.interrupt.nr,
1644 soft: ve.interrupt.soft != 0,
1645 shadow: if ve.flags & KVM_VCPUEVENT_VALID_SHADOW != 0 {
1646 Some(ve.interrupt.shadow)
1647 } else {
1648 None
1649 },
1650 };
1651
1652 let nmi = VcpuNmiState {
1653 injected: ve.interrupt.injected != 0,
1654 pending: if ve.flags & KVM_VCPUEVENT_VALID_NMI_PENDING != 0 {
1655 Some(ve.nmi.pending != 0)
1656 } else {
1657 None
1658 },
1659 masked: ve.nmi.masked != 0,
1660 };
1661
1662 let sipi_vector = if ve.flags & KVM_VCPUEVENT_VALID_SIPI_VECTOR != 0 {
1663 Some(ve.sipi_vector)
1664 } else {
1665 None
1666 };
1667
1668 let smi = VcpuSmiState {
1669 smm: if ve.flags & KVM_VCPUEVENT_VALID_SMM != 0 {
1670 Some(ve.smi.smm != 0)
1671 } else {
1672 None
1673 },
1674 pending: ve.smi.pending != 0,
1675 smm_inside_nmi: ve.smi.smm_inside_nmi != 0,
1676 latched_init: ve.smi.latched_init,
1677 };
1678
1679 let triple_fault = VcpuTripleFaultState {
1680 pending: if ve.flags & KVM_VCPUEVENT_VALID_TRIPLE_FAULT != 0 {
1681 Some(ve.triple_fault.pending != 0)
1682 } else {
1683 None
1684 },
1685 };
1686
1687 let exception_payload = if ve.flags & KVM_VCPUEVENT_VALID_PAYLOAD != 0 {
1688 Some(ve.exception_payload)
1689 } else {
1690 None
1691 };
1692
1693 VcpuEvents {
1694 exception,
1695 interrupt,
1696 nmi,
1697 sipi_vector,
1698 smi,
1699 triple_fault,
1700 exception_payload,
1701 }
1702 }
1703}
1704
1705impl From<&kvm_segment> for Segment {
1706 fn from(s: &kvm_segment) -> Self {
1707 Segment {
1708 base: s.base,
1709 limit_bytes: s.limit,
1710 selector: s.selector,
1711 type_: s.type_,
1712 present: s.present,
1713 dpl: s.dpl,
1714 db: s.db,
1715 s: s.s,
1716 l: s.l,
1717 g: s.g,
1718 avl: s.avl,
1719 }
1720 }
1721}
1722
1723impl From<&Segment> for kvm_segment {
1724 fn from(s: &Segment) -> Self {
1725 kvm_segment {
1726 base: s.base,
1727 limit: s.limit_bytes,
1728 selector: s.selector,
1729 type_: s.type_,
1730 present: s.present,
1731 dpl: s.dpl,
1732 db: s.db,
1733 s: s.s,
1734 l: s.l,
1735 g: s.g,
1736 avl: s.avl,
1737 unusable: match s.present {
1738 0 => 1,
1739 _ => 0,
1740 },
1741 ..Default::default()
1742 }
1743 }
1744}
1745
1746impl From<&kvm_dtable> for DescriptorTable {
1747 fn from(dt: &kvm_dtable) -> Self {
1748 DescriptorTable {
1749 base: dt.base,
1750 limit: dt.limit,
1751 }
1752 }
1753}
1754
1755impl From<&DescriptorTable> for kvm_dtable {
1756 fn from(dt: &DescriptorTable) -> Self {
1757 kvm_dtable {
1758 base: dt.base,
1759 limit: dt.limit,
1760 ..Default::default()
1761 }
1762 }
1763}
1764
1765impl From<&kvm_sregs> for Sregs {
1766 fn from(r: &kvm_sregs) -> Self {
1767 Sregs {
1768 cs: Segment::from(&r.cs),
1769 ds: Segment::from(&r.ds),
1770 es: Segment::from(&r.es),
1771 fs: Segment::from(&r.fs),
1772 gs: Segment::from(&r.gs),
1773 ss: Segment::from(&r.ss),
1774 tr: Segment::from(&r.tr),
1775 ldt: Segment::from(&r.ldt),
1776 gdt: DescriptorTable::from(&r.gdt),
1777 idt: DescriptorTable::from(&r.idt),
1778 cr0: r.cr0,
1779 cr2: r.cr2,
1780 cr3: r.cr3,
1781 cr4: r.cr4,
1782 cr8: r.cr8,
1783 efer: r.efer,
1784 }
1785 }
1786}
1787
1788impl From<&kvm_fpu> for Fpu {
1789 fn from(r: &kvm_fpu) -> Self {
1790 Fpu {
1791 fpr: FpuReg::from_16byte_arrays(&r.fpr),
1792 fcw: r.fcw,
1793 fsw: r.fsw,
1794 ftwx: r.ftwx,
1795 last_opcode: r.last_opcode,
1796 last_ip: r.last_ip,
1797 last_dp: r.last_dp,
1798 xmm: r.xmm,
1799 mxcsr: r.mxcsr,
1800 }
1801 }
1802}
1803
1804impl From<&Fpu> for kvm_fpu {
1805 fn from(r: &Fpu) -> Self {
1806 kvm_fpu {
1807 fpr: FpuReg::to_16byte_arrays(&r.fpr),
1808 fcw: r.fcw,
1809 fsw: r.fsw,
1810 ftwx: r.ftwx,
1811 last_opcode: r.last_opcode,
1812 last_ip: r.last_ip,
1813 last_dp: r.last_dp,
1814 xmm: r.xmm,
1815 mxcsr: r.mxcsr,
1816 ..Default::default()
1817 }
1818 }
1819}
1820
1821impl From<&kvm_debugregs> for DebugRegs {
1822 fn from(r: &kvm_debugregs) -> Self {
1823 DebugRegs {
1824 db: r.db,
1825 dr6: r.dr6,
1826 dr7: r.dr7,
1827 }
1828 }
1829}
1830
1831impl From<&DebugRegs> for kvm_debugregs {
1832 fn from(r: &DebugRegs) -> Self {
1833 kvm_debugregs {
1834 db: r.db,
1835 dr6: r.dr6,
1836 dr7: r.dr7,
1837 ..Default::default()
1838 }
1839 }
1840}
1841
1842#[cfg(test)]
1843mod tests {
1844 use super::*;
1845
1846 #[test]
1847 fn vcpu_event_to_from() {
1848 let mut kvm_ve: kvm_vcpu_events = Default::default();
1850 kvm_ve.exception.injected = 1;
1851 kvm_ve.exception.nr = 65;
1852 kvm_ve.exception.has_error_code = 1;
1853 kvm_ve.exception.error_code = 110;
1854 kvm_ve.exception.pending = 1;
1855
1856 kvm_ve.interrupt.injected = 1;
1857 kvm_ve.interrupt.nr = 100;
1858 kvm_ve.interrupt.soft = 1;
1859 kvm_ve.interrupt.shadow = 114;
1860
1861 kvm_ve.nmi.injected = 1;
1862 kvm_ve.nmi.pending = 1;
1863 kvm_ve.nmi.masked = 0;
1864
1865 kvm_ve.sipi_vector = 105;
1866
1867 kvm_ve.smi.smm = 1;
1868 kvm_ve.smi.pending = 1;
1869 kvm_ve.smi.smm_inside_nmi = 1;
1870 kvm_ve.smi.latched_init = 100;
1871
1872 kvm_ve.triple_fault.pending = 0;
1873
1874 kvm_ve.exception_payload = 33;
1875 kvm_ve.exception_has_payload = 1;
1876
1877 kvm_ve.flags = 0
1878 | KVM_VCPUEVENT_VALID_PAYLOAD
1879 | KVM_VCPUEVENT_VALID_SMM
1880 | KVM_VCPUEVENT_VALID_NMI_PENDING
1881 | KVM_VCPUEVENT_VALID_SIPI_VECTOR
1882 | KVM_VCPUEVENT_VALID_SHADOW;
1883
1884 let ve: VcpuEvents = VcpuEvents::from(&kvm_ve);
1885 assert_eq!(ve.exception.injected, true);
1886 assert_eq!(ve.exception.nr, 65);
1887 assert_eq!(ve.exception.has_error_code, true);
1888 assert_eq!(ve.exception.error_code, 110);
1889 assert_eq!(ve.exception.pending.unwrap(), true);
1890
1891 assert_eq!(ve.interrupt.injected, true);
1892 assert_eq!(ve.interrupt.nr, 100);
1893 assert_eq!(ve.interrupt.soft, true);
1894 assert_eq!(ve.interrupt.shadow.unwrap(), 114);
1895
1896 assert_eq!(ve.nmi.injected, true);
1897 assert_eq!(ve.nmi.pending.unwrap(), true);
1898 assert_eq!(ve.nmi.masked, false);
1899
1900 assert_eq!(ve.sipi_vector.unwrap(), 105);
1901
1902 assert_eq!(ve.smi.smm.unwrap(), true);
1903 assert_eq!(ve.smi.pending, true);
1904 assert_eq!(ve.smi.smm_inside_nmi, true);
1905 assert_eq!(ve.smi.latched_init, 100);
1906
1907 assert_eq!(ve.triple_fault.pending, None);
1908
1909 assert_eq!(ve.exception_payload.unwrap(), 33);
1910
1911 let kvm_ve_restored: kvm_vcpu_events = kvm_vcpu_events::from(&ve);
1912 assert_eq!(kvm_ve_restored.exception.injected, 1);
1913 assert_eq!(kvm_ve_restored.exception.nr, 65);
1914 assert_eq!(kvm_ve_restored.exception.has_error_code, 1);
1915 assert_eq!(kvm_ve_restored.exception.error_code, 110);
1916 assert_eq!(kvm_ve_restored.exception.pending, 1);
1917
1918 assert_eq!(kvm_ve_restored.interrupt.injected, 1);
1919 assert_eq!(kvm_ve_restored.interrupt.nr, 100);
1920 assert_eq!(kvm_ve_restored.interrupt.soft, 1);
1921 assert_eq!(kvm_ve_restored.interrupt.shadow, 114);
1922
1923 assert_eq!(kvm_ve_restored.nmi.injected, 1);
1924 assert_eq!(kvm_ve_restored.nmi.pending, 1);
1925 assert_eq!(kvm_ve_restored.nmi.masked, 0);
1926
1927 assert_eq!(kvm_ve_restored.sipi_vector, 105);
1928
1929 assert_eq!(kvm_ve_restored.smi.smm, 1);
1930 assert_eq!(kvm_ve_restored.smi.pending, 1);
1931 assert_eq!(kvm_ve_restored.smi.smm_inside_nmi, 1);
1932 assert_eq!(kvm_ve_restored.smi.latched_init, 100);
1933
1934 assert_eq!(kvm_ve_restored.triple_fault.pending, 0);
1935
1936 assert_eq!(kvm_ve_restored.exception_payload, 33);
1937 assert_eq!(kvm_ve_restored.exception_has_payload, 1);
1938 }
1939}