Skip to content

Commit 1da4e2f

Browse files
committed
KVM: PPC: Book3S HV: Don't let VCPU sleep if it has a doorbell pending
It is possible, through a narrow race condition, for a VCPU to exit the guest with a H_CEDE hypercall while it has a doorbell interrupt pending. In this case, the H_CEDE should return immediately, but in fact it puts the VCPU to sleep until some other interrupt becomes pending or a prod is received (via another VCPU doing H_PROD). This fixes it by checking the DPDES (Directed Privileged Doorbell Exception Status) bit for the thread along with the other interrupt pending bits. Signed-off-by: Paul Mackerras <[email protected]>
1 parent 1bc3fe8 commit 1da4e2f

File tree

1 file changed

+22
-3
lines changed

1 file changed

+22
-3
lines changed

arch/powerpc/kvm/book3s_hv.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,17 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
675675
vcpu->arch.dtl.dirty = true;
676676
}
677677

678+
/* See if there is a doorbell interrupt pending for a vcpu */
679+
static bool kvmppc_doorbell_pending(struct kvm_vcpu *vcpu)
680+
{
681+
int thr;
682+
struct kvmppc_vcore *vc;
683+
684+
vc = vcpu->arch.vcore;
685+
thr = vcpu->vcpu_id - vc->first_vcpuid;
686+
return !!(vc->dpdes & (1 << thr));
687+
}
688+
678689
static bool kvmppc_power8_compatible(struct kvm_vcpu *vcpu)
679690
{
680691
if (vcpu->arch.vcore->arch_compat >= PVR_ARCH_207)
@@ -2672,6 +2683,15 @@ static void shrink_halt_poll_ns(struct kvmppc_vcore *vc)
26722683
vc->halt_poll_ns /= halt_poll_ns_shrink;
26732684
}
26742685

2686+
static bool kvmppc_vcpu_woken(struct kvm_vcpu *vcpu)
2687+
{
2688+
if (vcpu->arch.pending_exceptions || vcpu->arch.prodded ||
2689+
kvmppc_doorbell_pending(vcpu))
2690+
return true;
2691+
2692+
return false;
2693+
}
2694+
26752695
/*
26762696
* Check to see if any of the runnable vcpus on the vcore have pending
26772697
* exceptions or are no longer ceded
@@ -2682,8 +2702,7 @@ static int kvmppc_vcore_check_block(struct kvmppc_vcore *vc)
26822702
int i;
26832703

26842704
for_each_runnable_thread(i, vcpu, vc) {
2685-
if (vcpu->arch.pending_exceptions || !vcpu->arch.ceded ||
2686-
vcpu->arch.prodded)
2705+
if (!vcpu->arch.ceded || kvmppc_vcpu_woken(vcpu))
26872706
return 1;
26882707
}
26892708

@@ -2869,7 +2888,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
28692888
break;
28702889
n_ceded = 0;
28712890
for_each_runnable_thread(i, v, vc) {
2872-
if (!v->arch.pending_exceptions && !v->arch.prodded)
2891+
if (!kvmppc_vcpu_woken(v))
28732892
n_ceded += v->arch.ceded;
28742893
else
28752894
v->arch.ceded = 0;

0 commit comments

Comments
 (0)