KVM: x86: Track required APICv inhibits with variable, not callback
authorSean Christopherson <seanjc@google.com>
Fri, 6 Jan 2023 01:13:04 +0000 (01:13 +0000)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 13 Jan 2023 15:45:34 +0000 (10:45 -0500)
Track the per-vendor required APICv inhibits with a variable instead of
calling into vendor code every time KVM wants to query the set of
required inhibits.  The required inhibits are a property of the vendor's
virtualization architecture, i.e. are 100% static.

Using a variable allows the compiler to inline the check, e.g. generate
a single-uop TEST+Jcc, and thus eliminates any desire to avoid checking
inhibits for performance reasons.

No functional change intended.

Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20230106011306.85230-32-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/kvm-x86-ops.h
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/svm/avic.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/svm/svm.h
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/x86.c

index abccd51..84f43ca 100644 (file)
@@ -76,7 +76,6 @@ KVM_X86_OP(set_nmi_mask)
 KVM_X86_OP(enable_nmi_window)
 KVM_X86_OP(enable_irq_window)
 KVM_X86_OP_OPTIONAL(update_cr8_intercept)
-KVM_X86_OP(check_apicv_inhibit_reasons)
 KVM_X86_OP(refresh_apicv_exec_ctrl)
 KVM_X86_OP_OPTIONAL(hwapic_irr_update)
 KVM_X86_OP_OPTIONAL(hwapic_isr_update)
index b41a01b..7ca8547 100644 (file)
@@ -1623,6 +1623,7 @@ struct kvm_x86_ops {
        void (*enable_irq_window)(struct kvm_vcpu *vcpu);
        void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr);
        bool (*check_apicv_inhibit_reasons)(enum kvm_apicv_inhibit reason);
+       const unsigned long required_apicv_inhibits;
        bool allow_apicv_in_x2apic_without_x2apic_virtualization;
        void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
        void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
index 80f346b..14677bc 100644 (file)
@@ -963,25 +963,6 @@ out:
        return ret;
 }
 
-bool avic_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason)
-{
-       ulong supported = BIT(APICV_INHIBIT_REASON_DISABLE) |
-                         BIT(APICV_INHIBIT_REASON_ABSENT) |
-                         BIT(APICV_INHIBIT_REASON_HYPERV) |
-                         BIT(APICV_INHIBIT_REASON_NESTED) |
-                         BIT(APICV_INHIBIT_REASON_IRQWIN) |
-                         BIT(APICV_INHIBIT_REASON_PIT_REINJ) |
-                         BIT(APICV_INHIBIT_REASON_BLOCKIRQ) |
-                         BIT(APICV_INHIBIT_REASON_SEV)      |
-                         BIT(APICV_INHIBIT_REASON_PHYSICAL_ID_ALIASED) |
-                         BIT(APICV_INHIBIT_REASON_APIC_ID_MODIFIED) |
-                         BIT(APICV_INHIBIT_REASON_APIC_BASE_MODIFIED) |
-                         BIT(APICV_INHIBIT_REASON_LOGICAL_ID_ALIASED);
-
-       return supported & BIT(reason);
-}
-
-
 static inline int
 avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int cpu, bool r)
 {
index 9f172f2..f2453df 100644 (file)
@@ -4773,8 +4773,8 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
        .update_cr8_intercept = svm_update_cr8_intercept,
        .set_virtual_apic_mode = avic_refresh_virtual_apic_mode,
        .refresh_apicv_exec_ctrl = avic_refresh_apicv_exec_ctrl,
-       .check_apicv_inhibit_reasons = avic_check_apicv_inhibit_reasons,
        .apicv_post_state_restore = avic_apicv_post_state_restore,
+       .required_apicv_inhibits = AVIC_REQUIRED_APICV_INHIBITS,
 
        .get_exit_info = svm_get_exit_info,
 
index 546825c..41eabb0 100644 (file)
@@ -621,6 +621,21 @@ void svm_switch_vmcb(struct vcpu_svm *svm, struct kvm_vmcb_info *target_vmcb);
 extern struct kvm_x86_nested_ops svm_nested_ops;
 
 /* avic.c */
+#define AVIC_REQUIRED_APICV_INHIBITS                   \
+(                                                      \
+       BIT(APICV_INHIBIT_REASON_DISABLE) |             \
+       BIT(APICV_INHIBIT_REASON_ABSENT) |              \
+       BIT(APICV_INHIBIT_REASON_HYPERV) |              \
+       BIT(APICV_INHIBIT_REASON_NESTED) |              \
+       BIT(APICV_INHIBIT_REASON_IRQWIN) |              \
+       BIT(APICV_INHIBIT_REASON_PIT_REINJ) |           \
+       BIT(APICV_INHIBIT_REASON_BLOCKIRQ) |            \
+       BIT(APICV_INHIBIT_REASON_SEV)      |            \
+       BIT(APICV_INHIBIT_REASON_PHYSICAL_ID_ALIASED) | \
+       BIT(APICV_INHIBIT_REASON_APIC_ID_MODIFIED) |    \
+       BIT(APICV_INHIBIT_REASON_APIC_BASE_MODIFIED) |  \
+       BIT(APICV_INHIBIT_REASON_LOGICAL_ID_ALIASED)    \
+)
 
 bool avic_hardware_setup(struct kvm_x86_ops *ops);
 int avic_ga_log_notifier(u32 ga_tag);
@@ -634,7 +649,6 @@ void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
 void avic_vcpu_put(struct kvm_vcpu *vcpu);
 void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu);
 void avic_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu);
