diff options
author | Tang Chen <tangchen@cn.fujitsu.com> | 2014-09-16 06:41:58 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-09-17 07:10:11 -0400 |
commit | a255d4795f83cf3e6a1c7d5ab998392d9413298c (patch) | |
tree | 79c39a27f4b9e3eb0707e6726d11b80397b6d996 | |
parent | 80ce1639727e9d38729c34f162378508c307ca25 (diff) |
kvm: Remove ept_identity_pagetable from struct kvm_arch.
kvm_arch->ept_identity_pagetable holds the ept identity pagetable page. But
it is never used to refer to the page at all.
In vcpu initialization, it indicates two things:
1. indicates if ept page is allocated
2. indicates if a memory slot for identity page is initialized
Actually, kvm_arch->ept_identity_pagetable_done is enough to tell if the ept
identity pagetable is initialized. So we can remove ept_identity_pagetable.
NOTE: In the original code, ept identity pagetable page is pinned in memroy.
As a result, it cannot be migrated/hot-removed. After this patch, since
kvm_arch->ept_identity_pagetable is removed, ept identity pagetable page
is no longer pinned in memory. And it can be migrated/hot-removed.
Signed-off-by: Tang Chen <tangchen@cn.fujitsu.com>
Reviewed-by: Gleb Natapov <gleb@kernel.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 47 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 2 |
3 files changed, 22 insertions, 28 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 2dbde3b7446c..028df8dc538e 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -578,7 +578,6 @@ struct kvm_arch { | |||
578 | 578 | ||
579 | gpa_t wall_clock; | 579 | gpa_t wall_clock; |
580 | 580 | ||
581 | struct page *ept_identity_pagetable; | ||
582 | bool ept_identity_pagetable_done; | 581 | bool ept_identity_pagetable_done; |
583 | gpa_t ept_identity_map_addr; | 582 | gpa_t ept_identity_map_addr; |
584 | 583 | ||
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 5db47db6574b..5de0d7b1d8a9 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -767,6 +767,7 @@ static u32 vmx_segment_access_rights(struct kvm_segment *var); | |||
767 | static void vmx_sync_pir_to_irr_dummy(struct kvm_vcpu *vcpu); | 767 | static void vmx_sync_pir_to_irr_dummy(struct kvm_vcpu *vcpu); |
768 | static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx); | 768 | static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx); |
769 | static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx); | 769 | static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx); |
770 | static int alloc_identity_pagetable(struct kvm *kvm); | ||
770 | 771 | ||
771 | static DEFINE_PER_CPU(struct vmcs *, vmxarea); | 772 | static DEFINE_PER_CPU(struct vmcs *, vmxarea); |
772 | static DEFINE_PER_CPU(struct vmcs *, current_vmcs); | 773 | static DEFINE_PER_CPU(struct vmcs *, current_vmcs); |
@@ -3962,21 +3963,27 @@ out: | |||
3962 | 3963 | ||
3963 | static int init_rmode_identity_map(struct kvm *kvm) | 3964 | static int init_rmode_identity_map(struct kvm *kvm) |
3964 | { | 3965 | { |
3965 | int i, idx, r, ret; | 3966 | int i, idx, r, ret = 0; |
3966 | pfn_t identity_map_pfn; | 3967 | pfn_t identity_map_pfn; |
3967 | u32 tmp; | 3968 | u32 tmp; |
3968 | 3969 | ||
3969 | if (!enable_ept) | 3970 | if (!enable_ept) |
3970 | return 1; | 3971 | return 1; |
3971 | if (unlikely(!kvm->arch.ept_identity_pagetable)) { | 3972 | |
3972 | printk(KERN_ERR "EPT: identity-mapping pagetable " | 3973 | /* Protect kvm->arch.ept_identity_pagetable_done. */ |
3973 | "haven't been allocated!\n"); | 3974 | mutex_lock(&kvm->slots_lock); |
3974 | return 0; | 3975 | |
3976 | if (likely(kvm->arch.ept_identity_pagetable_done)) { | ||
3977 | ret = 1; | ||
3978 | goto out2; | ||
3975 | } | 3979 | } |
3976 | if (likely(kvm->arch.ept_identity_pagetable_done)) | 3980 | |
3977 | return 1; | ||
3978 | ret = 0; | ||
3979 | identity_map_pfn = kvm->arch.ept_identity_map_addr >> PAGE_SHIFT; | 3981 | identity_map_pfn = kvm->arch.ept_identity_map_addr >> PAGE_SHIFT; |
3982 | |||
3983 | r = alloc_identity_pagetable(kvm); | ||
3984 | if (r) | ||
3985 | goto out2; | ||
3986 | |||
3980 | idx = srcu_read_lock(&kvm->srcu); | 3987 | idx = srcu_read_lock(&kvm->srcu); |
3981 | r = kvm_clear_guest_page(kvm, identity_map_pfn, 0, PAGE_SIZE); | 3988 | r = kvm_clear_guest_page(kvm, identity_map_pfn, 0, PAGE_SIZE); |
3982 | if (r < 0) | 3989 | if (r < 0) |
@@ -3994,6 +4001,9 @@ static int init_rmode_identity_map(struct kvm *kvm) | |||
3994 | ret = 1; | 4001 | ret = 1; |
3995 | out: | 4002 | out: |
3996 | srcu_read_unlock(&kvm->srcu, idx); | 4003 | srcu_read_unlock(&kvm->srcu, idx); |
4004 | |||
4005 | out2: | ||
4006 | mutex_unlock(&kvm->slots_lock); | ||
3997 | return ret; | 4007 | return ret; |
3998 | } | 4008 | } |
3999 | 4009 | ||
@@ -4043,31 +4053,20 @@ out: | |||
4043 | 4053 | ||
4044 | static int alloc_identity_pagetable(struct kvm *kvm) | 4054 | static int alloc_identity_pagetable(struct kvm *kvm) |
4045 | { | 4055 | { |
4046 | struct page *page; | 4056 | /* Called with kvm->slots_lock held. */ |
4057 | |||
4047 | struct kvm_userspace_memory_region kvm_userspace_mem; | 4058 | struct kvm_userspace_memory_region kvm_userspace_mem; |
4048 | int r = 0; | 4059 | int r = 0; |
4049 | 4060 | ||
4050 | mutex_lock(&kvm->slots_lock); | 4061 | BUG_ON(kvm->arch.ept_identity_pagetable_done); |
4051 | if (kvm->arch.ept_identity_pagetable) | 4062 | |
4052 | goto out; | ||
4053 | kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT; | 4063 | kvm_userspace_mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT; |
4054 | kvm_userspace_mem.flags = 0; | 4064 | kvm_userspace_mem.flags = 0; |
4055 | kvm_userspace_mem.guest_phys_addr = | 4065 | kvm_userspace_mem.guest_phys_addr = |
4056 | kvm->arch.ept_identity_map_addr; | 4066 | kvm->arch.ept_identity_map_addr; |
4057 | kvm_userspace_mem.memory_size = PAGE_SIZE; | 4067 | kvm_userspace_mem.memory_size = PAGE_SIZE; |
4058 | r = __kvm_set_memory_region(kvm, &kvm_userspace_mem); | 4068 | r = __kvm_set_memory_region(kvm, &kvm_userspace_mem); |
4059 | if (r) | ||
4060 | goto out; | ||
4061 | |||
4062 | page = gfn_to_page(kvm, kvm->arch.ept_identity_map_addr >> PAGE_SHIFT); | ||
4063 | if (is_error_page(page)) { | ||
4064 | r = -EFAULT; | ||
4065 | goto out; | ||
4066 | } | ||
4067 | 4069 | ||
4068 | kvm->arch.ept_identity_pagetable = page; | ||
4069 | out: | ||
4070 | mutex_unlock(&kvm->slots_lock); | ||
4071 | return r; | 4070 | return r; |
4072 | } | 4071 | } |
4073 | 4072 | ||
@@ -7758,8 +7757,6 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id) | |||
7758 | kvm->arch.ept_identity_map_addr = | 7757 | kvm->arch.ept_identity_map_addr = |
7759 | VMX_EPT_IDENTITY_PAGETABLE_ADDR; | 7758 | VMX_EPT_IDENTITY_PAGETABLE_ADDR; |
7760 | err = -ENOMEM; | 7759 | err = -ENOMEM; |
7761 | if (alloc_identity_pagetable(kvm) != 0) | ||
7762 | goto free_vmcs; | ||
7763 | if (!init_rmode_identity_map(kvm)) | 7760 | if (!init_rmode_identity_map(kvm)) |
7764 | goto free_vmcs; | 7761 | goto free_vmcs; |
7765 | } | 7762 | } |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 68660b31457e..2d7f65daa8d0 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -7273,8 +7273,6 @@ void kvm_arch_destroy_vm(struct kvm *kvm) | |||
7273 | kvm_free_vcpus(kvm); | 7273 | kvm_free_vcpus(kvm); |
7274 | if (kvm->arch.apic_access_page) | 7274 | if (kvm->arch.apic_access_page) |
7275 | put_page(kvm->arch.apic_access_page); | 7275 | put_page(kvm->arch.apic_access_page); |
7276 | if (kvm->arch.ept_identity_pagetable) | ||
7277 | put_page(kvm->arch.ept_identity_pagetable); | ||
7278 | kfree(rcu_dereference_check(kvm->arch.apic_map, 1)); | 7276 | kfree(rcu_dereference_check(kvm->arch.apic_map, 1)); |
7279 | } | 7277 | } |
7280 | 7278 | ||