From d22ef1f51852dfb055da38004e1a4fed81246f81 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Fri, 3 Dec 2021 16:38:31 +0100 Subject: [PATCH] Add support for KVM_SET_IDENTITY_MAP_ADDR Adding a missing ioctl to the list of supported ioctls. It is useful to define the address of a one-page region that is needed on Intel hardware because of a quirk in the virtualization implementation. Signed-off-by: Sebastien Boeuf --- coverage_config_x86_64.json | 2 +- src/ioctls/vm.rs | 41 +++++++++++++++++++++++++++++++++++++ src/kvm_ioctls.rs | 3 +++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/coverage_config_x86_64.json b/coverage_config_x86_64.json index 7abd6c69..105c5c0f 100644 --- a/coverage_config_x86_64.json +++ b/coverage_config_x86_64.json @@ -1,5 +1,5 @@ { - "coverage_score": 87.7, + "coverage_score": 87.9, "exclude_path": "", "crate_features": "" } diff --git a/src/ioctls/vm.rs b/src/ioctls/vm.rs index 1662ebd2..32087d9c 100644 --- a/src/ioctls/vm.rs +++ b/src/ioctls/vm.rs @@ -136,6 +136,34 @@ impl VmFd { } } + /// Sets the address of the one-page region in the VM's address space. + /// + /// See the documentation for `KVM_SET_IDENTITY_MAP_ADDR`. + /// + /// # Arguments + /// + /// * `address` - Physical address of a one-page region in the guest's physical address space. + /// + /// # Example + /// + /// ```rust + /// # extern crate kvm_ioctls; + /// # use kvm_ioctls::Kvm; + /// let kvm = Kvm::new().unwrap(); + /// let vm = kvm.create_vm().unwrap(); + /// vm.set_identity_map_address(0xfffb_c000).unwrap(); + /// ``` + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + pub fn set_identity_map_address(&self, address: u64) -> Result<()> { + // Safe because we know that our file is a VM fd and we verify the return result. + let ret = unsafe { ioctl_with_ref(self, KVM_SET_IDENTITY_MAP_ADDR(), &address) }; + if ret == 0 { + Ok(()) + } else { + Err(errno::Error::last()) + } + } + /// Creates an in-kernel interrupt controller. /// /// See the documentation for `KVM_CREATE_IRQCHIP`. @@ -1584,6 +1612,19 @@ mod tests { assert!(vm.set_tss_address(0xfffb_d000).is_ok()); } + #[test] + #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] + fn test_set_identity_map_address() { + let kvm = Kvm::new().unwrap(); + if kvm.check_extension(Cap::SetIdentityMapAddr) { + let vm = kvm.create_vm().unwrap(); + assert!(vm.set_identity_map_address(0xfffb_c000).is_ok()); + vm.create_vcpu(0).unwrap(); + // Setting the identity map after creating a vCPU must fail. + assert!(vm.set_identity_map_address(0xfffb_c000).is_err()); + } + } + #[test] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] fn test_irq_chip() { diff --git a/src/kvm_ioctls.rs b/src/kvm_ioctls.rs index cc9feb45..9138befa 100644 --- a/src/kvm_ioctls.rs +++ b/src/kvm_ioctls.rs @@ -36,6 +36,9 @@ ioctl_iow_nr!( /* Available with KVM_CAP_SET_TSS_ADDR */ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] ioctl_io_nr!(KVM_SET_TSS_ADDR, KVMIO, 0x47); +/* Available with KVM_CAP_SET_IDENTITY_MAP_ADDR */ +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +ioctl_iow_nr!(KVM_SET_IDENTITY_MAP_ADDR, KVMIO, 0x48, u64); /* Available with KVM_CAP_IRQCHIP */ #[cfg(any( target_arch = "x86",