[PATCH v10 10/20] KVM: arm64: PMU: Recreate events after userspace event writes

From: Akihiko Odaki

Date: Mon Sep 14 2026 - 07:54:15 EST


KVM_SET_ONE_REG writes to PMEVTYPERn_EL0 and PMCCFILTR_EL0 use the
generic raw system register assignment. If a backing perf event already
exists, it keeps its old event selection and privilege filters.

Add a setter that preserves the raw userspace register value and
requests deferred event recreation. This rebuilds the event on the vCPU
thread without changing values returned by KVM_GET_ONE_REG or applying
guest-write masking.

Fixes: 9feb21ac57d5 ("arm64: KVM: Add access handler for event type register")
Closes: https://sashiko.dev/#/patchset/20260720-hybrid-v9-0-2b713ca1b5dc@xxxxxxxxxxxxxxxxxxxxxx?part=6
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Akihiko Odaki <odaki@xxxxxxxxxxxxxxxxxxxxxx>
---
arch/arm64/kvm/sys_regs.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 2754b743da01..a5c121482c71 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1334,6 +1334,15 @@ static int set_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 va
return 0;
}

+static int set_pmu_evtyper(struct kvm_vcpu *vcpu,
+ const struct sys_reg_desc *r, u64 val)
+{
+ __vcpu_assign_sys_reg(vcpu, r->reg, val);
+ kvm_pmu_request_recreate(vcpu);
+
+ return 0;
+}
+
static int get_pmreg(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r, u64 *val)
{
u64 mask = kvm_pmu_implemented_counter_mask(vcpu);
@@ -1584,7 +1593,7 @@ static int set_pmcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r,
/* Macro to expand the PMEVTYPERn_EL0 register */
#define PMU_PMEVTYPER_EL0(n) \
{ PMU_SYS_REG(PMEVTYPERn_EL0(n)), \
- .reset = reset_pmevtyper, \
+ .reset = reset_pmevtyper, .set_user = set_pmu_evtyper, \
.access = access_pmu_evtyper, .reg = (PMEVTYPER0_EL0 + n), }

/* Macro to expand the AMU counter and type registers*/
@@ -3833,7 +3842,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
* in 32bit mode. Here we choose to reset it as zero for consistency.
*/
{ PMU_SYS_REG(PMCCFILTR_EL0), .access = access_pmu_evtyper,
- .reset = reset_val, .reg = PMCCFILTR_EL0, .val = 0 },
+ .reset = reset_val, .reg = PMCCFILTR_EL0, .val = 0,
+ .set_user = set_pmu_evtyper },

EL2_REG_VNCR(VPIDR_EL2, reset_unknown, 0),
EL2_REG_VNCR(VMPIDR_EL2, reset_unknown, 0),

--
2.55.0