]> www.infradead.org Git - users/hch/misc.git/commit
KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs
authorAkihiko Odaki <akihiko.odaki@daynix.com>
Sat, 15 Mar 2025 09:12:12 +0000 (18:12 +0900)
committerOliver Upton <oliver.upton@linux.dev>
Mon, 17 Mar 2025 17:45:21 +0000 (10:45 -0700)
commit64074ca8ca92b8e6b6f76f5ea6982cd55bbc27bf
treea57cebad803c7a50dcaebecaefeac1bcb807f6c3
parentbe5ccac3f15ea6f0e9086a98dc3ee4f15e873ccb
KVM: arm64: PMU: Fix SET_ONE_REG for vPMC regs

Reload the perf event when setting the vPMU counter (vPMC) registers
(PMCCNTR_EL0 and PMEVCNTR<n>_EL0). This is a change corresponding to
commit 9228b26194d1 ("KVM: arm64: PMU: Fix GET_ONE_REG
for vPMC regs to return the current value") but for SET_ONE_REG.

Values of vPMC registers are saved in sysreg files on certain occasions.
These saved values don't represent the current values of the vPMC
registers if the perf events for the vPMCs count events after the save.
The current values of those registers are the sum of the sysreg file
value and the current perf event counter value.  But, when userspace
writes those registers (using KVM_SET_ONE_REG), KVM only updates the
sysreg file value and leaves the current perf event counter value as is.

It is also important to keep the correct state even if userspace writes
them after first run, specifically when debugging Windows on QEMU with
GDB; QEMU tries to write back all visible registers when resuming the VM
execution with GDB, corrupting the PMU state. Windows always uses the
PMU so this can cause adverse effects on that particular OS.

Fix this by releasing the current perf event and trigger recreating one
with KVM_REQ_RELOAD_PMU.

Fixes: 051ff581ce70 ("arm64: KVM: Add access handler for event counter register")
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250315-pmc-v5-3-ecee87dab216@daynix.com
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/pmu-emul.c
arch/arm64/kvm/sys_regs.c
include/kvm/arm_pmu.h