summary refs log tree commit diff
path: root/kvm
diff options
context:
space:
mode:
Diffstat (limited to 'kvm')
-rw-r--r--kvm/src/cap.rs1
-rw-r--r--kvm/src/lib.rs44
2 files changed, 45 insertions, 0 deletions
diff --git a/kvm/src/cap.rs b/kvm/src/cap.rs
index 7dfd965..ff65b59 100644
--- a/kvm/src/cap.rs
+++ b/kvm/src/cap.rs
@@ -119,4 +119,5 @@ pub enum Cap {
     CheckExtensionVm = KVM_CAP_CHECK_EXTENSION_VM,
     S390UserSigp = KVM_CAP_S390_USER_SIGP,
     ImmediateExit = KVM_CAP_IMMEDIATE_EXIT,
+    ArmPmuV3 = KVM_CAP_ARM_PMU_V3,
 }
diff --git a/kvm/src/lib.rs b/kvm/src/lib.rs
index b8cd12b..8b98b7c 100644
--- a/kvm/src/lib.rs
+++ b/kvm/src/lib.rs
@@ -1763,6 +1763,50 @@ impl Vcpu {
         if ret < 0 {
             return errno_result();
         }
+
+        Ok(())
+    }
+
+    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
+    pub fn arm_pmu_init(&self, irq: u64) -> Result<()> {
+        let irq_addr = &irq as *const u64;
+
+        // The in-kernel PMU virtualization is initialized by setting the irq
+        // with KVM_ARM_VCPU_PMU_V3_IRQ and then by KVM_ARM_VCPU_PMU_V3_INIT.
+
+        let irq_attr = kvm_device_attr {
+            group: kvm_sys::KVM_ARM_VCPU_PMU_V3_CTRL,
+            attr: kvm_sys::KVM_ARM_VCPU_PMU_V3_IRQ as u64,
+            addr: irq_addr as u64,
+            flags: 0,
+        };
+        // safe becuase we allocated the struct and we know the kernel will read
+        // exactly the size of the struct
+        let ret = unsafe { ioctl_with_ref(self, kvm_sys::KVM_HAS_DEVICE_ATTR(), &irq_attr) };
+        if ret < 0 {
+            return errno_result();
+        }
+
+        // safe becuase we allocated the struct and we know the kernel will read
+        // exactly the size of the struct
+        let ret = unsafe { ioctl_with_ref(self, kvm_sys::KVM_SET_DEVICE_ATTR(), &irq_attr) };
+        if ret < 0 {
+            return errno_result();
+        }
+
+        let init_attr = kvm_device_attr {
+            group: kvm_sys::KVM_ARM_VCPU_PMU_V3_CTRL,
+            attr: kvm_sys::KVM_ARM_VCPU_PMU_V3_INIT as u64,
+            addr: 0,
+            flags: 0,
+        };
+        // safe becuase we allocated the struct and we know the kernel will read
+        // exactly the size of the struct
+        let ret = unsafe { ioctl_with_ref(self, kvm_sys::KVM_SET_DEVICE_ATTR(), &init_attr) };
+        if ret < 0 {
+            return errno_result();
+        }
+
         Ok(())
     }