aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/vmx.h1
-rw-r--r--arch/x86/kvm/mmu.c8
-rw-r--r--arch/x86/kvm/vmx.c11
3 files changed, 16 insertions, 4 deletions
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 713ed9a5b1d3..43f1e9b45917 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -364,6 +364,7 @@ enum vmcs_field {
364#define VMX_EPTP_UC_BIT (1ull << 8) 364#define VMX_EPTP_UC_BIT (1ull << 8)
365#define VMX_EPTP_WB_BIT (1ull << 14) 365#define VMX_EPTP_WB_BIT (1ull << 14)
366#define VMX_EPT_2MB_PAGE_BIT (1ull << 16) 366#define VMX_EPT_2MB_PAGE_BIT (1ull << 16)
367#define VMX_EPT_1GB_PAGE_BIT (1ull << 17)
367#define VMX_EPT_EXTENT_INDIVIDUAL_BIT (1ull << 24) 368#define VMX_EPT_EXTENT_INDIVIDUAL_BIT (1ull << 24)
368#define VMX_EPT_EXTENT_CONTEXT_BIT (1ull << 25) 369#define VMX_EPT_EXTENT_CONTEXT_BIT (1ull << 25)
369#define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26) 370#define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26)
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 12ccf14f8539..4f5508c35100 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -500,8 +500,7 @@ out:
500static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) 500static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)
501{ 501{
502 struct kvm_memory_slot *slot; 502 struct kvm_memory_slot *slot;
503 int host_level; 503 int host_level, level, max_level;
504 int level = PT_PAGE_TABLE_LEVEL;
505 504
506 slot = gfn_to_memslot(vcpu->kvm, large_gfn); 505 slot = gfn_to_memslot(vcpu->kvm, large_gfn);
507 if (slot && slot->dirty_bitmap) 506 if (slot && slot->dirty_bitmap)
@@ -512,7 +511,10 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)
512 if (host_level == PT_PAGE_TABLE_LEVEL) 511 if (host_level == PT_PAGE_TABLE_LEVEL)
513 return host_level; 512 return host_level;
514 513
515 for (level = PT_DIRECTORY_LEVEL; level <= host_level; ++level) 514 max_level = kvm_x86_ops->get_lpage_level() < host_level ?
515 kvm_x86_ops->get_lpage_level() : host_level;
516
517 for (level = PT_DIRECTORY_LEVEL; level <= max_level; ++level)
516 if (has_wrprotected_page(vcpu->kvm, large_gfn, level)) 518 if (has_wrprotected_page(vcpu->kvm, large_gfn, level))
517 break; 519 break;
518 520
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 0fd0892553ec..9b197b25b66d 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -318,6 +318,11 @@ static inline bool cpu_has_vmx_ept_2m_page(void)
318 return !!(vmx_capability.ept & VMX_EPT_2MB_PAGE_BIT); 318 return !!(vmx_capability.ept & VMX_EPT_2MB_PAGE_BIT);
319} 319}
320 320
321static inline bool cpu_has_vmx_ept_1g_page(void)
322{
323 return !!(vmx_capability.ept & VMX_EPT_1GB_PAGE_BIT);
324}
325
321static inline int cpu_has_vmx_invept_individual_addr(void) 326static inline int cpu_has_vmx_invept_individual_addr(void)
322{ 327{
323 return !!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT); 328 return !!(vmx_capability.ept & VMX_EPT_EXTENT_INDIVIDUAL_BIT);
@@ -4038,7 +4043,11 @@ static const struct trace_print_flags vmx_exit_reasons_str[] = {
4038 4043
4039static int vmx_get_lpage_level(void) 4044static int vmx_get_lpage_level(void)
4040{ 4045{
4041 return PT_DIRECTORY_LEVEL; 4046 if (enable_ept && !cpu_has_vmx_ept_1g_page())
4047 return PT_DIRECTORY_LEVEL;
4048 else
4049 /* For shadow and EPT supported 1GB page */
4050 return PT_PDPE_LEVEL;
4042} 4051}
4043 4052
4044static inline u32 bit(int bitno) 4053static inline u32 bit(int bitno)