KVM: arm64: PMU: Don't overwrite PMUSERENR with vcpu loaded
authorReiji Watanabe <reijiw@google.com>
Sat, 3 Jun 2023 02:50:35 +0000 (19:50 -0700)
committerMarc Zyngier <maz@kernel.org>
Sun, 4 Jun 2023 16:19:36 +0000 (17:19 +0100)
commit0c2f9acf6ae74118385f7a7d48f4b2d93637b628
tree67a9f501d20ead1f5317bca1a38fd7bcafe17eb3
parent8681f71759010503892f9e3ddb05f65c0f21b690
KVM: arm64: PMU: Don't overwrite PMUSERENR with vcpu loaded

Currently, with VHE, KVM sets ER, CR, SW and EN bits of
PMUSERENR_EL0 to 1 on vcpu_load(), and saves and restores
the register value for the host on vcpu_load() and vcpu_put().
If the value of those bits are cleared on a pCPU with a vCPU
loaded (armv8pmu_start() would do that when PMU counters are
programmed for the guest), PMU access from the guest EL0 might
be trapped to the guest EL1 directly regardless of the current
PMUSERENR_EL0 value of the vCPU.

Fix this by not letting armv8pmu_start() overwrite PMUSERENR_EL0
on the pCPU where PMUSERENR_EL0 for the guest is loaded, and
instead updating the saved shadow register value for the host
so that the value can be restored on vcpu_put() later.
While vcpu_{put,load}() are manipulating PMUSERENR_EL0, disable
IRQs to prevent a race condition between these processes and IPIs
that attempt to update PMUSERENR_EL0 for the host EL0.

Suggested-by: Mark Rutland <mark.rutland@arm.com>
Suggested-by: Marc Zyngier <maz@kernel.org>
Fixes: 83a7a4d643d3 ("arm64: perf: Enable PMU counter userspace access for perf event")
Signed-off-by: Reiji Watanabe <reijiw@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20230603025035.3781797-3-reijiw@google.com
arch/arm/include/asm/arm_pmuv3.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/kvm/hyp/include/hyp/switch.h
arch/arm64/kvm/hyp/vhe/switch.c
arch/arm64/kvm/pmu.c
drivers/perf/arm_pmuv3.c