diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2009-06-11 11:07:44 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-09-10 01:32:56 -0400 |
commit | 54dee9933e8d93589ad63ec3d6be39f1921b0767 (patch) | |
tree | 77aa79604ddfb6f842e582e7b8ce7cdbc54b2060 | |
parent | 68f89400bc92421d6da22e1ec8e3ec599c3c8244 (diff) |
KVM: VMX: conditionally disable 2M pages
Disable usage of 2M pages if VMX_EPT_2MB_PAGE_BIT (bit 16) is clear
in MSR_IA32_VMX_EPT_VPID_CAP and EPT is enabled.
[avi: s/largepages_disabled/largepages_enabled/ to avoid negative logic]
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r-- | arch/x86/kvm/vmx.c | 3 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 14 |
3 files changed, 16 insertions, 2 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 94c07ada103e..fc8d49c6bc51 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -1381,6 +1381,9 @@ static __init int hardware_setup(void) | |||
1381 | if (!cpu_has_vmx_tpr_shadow()) | 1381 | if (!cpu_has_vmx_tpr_shadow()) |
1382 | kvm_x86_ops->update_cr8_intercept = NULL; | 1382 | kvm_x86_ops->update_cr8_intercept = NULL; |
1383 | 1383 | ||
1384 | if (enable_ept && !cpu_has_vmx_ept_2m_page()) | ||
1385 | kvm_disable_largepages(); | ||
1386 | |||
1384 | return alloc_kvm_area(); | 1387 | return alloc_kvm_area(); |
1385 | } | 1388 | } |
1386 | 1389 | ||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index c6e4d02067fe..6988858dc56e 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -224,6 +224,7 @@ int kvm_arch_set_memory_region(struct kvm *kvm, | |||
224 | struct kvm_userspace_memory_region *mem, | 224 | struct kvm_userspace_memory_region *mem, |
225 | struct kvm_memory_slot old, | 225 | struct kvm_memory_slot old, |
226 | int user_alloc); | 226 | int user_alloc); |
227 | void kvm_disable_largepages(void); | ||
227 | void kvm_arch_flush_shadow(struct kvm *kvm); | 228 | void kvm_arch_flush_shadow(struct kvm *kvm); |
228 | gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn); | 229 | gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn); |
229 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn); | 230 | struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn); |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 777fe533cfe7..48d5e697bf44 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -85,6 +85,8 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl, | |||
85 | 85 | ||
86 | static bool kvm_rebooting; | 86 | static bool kvm_rebooting; |
87 | 87 | ||
88 | static bool largepages_enabled = true; | ||
89 | |||
88 | #ifdef KVM_CAP_DEVICE_ASSIGNMENT | 90 | #ifdef KVM_CAP_DEVICE_ASSIGNMENT |
89 | static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head, | 91 | static struct kvm_assigned_dev_kernel *kvm_find_assigned_dev(struct list_head *head, |
90 | int assigned_dev_id) | 92 | int assigned_dev_id) |
@@ -1174,9 +1176,11 @@ int __kvm_set_memory_region(struct kvm *kvm, | |||
1174 | ugfn = new.userspace_addr >> PAGE_SHIFT; | 1176 | ugfn = new.userspace_addr >> PAGE_SHIFT; |
1175 | /* | 1177 | /* |
1176 | * If the gfn and userspace address are not aligned wrt each | 1178 | * If the gfn and userspace address are not aligned wrt each |
1177 | * other, disable large page support for this slot | 1179 | * other, or if explicitly asked to, disable large page |
1180 | * support for this slot | ||
1178 | */ | 1181 | */ |
1179 | if ((base_gfn ^ ugfn) & (KVM_PAGES_PER_HPAGE - 1)) | 1182 | if ((base_gfn ^ ugfn) & (KVM_PAGES_PER_HPAGE - 1) || |
1183 | !largepages_enabled) | ||
1180 | for (i = 0; i < largepages; ++i) | 1184 | for (i = 0; i < largepages; ++i) |
1181 | new.lpage_info[i].write_count = 1; | 1185 | new.lpage_info[i].write_count = 1; |
1182 | } | 1186 | } |
@@ -1291,6 +1295,12 @@ out: | |||
1291 | return r; | 1295 | return r; |
1292 | } | 1296 | } |
1293 | 1297 | ||
1298 | void kvm_disable_largepages(void) | ||
1299 | { | ||
1300 | largepages_enabled = false; | ||
1301 | } | ||
1302 | EXPORT_SYMBOL_GPL(kvm_disable_largepages); | ||
1303 | |||
1294 | int is_error_page(struct page *page) | 1304 | int is_error_page(struct page *page) |
1295 | { | 1305 | { |
1296 | return page == bad_page; | 1306 | return page == bad_page; |