[RFC PATCH v6 23/35] KVM: arm64: Allow guest SPE physical timestamps only if perfmon_capable()

Alexandru Elisei alexandru.elisei at arm.com
Fri Nov 14 08:07:04 PST 2025


The SPE driver allows userspace to use physical timestamps for records only
if the process if perfmon_capable(). Do the same for a virtual machine.

Signed-off-by: Alexandru Elisei <alexandru.elisei at arm.com>
---
 arch/arm64/include/asm/kvm_spe.h |  1 +
 arch/arm64/kvm/spe.c             | 16 ++++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_spe.h b/arch/arm64/include/asm/kvm_spe.h
index 077ca1e596b8..a61c1c1de76f 100644
--- a/arch/arm64/include/asm/kvm_spe.h
+++ b/arch/arm64/include/asm/kvm_spe.h
@@ -13,6 +13,7 @@
 struct kvm_spe {
 	struct arm_spe_pmu *arm_spu;
 	u64 max_buffer_size;	/* Maximum per VCPU buffer size */
+	u64 guest_pmscr_el2;
 };
 
 struct kvm_vcpu_spe {
diff --git a/arch/arm64/kvm/spe.c b/arch/arm64/kvm/spe.c
index 32156e43f454..85a1ac8bb57f 100644
--- a/arch/arm64/kvm/spe.c
+++ b/arch/arm64/kvm/spe.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/capability.h>
 #include <linux/cpumask.h>
 #include <linux/kvm_host.h>
 #include <linux/perf/arm_spe_pmu.h>
@@ -64,6 +65,8 @@ void kvm_spe_init_vm(struct kvm *kvm)
 
 int kvm_spe_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 {
+	struct kvm *kvm = vcpu->kvm;
+	struct kvm_spe *kvm_spe = &kvm->arch.kvm_spe;
 	struct kvm_vcpu_spe *vcpu_spe = &vcpu->arch.vcpu_spe;
 
 	if (!vcpu_has_spe(vcpu))
@@ -72,6 +75,12 @@ int kvm_spe_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 	if (!vcpu_spe->initialized)
 		return -EINVAL;
 
+	if (kvm_vm_has_ran_once(kvm))
+		return 0;
+
+	if (perfmon_capable())
+		kvm_spe->guest_pmscr_el2 = PMSCR_EL2_PCT_PHYS;
+
 	return 0;
 }
 
@@ -217,8 +226,11 @@ void kvm_vcpu_spe_load(struct kvm_vcpu *vcpu)
 	local_irq_disable();
 
 	host_pmscr_el2 = read_sysreg_el2(SYS_PMSCR);
-	write_sysreg_el2(0, SYS_PMSCR);
-	/* Host was profiling, synchronize the write to PMSCR_EL2. */
+	write_sysreg_el2(vcpu->kvm->arch.kvm_spe.guest_pmscr_el2, SYS_PMSCR);
+	/*
+	 * Host was profiling, synchronize the write to PMSCR_EL2 with the guest
+	 * value which disables profiling at EL2.
+	 */
 	if (FIELD_GET(PMSCR_EL2_E2SPE, host_pmscr_el2))
 		isb();
 
-- 
2.51.2




More information about the linux-arm-kernel mailing list