// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 OR MIT // // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the THIRD-PARTY file. use std::os::unix::io::AsRawFd; use std::ptr::null_mut; use kvm_bindings::kvm_run; use vmm_sys_util::errno; /// Wrappers over KVM device ioctls. pub mod device; /// Wrappers over KVM system ioctls. pub mod system; /// Wrappers over KVM VCPU ioctls. pub mod vcpu; /// Wrappers over KVM Virtual Machine ioctls. pub mod vm; /// A specialized `Result` type for KVM ioctls. /// /// This typedef is generally used to avoid writing out errno::Error directly and /// is otherwise a direct mapping to Result. pub type Result = std::result::Result; /// Safe wrapper over the `kvm_run` struct. /// /// The wrapper is needed for sending the pointer to `kvm_run` between /// threads as raw pointers do not implement `Send` and `Sync`. pub struct KvmRunWrapper { kvm_run_ptr: *mut u8, // This field is need so we can `munmap` the memory mapped to hold `kvm_run`. mmap_size: usize, } // Send and Sync aren't automatically inherited for the raw address pointer. // Accessing that pointer is only done through the stateless interface which // allows the object to be shared by multiple threads without a decrease in // safety. unsafe impl Send for KvmRunWrapper {} unsafe impl Sync for KvmRunWrapper {} impl KvmRunWrapper { /// Maps the first `size` bytes of the given `fd`. /// /// # Arguments /// * `fd` - File descriptor to mmap from. /// * `size` - Size of memory region in bytes. pub fn mmap_from_fd(fd: &dyn AsRawFd, size: usize) -> Result { // This is safe because we are creating a mapping in a place not already used by any other // area in this process. let addr = unsafe { libc::mmap( null_mut(), size, libc::PROT_READ | libc::PROT_WRITE, libc::MAP_SHARED, fd.as_raw_fd(), 0, ) }; if addr == libc::MAP_FAILED { return Err(errno::Error::last()); } Ok(KvmRunWrapper { kvm_run_ptr: addr as *mut u8, mmap_size: size, }) } /// Returns a mutable reference to `kvm_run`. /// #[allow(clippy::mut_from_ref)] pub fn as_mut_ref(&self) -> &mut kvm_run { // Safe because we know we mapped enough memory to hold the kvm_run struct because the // kernel told us how large it was. #[allow(clippy::cast_ptr_alignment)] unsafe { &mut *(self.kvm_run_ptr as *mut kvm_run) } } } impl Drop for KvmRunWrapper { fn drop(&mut self) { // This is safe because we mmap the area at kvm_run_ptr ourselves, // and nobody else is holding a reference to it. unsafe { libc::munmap(self.kvm_run_ptr as *mut libc::c_void, self.mmap_size); } } }