Skip to contentSkip to conversation

EPT 1GB page support

PATCH Applied Sheng Yang 2 participants 8 messages Jan 5, 2010 – Jan 6, 2010

Subsystems (3)
lore
Share & tools
lore
author
#1 lore raw

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
index c43c2ab..15daf3c 100644
@@ -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
index 4567d80..ff58342 100644
@@ -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
author
#2 lore raw

PATCH v2 2/4 KVM: x86: Rename gb_page_enable() to get_lpage_level() in kvm_x86_ops

In reply to Sheng Yang

Then 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
index fe4df46..31b986f 100644
@@ -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
index b373ae6..cf64fc0 100644
@@ -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
index 2cc9b7e..4177473 100644
@@ -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
index fd6e1a5..bc8881a 100644
@@ -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
author
#3 lore raw

PATCH v2 3/4 KVM: x86: Fix host_mapping_level()

In reply to Sheng Yang

When 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
index 15daf3c..43cf2ea 100644
@@ -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(&current->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
author
#4 lore raw

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
index 713ed9a..43f1e9b 100644
@@ -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
index 43cf2ea..9012541 100644
@@ -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
index 4177473..12b5661 100644
@@ -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
#5 lore raw

Re: [PATCH 4/4] KVM: VMX: Enable EPT 1GB page support

Quoted 35 lines · 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
index 713ed9a..43f1e9b 100644
@@ -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
index 43cf2ea..9012541 100644
@@ -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.

author
#6 lore raw

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
---
 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
index 713ed9a..43f1e9b 100644
@@ -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
index 43cf2ea..9012541 100644
@@ -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
#7 lore raw

Re: [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.