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/[email protected]?part=6
Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Akihiko Odaki <[email protected]>
---
 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


Reply via email to