KVM_GUESTDBG_BLOCKIRQ relies on interrupts being injected using
standard kvm's inject_pending_event, and not via APICv/AVIC.
Since this is a debug feature, just inhibit APICv/AVIC while
KVM_GUESTDBG_BLOCKIRQ is in use on at least one vCPU.
Fixes: 61e5f69ef0837 ("KVM: x86: implement KVM_GUESTDBG_BLOCKIRQ")
Reported-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
Reviewed-by: Sean Christopherson <seanjc@google.com>
Tested-by: Sean Christopherson <seanjc@google.com>
Message-Id: <
20211108090245.166408-1-mlevitsk@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
 
 #define APICV_INHIBIT_REASON_IRQWIN     3
 #define APICV_INHIBIT_REASON_PIT_REINJ  4
 #define APICV_INHIBIT_REASON_X2APIC    5
+#define APICV_INHIBIT_REASON_BLOCKIRQ  6
 
 struct kvm_arch {
        unsigned long n_used_mmu_pages;
 
                          BIT(APICV_INHIBIT_REASON_NESTED) |
                          BIT(APICV_INHIBIT_REASON_IRQWIN) |
                          BIT(APICV_INHIBIT_REASON_PIT_REINJ) |
-                         BIT(APICV_INHIBIT_REASON_X2APIC);
+                         BIT(APICV_INHIBIT_REASON_X2APIC) |
+                         BIT(APICV_INHIBIT_REASON_BLOCKIRQ);
 
        return supported & BIT(bit);
 }
 
 static bool vmx_check_apicv_inhibit_reasons(ulong bit)
 {
        ulong supported = BIT(APICV_INHIBIT_REASON_DISABLE) |
-                         BIT(APICV_INHIBIT_REASON_HYPERV);
+                         BIT(APICV_INHIBIT_REASON_HYPERV) |
+                         BIT(APICV_INHIBIT_REASON_BLOCKIRQ);
 
        return supported & BIT(bit);
 }
 
        return ret;
 }
 
+static void kvm_arch_vcpu_guestdbg_update_apicv_inhibit(struct kvm *kvm)
+{
+       bool inhibit = false;
+       struct kvm_vcpu *vcpu;
+       int i;
+
+       down_write(&kvm->arch.apicv_update_lock);
+
+       kvm_for_each_vcpu(i, vcpu, kvm) {
+               if (vcpu->guest_debug & KVM_GUESTDBG_BLOCKIRQ) {
+                       inhibit = true;
+                       break;
+               }
+       }
+       __kvm_request_apicv_update(kvm, !inhibit, APICV_INHIBIT_REASON_BLOCKIRQ);
+       up_write(&kvm->arch.apicv_update_lock);
+}
+
 int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
                                        struct kvm_guest_debug *dbg)
 {
 
        static_call(kvm_x86_update_exception_bitmap)(vcpu);
 
+       kvm_arch_vcpu_guestdbg_update_apicv_inhibit(vcpu->kvm);
+
        r = 0;
 
 out: