KVM: x86: fix deadlock in clock-in-progress request handling
There is a deadlock in pvclock handling:
cpu0: cpu1:kvm_gen_update_masterclock()
kvm_guest_time_update()
spin_lock(pvclock_gtod_sync_lock)
local_irq_save(flags)
spin_lock(pvclock_gtod_sync_lock)
kvm_make_mclock_inprogress_request(kvm)
make_all_cpus_request()
smp_call_function_many()
Now if smp_call_function_many() called by cpu0 tries to call function on cpu1 there will be a deadlock.
Fix by moving pvclock_gtod_sync_lock protected section outside irq disabled section.
Analyzed by Gleb Natapov <[email protected]>
arch/x86/kvm/x86.c +9 -9
@@ -1416,15 +1416,6 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) kernel_ns =0 ; host_tsc =0 ; -/* Keep irq disabled to prevent changes to the clock */ -local_irq_save (flags); - this_tsc_khz =__get_cpu_var (cpu_tsc_khz); -if (unlikely (this_tsc_khz ==0 )) { -local_irq_restore (flags); -kvm_make_request (KVM_REQ_CLOCK_UPDATE , v); -return 1 ; - } -/* * If the host uses TSC clock, then passthrough TSC as stable * to the guest.
@@ -1436,6 +1427,15 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) kernel_ns = ka->master_kernel_ns; }spin_unlock (&ka->pvclock_gtod_sync_lock); + +/* Keep irq disabled to prevent changes to the clock */ +local_irq_save (flags); + this_tsc_khz =__get_cpu_var (cpu_tsc_khz); +if (unlikely (this_tsc_khz ==0 )) { +local_irq_restore (flags); +kvm_make_request (KVM_REQ_CLOCK_UPDATE , v); +return 1 ; + }if (!use_master_clock) { host_tsc =native_read_tsc (); kernel_ns =get_kernel_ns ();
Gleb Natapov
Acked-byQuoted 18 lines · Marcelo Tosatti
There is a deadlock in pvclock handling:
cpu0: cpu1:
kvm_gen_update_masterclock()
kvm_guest_time_update()
spin_lock(pvclock_gtod_sync_lock)
local_irq_save(flags)
spin_lock(pvclock_gtod_sync_lock)
kvm_make_mclock_inprogress_request(kvm)
make_all_cpus_request()
smp_call_function_many()Now if
smp_call_function_many()called by cpu0 tries to call function on cpu1 there will be a deadlock.
Quoted 7 lines
Fix by moving
pvclock_gtod_sync_lockprotected section outside irq disabled section.Analyzed by Gleb Natapov <[email protected]>
Reported-and-Tested-by Yongjie Ren <[email protected]>Signed-off-by Marcelo Tosatti <[email protected]>
Quoted 26 lines
arch/x86/kvm/x86.c +2
-9@@ -1416,15 +1416,6 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) kernel_ns =0 ; host_tsc =0 ; -/* Keep irq disabled to prevent changes to the clock */ -local_irq_save (flags); - this_tsc_khz =__get_cpu_var (cpu_tsc_khz); -if (unlikely (this_tsc_khz ==0 )) { -local_irq_restore (flags); -kvm_make_request (KVM_REQ_CLOCK_UPDATE , v); -return 1 ; - } -/* * If the host uses TSC clock, then passthrough TSC as stable * to the guest. @@ -1436,6 +1427,15 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) kernel_ns = ka->master_kernel_ns; }spin_unlock (&ka->pvclock_gtod_sync_lock); + +/* Keep irq disabled to prevent changes to the clock */
arch/x86/kvm/x86.c static int kvm_guest_time_update(struct kvm_vcpu *v) · line 1441
Quoted 10 lines
arch/x86/kvm/x86.c +7
-0+local_irq_save (flags); + this_tsc_khz =__get_cpu_var (cpu_tsc_khz); +if (unlikely (this_tsc_khz ==0 )) { +local_irq_restore (flags); +kvm_make_request (KVM_REQ_CLOCK_UPDATE , v); +return 1 ; + }if (!use_master_clock) { host_tsc =native_read_tsc (); kernel_ns =get_kernel_ns ();
--
Gleb.