Add necessary logics for supporting activate/deactivate AVIC at runtime.

Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpa...@amd.com>
---
 arch/x86/kvm/svm.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 2e06ee2..a01bc6a 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -388,6 +388,7 @@ struct amd_svm_iommu_ir {
 static void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
 static void svm_flush_tlb(struct kvm_vcpu *vcpu, bool invalidate_gpa);
 static void svm_complete_interrupts(struct vcpu_svm *svm);
+static inline void avic_post_state_restore(struct kvm_vcpu *vcpu);
 
 static int nested_svm_exit_handled(struct vcpu_svm *svm);
 static int nested_svm_intercept(struct vcpu_svm *svm);
@@ -2365,6 +2366,10 @@ static void svm_vcpu_blocking(struct kvm_vcpu *vcpu)
 
 static void svm_vcpu_unblocking(struct kvm_vcpu *vcpu)
 {
+       if (kvm_check_request(KVM_REQ_APICV_ACTIVATE, vcpu))
+               kvm_vcpu_activate_apicv(vcpu);
+       if (kvm_check_request(KVM_REQ_APICV_DEACTIVATE, vcpu))
+               kvm_vcpu_deactivate_apicv(vcpu);
        avic_set_running(vcpu, true);
 }
 
@@ -5204,10 +5209,19 @@ static void svm_refresh_apicv_exec_ctrl(struct kvm_vcpu 
*vcpu)
        struct vcpu_svm *svm = to_svm(vcpu);
        struct vmcb *vmcb = svm->vmcb;
 
-       if (kvm_vcpu_apicv_active(vcpu))
+       if (kvm_vcpu_apicv_active(vcpu)) {
+               /**
+                * During AVIC temporary deactivation, guest could update
+                * APIC ID, DFR and LDR registers, which would not be trapped
+                * by avic_unaccelerated_access_interception(). In this case,
+                * we need to check and update the AVIC logical APIC ID table
+                * accordingly before re-activating.
+                */
+               avic_post_state_restore(vcpu);
                vmcb->control.int_ctl |= AVIC_ENABLE_MASK;
-       else
+       } else {
                vmcb->control.int_ctl &= ~AVIC_ENABLE_MASK;
+       }
        mark_dirty(vmcb, VMCB_AVIC);
 }
 
@@ -7283,6 +7297,14 @@ static bool svm_need_emulation_on_page_fault(struct 
kvm_vcpu *vcpu)
        return false;
 }
 
+static void svm_pre_update_apicv_exec_ctrl(struct kvm_vcpu *vcpu, bool 
activate)
+{
+       if (activate)
+               avic_setup_access_page(vcpu, false);
+       else
+               avic_destroy_access_page(vcpu);
+}
+
 static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .cpu_has_kvm_support = has_svm,
        .disabled_by_bios = is_disabled,
@@ -7360,6 +7382,7 @@ static bool svm_need_emulation_on_page_fault(struct 
kvm_vcpu *vcpu)
        .set_virtual_apic_mode = svm_set_virtual_apic_mode,
        .get_enable_apicv = svm_get_enable_apicv,
        .refresh_apicv_exec_ctrl = svm_refresh_apicv_exec_ctrl,
+       .pre_update_apicv_exec_ctrl = svm_pre_update_apicv_exec_ctrl,
        .load_eoi_exitmap = svm_load_eoi_exitmap,
        .hwapic_irr_update = svm_hwapic_irr_update,
        .hwapic_isr_update = svm_hwapic_isr_update,
-- 
1.8.3.1

Reply via email to