summary refs log tree commit diff
path: root/kvm
diff options
context:
space:
mode:
authorSuleiman Souhlal <suleiman@google.com>2020-04-21 14:11:47 +0900
committerCommit Bot <commit-bot@chromium.org>2020-05-08 03:25:38 +0000
commit7dc915dd2af19ed4dbafb6b1b6e86733af5a922d (patch)
treed1820536e6f433eaf155b259c9d831b9360df807 /kvm
parenta1c0e3c680c44ae4a949744b27f3cf0f7ea77939 (diff)
downloadcrosvm-7dc915dd2af19ed4dbafb6b1b6e86733af5a922d.tar
crosvm-7dc915dd2af19ed4dbafb6b1b6e86733af5a922d.tar.gz
crosvm-7dc915dd2af19ed4dbafb6b1b6e86733af5a922d.tar.bz2
crosvm-7dc915dd2af19ed4dbafb6b1b6e86733af5a922d.tar.lz
crosvm-7dc915dd2af19ed4dbafb6b1b6e86733af5a922d.tar.xz
crosvm-7dc915dd2af19ed4dbafb6b1b6e86733af5a922d.tar.zst
crosvm-7dc915dd2af19ed4dbafb6b1b6e86733af5a922d.zip
aarch64: Enable PMU in the guest.
This allows us to use perf/simpleperf in the guest.

BUG=b:153708112
TEST=Use simpleperf in ARCVM guest on jacuzzi board.

Change-Id: Ia3d7dc5bcd3ca033ddf05b5ee2593102c98e8b49
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2156592
Tested-by: kokoro <noreply+kokoro@google.com>
Tested-by: Suleiman Souhlal <suleiman@chromium.org>
Reviewed-by: Sonny Rao <sonnyrao@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
Commit-Queue: Suleiman Souhlal <suleiman@chromium.org>
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(())
     }