| From de3918fc020ae25d914de1503b96aa7ee5f01f54 Mon Sep 17 00:00:00 2001 |
| From: Paul Mackerras <paulus@ozlabs.org> |
| Date: Tue, 27 Aug 2019 11:35:40 +1000 |
| Subject: [PATCH] KVM: PPC: Book3S HV: Don't lose pending doorbell request on |
| migration on P9 |
| |
| commit ff42df49e75f053a8a6b4c2533100cdcc23afe69 upstream. |
| |
| On POWER9, when userspace reads the value of the DPDES register on a |
| vCPU, it is possible for 0 to be returned although there is a doorbell |
| interrupt pending for the vCPU. This can lead to a doorbell interrupt |
| being lost across migration. If the guest kernel uses doorbell |
| interrupts for IPIs, then it could malfunction because of the lost |
| interrupt. |
| |
| This happens because a newly-generated doorbell interrupt is signalled |
| by setting vcpu->arch.doorbell_request to 1; the DPDES value in |
| vcpu->arch.vcore->dpdes is not updated, because it can only be updated |
| when holding the vcpu mutex, in order to avoid races. |
| |
| To fix this, we OR in vcpu->arch.doorbell_request when reading the |
| DPDES value. |
| |
| Cc: stable@vger.kernel.org # v4.13+ |
| Fixes: 579006944e0d ("KVM: PPC: Book3S HV: Virtualize doorbell facility on POWER9") |
| Signed-off-by: Paul Mackerras <paulus@ozlabs.org> |
| Tested-by: Alexey Kardashevskiy <aik@ozlabs.ru> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c |
| index 36d72e9faddf..f8975c620f41 100644 |
| --- a/arch/powerpc/kvm/book3s_hv.c |
| +++ b/arch/powerpc/kvm/book3s_hv.c |
| @@ -1678,7 +1678,14 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, |
| *val = get_reg_val(id, vcpu->arch.pspb); |
| break; |
| case KVM_REG_PPC_DPDES: |
| - *val = get_reg_val(id, vcpu->arch.vcore->dpdes); |
| + /* |
| + * On POWER9, where we are emulating msgsndp etc., |
| + * we return 1 bit for each vcpu, which can come from |
| + * either vcore->dpdes or doorbell_request. |
| + * On POWER8, doorbell_request is 0. |
| + */ |
| + *val = get_reg_val(id, vcpu->arch.vcore->dpdes | |
| + vcpu->arch.doorbell_request); |
| break; |
| case KVM_REG_PPC_VTB: |
| *val = get_reg_val(id, vcpu->arch.vcore->vtb); |
| -- |
| 2.7.4 |
| |