diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d1db427..91550fbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Upcoming Release +# v0.15.0 + +## Added + +- [[#228](https://github.com/rust-vmm/kvm-ioctls/pull/228)] arm64: add +support for vCPU SVE feature + # v0.14.0 ## Added diff --git a/src/cap.rs b/src/cap.rs index f8a2274c..ebea2442 100644 --- a/src/cap.rs +++ b/src/cap.rs @@ -148,4 +148,6 @@ pub enum Cap { DebugHwBps = KVM_CAP_GUEST_DEBUG_HW_BPS, DebugHwWps = KVM_CAP_GUEST_DEBUG_HW_WPS, GetMsrFeatures = KVM_CAP_GET_MSR_FEATURES, + #[cfg(target_arch = "aarch64")] + ArmSve = KVM_CAP_ARM_SVE, } diff --git a/src/ioctls/vcpu.rs b/src/ioctls/vcpu.rs index 26377624..681d4029 100644 --- a/src/ioctls/vcpu.rs +++ b/src/ioctls/vcpu.rs @@ -1067,6 +1067,62 @@ impl VcpuFd { Ok(()) } + /// Finalizes the configuration of the specified vcpu feature. + /// + /// The vcpu must already have been initialised, enabling the affected feature, + /// by means of a successful KVM_ARM_VCPU_INIT call with the appropriate flag set + /// in features[]. + /// + /// For affected vcpu features, this is a mandatory step that must be performed before + /// the vcpu is fully usable. + /// + /// Between KVM_ARM_VCPU_INIT and KVM_ARM_VCPU_FINALIZE, the feature may be configured + /// by use of ioctls such as KVM_SET_ONE_REG. The exact configuration that should be + /// performaned and how to do it are feature-dependent. + /// + /// Other calls that depend on a particular feature being finalized, such as KVM_RUN, + /// KVM_GET_REG_LIST, KVM_GET_ONE_REG and KVM_SET_ONE_REG, will fail with -EPERM unless + /// the feature has already been finalized by means of a KVM_ARM_VCPU_FINALIZE call. + /// + /// See KVM_ARM_VCPU_INIT for details of vcpu features that require finalization using this ioctl. + /// [KVM_ARM_VCPU_FINALIZE](https://www.kernel.org/doc/html/latest/virt/kvm/api.html#kvm-arm-vcpu-finalize). + /// + /// # Arguments + /// + /// * `feature` - vCPU features that needs to be finalized. + /// + /// # Example + /// ```rust + /// # extern crate kvm_ioctls; + /// # extern crate kvm_bindings; + /// # use kvm_ioctls::Kvm; + /// use std::arch::is_aarch64_feature_detected; + /// + /// use kvm_bindings::{kvm_vcpu_init, KVM_ARM_VCPU_SVE}; + /// let kvm = Kvm::new().unwrap(); + /// let vm = kvm.create_vm().unwrap(); + /// let vcpu = vm.create_vcpu(0).unwrap(); + /// + /// let mut kvi = kvm_vcpu_init::default(); + /// vm.get_preferred_target(&mut kvi).unwrap(); + /// kvi.features[0] |= 1 << KVM_ARM_VCPU_SVE; + /// if is_aarch64_feature_detected!("sve2") || is_aarch64_feature_detected!("sve") { + /// vcpu.vcpu_init(&kvi).unwrap(); + /// let feature = KVM_ARM_VCPU_SVE as i32; + /// vcpu.vcpu_finalize(&feature).unwrap(); + /// } + /// ``` + #[cfg(target_arch = "aarch64")] + pub fn vcpu_finalize(&self, feature: &std::os::raw::c_int) -> Result<()> { + // SAFETY: This is safe because we know the kernel will only read this + // parameter to select the correct finalization case in KVM. + let ret = unsafe { ioctl_with_ref(self, KVM_ARM_VCPU_FINALIZE(), feature) }; + if ret < 0 { + return Err(errno::Error::last()); + } + Ok(()) + } + /// Returns the guest registers that are supported for the /// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. /// diff --git a/src/kvm_ioctls.rs b/src/kvm_ioctls.rs index 0133c66c..5b9360c6 100644 --- a/src/kvm_ioctls.rs +++ b/src/kvm_ioctls.rs @@ -240,6 +240,10 @@ ioctl_ior_nr!(KVM_ARM_PREFERRED_TARGET, KVMIO, 0xaf, kvm_vcpu_init); #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] ioctl_iowr_nr!(KVM_GET_REG_LIST, KVMIO, 0xb0, kvm_reg_list); +/* Available with KVM_CAP_ARM_SVE */ +#[cfg(target_arch = "aarch64")] +ioctl_iow_nr!(KVM_ARM_VCPU_FINALIZE, KVMIO, 0xc2, std::os::raw::c_int); + /* Available with KVM_CAP_SET_GUEST_DEBUG */ ioctl_iow_nr!(KVM_SET_GUEST_DEBUG, KVMIO, 0x9b, kvm_guest_debug);