mirror of
https://github.com/torvalds/linux.git
synced 2024-12-31 23:31:29 +00:00
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 <paulus@ozlabs.org>
This commit is contained in:
parent
1bc3fe818c
commit
1da4e2f4fb
@ -675,6 +675,17 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu,
|
||||
vcpu->arch.dtl.dirty = true;
|
||||
}
|
||||
|
||||
/* See if there is a doorbell interrupt pending for a vcpu */
|
||||
static bool kvmppc_doorbell_pending(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
int thr;
|
||||
struct kvmppc_vcore *vc;
|
||||
|
||||
vc = vcpu->arch.vcore;
|
||||
thr = vcpu->vcpu_id - vc->first_vcpuid;
|
||||
return !!(vc->dpdes & (1 << thr));
|
||||
}
|
||||
|
||||
static bool kvmppc_power8_compatible(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (vcpu->arch.vcore->arch_compat >= PVR_ARCH_207)
|
||||
@ -2672,6 +2683,15 @@ static void shrink_halt_poll_ns(struct kvmppc_vcore *vc)
|
||||
vc->halt_poll_ns /= halt_poll_ns_shrink;
|
||||
}
|
||||
|
||||
static bool kvmppc_vcpu_woken(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
if (vcpu->arch.pending_exceptions || vcpu->arch.prodded ||
|
||||
kvmppc_doorbell_pending(vcpu))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if any of the runnable vcpus on the vcore have pending
|
||||
* exceptions or are no longer ceded
|
||||
@ -2682,8 +2702,7 @@ static int kvmppc_vcore_check_block(struct kvmppc_vcore *vc)
|
||||
int i;
|
||||
|
||||
for_each_runnable_thread(i, vcpu, vc) {
|
||||
if (vcpu->arch.pending_exceptions || !vcpu->arch.ceded ||
|
||||
vcpu->arch.prodded)
|
||||
if (!vcpu->arch.ceded || kvmppc_vcpu_woken(vcpu))
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2869,7 +2888,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
|
||||
break;
|
||||
n_ceded = 0;
|
||||
for_each_runnable_thread(i, v, vc) {
|
||||
if (!v->arch.pending_exceptions && !v->arch.prodded)
|
||||
if (!kvmppc_vcpu_woken(v))
|
||||
n_ceded += v->arch.ceded;
|
||||
else
|
||||
v->arch.ceded = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user