Skip to content

Commit ddfcae9

Browse files
vittyvkgregkh
authored andcommitted
x86/hyperv: Protect set_hv_tscchange_cb() against getting preempted
[ Upstream commit 285f68a ] The following issue is observed with CONFIG_DEBUG_PREEMPT when KVM loads: KVM: vmx: using Hyper-V Enlightened VMCS BUG: using smp_processor_id() in preemptible [00000000] code: systemd-udevd/488 caller is set_hv_tscchange_cb+0x16/0x80 CPU: 1 PID: 488 Comm: systemd-udevd Not tainted 5.15.0-rc5+ #396 Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS Hyper-V UEFI Release v4.0 12/17/2019 Call Trace: dump_stack_lvl+0x6a/0x9a check_preemption_disabled+0xde/0xe0 ? kvm_gen_update_masterclock+0xd0/0xd0 [kvm] set_hv_tscchange_cb+0x16/0x80 kvm_arch_init+0x23f/0x290 [kvm] kvm_init+0x30/0x310 [kvm] vmx_init+0xaf/0x134 [kvm_intel] ... set_hv_tscchange_cb() can get preempted in between acquiring smp_processor_id() and writing to HV_X64_MSR_REENLIGHTENMENT_CONTROL. This is not an issue by itself: HV_X64_MSR_REENLIGHTENMENT_CONTROL is a partition-wide MSR and it doesn't matter which particular CPU will be used to receive reenlightenment notifications. The only real problem can (in theory) be observed if the CPU whose id was acquired with smp_processor_id() goes offline before we manage to write to the MSR, the logic in hv_cpu_die() won't be able to reassign it correctly. Reported-by: Michael Kelley <[email protected]> Signed-off-by: Vitaly Kuznetsov <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Wei Liu <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent c4cfdf5 commit ddfcae9

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

arch/x86/hyperv/hv_init.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ void set_hv_tscchange_cb(void (*cb)(void))
168168
struct hv_reenlightenment_control re_ctrl = {
169169
.vector = HYPERV_REENLIGHTENMENT_VECTOR,
170170
.enabled = 1,
171-
.target_vp = hv_vp_index[smp_processor_id()]
172171
};
173172
struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1};
174173

@@ -182,8 +181,12 @@ void set_hv_tscchange_cb(void (*cb)(void))
182181
/* Make sure callback is registered before we write to MSRs */
183182
wmb();
184183

184+
re_ctrl.target_vp = hv_vp_index[get_cpu()];
185+
185186
wrmsrl(HV_X64_MSR_REENLIGHTENMENT_CONTROL, *((u64 *)&re_ctrl));
186187
wrmsrl(HV_X64_MSR_TSC_EMULATION_CONTROL, *((u64 *)&emu_ctrl));
188+
189+
put_cpu();
187190
}
188191
EXPORT_SYMBOL_GPL(set_hv_tscchange_cb);
189192

0 commit comments

Comments
 (0)