hypervisor/kvm/
mod.rs

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