diff options
-rw-r--r-- | arch/x86/include/asm/vmx.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/mmu.c | 8 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 11 |
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: | |||
500 | static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) | 500 | static 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 | ||
321 | static inline bool cpu_has_vmx_ept_1g_page(void) | ||
322 | { | ||
323 | return !!(vmx_capability.ept & VMX_EPT_1GB_PAGE_BIT); | ||
324 | } | ||
325 | |||
321 | static inline int cpu_has_vmx_invept_individual_addr(void) | 326 | static 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 | ||
4039 | static int vmx_get_lpage_level(void) | 4044 | static 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 | ||
4044 | static inline u32 bit(int bitno) | 4053 | static inline u32 bit(int bitno) |