summaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
authorTang Chen2014-09-24 09:57:58 +0200
committerPaolo Bonzini2014-09-24 14:08:01 +0200
commitc24ae0dcd3e8695efa43e71704d1fc4bc7e29e9b (patch)
tree9cd5baf0a56807097bebe6ccea30664e581c61ef /arch/x86/kvm/x86.c
parentkvm: vmx: Implement set_apic_access_page_addr (diff)
downloadkernel-qcow2-linux-c24ae0dcd3e8695efa43e71704d1fc4bc7e29e9b.tar.gz
kernel-qcow2-linux-c24ae0dcd3e8695efa43e71704d1fc4bc7e29e9b.tar.xz
kernel-qcow2-linux-c24ae0dcd3e8695efa43e71704d1fc4bc7e29e9b.zip
kvm: x86: Unpin and remove kvm_arch->apic_access_page
In order to make the APIC access page migratable, stop pinning it in memory. And because the APIC access page is not pinned in memory, we can remove kvm_arch->apic_access_page. When we need to write its physical address into vmcs, we use gfn_to_page() to get its page struct, which is needed to call page_to_phys(); the page is then immediately unpinned. Suggested-by: Gleb Natapov <gleb@kernel.org> Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index c1412f5d93db..6857257f3810 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6028,19 +6028,31 @@ static void kvm_vcpu_flush_tlb(struct kvm_vcpu *vcpu)
void kvm_vcpu_reload_apic_access_page(struct kvm_vcpu *vcpu)
{
+ struct page *page = NULL;
+
if (!kvm_x86_ops->set_apic_access_page_addr)
return;
- vcpu->kvm->arch.apic_access_page = gfn_to_page(vcpu->kvm,
- APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
- kvm_x86_ops->set_apic_access_page_addr(vcpu,
- page_to_phys(vcpu->kvm->arch.apic_access_page));
+ page = gfn_to_page(vcpu->kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
+ kvm_x86_ops->set_apic_access_page_addr(vcpu, page_to_phys(page));
+
+ /*
+ * Do not pin apic access page in memory, the MMU notifier
+ * will call us again if it is migrated or swapped out.
+ */
+ put_page(page);
}
EXPORT_SYMBOL_GPL(kvm_vcpu_reload_apic_access_page);
void kvm_arch_mmu_notifier_invalidate_page(struct kvm *kvm,
unsigned long address)
{
+ /*
+ * The physical address of apic access page is stored in the VMCS.
+ * Update it when it becomes invalid.
+ */
+ if (address == gfn_to_hva(kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT))
+ kvm_make_all_cpus_request(kvm, KVM_REQ_APIC_PAGE_RELOAD);
}
/*
@@ -7297,8 +7309,6 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
kfree(kvm->arch.vpic);
kfree(kvm->arch.vioapic);
kvm_free_vcpus(kvm);
- if (kvm->arch.apic_access_page)
- put_page(kvm->arch.apic_access_page);
kfree(rcu_dereference_check(kvm->arch.apic_map, 1));
}