Skip to content

Commit 146f76c

Browse files
author
Marc Zyngier
committed
KVM: arm64: PMU: Fix per-CPU access in preemptible context
Commit 07da1ff ("KVM: arm64: Remove host_cpu_context member from vcpu structure") has, by removing the host CPU context pointer, exposed that kvm_vcpu_pmu_restore_guest is called in preemptible contexts: [ 266.932442] BUG: using smp_processor_id() in preemptible [00000000] code: qemu-system-aar/779 [ 266.939721] caller is debug_smp_processor_id+0x20/0x30 [ 266.944157] CPU: 2 PID: 779 Comm: qemu-system-aar Tainted: G E 5.8.0-rc3-00015-g8d4aa58b2fe3 #1374 [ 266.954268] Hardware name: amlogic w400/w400, BIOS 2020.04 05/22/2020 [ 266.960640] Call trace: [ 266.963064] dump_backtrace+0x0/0x1e0 [ 266.966679] show_stack+0x20/0x30 [ 266.969959] dump_stack+0xe4/0x154 [ 266.973338] check_preemption_disabled+0xf8/0x108 [ 266.977978] debug_smp_processor_id+0x20/0x30 [ 266.982307] kvm_vcpu_pmu_restore_guest+0x2c/0x68 [ 266.986949] access_pmcr+0xf8/0x128 [ 266.990399] perform_access+0x8c/0x250 [ 266.994108] kvm_handle_sys_reg+0x10c/0x2f8 [ 266.998247] handle_exit+0x78/0x200 [ 267.001697] kvm_arch_vcpu_ioctl_run+0x2ac/0xab8 Note that the bug was always there, it is only the switch to using percpu accessors that made it obvious. The fix is to wrap these accesses in a preempt-disabled section, so that we sample a coherent context on trap from the guest. Fixes: 435e53f ("arm64: KVM: Enable VHE support for :G/:H perf event modifiers") Cc:: Andrew Murray <[email protected]> Signed-off-by: Marc Zyngier <[email protected]>
1 parent a3f574c commit 146f76c

File tree

1 file changed

+6
-1
lines changed

1 file changed

+6
-1
lines changed

arch/arm64/kvm/pmu.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,10 @@ static void kvm_vcpu_pmu_disable_el0(unsigned long events)
159159
}
160160

161161
/*
162-
* On VHE ensure that only guest events have EL0 counting enabled
162+
* On VHE ensure that only guest events have EL0 counting enabled.
163+
* This is called from both vcpu_{load,put} and the sysreg handling.
164+
* Since the latter is preemptible, special care must be taken to
165+
* disable preemption.
163166
*/
164167
void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu)
165168
{
@@ -169,12 +172,14 @@ void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu)
169172
if (!has_vhe())
170173
return;
171174

175+
preempt_disable();
172176
host = this_cpu_ptr(&kvm_host_data);
173177
events_guest = host->pmu_events.events_guest;
174178
events_host = host->pmu_events.events_host;
175179

176180
kvm_vcpu_pmu_enable_el0(events_guest);
177181
kvm_vcpu_pmu_disable_el0(events_host);
182+
preempt_enable();
178183
}
179184

180185
/*

0 commit comments

Comments
 (0)