Activate/deactivate AVIC requires setting/unsetting the memory region used for APIC_ACCESS_PAGE_PRIVATE_MEMSLOT. So, re-factor avic_init_access_page() to avic_setup_access_page() and add srcu_read_lock/unlock, which are needed to allow this function to be called during run-time. Also, introduce avic_destroy_access_page() to unset the page when deactivate AVIC. Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx> Cc: Radim Krčmář <rkrcmar@xxxxxxxxxx> Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx> --- arch/x86/kvm/svm.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index c33f02b4a19e..a23b1e77acb6 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1658,7 +1658,7 @@ static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu, * field of the VMCB. Therefore, we set up the * APIC_ACCESS_PAGE_PRIVATE_MEMSLOT (4KB) here. */ -static int avic_init_access_page(struct kvm_vcpu *vcpu) +static int avic_setup_access_page(struct kvm_vcpu *vcpu, bool init) { struct kvm *kvm = vcpu->kvm; int ret = 0; @@ -1667,10 +1667,14 @@ static int avic_init_access_page(struct kvm_vcpu *vcpu) if (kvm->arch.apic_access_page_done) goto out; + if (!init) + srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx); ret = __x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT, APIC_DEFAULT_PHYS_BASE, PAGE_SIZE); + if (!init) + vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); if (ret) goto out; @@ -1680,6 +1684,26 @@ static int avic_init_access_page(struct kvm_vcpu *vcpu) return ret; } +static void avic_destroy_access_page(struct kvm_vcpu *vcpu) +{ + struct kvm *kvm = vcpu->kvm; + + mutex_lock(&kvm->slots_lock); + + if (!kvm->arch.apic_access_page_done) + goto out; + + srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx); + __x86_set_memory_region(kvm, + APIC_ACCESS_PAGE_PRIVATE_MEMSLOT, + APIC_DEFAULT_PHYS_BASE, + 0); + vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); + kvm->arch.apic_access_page_done = false; +out: + mutex_unlock(&kvm->slots_lock); +} + static int avic_init_backing_page(struct kvm_vcpu *vcpu) { int ret; @@ -1687,7 +1711,7 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu) int id = vcpu->vcpu_id; struct vcpu_svm *svm = to_svm(vcpu); - ret = avic_init_access_page(vcpu); + ret = avic_setup_access_page(vcpu, true); if (ret) return ret; -- 2.17.1