Skip to content

Commit 91648ec

Browse files
pfliuagraf
authored andcommitted
powerpc: kvm: fix rare but potential deadlock scene
Since kvmppc_hv_find_lock_hpte() is called from both virtmode and realmode, so it can trigger the deadlock. Suppose the following scene: Two physical cpuM, cpuN, two VM instances A, B, each VM has a group of vcpus. If on cpuM, vcpu_A_1 holds bitlock X (HPTE_V_HVLOCK), then is switched out, and on cpuN, vcpu_A_2 try to lock X in realmode, then cpuN will be caught in realmode for a long time. What makes things even worse if the following happens, On cpuM, bitlockX is hold, on cpuN, Y is hold. vcpu_B_2 try to lock Y on cpuM in realmode vcpu_A_2 try to lock X on cpuN in realmode Oops! deadlock happens Signed-off-by: Liu Ping Fan <[email protected]> Reviewed-by: Paul Mackerras <[email protected]> CC: [email protected] Signed-off-by: Alexander Graf <[email protected]>
1 parent c943809 commit 91648ec

File tree

2 files changed

+9
-1
lines changed

2 files changed

+9
-1
lines changed

arch/powerpc/kvm/book3s_64_mmu_hv.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,18 +469,22 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
469469
slb_v = vcpu->kvm->arch.vrma_slb_v;
470470
}
471471

472+
preempt_disable();
472473
/* Find the HPTE in the hash table */
473474
index = kvmppc_hv_find_lock_hpte(kvm, eaddr, slb_v,
474475
HPTE_V_VALID | HPTE_V_ABSENT);
475-
if (index < 0)
476+
if (index < 0) {
477+
preempt_enable();
476478
return -ENOENT;
479+
}
477480
hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4));
478481
v = hptep[0] & ~HPTE_V_HVLOCK;
479482
gr = kvm->arch.revmap[index].guest_rpte;
480483

481484
/* Unlock the HPTE */
482485
asm volatile("lwsync" : : : "memory");
483486
hptep[0] = v;
487+
preempt_enable();
484488

485489
gpte->eaddr = eaddr;
486490
gpte->vpage = ((v & HPTE_V_AVPN) << 4) | ((eaddr >> 12) & 0xfff);

arch/powerpc/kvm/book3s_hv_rm_mmu.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,10 @@ static int slb_base_page_shift[4] = {
749749
20, /* 1M, unsupported */
750750
};
751751

752+
/* When called from virtmode, this func should be protected by
753+
* preempt_disable(), otherwise, the holding of HPTE_V_HVLOCK
754+
* can trigger deadlock issue.
755+
*/
752756
long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v,
753757
unsigned long valid)
754758
{

0 commit comments

Comments
 (0)