EPT 1GB page support
v2 cover EPT 1GB page support
PATCH v2 1/4 KVM: x86: Moving PT_*_LEVEL to mmu.h
We can use them in x86.c and vmx.c now...
--- arch/x86/kvm/mmu.c | 4 ---- arch/x86/kvm/mmu.h | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-)
arch/x86/kvm/mmu.c +0 -4
@@ -142,10 +142,6 @@ module_param(oos_shadow, bool, 0644);#define PFERR_RSVD_MASK (1U << 3)#define PFERR_FETCH_MASK (1U << 4) -#define PT_PDPE_LEVEL 3 -#define PT_DIRECTORY_LEVEL 2 -#define PT_PAGE_TABLE_LEVEL 1 -#define RMAP_EXT 4#define ACC_EXEC_MASK 1
arch/x86/kvm/mmu.h +4 -0
@@ -38,6 +38,10 @@#define PT32_ROOT_LEVEL 2#define PT32E_ROOT_LEVEL 3 +#define PT_PDPE_LEVEL 3 +#define PT_DIRECTORY_LEVEL 2 +#define PT_PAGE_TABLE_LEVEL 1 +int kvm_mmu_get_spte_hierarchy (struct kvm_vcpu *vcpu,u64 addr,u64 sptes[4 ]);static inline void kvm_mmu_free_some_pages (struct kvm_vcpu *vcpu)
Signature · 1 line
1.5.4.5
PATCH v2 2/4 KVM: x86: Rename gb_page_enable() to get_lpage_level() in kvm_x86_ops
In reply to Sheng YangThen the callback can provide the maximum supported large page level, which is more flexible.
Also move the gb page support into x86_64 specific.
--- arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kvm/svm.c | 6 +++--- arch/x86/kvm/vmx.c | 6 +++--- arch/x86/kvm/x86.c | 4 +++- 4 files changed, 10 insertions(+), 8 deletions(-)
arch/x86/include/asm/kvm_host.h +1 -1
@@ -520,7 +520,7 @@ struct kvm_x86_ops {int (*set_tss_addr)(struct kvm *kvm,unsigned int addr);int (*get_tdp_level)(void );u64 (*get_mt_mask)(struct kvm_vcpu *vcpu,gfn_t gfn,bool is_mmio); -bool (*gb_page_enable)(void ); +int (*get_lpage_level)(void );bool (*rdtscp_supported)(void );const struct trace_print_flags *exit_reasons_str;
arch/x86/kvm/svm.c +3 -3
@@ -2911,9 +2911,9 @@ static const struct trace_print_flags svm_exit_reasons_str[] = { { -1, NULL } }; -static bool svm_gb_page_enable (void ) +static int svm_get_lpage_level (void ) { -return true; +return PT_PDPE_LEVEL ; }static bool svm_rdtscp_supported (void )
@@ -2986,7 +2986,7 @@ static struct kvm_x86_ops svm_x86_ops = { .get_mt_mask = svm_get_mt_mask, .exit_reasons_str = svm_exit_reasons_str, - .gb_page_enable = svm_gb_page_enable, + .get_lpage_level = svm_get_lpage_level, .cpuid_update = svm_cpuid_update,
arch/x86/kvm/vmx.c +3 -3
@@ -4011,9 +4011,9 @@ static const struct trace_print_flags vmx_exit_reasons_str[] = { { -1, NULL } }; -static bool vmx_gb_page_enable (void ) +static int vmx_get_lpage_level (void ) { -return false; +return PT_DIRECTORY_LEVEL ; }static inline u32 bit (int bitno)
@@ -4106,7 +4106,7 @@ static struct kvm_x86_ops vmx_x86_ops = { .get_mt_mask = vmx_get_mt_mask, .exit_reasons_str = vmx_exit_reasons_str, - .gb_page_enable = vmx_gb_page_enable, + .get_lpage_level = vmx_get_lpage_level, .cpuid_update = vmx_cpuid_update,
arch/x86/kvm/x86.c +3 -1
@@ -1641,10 +1641,12 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, u32 index, int *nent, int maxnent) { unsigned f_nx = is_efer_nx() ? F(NX) : 0; -unsigned f_gbpages = kvm_x86_ops->gb_page_enable () ?F (GBPAGES ) :0 ;#ifdef CONFIG_X86_64 +unsigned f_gbpages = (kvm_x86_ops->get_lpage_level () ==PT_PDPE_LEVEL ) + ?F (GBPAGES ) :0 ;unsigned f_lm =F (LM );#else +unsigned f_gbpages =0 ;unsigned f_lm =0 ;#endif unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported () ?F (RDTSCP ) :0 ;
Signature · 1 line
1.5.4.5
PATCH v2 3/4 KVM: x86: Fix host_mapping_level()
In reply to Sheng YangWhen found a error hva, should not return PAGE_SIZE but the level...
Also clean up the coding style of the following loop.
--- arch/x86/kvm/mmu.c | 6 ++---- 1 files changed, 2 insertions(+), 4 deletions(-)
arch/x86/kvm/mmu.c +2 -4
@@ -473,7 +473,7 @@ static int host_mapping_level(struct kvm *kvm, gfn_t gfn) addr =gfn_to_hva (kvm, gfn);if (kvm_is_error_hva (addr)) -return page_size; +return PT_PAGE_TABLE_LEVEL ;down_read (¤t->mm->mmap_sem); vma =find_vma (current->mm, addr);
@@ -511,11 +511,9 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)if (host_level ==PT_PAGE_TABLE_LEVEL )return host_level; -for (level =PT_DIRECTORY_LEVEL ; level <= host_level; ++level) { - +for (level =PT_DIRECTORY_LEVEL ; level <= host_level; ++level)if (has_wrprotected_page (vcpu->kvm, large_gfn, level))break ; - }return level -1 ; }
Signature · 1 line
1.5.4.5
PATCH v2 4/4 KVM: VMX: Enable EPT 1GB page support
In reply to Sheng Yang--- arch/x86/include/asm/vmx.h | 1 + arch/x86/kvm/mmu.c | 8 +++++--- arch/x86/kvm/vmx.c | 11 ++++++++++- 3 files changed, 16 insertions(+), 4 deletions(-)
arch/x86/include/asm/vmx.h +1 -0
@@ -364,6 +364,7 @@ enum vmcs_field {#define VMX_EPTP_UC_BIT (1ull << 8)#define VMX_EPTP_WB_BIT (1ull << 14)#define VMX_EPT_2MB_PAGE_BIT (1ull << 16) +#define VMX_EPT_1GB_PAGE_BIT (1ull << 17)#define VMX_EPT_EXTENT_INDIVIDUAL_BIT (1ull << 24)#define VMX_EPT_EXTENT_CONTEXT_BIT (1ull << 25)#define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26)
arch/x86/kvm/mmu.c +5 -3
@@ -499,8 +499,7 @@ out:static int mapping_level (struct kvm_vcpu *vcpu,gfn_t large_gfn) {struct kvm_memory_slot *slot; -int host_level; -int level =PT_PAGE_TABLE_LEVEL ; +int host_level, level, max_level; slot =gfn_to_memslot (vcpu->kvm, large_gfn);if (slot && slot->dirty_bitmap)
@@ -511,7 +510,10 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)if (host_level ==PT_PAGE_TABLE_LEVEL )return host_level; -for (level =PT_DIRECTORY_LEVEL ; level <= host_level; ++level) + max_level = kvm_x86_ops->get_lpage_level () < host_level ? + kvm_x86_ops->get_lpage_level () : host_level; + +for (level =PT_DIRECTORY_LEVEL ; level <= max_level; ++level)if (has_wrprotected_page (vcpu->kvm, large_gfn, level))break ;
arch/x86/kvm/vmx.c +10 -1
@@ -318,6 +318,11 @@ static inline bool cpu_has_vmx_ept_2m_page(void)return !!(vmx_capability.ept &VMX_EPT_2MB_PAGE_BIT ); } +static inline bool cpu_has_vmx_ept_1g_page (void ) +{ +return !!(vmx_capability.ept &VMX_EPT_1GB_PAGE_BIT ); +} +static inline int cpu_has_vmx_invept_individual_addr (void ) {return !!(vmx_capability.ept &VMX_EPT_EXTENT_INDIVIDUAL_BIT );
@@ -4013,7 +4018,11 @@ static const struct trace_print_flags vmx_exit_reasons_str[] = {static int vmx_get_lpage_level (void ) { -return PT_DIRECTORY_LEVEL ; +if (enable_ept && !cpu_has_vmx_ept_1g_page ()) +return PT_DIRECTORY_LEVEL ; +else +/* For shadow and EPT supported 1GB page */ +return PT_PDPE_LEVEL ; }static inline u32 bit (int bitno)
Signature · 1 line
1.5.4.5
Re: [PATCH 4/4] KVM: VMX: Enable EPT 1GB page support
Quoted 35 lines · Sheng Yang
Signed-off-by Sheng Yang <[email protected]>--- arch/x86/include/asm/vmx.h | 1 + arch/x86/kvm/mmu.c | 8 +++++--- arch/x86/kvm/vmx.c | 11 ++++++++++- 3 files changed, 16 insertions(+), 4 deletions(-)arch/x86/include/asm/vmx.h +1
-0@@ -364,6 +364,7 @@ enum vmcs_field {#define VMX_EPTP_UC_BIT (1ull << 8)#define VMX_EPTP_WB_BIT (1ull << 14)#define VMX_EPT_2MB_PAGE_BIT (1ull << 16) +#define VMX_EPT_1GB_PAGE_BIT (1ull << 17)#define VMX_EPT_EXTENT_INDIVIDUAL_BIT (1ull << 24)#define VMX_EPT_EXTENT_CONTEXT_BIT (1ull << 25)#define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26)arch/x86/kvm/mmu.c +1
-2@@ -499,8 +499,7 @@ out:static int mapping_level (struct kvm_vcpu *vcpu,gfn_t large_gfn) {struct kvm_memory_slot *slot; -int host_level; -int level =PT_PAGE_TABLE_LEVEL ; +int host_level, level, max_level; slot =gfn_to_memslot (vcpu->kvm, large_gfn);if (slot && slot->dirty_bitmap)
arch/x86/kvm/mmu.c static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) · line 515
Quoted 7 lines
arch/x86/kvm/mmu.c +3
-1@@ -511,7 +510,10 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)if (host_level ==PT_PAGE_TABLE_LEVEL )return host_level; -for (level =PT_DIRECTORY_LEVEL ; level <= host_level; ++level) + max_level = kvm_x86_ops->get_lpage_level () < host_level ? + kvm_x86_ops->get_lpage_level () : host_level; +
BUG_ON(kvm_x86_ops->get_lpage_level() < host_level) instead? See the if (host_level == PT_PAGE_TABLE_LEVEL) above.
Re: [PATCH 4/4] KVM: VMX: Enable EPT 1GB page support
Quoted 38 lines · On Wednesday 06 January 2010 17:19:15 Marcelo Tosatti wrote:
Quoted 37 lines · Sheng Yang
Signed-off-by Sheng Yang <[email protected]>--- arch/x86/include/asm/vmx.h | 1 + arch/x86/kvm/mmu.c | 8 +++++--- arch/x86/kvm/vmx.c | 11 ++++++++++- 3 files changed, 16 insertions(+), 4 deletions(-)arch/x86/include/asm/vmx.h +1
-0@@ -364,6 +364,7 @@ enum vmcs_field {#define VMX_EPTP_UC_BIT (1ull << 8)#define VMX_EPTP_WB_BIT (1ull << 14)#define VMX_EPT_2MB_PAGE_BIT (1ull << 16) +#define VMX_EPT_1GB_PAGE_BIT (1ull << 17)#define VMX_EPT_EXTENT_INDIVIDUAL_BIT (1ull << 24)#define VMX_EPT_EXTENT_CONTEXT_BIT (1ull << 25)#define VMX_EPT_EXTENT_GLOBAL_BIT (1ull << 26)arch/x86/kvm/mmu.c +1
-2@@ -499,8 +499,7 @@ out:static int mapping_level (struct kvm_vcpu *vcpu,gfn_t large_gfn) {struct kvm_memory_slot *slot; -int host_level; -int level =PT_PAGE_TABLE_LEVEL ; +int host_level, level, max_level; slot =gfn_to_memslot (vcpu->kvm, large_gfn);if (slot && slot->dirty_bitmap)@@ -511,7 +510,10 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) if (host_level == PT_PAGE_TABLE_LEVEL)return host_level;
Quoted 7 lines
arch/x86/kvm/mmu.c static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) · line 515
Quoted 4 lines
arch/x86/kvm/mmu.c +3
-1-for (level =PT_DIRECTORY_LEVEL ; level <= host_level; ++level) + max_level = kvm_x86_ops->get_lpage_level () < host_level ? + kvm_x86_ops->get_lpage_level () : host_level; +
BUG_ON(kvm_x86_ops->get_lpage_level() < host_level)instead? See the if (host_level==PT_PAGE_TABLE_LEVEL) above.
Sorry, I don't understand...
Here, EPT can support either 2MB or 1GB page at most, So we represent the value through get_lpage_level(). Now 1GB page backed host memory can still using by 2MB page backed EPT if 1GB page EPT is not supported in the processor.
Signature · 2 lines
regards Yang, Sheng
Marcelo Tosatti
AppliedRe: [PATCH 4/4] KVM: VMX: Enable EPT 1GB page support
Quoted 8 lines · Sheng Yang
Quoted 7 lines
arch/x86/kvm/mmu.c static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn) · line 515
Quoted 4 lines
arch/x86/kvm/mmu.c +3
-1-for (level =PT_DIRECTORY_LEVEL ; level <= host_level; ++level) + max_level = kvm_x86_ops->get_lpage_level () < host_level ? + kvm_x86_ops->get_lpage_level () : host_level; +
BUG_ON(kvm_x86_ops->get_lpage_level() < host_level)instead? See the if (host_level==PT_PAGE_TABLE_LEVEL) above.
Quoted 6 lines
Sorry, I don't understand...
Here, EPT can support either 2MB or 1GB page at most, So we represent the value through
get_lpage_level(). Now 1GB page backed host memory can still using by 2MB page backed EPT if 1GB page EPT is not supported in the processor.
Oh, OK, i misundertood.
Applied, thanks.