Skip to content

Commit

Permalink
kvm: x86: Unpin and remove kvm_arch->apic_access_page
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Tang Chen <[email protected]>
Signed-off-by: Paolo Bonzini <[email protected]>
  • Loading branch information
tang-chen authored and bonzini committed Sep 24, 2014
1 parent 38b9917 commit c24ae0d
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 9 deletions.
2 changes: 1 addition & 1 deletion arch/x86/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ struct kvm_arch {
struct kvm_apic_map *apic_map;

unsigned int tss_addr;
struct page *apic_access_page;
bool apic_access_page_done;

gpa_t wall_clock;

Expand Down
9 changes: 7 additions & 2 deletions arch/x86/kvm/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -4033,7 +4033,7 @@ static int alloc_apic_access_page(struct kvm *kvm)
int r = 0;

mutex_lock(&kvm->slots_lock);
if (kvm->arch.apic_access_page)
if (kvm->arch.apic_access_page_done)
goto out;
kvm_userspace_mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT;
kvm_userspace_mem.flags = 0;
Expand All @@ -4049,7 +4049,12 @@ static int alloc_apic_access_page(struct kvm *kvm)
goto out;
}

kvm->arch.apic_access_page = page;
/*
* Do not pin the page in memory, so that memory hot-unplug
* is able to migrate it.
*/
put_page(page);
kvm->arch.apic_access_page_done = true;
out:
mutex_unlock(&kvm->slots_lock);
return r;
Expand Down
22 changes: 16 additions & 6 deletions arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/*
Expand Down Expand Up @@ -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));
}

Expand Down

0 comments on commit c24ae0d

Please sign in to comment.