xref: /aosp_15_r20/external/crosvm/hypervisor/src/kvm/mod.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2020 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
6 mod aarch64;
7 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
8 pub use aarch64::*;
9 
10 mod cap;
11 pub use cap::KvmCap;
12 
13 #[cfg(target_arch = "riscv64")]
14 mod riscv64;
15 
16 #[cfg(target_arch = "x86_64")]
17 mod x86_64;
18 
19 use std::cmp::Reverse;
20 use std::collections::BTreeMap;
21 use std::collections::BinaryHeap;
22 use std::convert::TryFrom;
23 use std::ffi::CString;
24 use std::fs::File;
25 use std::os::raw::c_ulong;
26 use std::os::raw::c_void;
27 use std::os::unix::prelude::OsStrExt;
28 use std::path::Path;
29 use std::sync::Arc;
30 
31 use base::errno_result;
32 use base::error;
33 use base::ioctl;
34 use base::ioctl_with_mut_ref;
35 use base::ioctl_with_ref;
36 use base::ioctl_with_val;
37 use base::pagesize;
38 use base::AsRawDescriptor;
39 use base::Error;
40 use base::Event;
41 use base::FromRawDescriptor;
42 use base::MappedRegion;
43 use base::MemoryMapping;
44 use base::MemoryMappingBuilder;
45 use base::MmapError;
46 use base::Protection;
47 use base::RawDescriptor;
48 use base::Result;
49 use base::SafeDescriptor;
50 use data_model::vec_with_array_field;
51 use kvm_sys::*;
52 use libc::open64;
53 use libc::EFAULT;
54 use libc::EINVAL;
55 use libc::EIO;
56 use libc::ENOENT;
57 use libc::ENOSPC;
58 use libc::ENOSYS;
59 use libc::EOVERFLOW;
60 use libc::O_CLOEXEC;
61 use libc::O_RDWR;
62 #[cfg(target_arch = "riscv64")]
63 use riscv64::*;
64 use sync::Mutex;
65 use vm_memory::GuestAddress;
66 use vm_memory::GuestMemory;
67 #[cfg(target_arch = "x86_64")]
68 pub use x86_64::*;
69 
70 use crate::BalloonEvent;
71 use crate::ClockState;
72 use crate::Config;
73 use crate::Datamatch;
74 use crate::DeviceKind;
75 use crate::Hypervisor;
76 use crate::HypervisorCap;
77 use crate::IoEventAddress;
78 use crate::IoOperation;
79 use crate::IoParams;
80 use crate::IrqRoute;
81 use crate::IrqSource;
82 use crate::MPState;
83 use crate::MemCacheType;
84 use crate::MemSlot;
85 use crate::Vcpu;
86 use crate::VcpuExit;
87 use crate::VcpuSignalHandle;
88 use crate::VcpuSignalHandleInner;
89 use crate::Vm;
90 use crate::VmCap;
91 
92 // Wrapper around KVM_SET_USER_MEMORY_REGION ioctl, which creates, modifies, or deletes a mapping
93 // from guest physical to host user pages.
94 //
95 // SAFETY:
96 // Safe when the guest regions are guaranteed not to overlap.
set_user_memory_region( descriptor: &SafeDescriptor, slot: MemSlot, read_only: bool, log_dirty_pages: bool, cache: MemCacheType, guest_addr: u64, memory_size: u64, userspace_addr: *mut u8, ) -> Result<()>97 unsafe fn set_user_memory_region(
98     descriptor: &SafeDescriptor,
99     slot: MemSlot,
100     read_only: bool,
101     log_dirty_pages: bool,
102     cache: MemCacheType,
103     guest_addr: u64,
104     memory_size: u64,
105     userspace_addr: *mut u8,
106 ) -> Result<()> {
107     let mut flags = if read_only { KVM_MEM_READONLY } else { 0 };
108     if log_dirty_pages {
109         flags |= KVM_MEM_LOG_DIRTY_PAGES;
110     }
111     if cache == MemCacheType::CacheNonCoherent {
112         flags |= KVM_MEM_NON_COHERENT_DMA;
113     }
114     let region = kvm_userspace_memory_region {
115         slot,
116         flags,
117         guest_phys_addr: guest_addr,
118         memory_size,
119         userspace_addr: userspace_addr as u64,
120     };
121 
122     let ret = ioctl_with_ref(descriptor, KVM_SET_USER_MEMORY_REGION, &region);
123     if ret == 0 {
124         Ok(())
125     } else {
126         errno_result()
127     }
128 }
129 
130 /// Helper function to determine the size in bytes of a dirty log bitmap for the given memory region
131 /// size.
132 ///
133 /// # Arguments
134 ///
135 /// * `size` - Number of bytes in the memory region being queried.
dirty_log_bitmap_size(size: usize) -> usize136 pub fn dirty_log_bitmap_size(size: usize) -> usize {
137     let page_size = pagesize();
138     (((size + page_size - 1) / page_size) + 7) / 8
139 }
140 
141 pub struct Kvm {
142     kvm: SafeDescriptor,
143     vcpu_mmap_size: usize,
144 }
145 
146 impl Kvm {
new_with_path(device_path: &Path) -> Result<Kvm>147     pub fn new_with_path(device_path: &Path) -> Result<Kvm> {
148         let c_path = CString::new(device_path.as_os_str().as_bytes()).unwrap();
149         // SAFETY:
150         // Open calls are safe because we give a nul-terminated string and verify the result.
151         let ret = unsafe { open64(c_path.as_ptr(), O_RDWR | O_CLOEXEC) };
152         if ret < 0 {
153             return errno_result();
154         }
155         // SAFETY:
156         // Safe because we verify that ret is valid and we own the fd.
157         let kvm = unsafe { SafeDescriptor::from_raw_descriptor(ret) };
158 
159         // SAFETY:
160         // Safe because we know that the descriptor is valid and we verify the return result.
161         let version = unsafe { ioctl(&kvm, KVM_GET_API_VERSION) };
162         if version < 0 {
163             return errno_result();
164         }
165 
166         // Per the kernel KVM API documentation: "Applications should refuse to run if
167         // KVM_GET_API_VERSION returns a value other than 12."
168         if version as u32 != KVM_API_VERSION {
169             error!(
170                 "KVM_GET_API_VERSION: expected {}, got {}",
171                 KVM_API_VERSION, version,
172             );
173             return Err(Error::new(ENOSYS));
174         }
175 
176         // SAFETY:
177         // Safe because we know that our file is a KVM fd and we verify the return result.
178         let res = unsafe { ioctl(&kvm, KVM_GET_VCPU_MMAP_SIZE) };
179         if res <= 0 {
180             return errno_result();
181         }
182         let vcpu_mmap_size = res as usize;
183 
184         Ok(Kvm {
185             kvm,
186             vcpu_mmap_size,
187         })
188     }
189 
190     /// Opens `/dev/kvm` and returns a Kvm object on success.
new() -> Result<Kvm>191     pub fn new() -> Result<Kvm> {
192         Kvm::new_with_path(Path::new("/dev/kvm"))
193     }
194 }
195 
196 impl AsRawDescriptor for Kvm {
as_raw_descriptor(&self) -> RawDescriptor197     fn as_raw_descriptor(&self) -> RawDescriptor {
198         self.kvm.as_raw_descriptor()
199     }
200 }
201 
202 impl Hypervisor for Kvm {
try_clone(&self) -> Result<Self>203     fn try_clone(&self) -> Result<Self> {
204         Ok(Kvm {
205             kvm: self.kvm.try_clone()?,
206             vcpu_mmap_size: self.vcpu_mmap_size,
207         })
208     }
209 
check_capability(&self, cap: HypervisorCap) -> bool210     fn check_capability(&self, cap: HypervisorCap) -> bool {
211         if let Ok(kvm_cap) = KvmCap::try_from(cap) {
212             // SAFETY:
213             // this ioctl is safe because we know this kvm descriptor is valid,
214             // and we are copying over the kvm capability (u32) as a c_ulong value.
215             unsafe { ioctl_with_val(self, KVM_CHECK_EXTENSION, kvm_cap as c_ulong) == 1 }
216         } else {
217             // this capability cannot be converted on this platform, so return false
218             false
219         }
220     }
221 }
222 
223 /// A wrapper around creating and using a KVM VM.
224 pub struct KvmVm {
225     kvm: Kvm,
226     vm: SafeDescriptor,
227     guest_mem: GuestMemory,
228     mem_regions: Arc<Mutex<BTreeMap<MemSlot, Box<dyn MappedRegion>>>>,
229     /// A min heap of MemSlot numbers that were used and then removed and can now be re-used
230     mem_slot_gaps: Arc<Mutex<BinaryHeap<Reverse<MemSlot>>>>,
231     cap_kvmclock_ctrl: bool,
232 }
233 
234 impl KvmVm {
235     /// Constructs a new `KvmVm` using the given `Kvm` instance.
new(kvm: &Kvm, guest_mem: GuestMemory, cfg: Config) -> Result<KvmVm>236     pub fn new(kvm: &Kvm, guest_mem: GuestMemory, cfg: Config) -> Result<KvmVm> {
237         // SAFETY:
238         // Safe because we know kvm is a real kvm fd as this module is the only one that can make
239         // Kvm objects.
240         let ret = unsafe {
241             ioctl_with_val(
242                 kvm,
243                 KVM_CREATE_VM,
244                 kvm.get_vm_type(cfg.protection_type)? as c_ulong,
245             )
246         };
247         if ret < 0 {
248             return errno_result();
249         }
250         // SAFETY:
251         // Safe because we verify that ret is valid and we own the fd.
252         let vm_descriptor = unsafe { SafeDescriptor::from_raw_descriptor(ret) };
253         for region in guest_mem.regions() {
254             // SAFETY:
255             // Safe because the guest regions are guaranteed not to overlap.
256             unsafe {
257                 set_user_memory_region(
258                     &vm_descriptor,
259                     region.index as MemSlot,
260                     false,
261                     false,
262                     MemCacheType::CacheCoherent,
263                     region.guest_addr.offset(),
264                     region.size as u64,
265                     region.host_addr as *mut u8,
266                 )
267             }?;
268         }
269 
270         let mut vm = KvmVm {
271             kvm: kvm.try_clone()?,
272             vm: vm_descriptor,
273             guest_mem,
274             mem_regions: Arc::new(Mutex::new(BTreeMap::new())),
275             mem_slot_gaps: Arc::new(Mutex::new(BinaryHeap::new())),
276             cap_kvmclock_ctrl: false,
277         };
278         vm.cap_kvmclock_ctrl = vm.check_raw_capability(KvmCap::KvmclockCtrl);
279         vm.init_arch(&cfg)?;
280         Ok(vm)
281     }
282 
create_kvm_vcpu(&self, id: usize) -> Result<KvmVcpu>283     pub fn create_kvm_vcpu(&self, id: usize) -> Result<KvmVcpu> {
284         // SAFETY:
285         // Safe because we know that our file is a VM fd and we verify the return result.
286         let fd = unsafe { ioctl_with_val(self, KVM_CREATE_VCPU, c_ulong::try_from(id).unwrap()) };
287         if fd < 0 {
288             return errno_result();
289         }
290 
291         // SAFETY:
292         // Wrap the vcpu now in case the following ? returns early. This is safe because we verified
293         // the value of the fd and we own the fd.
294         let vcpu = unsafe { File::from_raw_descriptor(fd) };
295 
296         // The VCPU mapping is held by an `Arc` inside `KvmVcpu`, and it can also be cloned by
297         // `signal_handle()` for use in `KvmVcpuSignalHandle`. The mapping will not be destroyed
298         // until all references are dropped, so it is safe to reference `kvm_run` fields via the
299         // `as_ptr()` function during either type's lifetime.
300         let run_mmap = MemoryMappingBuilder::new(self.kvm.vcpu_mmap_size)
301             .from_file(&vcpu)
302             .build()
303             .map_err(|_| Error::new(ENOSPC))?;
304 
305         Ok(KvmVcpu {
306             kvm: self.kvm.try_clone()?,
307             vm: self.vm.try_clone()?,
308             vcpu,
309             id,
310             cap_kvmclock_ctrl: self.cap_kvmclock_ctrl,
311             run_mmap: Arc::new(run_mmap),
312         })
313     }
314 
315     /// Creates an in kernel interrupt controller.
316     ///
317     /// See the documentation on the KVM_CREATE_IRQCHIP ioctl.
create_irq_chip(&self) -> Result<()>318     pub fn create_irq_chip(&self) -> Result<()> {
319         // SAFETY:
320         // Safe because we know that our file is a VM fd and we verify the return result.
321         let ret = unsafe { ioctl(self, KVM_CREATE_IRQCHIP) };
322         if ret == 0 {
323             Ok(())
324         } else {
325             errno_result()
326         }
327     }
328 
329     /// Sets the level on the given irq to 1 if `active` is true, and 0 otherwise.
set_irq_line(&self, irq: u32, active: bool) -> Result<()>330     pub fn set_irq_line(&self, irq: u32, active: bool) -> Result<()> {
331         let mut irq_level = kvm_irq_level::default();
332         irq_level.__bindgen_anon_1.irq = irq;
333         irq_level.level = active.into();
334 
335         // SAFETY:
336         // Safe because we know that our file is a VM fd, we know the kernel will only read the
337         // correct amount of memory from our pointer, and we verify the return result.
338         let ret = unsafe { ioctl_with_ref(self, KVM_IRQ_LINE, &irq_level) };
339         if ret == 0 {
340             Ok(())
341         } else {
342             errno_result()
343         }
344     }
345 
346     /// Registers an event that will, when signalled, trigger the `gsi` irq, and `resample_evt`
347     /// ( when not None ) will be triggered when the irqchip is resampled.
register_irqfd( &self, gsi: u32, evt: &Event, resample_evt: Option<&Event>, ) -> Result<()>348     pub fn register_irqfd(
349         &self,
350         gsi: u32,
351         evt: &Event,
352         resample_evt: Option<&Event>,
353     ) -> Result<()> {
354         let mut irqfd = kvm_irqfd {
355             fd: evt.as_raw_descriptor() as u32,
356             gsi,
357             ..Default::default()
358         };
359 
360         if let Some(r_evt) = resample_evt {
361             irqfd.flags = KVM_IRQFD_FLAG_RESAMPLE;
362             irqfd.resamplefd = r_evt.as_raw_descriptor() as u32;
363         }
364 
365         // SAFETY:
366         // Safe because we know that our file is a VM fd, we know the kernel will only read the
367         // correct amount of memory from our pointer, and we verify the return result.
368         let ret = unsafe { ioctl_with_ref(self, KVM_IRQFD, &irqfd) };
369         if ret == 0 {
370             Ok(())
371         } else {
372             errno_result()
373         }
374     }
375 
376     /// Unregisters an event that was previously registered with
377     /// `register_irqfd`.
378     ///
379     /// The `evt` and `gsi` pair must be the same as the ones passed into
380     /// `register_irqfd`.
unregister_irqfd(&self, gsi: u32, evt: &Event) -> Result<()>381     pub fn unregister_irqfd(&self, gsi: u32, evt: &Event) -> Result<()> {
382         let irqfd = kvm_irqfd {
383             fd: evt.as_raw_descriptor() as u32,
384             gsi,
385             flags: KVM_IRQFD_FLAG_DEASSIGN,
386             ..Default::default()
387         };
388         // SAFETY:
389         // Safe because we know that our file is a VM fd, we know the kernel will only read the
390         // correct amount of memory from our pointer, and we verify the return result.
391         let ret = unsafe { ioctl_with_ref(self, KVM_IRQFD, &irqfd) };
392         if ret == 0 {
393             Ok(())
394         } else {
395             errno_result()
396         }
397     }
398 
399     /// Sets the GSI routing table, replacing any table set with previous calls to
400     /// `set_gsi_routing`.
set_gsi_routing(&self, routes: &[IrqRoute]) -> Result<()>401     pub fn set_gsi_routing(&self, routes: &[IrqRoute]) -> Result<()> {
402         let mut irq_routing =
403             vec_with_array_field::<kvm_irq_routing, kvm_irq_routing_entry>(routes.len());
404         irq_routing[0].nr = routes.len() as u32;
405 
406         // SAFETY:
407         // Safe because we ensured there is enough space in irq_routing to hold the number of
408         // route entries.
409         let irq_routes = unsafe { irq_routing[0].entries.as_mut_slice(routes.len()) };
410         for (route, irq_route) in routes.iter().zip(irq_routes.iter_mut()) {
411             *irq_route = kvm_irq_routing_entry::from(route);
412         }
413 
414         // TODO(b/315998194): Add safety comment
415         #[allow(clippy::undocumented_unsafe_blocks)]
416         let ret = unsafe { ioctl_with_ref(self, KVM_SET_GSI_ROUTING, &irq_routing[0]) };
417         if ret == 0 {
418             Ok(())
419         } else {
420             errno_result()
421         }
422     }
423 
ioeventfd( &self, evt: &Event, addr: IoEventAddress, datamatch: Datamatch, deassign: bool, ) -> Result<()>424     fn ioeventfd(
425         &self,
426         evt: &Event,
427         addr: IoEventAddress,
428         datamatch: Datamatch,
429         deassign: bool,
430     ) -> Result<()> {
431         let (do_datamatch, datamatch_value, datamatch_len) = match datamatch {
432             Datamatch::AnyLength => (false, 0, 0),
433             Datamatch::U8(v) => match v {
434                 Some(u) => (true, u as u64, 1),
435                 None => (false, 0, 1),
436             },
437             Datamatch::U16(v) => match v {
438                 Some(u) => (true, u as u64, 2),
439                 None => (false, 0, 2),
440             },
441             Datamatch::U32(v) => match v {
442                 Some(u) => (true, u as u64, 4),
443                 None => (false, 0, 4),
444             },
445             Datamatch::U64(v) => match v {
446                 Some(u) => (true, u, 8),
447                 None => (false, 0, 8),
448             },
449         };
450         let mut flags = 0;
451         if deassign {
452             flags |= 1 << kvm_ioeventfd_flag_nr_deassign;
453         }
454         if do_datamatch {
455             flags |= 1 << kvm_ioeventfd_flag_nr_datamatch
456         }
457         if let IoEventAddress::Pio(_) = addr {
458             flags |= 1 << kvm_ioeventfd_flag_nr_pio;
459         }
460         let ioeventfd = kvm_ioeventfd {
461             datamatch: datamatch_value,
462             len: datamatch_len,
463             addr: match addr {
464                 IoEventAddress::Pio(p) => p,
465                 IoEventAddress::Mmio(m) => m,
466             },
467             fd: evt.as_raw_descriptor(),
468             flags,
469             ..Default::default()
470         };
471         // SAFETY:
472         // Safe because we know that our file is a VM fd, we know the kernel will only read the
473         // correct amount of memory from our pointer, and we verify the return result.
474         let ret = unsafe { ioctl_with_ref(self, KVM_IOEVENTFD, &ioeventfd) };
475         if ret == 0 {
476             Ok(())
477         } else {
478             errno_result()
479         }
480     }
481 
482     /// Checks whether a particular KVM-specific capability is available for this VM.
check_raw_capability(&self, capability: KvmCap) -> bool483     pub fn check_raw_capability(&self, capability: KvmCap) -> bool {
484         // SAFETY:
485         // Safe because we know that our file is a KVM fd, and if the cap is invalid KVM assumes
486         // it's an unavailable extension and returns 0.
487         let ret = unsafe { ioctl_with_val(self, KVM_CHECK_EXTENSION, capability as c_ulong) };
488         match capability {
489             #[cfg(target_arch = "x86_64")]
490             KvmCap::BusLockDetect => {
491                 if ret > 0 {
492                     ret as u32 & KVM_BUS_LOCK_DETECTION_EXIT == KVM_BUS_LOCK_DETECTION_EXIT
493                 } else {
494                     false
495                 }
496             }
497             _ => ret == 1,
498         }
499     }
500 
501     // Currently only used on aarch64, but works on any architecture.
502     #[allow(dead_code)]
503     /// Enables a KVM-specific capability for this VM, with the given arguments.
504     ///
505     /// # Safety
506     /// This function is marked as unsafe because `args` may be interpreted as pointers for some
507     /// capabilities. The caller must ensure that any pointers passed in the `args` array are
508     /// allocated as the kernel expects, and that mutable pointers are owned.
enable_raw_capability( &self, capability: KvmCap, flags: u32, args: &[u64; 4], ) -> Result<()>509     unsafe fn enable_raw_capability(
510         &self,
511         capability: KvmCap,
512         flags: u32,
513         args: &[u64; 4],
514     ) -> Result<()> {
515         let kvm_cap = kvm_enable_cap {
516             cap: capability as u32,
517             args: *args,
518             flags,
519             ..Default::default()
520         };
521         // SAFETY:
522         // Safe because we allocated the struct and we know the kernel will read exactly the size of
523         // the struct, and because we assume the caller has allocated the args appropriately.
524         let ret = ioctl_with_ref(self, KVM_ENABLE_CAP, &kvm_cap);
525         if ret == 0 {
526             Ok(())
527         } else {
528             errno_result()
529         }
530     }
531 
handle_inflate(&mut self, guest_address: GuestAddress, size: u64) -> Result<()>532     fn handle_inflate(&mut self, guest_address: GuestAddress, size: u64) -> Result<()> {
533         match self.guest_mem.remove_range(guest_address, size) {
534             Ok(_) => Ok(()),
535             Err(vm_memory::Error::MemoryAccess(_, MmapError::SystemCallFailed(e))) => Err(e),
536             Err(_) => Err(Error::new(EIO)),
537         }
538     }
539 
handle_deflate(&mut self, _guest_address: GuestAddress, _size: u64) -> Result<()>540     fn handle_deflate(&mut self, _guest_address: GuestAddress, _size: u64) -> Result<()> {
541         // No-op, when the guest attempts to access the pages again, Linux/KVM will provide them.
542         Ok(())
543     }
544 }
545 
546 impl Vm for KvmVm {
try_clone(&self) -> Result<Self>547     fn try_clone(&self) -> Result<Self> {
548         Ok(KvmVm {
549             kvm: self.kvm.try_clone()?,
550             vm: self.vm.try_clone()?,
551             guest_mem: self.guest_mem.clone(),
552             mem_regions: self.mem_regions.clone(),
553             mem_slot_gaps: self.mem_slot_gaps.clone(),
554             cap_kvmclock_ctrl: self.cap_kvmclock_ctrl,
555         })
556     }
557 
check_capability(&self, c: VmCap) -> bool558     fn check_capability(&self, c: VmCap) -> bool {
559         if let Some(val) = self.check_capability_arch(c) {
560             return val;
561         }
562         match c {
563             VmCap::DirtyLog => true,
564             VmCap::PvClock => false,
565             VmCap::Protected => self.check_raw_capability(KvmCap::ArmProtectedVm),
566             VmCap::EarlyInitCpuid => false,
567             #[cfg(target_arch = "x86_64")]
568             VmCap::BusLockDetect => self.check_raw_capability(KvmCap::BusLockDetect),
569             // When pKVM is the hypervisor, read-only memslots aren't supported, even for
570             // non-protected VMs.
571             VmCap::ReadOnlyMemoryRegion => !self.is_pkvm(),
572             VmCap::MemNoncoherentDma => {
573                 cfg!(feature = "noncoherent-dma")
574                     && self.check_raw_capability(KvmCap::MemNoncoherentDma)
575             }
576         }
577     }
578 
enable_capability(&self, c: VmCap, _flags: u32) -> Result<bool>579     fn enable_capability(&self, c: VmCap, _flags: u32) -> Result<bool> {
580         match c {
581             #[cfg(target_arch = "x86_64")]
582             VmCap::BusLockDetect => {
583                 let args = [KVM_BUS_LOCK_DETECTION_EXIT as u64, 0, 0, 0];
584                 Ok(
585                     // TODO(b/315998194): Add safety comment
586                     #[allow(clippy::undocumented_unsafe_blocks)]
587                     unsafe {
588                         self.enable_raw_capability(KvmCap::BusLockDetect, _flags, &args) == Ok(())
589                     },
590                 )
591             }
592             _ => Ok(false),
593         }
594     }
595 
get_guest_phys_addr_bits(&self) -> u8596     fn get_guest_phys_addr_bits(&self) -> u8 {
597         self.kvm.get_guest_phys_addr_bits()
598     }
599 
get_memory(&self) -> &GuestMemory600     fn get_memory(&self) -> &GuestMemory {
601         &self.guest_mem
602     }
603 
add_memory_region( &mut self, guest_addr: GuestAddress, mem: Box<dyn MappedRegion>, read_only: bool, log_dirty_pages: bool, cache: MemCacheType, ) -> Result<MemSlot>604     fn add_memory_region(
605         &mut self,
606         guest_addr: GuestAddress,
607         mem: Box<dyn MappedRegion>,
608         read_only: bool,
609         log_dirty_pages: bool,
610         cache: MemCacheType,
611     ) -> Result<MemSlot> {
612         let pgsz = pagesize() as u64;
613         // KVM require to set the user memory region with page size aligned size. Safe to extend
614         // the mem.size() to be page size aligned because the mmap will round up the size to be
615         // page size aligned if it is not.
616         let size = (mem.size() as u64 + pgsz - 1) / pgsz * pgsz;
617         let end_addr = guest_addr
618             .checked_add(size)
619             .ok_or_else(|| Error::new(EOVERFLOW))?;
620         if self.guest_mem.range_overlap(guest_addr, end_addr) {
621             return Err(Error::new(ENOSPC));
622         }
623         let mut regions = self.mem_regions.lock();
624         let mut gaps = self.mem_slot_gaps.lock();
625         let slot = match gaps.pop() {
626             Some(gap) => gap.0,
627             None => (regions.len() + self.guest_mem.num_regions() as usize) as MemSlot,
628         };
629 
630         let cache_type = if self.check_capability(VmCap::MemNoncoherentDma) {
631             cache
632         } else {
633             MemCacheType::CacheCoherent
634         };
635 
636         // SAFETY:
637         // Safe because we check that the given guest address is valid and has no overlaps. We also
638         // know that the pointer and size are correct because the MemoryMapping interface ensures
639         // this. We take ownership of the memory mapping so that it won't be unmapped until the slot
640         // is removed.
641         let res = unsafe {
642             set_user_memory_region(
643                 &self.vm,
644                 slot,
645                 read_only,
646                 log_dirty_pages,
647                 cache_type,
648                 guest_addr.offset(),
649                 size,
650                 mem.as_ptr(),
651             )
652         };
653 
654         if let Err(e) = res {
655             gaps.push(Reverse(slot));
656             return Err(e);
657         }
658         regions.insert(slot, mem);
659         Ok(slot)
660     }
661 
msync_memory_region(&mut self, slot: MemSlot, offset: usize, size: usize) -> Result<()>662     fn msync_memory_region(&mut self, slot: MemSlot, offset: usize, size: usize) -> Result<()> {
663         let mut regions = self.mem_regions.lock();
664         let mem = regions.get_mut(&slot).ok_or_else(|| Error::new(ENOENT))?;
665 
666         mem.msync(offset, size).map_err(|err| match err {
667             MmapError::InvalidAddress => Error::new(EFAULT),
668             MmapError::NotPageAligned => Error::new(EINVAL),
669             MmapError::SystemCallFailed(e) => e,
670             _ => Error::new(EIO),
671         })
672     }
673 
madvise_pageout_memory_region( &mut self, slot: MemSlot, offset: usize, size: usize, ) -> Result<()>674     fn madvise_pageout_memory_region(
675         &mut self,
676         slot: MemSlot,
677         offset: usize,
678         size: usize,
679     ) -> Result<()> {
680         let mut regions = self.mem_regions.lock();
681         let mem = regions.get_mut(&slot).ok_or_else(|| Error::new(ENOENT))?;
682 
683         mem.madvise(offset, size, libc::MADV_PAGEOUT)
684             .map_err(|err| match err {
685                 MmapError::InvalidAddress => Error::new(EFAULT),
686                 MmapError::NotPageAligned => Error::new(EINVAL),
687                 MmapError::SystemCallFailed(e) => e,
688                 _ => Error::new(EIO),
689             })
690     }
691 
madvise_remove_memory_region( &mut self, slot: MemSlot, offset: usize, size: usize, ) -> Result<()>692     fn madvise_remove_memory_region(
693         &mut self,
694         slot: MemSlot,
695         offset: usize,
696         size: usize,
697     ) -> Result<()> {
698         let mut regions = self.mem_regions.lock();
699         let mem = regions.get_mut(&slot).ok_or_else(|| Error::new(ENOENT))?;
700 
701         mem.madvise(offset, size, libc::MADV_REMOVE)
702             .map_err(|err| match err {
703                 MmapError::InvalidAddress => Error::new(EFAULT),
704                 MmapError::NotPageAligned => Error::new(EINVAL),
705                 MmapError::SystemCallFailed(e) => e,
706                 _ => Error::new(EIO),
707             })
708     }
709 
remove_memory_region(&mut self, slot: MemSlot) -> Result<Box<dyn MappedRegion>>710     fn remove_memory_region(&mut self, slot: MemSlot) -> Result<Box<dyn MappedRegion>> {
711         let mut regions = self.mem_regions.lock();
712         if !regions.contains_key(&slot) {
713             return Err(Error::new(ENOENT));
714         }
715         // SAFETY:
716         // Safe because the slot is checked against the list of memory slots.
717         unsafe {
718             set_user_memory_region(
719                 &self.vm,
720                 slot,
721                 false,
722                 false,
723                 MemCacheType::CacheCoherent,
724                 0,
725                 0,
726                 std::ptr::null_mut(),
727             )?;
728         }
729         self.mem_slot_gaps.lock().push(Reverse(slot));
730         // This remove will always succeed because of the contains_key check above.
731         Ok(regions.remove(&slot).unwrap())
732     }
733 
create_device(&self, kind: DeviceKind) -> Result<SafeDescriptor>734     fn create_device(&self, kind: DeviceKind) -> Result<SafeDescriptor> {
735         let mut device = if let Some(dev) = self.get_device_params_arch(kind) {
736             dev
737         } else {
738             match kind {
739                 DeviceKind::Vfio => kvm_create_device {
740                     type_: kvm_device_type_KVM_DEV_TYPE_VFIO,
741                     fd: 0,
742                     flags: 0,
743                 },
744 
745                 // ARM and risc-v have additional DeviceKinds, so it needs the catch-all pattern
746                 #[cfg(any(target_arch = "arm", target_arch = "aarch64", target_arch = "riscv64"))]
747                 _ => return Err(Error::new(libc::ENXIO)),
748             }
749         };
750 
751         // SAFETY:
752         // Safe because we know that our file is a VM fd, we know the kernel will only write correct
753         // amount of memory to our pointer, and we verify the return result.
754         let ret = unsafe { base::ioctl_with_mut_ref(self, KVM_CREATE_DEVICE, &mut device) };
755         if ret == 0 {
756             Ok(
757                 // SAFETY:
758                 // Safe because we verify that ret is valid and we own the fd.
759                 unsafe { SafeDescriptor::from_raw_descriptor(device.fd as i32) },
760             )
761         } else {
762             errno_result()
763         }
764     }
765 
get_dirty_log(&self, slot: MemSlot, dirty_log: &mut [u8]) -> Result<()>766     fn get_dirty_log(&self, slot: MemSlot, dirty_log: &mut [u8]) -> Result<()> {
767         let regions = self.mem_regions.lock();
768         let mmap = regions.get(&slot).ok_or_else(|| Error::new(ENOENT))?;
769         // Ensures that there are as many bytes in dirty_log as there are pages in the mmap.
770         if dirty_log_bitmap_size(mmap.size()) > dirty_log.len() {
771             return Err(Error::new(EINVAL));
772         }
773 
774         let mut dirty_log_kvm = kvm_dirty_log {
775             slot,
776             ..Default::default()
777         };
778         dirty_log_kvm.__bindgen_anon_1.dirty_bitmap = dirty_log.as_ptr() as *mut c_void;
779         // SAFETY:
780         // Safe because the `dirty_bitmap` pointer assigned above is guaranteed to be valid (because
781         // it's from a slice) and we checked that it will be large enough to hold the entire log.
782         let ret = unsafe { ioctl_with_ref(self, KVM_GET_DIRTY_LOG, &dirty_log_kvm) };
783         if ret == 0 {
784             Ok(())
785         } else {
786             errno_result()
787         }
788     }
789 
register_ioevent( &mut self, evt: &Event, addr: IoEventAddress, datamatch: Datamatch, ) -> Result<()>790     fn register_ioevent(
791         &mut self,
792         evt: &Event,
793         addr: IoEventAddress,
794         datamatch: Datamatch,
795     ) -> Result<()> {
796         self.ioeventfd(evt, addr, datamatch, false)
797     }
798 
unregister_ioevent( &mut self, evt: &Event, addr: IoEventAddress, datamatch: Datamatch, ) -> Result<()>799     fn unregister_ioevent(
800         &mut self,
801         evt: &Event,
802         addr: IoEventAddress,
803         datamatch: Datamatch,
804     ) -> Result<()> {
805         self.ioeventfd(evt, addr, datamatch, true)
806     }
807 
handle_io_events(&self, _addr: IoEventAddress, _data: &[u8]) -> Result<()>808     fn handle_io_events(&self, _addr: IoEventAddress, _data: &[u8]) -> Result<()> {
809         // KVM delivers IO events in-kernel with ioeventfds, so this is a no-op
810         Ok(())
811     }
812 
get_pvclock(&self) -> Result<ClockState>813     fn get_pvclock(&self) -> Result<ClockState> {
814         self.get_pvclock_arch()
815     }
816 
set_pvclock(&self, state: &ClockState) -> Result<()>817     fn set_pvclock(&self, state: &ClockState) -> Result<()> {
818         self.set_pvclock_arch(state)
819     }
820 
add_fd_mapping( &mut self, slot: u32, offset: usize, size: usize, fd: &dyn AsRawDescriptor, fd_offset: u64, prot: Protection, ) -> Result<()>821     fn add_fd_mapping(
822         &mut self,
823         slot: u32,
824         offset: usize,
825         size: usize,
826         fd: &dyn AsRawDescriptor,
827         fd_offset: u64,
828         prot: Protection,
829     ) -> Result<()> {
830         let mut regions = self.mem_regions.lock();
831         let region = regions.get_mut(&slot).ok_or_else(|| Error::new(EINVAL))?;
832 
833         match region.add_fd_mapping(offset, size, fd, fd_offset, prot) {
834             Ok(()) => Ok(()),
835             Err(MmapError::SystemCallFailed(e)) => Err(e),
836             Err(_) => Err(Error::new(EIO)),
837         }
838     }
839 
remove_mapping(&mut self, slot: u32, offset: usize, size: usize) -> Result<()>840     fn remove_mapping(&mut self, slot: u32, offset: usize, size: usize) -> Result<()> {
841         let mut regions = self.mem_regions.lock();
842         let region = regions.get_mut(&slot).ok_or_else(|| Error::new(EINVAL))?;
843 
844         match region.remove_mapping(offset, size) {
845             Ok(()) => Ok(()),
846             Err(MmapError::SystemCallFailed(e)) => Err(e),
847             Err(_) => Err(Error::new(EIO)),
848         }
849     }
850 
handle_balloon_event(&mut self, event: BalloonEvent) -> Result<()>851     fn handle_balloon_event(&mut self, event: BalloonEvent) -> Result<()> {
852         match event {
853             BalloonEvent::Inflate(m) => self.handle_inflate(m.guest_address, m.size),
854             BalloonEvent::Deflate(m) => self.handle_deflate(m.guest_address, m.size),
855             BalloonEvent::BalloonTargetReached(_) => Ok(()),
856         }
857     }
858 }
859 
860 impl AsRawDescriptor for KvmVm {
as_raw_descriptor(&self) -> RawDescriptor861     fn as_raw_descriptor(&self) -> RawDescriptor {
862         self.vm.as_raw_descriptor()
863     }
864 }
865 
866 struct KvmVcpuSignalHandle {
867     run_mmap: Arc<MemoryMapping>,
868 }
869 
870 impl VcpuSignalHandleInner for KvmVcpuSignalHandle {
signal_immediate_exit(&self)871     fn signal_immediate_exit(&self) {
872         // SAFETY: we ensure `run_mmap` is a valid mapping of `kvm_run` at creation time, and the
873         // `Arc` ensures the mapping still exists while we hold a reference to it.
874         unsafe {
875             let run = self.run_mmap.as_ptr() as *mut kvm_run;
876             (*run).immediate_exit = 1;
877         }
878     }
879 }
880 
881 /// A wrapper around using a KVM Vcpu.
882 pub struct KvmVcpu {
883     kvm: Kvm,
884     vm: SafeDescriptor,
885     vcpu: File,
886     id: usize,
887     cap_kvmclock_ctrl: bool,
888     run_mmap: Arc<MemoryMapping>,
889 }
890 
891 impl Vcpu for KvmVcpu {
try_clone(&self) -> Result<Self>892     fn try_clone(&self) -> Result<Self> {
893         let vm = self.vm.try_clone()?;
894         let vcpu = self.vcpu.try_clone()?;
895 
896         Ok(KvmVcpu {
897             kvm: self.kvm.try_clone()?,
898             vm,
899             vcpu,
900             cap_kvmclock_ctrl: self.cap_kvmclock_ctrl,
901             id: self.id,
902             run_mmap: self.run_mmap.clone(),
903         })
904     }
905 
as_vcpu(&self) -> &dyn Vcpu906     fn as_vcpu(&self) -> &dyn Vcpu {
907         self
908     }
909 
id(&self) -> usize910     fn id(&self) -> usize {
911         self.id
912     }
913 
914     #[allow(clippy::cast_ptr_alignment)]
set_immediate_exit(&self, exit: bool)915     fn set_immediate_exit(&self, exit: bool) {
916         // SAFETY:
917         // Safe because we know we mapped enough memory to hold the kvm_run struct because the
918         // kernel told us how large it was. The pointer is page aligned so casting to a different
919         // type is well defined, hence the clippy allow attribute.
920         let run = unsafe { &mut *(self.run_mmap.as_ptr() as *mut kvm_run) };
921         run.immediate_exit = exit.into();
922     }
923 
signal_handle(&self) -> VcpuSignalHandle924     fn signal_handle(&self) -> VcpuSignalHandle {
925         VcpuSignalHandle {
926             inner: Box::new(KvmVcpuSignalHandle {
927                 run_mmap: self.run_mmap.clone(),
928             }),
929         }
930     }
931 
on_suspend(&self) -> Result<()>932     fn on_suspend(&self) -> Result<()> {
933         // On KVM implementations that use a paravirtualized clock (e.g. x86), a flag must be set to
934         // indicate to the guest kernel that a vCPU was suspended. The guest kernel will use this
935         // flag to prevent the soft lockup detection from triggering when this vCPU resumes, which
936         // could happen days later in realtime.
937         if self.cap_kvmclock_ctrl {
938             // SAFETY:
939             // The ioctl is safe because it does not read or write memory in this process.
940             if unsafe { ioctl(self, KVM_KVMCLOCK_CTRL) } != 0 {
941                 // Even if the host kernel supports the capability, it may not be configured by
942                 // the guest - for example, when the guest kernel offlines a CPU.
943                 if Error::last().errno() != libc::EINVAL {
944                     return errno_result();
945                 }
946             }
947         }
948 
949         Ok(())
950     }
951 
enable_raw_capability(&self, cap: u32, args: &[u64; 4]) -> Result<()>952     unsafe fn enable_raw_capability(&self, cap: u32, args: &[u64; 4]) -> Result<()> {
953         let kvm_cap = kvm_enable_cap {
954             cap,
955             args: *args,
956             ..Default::default()
957         };
958         // SAFETY:
959         // Safe because we allocated the struct and we know the kernel will read exactly the size of
960         // the struct, and because we assume the caller has allocated the args appropriately.
961         let ret = ioctl_with_ref(self, KVM_ENABLE_CAP, &kvm_cap);
962         if ret == 0 {
963             Ok(())
964         } else {
965             errno_result()
966         }
967     }
968 
969     #[allow(clippy::cast_ptr_alignment)]
970     // The pointer is page aligned so casting to a different type is well defined, hence the clippy
971     // allow attribute.
run(&mut self) -> Result<VcpuExit>972     fn run(&mut self) -> Result<VcpuExit> {
973         // SAFETY:
974         // Safe because we know that our file is a VCPU fd and we verify the return result.
975         let ret = unsafe { ioctl(self, KVM_RUN) };
976         if ret != 0 {
977             return errno_result();
978         }
979 
980         // SAFETY:
981         // Safe because we know we mapped enough memory to hold the kvm_run struct because the
982         // kernel told us how large it was.
983         let run = unsafe { &mut *(self.run_mmap.as_ptr() as *mut kvm_run) };
984 
985         // Check for architecture-specific VM exit reasons first in case the architecture wants to
986         // override the default handling.
987         if let Some(vcpu_exit) = self.handle_vm_exit_arch(run) {
988             return Ok(vcpu_exit);
989         }
990 
991         match run.exit_reason {
992             KVM_EXIT_MMIO => Ok(VcpuExit::Mmio),
993             KVM_EXIT_EXCEPTION => Ok(VcpuExit::Exception),
994             KVM_EXIT_HYPERCALL => Ok(VcpuExit::Hypercall),
995             KVM_EXIT_DEBUG => Ok(VcpuExit::Debug),
996             KVM_EXIT_IRQ_WINDOW_OPEN => Ok(VcpuExit::IrqWindowOpen),
997             KVM_EXIT_SHUTDOWN => Ok(VcpuExit::Shutdown(Ok(()))),
998             KVM_EXIT_FAIL_ENTRY => {
999                 // SAFETY:
1000                 // Safe because the exit_reason (which comes from the kernel) told us which
1001                 // union field to use.
1002                 let hardware_entry_failure_reason = unsafe {
1003                     run.__bindgen_anon_1
1004                         .fail_entry
1005                         .hardware_entry_failure_reason
1006                 };
1007                 Ok(VcpuExit::FailEntry {
1008                     hardware_entry_failure_reason,
1009                 })
1010             }
1011             KVM_EXIT_INTR => Ok(VcpuExit::Intr),
1012             KVM_EXIT_INTERNAL_ERROR => Ok(VcpuExit::InternalError),
1013             KVM_EXIT_SYSTEM_EVENT => {
1014                 // SAFETY:
1015                 // Safe because we know the exit reason told us this union
1016                 // field is valid
1017                 let event_type = unsafe { run.__bindgen_anon_1.system_event.type_ };
1018                 let event_flags =
1019                     // SAFETY:
1020                     // Safe because we know the exit reason told us this union
1021                     // field is valid
1022                     unsafe { run.__bindgen_anon_1.system_event.__bindgen_anon_1.flags };
1023                 match event_type {
1024                     KVM_SYSTEM_EVENT_SHUTDOWN => Ok(VcpuExit::SystemEventShutdown),
1025                     KVM_SYSTEM_EVENT_RESET => self.system_event_reset(event_flags),
1026                     KVM_SYSTEM_EVENT_CRASH => Ok(VcpuExit::SystemEventCrash),
1027                     _ => {
1028                         error!(
1029                             "Unknown KVM system event {} with flags {}",
1030                             event_type, event_flags
1031                         );
1032                         Err(Error::new(EINVAL))
1033                     }
1034                 }
1035             }
1036             r => panic!("unknown kvm exit reason: {}", r),
1037         }
1038     }
1039 
handle_mmio(&self, handle_fn: &mut dyn FnMut(IoParams) -> Result<()>) -> Result<()>1040     fn handle_mmio(&self, handle_fn: &mut dyn FnMut(IoParams) -> Result<()>) -> Result<()> {
1041         // SAFETY:
1042         // Safe because we know we mapped enough memory to hold the kvm_run struct because the
1043         // kernel told us how large it was.
1044         let run = unsafe { &mut *(self.run_mmap.as_ptr() as *mut kvm_run) };
1045         // Verify that the handler is called in the right context.
1046         assert!(run.exit_reason == KVM_EXIT_MMIO);
1047         // SAFETY:
1048         // Safe because the exit_reason (which comes from the kernel) told us which
1049         // union field to use.
1050         let mmio = unsafe { &mut run.__bindgen_anon_1.mmio };
1051         let address = mmio.phys_addr;
1052         let data = &mut mmio.data[..mmio.len as usize];
1053         if mmio.is_write != 0 {
1054             handle_fn(IoParams {
1055                 address,
1056                 operation: IoOperation::Write(data),
1057             })
1058         } else {
1059             handle_fn(IoParams {
1060                 address,
1061                 operation: IoOperation::Read(data),
1062             })
1063         }
1064     }
1065 
handle_io(&self, handle_fn: &mut dyn FnMut(IoParams)) -> Result<()>1066     fn handle_io(&self, handle_fn: &mut dyn FnMut(IoParams)) -> Result<()> {
1067         // SAFETY:
1068         // Safe because we know we mapped enough memory to hold the kvm_run struct because the
1069         // kernel told us how large it was.
1070         let run = unsafe { &mut *(self.run_mmap.as_ptr() as *mut kvm_run) };
1071         // Verify that the handler is called in the right context.
1072         assert!(run.exit_reason == KVM_EXIT_IO);
1073         // SAFETY:
1074         // Safe because the exit_reason (which comes from the kernel) told us which
1075         // union field to use.
1076         let io = unsafe { run.__bindgen_anon_1.io };
1077         let address = u64::from(io.port);
1078         let size = usize::from(io.size);
1079         let count = io.count as usize;
1080         let data_len = count * size;
1081         let data_offset = io.data_offset as usize;
1082         assert!(data_offset + data_len <= self.run_mmap.size());
1083 
1084         // SAFETY:
1085         // The data_offset is defined by the kernel to be some number of bytes into the kvm_run
1086         // structure, which we have fully mmap'd.
1087         let buffer: &mut [u8] = unsafe {
1088             std::slice::from_raw_parts_mut(
1089                 (run as *mut kvm_run as *mut u8).add(data_offset),
1090                 data_len,
1091             )
1092         };
1093         let data_chunks = buffer.chunks_mut(size);
1094 
1095         if io.direction == KVM_EXIT_IO_IN as u8 {
1096             for data in data_chunks {
1097                 handle_fn(IoParams {
1098                     address,
1099                     operation: IoOperation::Read(data),
1100                 });
1101             }
1102         } else {
1103             debug_assert_eq!(io.direction, KVM_EXIT_IO_OUT as u8);
1104             for data in data_chunks {
1105                 handle_fn(IoParams {
1106                     address,
1107                     operation: IoOperation::Write(data),
1108                 });
1109             }
1110         }
1111 
1112         Ok(())
1113     }
1114 }
1115 
1116 impl KvmVcpu {
1117     /// Gets the vcpu's current "multiprocessing state".
1118     ///
1119     /// See the documentation for KVM_GET_MP_STATE. This call can only succeed after
1120     /// a call to `Vm::create_irq_chip`.
1121     ///
1122     /// Note that KVM defines the call for both x86 and s390 but we do not expect anyone
1123     /// to run crosvm on s390.
get_mp_state(&self) -> Result<kvm_mp_state>1124     pub fn get_mp_state(&self) -> Result<kvm_mp_state> {
1125         // SAFETY: trivially safe
1126         let mut state: kvm_mp_state = unsafe { std::mem::zeroed() };
1127         let ret = {
1128             // SAFETY:
1129             // Safe because we know that our file is a VCPU fd, we know the kernel will only write
1130             // the correct amount of memory to our pointer, and we verify the return
1131             // result.
1132             unsafe { ioctl_with_mut_ref(self, KVM_GET_MP_STATE, &mut state) }
1133         };
1134         if ret < 0 {
1135             return errno_result();
1136         }
1137         Ok(state)
1138     }
1139 
1140     /// Sets the vcpu's current "multiprocessing state".
1141     ///
1142     /// See the documentation for KVM_SET_MP_STATE. This call can only succeed after
1143     /// a call to `Vm::create_irq_chip`.
1144     ///
1145     /// Note that KVM defines the call for both x86 and s390 but we do not expect anyone
1146     /// to run crosvm on s390.
set_mp_state(&self, state: &kvm_mp_state) -> Result<()>1147     pub fn set_mp_state(&self, state: &kvm_mp_state) -> Result<()> {
1148         let ret = {
1149             // SAFETY:
1150             // The ioctl is safe because the kernel will only read from the kvm_mp_state struct.
1151             unsafe { ioctl_with_ref(self, KVM_SET_MP_STATE, state) }
1152         };
1153         if ret < 0 {
1154             return errno_result();
1155         }
1156         Ok(())
1157     }
1158 }
1159 
1160 impl AsRawDescriptor for KvmVcpu {
as_raw_descriptor(&self) -> RawDescriptor1161     fn as_raw_descriptor(&self) -> RawDescriptor {
1162         self.vcpu.as_raw_descriptor()
1163     }
1164 }
1165 
1166 impl TryFrom<HypervisorCap> for KvmCap {
1167     type Error = Error;
1168 
try_from(cap: HypervisorCap) -> Result<KvmCap>1169     fn try_from(cap: HypervisorCap) -> Result<KvmCap> {
1170         match cap {
1171             HypervisorCap::ArmPmuV3 => Ok(KvmCap::ArmPmuV3),
1172             HypervisorCap::ImmediateExit => Ok(KvmCap::ImmediateExit),
1173             HypervisorCap::S390UserSigp => Ok(KvmCap::S390UserSigp),
1174             HypervisorCap::TscDeadlineTimer => Ok(KvmCap::TscDeadlineTimer),
1175             HypervisorCap::UserMemory => Ok(KvmCap::UserMemory),
1176             #[cfg(target_arch = "x86_64")]
1177             HypervisorCap::Xcrs => Ok(KvmCap::Xcrs),
1178             #[cfg(target_arch = "x86_64")]
1179             HypervisorCap::CalibratedTscLeafRequired => Err(Error::new(libc::EINVAL)),
1180             HypervisorCap::StaticSwiotlbAllocationRequired => Err(Error::new(libc::EINVAL)),
1181             HypervisorCap::HypervisorInitializedBootContext => Err(Error::new(libc::EINVAL)),
1182         }
1183     }
1184 }
1185 
1186 impl From<&IrqRoute> for kvm_irq_routing_entry {
from(item: &IrqRoute) -> Self1187     fn from(item: &IrqRoute) -> Self {
1188         match &item.source {
1189             IrqSource::Irqchip { chip, pin } => kvm_irq_routing_entry {
1190                 gsi: item.gsi,
1191                 type_: KVM_IRQ_ROUTING_IRQCHIP,
1192                 u: kvm_irq_routing_entry__bindgen_ty_1 {
1193                     irqchip: kvm_irq_routing_irqchip {
1194                         irqchip: chip_to_kvm_chip(*chip),
1195                         pin: *pin,
1196                     },
1197                 },
1198                 ..Default::default()
1199             },
1200             IrqSource::Msi { address, data } => kvm_irq_routing_entry {
1201                 gsi: item.gsi,
1202                 type_: KVM_IRQ_ROUTING_MSI,
1203                 u: kvm_irq_routing_entry__bindgen_ty_1 {
1204                     msi: kvm_irq_routing_msi {
1205                         address_lo: *address as u32,
1206                         address_hi: (*address >> 32) as u32,
1207                         data: *data,
1208                         ..Default::default()
1209                     },
1210                 },
1211                 ..Default::default()
1212             },
1213         }
1214     }
1215 }
1216 
1217 impl From<&kvm_mp_state> for MPState {
from(item: &kvm_mp_state) -> Self1218     fn from(item: &kvm_mp_state) -> Self {
1219         match item.mp_state {
1220             KVM_MP_STATE_RUNNABLE => MPState::Runnable,
1221             KVM_MP_STATE_UNINITIALIZED => MPState::Uninitialized,
1222             KVM_MP_STATE_INIT_RECEIVED => MPState::InitReceived,
1223             KVM_MP_STATE_HALTED => MPState::Halted,
1224             KVM_MP_STATE_SIPI_RECEIVED => MPState::SipiReceived,
1225             KVM_MP_STATE_STOPPED => MPState::Stopped,
1226             state => {
1227                 error!(
1228                     "unrecognized kvm_mp_state {}, setting to KVM_MP_STATE_RUNNABLE",
1229                     state
1230                 );
1231                 MPState::Runnable
1232             }
1233         }
1234     }
1235 }
1236 
1237 impl From<&MPState> for kvm_mp_state {
from(item: &MPState) -> Self1238     fn from(item: &MPState) -> Self {
1239         kvm_mp_state {
1240             mp_state: match item {
1241                 MPState::Runnable => KVM_MP_STATE_RUNNABLE,
1242                 MPState::Uninitialized => KVM_MP_STATE_UNINITIALIZED,
1243                 MPState::InitReceived => KVM_MP_STATE_INIT_RECEIVED,
1244                 MPState::Halted => KVM_MP_STATE_HALTED,
1245                 MPState::SipiReceived => KVM_MP_STATE_SIPI_RECEIVED,
1246                 MPState::Stopped => KVM_MP_STATE_STOPPED,
1247             },
1248         }
1249     }
1250 }
1251