-bool avic_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason);
 int avic_pi_update_irte(struct kvm *kvm, unsigned int host_irq,
                        uint32_t guest_irq, bool set);
 void avic_vcpu_blocking(struct kvm_vcpu *vcpu);
index ef84d11..ad2ac66 100644 (file)
@@ -8023,18 +8023,16 @@ static void vmx_hardware_unsetup(void)
        free_kvm_area();
 }
 
-static bool vmx_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason)
-{
-       ulong supported = BIT(APICV_INHIBIT_REASON_DISABLE) |
-                         BIT(APICV_INHIBIT_REASON_ABSENT) |
-                         BIT(APICV_INHIBIT_REASON_HYPERV) |
-                         BIT(APICV_INHIBIT_REASON_BLOCKIRQ) |
-                         BIT(APICV_INHIBIT_REASON_PHYSICAL_ID_ALIASED) |
-                         BIT(APICV_INHIBIT_REASON_APIC_ID_MODIFIED) |
-                         BIT(APICV_INHIBIT_REASON_APIC_BASE_MODIFIED);
-
-       return supported & BIT(reason);
-}
+#define VMX_REQUIRED_APICV_INHIBITS                    \
+(                                                      \
+       BIT(APICV_INHIBIT_REASON_DISABLE)|              \
+       BIT(APICV_INHIBIT_REASON_ABSENT) |              \
+       BIT(APICV_INHIBIT_REASON_HYPERV) |              \
+       BIT(APICV_INHIBIT_REASON_BLOCKIRQ) |            \
+       BIT(APICV_INHIBIT_REASON_PHYSICAL_ID_ALIASED) | \
+       BIT(APICV_INHIBIT_REASON_APIC_ID_MODIFIED) |    \
+       BIT(APICV_INHIBIT_REASON_APIC_BASE_MODIFIED)    \
+)
 
 static void vmx_vm_destroy(struct kvm *kvm)
 {
@@ -8118,7 +8116,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
        .refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl,
        .load_eoi_exitmap = vmx_load_eoi_exitmap,
        .apicv_post_state_restore = vmx_apicv_post_state_restore,
-       .check_apicv_inhibit_reasons = vmx_check_apicv_inhibit_reasons,
+       .required_apicv_inhibits = VMX_REQUIRED_APICV_INHIBITS,
        .hwapic_irr_update = vmx_hwapic_irr_update,
        .hwapic_isr_update = vmx_hwapic_isr_update,
        .guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
index 1abe3f1..5becce5 100644 (file)
@@ -10112,7 +10112,7 @@ void __kvm_set_or_clear_apicv_inhibit(struct kvm *kvm,
 
        lockdep_assert_held_write(&kvm->arch.apicv_update_lock);
 
-       if (!static_call(kvm_x86_check_apicv_inhibit_reasons)(reason))
+       if (!(kvm_x86_ops.required_apicv_inhibits & BIT(reason)))
                return;
 
        old = new = kvm->arch.apicv_inhibit_reasons;