Re-queue an APICv update request if deleting the APIC access page memslot
fails when trying to (permanently) inhibit the APIC access page. Sadly,
memslot deletion requires a memory allocation and so can fail even if KVM
does everything right.
Fixes: 2008fab34530 ("KVM: x86: Inhibit APIC memslot if x2APIC and AVIC are
enabled")
Signed-off-by: Sean Christopherson <[email protected]>
---
arch/x86/kvm/lapic.c | 38 ++++++++++++++++++++++----------------
1 file changed, 22 insertions(+), 16 deletions(-)
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index ecf611845fb1..c20e2a25834f 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2931,6 +2931,7 @@
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_alloc_apic_access_page);
void kvm_inhibit_apic_access_page(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = vcpu->kvm;
+ void __user *p;
if (!kvm->arch.apic_access_memslot_enabled)
return;
@@ -2939,25 +2940,30 @@ void kvm_inhibit_apic_access_page(struct kvm_vcpu *vcpu)
mutex_lock(&kvm->slots_lock);
- if (kvm->arch.apic_access_memslot_enabled) {
- __x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
0, 0);
- /*
- * Clear "enabled" after the memslot is deleted so that a
- * different vCPU doesn't get a false negative when checking
- * the flag out of slots_lock. No additional memory barrier is
- * needed as modifying memslots requires waiting other vCPUs to
- * drop SRCU (see above), and false positives are ok as the
- * flag is rechecked after acquiring slots_lock.
- */
- kvm->arch.apic_access_memslot_enabled = false;
+ if (!kvm->arch.apic_access_memslot_enabled)
+ goto out;
- /*
- * Mark the memslot as inhibited to prevent reallocating the
- * memslot during vCPU creation, e.g. if a vCPU is hotplugged.
- */
- kvm->arch.apic_access_memslot_inhibited = true;
+ p = __x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT, 0,
0);
+ if (IS_ERR(p)) {
+ kvm_make_request(KVM_REQ_APICV_UPDATE, vcpu);
+ goto out;
}
+ /*
+ * Clear "enabled" after the memslot is deleted so that a different vCPU
+ * doesn't get a false negative when checking the flag out of
slots_lock.
+ * No additional memory barrier is needed as modifying memslots requires
+ * waiting other vCPUs to drop SRCU (see above), and false positives are
+ * ok as the flag is rechecked after acquiring slots_lock.
+ */
+ kvm->arch.apic_access_memslot_enabled = false;
+
+ /*
+ * Mark the memslot as inhibited to prevent reallocating the memslot
+ * during vCPU creation, e.g. if a vCPU is hotplugged.
+ */
+ kvm->arch.apic_access_memslot_inhibited = true;
+out:
mutex_unlock(&kvm->slots_lock);
kvm_vcpu_srcu_read_lock(vcpu);
--
2.56.0.385.gac671c819a-goog