KVM: x86: Track required APICv inhibits with variable, not callback
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>
This commit is contained in:
parent
e2ed3e64a2
commit
b3f257a846
@ -76,7 +76,6 @@ KVM_X86_OP(set_nmi_mask)
|
|||||||
KVM_X86_OP(enable_nmi_window)
|
KVM_X86_OP(enable_nmi_window)
|
||||||
KVM_X86_OP(enable_irq_window)
|
KVM_X86_OP(enable_irq_window)
|
||||||
KVM_X86_OP_OPTIONAL(update_cr8_intercept)
|
KVM_X86_OP_OPTIONAL(update_cr8_intercept)
|
||||||
KVM_X86_OP(check_apicv_inhibit_reasons)
|
|
||||||
KVM_X86_OP(refresh_apicv_exec_ctrl)
|
KVM_X86_OP(refresh_apicv_exec_ctrl)
|
||||||
KVM_X86_OP_OPTIONAL(hwapic_irr_update)
|
KVM_X86_OP_OPTIONAL(hwapic_irr_update)
|
||||||
KVM_X86_OP_OPTIONAL(hwapic_isr_update)
|
KVM_X86_OP_OPTIONAL(hwapic_isr_update)
|
||||||
|
@ -1623,6 +1623,7 @@ struct kvm_x86_ops {
|
|||||||
void (*enable_irq_window)(struct kvm_vcpu *vcpu);
|
void (*enable_irq_window)(struct kvm_vcpu *vcpu);
|
||||||
void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr);
|
void (*update_cr8_intercept)(struct kvm_vcpu *vcpu, int tpr, int irr);
|
||||||
bool (*check_apicv_inhibit_reasons)(enum kvm_apicv_inhibit reason);
|
bool (*check_apicv_inhibit_reasons)(enum kvm_apicv_inhibit reason);
|
||||||
|
const unsigned long required_apicv_inhibits;
|
||||||
bool allow_apicv_in_x2apic_without_x2apic_virtualization;
|
bool allow_apicv_in_x2apic_without_x2apic_virtualization;
|
||||||
void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
|
void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
|
||||||
void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
|
void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
|
||||||
|
@ -963,25 +963,6 @@ out:
|
|||||||
return ret;
|
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
|
static inline int
|
||||||
avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int cpu, bool r)
|
avic_update_iommu_vcpu_affinity(struct kvm_vcpu *vcpu, int cpu, bool r)
|
||||||
{
|
{
|
||||||
|
@ -4773,8 +4773,8 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
|
|||||||
.update_cr8_intercept = svm_update_cr8_intercept,
|
.update_cr8_intercept = svm_update_cr8_intercept,
|
||||||
.set_virtual_apic_mode = avic_refresh_virtual_apic_mode,
|
.set_virtual_apic_mode = avic_refresh_virtual_apic_mode,
|
||||||
.refresh_apicv_exec_ctrl = avic_refresh_apicv_exec_ctrl,
|
.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,
|
.apicv_post_state_restore = avic_apicv_post_state_restore,
|
||||||
|
.required_apicv_inhibits = AVIC_REQUIRED_APICV_INHIBITS,
|
||||||
|
|
||||||
.get_exit_info = svm_get_exit_info,
|
.get_exit_info = svm_get_exit_info,
|
||||||
|
|
||||||
|
@ -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;
|
extern struct kvm_x86_nested_ops svm_nested_ops;
|
||||||
|
|
||||||
/* avic.c */
|
/* 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);
|
bool avic_hardware_setup(struct kvm_x86_ops *ops);
|
||||||
int avic_ga_log_notifier(u32 ga_tag);
|
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_vcpu_put(struct kvm_vcpu *vcpu);
|
||||||
void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu);
|
void avic_apicv_post_state_restore(struct kvm_vcpu *vcpu);
|
||||||
void avic_refresh_apicv_exec_ctrl(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,
|
int avic_pi_update_irte(struct kvm *kvm, unsigned int host_irq,
|
||||||
uint32_t guest_irq, bool set);
|
uint32_t guest_irq, bool set);
|
||||||
void avic_vcpu_blocking(struct kvm_vcpu *vcpu);
|
void avic_vcpu_blocking(struct kvm_vcpu *vcpu);
|
||||||
|
@ -8023,18 +8023,16 @@ static void vmx_hardware_unsetup(void)
|
|||||||
free_kvm_area();
|
free_kvm_area();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool vmx_check_apicv_inhibit_reasons(enum kvm_apicv_inhibit reason)
|
#define VMX_REQUIRED_APICV_INHIBITS \
|
||||||
{
|
( \
|
||||||
ulong supported = BIT(APICV_INHIBIT_REASON_DISABLE) |
|
BIT(APICV_INHIBIT_REASON_DISABLE)| \
|
||||||
BIT(APICV_INHIBIT_REASON_ABSENT) |
|
BIT(APICV_INHIBIT_REASON_ABSENT) | \
|
||||||
BIT(APICV_INHIBIT_REASON_HYPERV) |
|
BIT(APICV_INHIBIT_REASON_HYPERV) | \
|
||||||
BIT(APICV_INHIBIT_REASON_BLOCKIRQ) |
|
BIT(APICV_INHIBIT_REASON_BLOCKIRQ) | \
|
||||||
BIT(APICV_INHIBIT_REASON_PHYSICAL_ID_ALIASED) |
|
BIT(APICV_INHIBIT_REASON_PHYSICAL_ID_ALIASED) | \
|
||||||
BIT(APICV_INHIBIT_REASON_APIC_ID_MODIFIED) |
|
BIT(APICV_INHIBIT_REASON_APIC_ID_MODIFIED) | \
|
||||||
BIT(APICV_INHIBIT_REASON_APIC_BASE_MODIFIED);
|
BIT(APICV_INHIBIT_REASON_APIC_BASE_MODIFIED) \
|
||||||
|
)
|
||||||
return supported & BIT(reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void vmx_vm_destroy(struct kvm *kvm)
|
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,
|
.refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl,
|
||||||
.load_eoi_exitmap = vmx_load_eoi_exitmap,
|
.load_eoi_exitmap = vmx_load_eoi_exitmap,
|
||||||
.apicv_post_state_restore = vmx_apicv_post_state_restore,
|
.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_irr_update = vmx_hwapic_irr_update,
|
||||||
.hwapic_isr_update = vmx_hwapic_isr_update,
|
.hwapic_isr_update = vmx_hwapic_isr_update,
|
||||||
.guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
|
.guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
|
||||||
|
@ -10112,7 +10112,7 @@ void __kvm_set_or_clear_apicv_inhibit(struct kvm *kvm,
|
|||||||
|
|
||||||
lockdep_assert_held_write(&kvm->arch.apicv_update_lock);
|
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;
|
return;
|
||||||
|
|
||||||
old = new = kvm->arch.apicv_inhibit_reasons;
|
old = new = kvm->arch.apicv_inhibit_reasons;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user