kvmarm.lists.cs.columbia.edu archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/5] KVM: arm64: Add support for contiguous PTE/PMD hugepages at stage2
@ 2019-05-01  9:44 Zenghui Yu
  2019-05-01  9:44 ` Zenghui Yu
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Zenghui Yu @ 2019-05-01  9:44 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel, kvm
  Cc: marc.zyngier, catalin.marinas, will.deacon, linux

Currently, we support the following page sizes at stage2:

                PTE     PMD     PUD
               -----   -----   -----
 4K granule:     4K      2M      1G
16K granule:    16K     32M
64K granule:    64K    512M

And we have Contiguous bit[52] in stage2 VMSAv8-64 block and page
descriptors. As ARM ARM said, when the value of the Contiguous bit
is 1, it indicates that the entry is one of a number of adjacent
translation table entries that point to a contiguous output address
range.

This series add support for contiguous PTE/PMD hugepages at stage2
and then we can create huge mappings with following additional
sizes:

                CONT PTE     CONT PMD
                --------     --------
 4K granule:      64K          32M
16K granule:       2M           1G
64K granule:       2M          16G

These patches are based on v5.1.0-rc7 and have been tested on
Taishan 2280 server (D05) with 4K and 64K granule.

Any comments will be appreciated, thanks!

Zenghui Yu (5):
  KVM: arm/arm64: Introduce helpers for page table enties with
    contiguous bit
  KVM: arm/arm64: Re-factor building the stage2 page table entries
  KVM: arm/arm64: Support dirty page tracking for contiguous hugepages
  KVM: arm/arm64: Add support for creating PTE contiguous hugepages at
    stage2
  KVM: arm/arm64: Add support for creating PMD contiguous hugepages at
    stage2

 arch/arm/include/asm/kvm_mmu.h       |  22 +++
 arch/arm/include/asm/pgtable-hwdef.h |   8 +
 arch/arm64/include/asm/kvm_mmu.h     |  20 +++
 virt/kvm/arm/mmu.c                   | 299 ++++++++++++++++++++++++++++++-----
 4 files changed, 312 insertions(+), 37 deletions(-)

-- 
1.8.3.1

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [RFC PATCH 0/5] KVM: arm64: Add support for contiguous PTE/PMD hugepages at stage2
  2019-05-01  9:44 [RFC PATCH 0/5] KVM: arm64: Add support for contiguous PTE/PMD hugepages at stage2 Zenghui Yu
@ 2019-05-01  9:44 ` Zenghui Yu
  2019-05-01  9:44 ` [PATCH 1/5] KVM: arm/arm64: Introduce helpers for page table enties with contiguous bit Zenghui Yu
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Zenghui Yu @ 2019-05-01  9:44 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel, kvm
  Cc: marc.zyngier, catalin.marinas, will.deacon, linux

Currently, we support the following page sizes at stage2:

                PTE     PMD     PUD
               -----   -----   -----
 4K granule:     4K      2M      1G
16K granule:    16K     32M
64K granule:    64K    512M

And we have Contiguous bit[52] in stage2 VMSAv8-64 block and page
descriptors. As ARM ARM said, when the value of the Contiguous bit
is 1, it indicates that the entry is one of a number of adjacent
translation table entries that point to a contiguous output address
range.

This series add support for contiguous PTE/PMD hugepages at stage2
and then we can create huge mappings with following additional
sizes:

                CONT PTE     CONT PMD
                --------     --------
 4K granule:      64K          32M
16K granule:       2M           1G
64K granule:       2M          16G

These patches are based on v5.1.0-rc7 and have been tested on
Taishan 2280 server (D05) with 4K and 64K granule.

Any comments will be appreciated, thanks!

Zenghui Yu (5):
  KVM: arm/arm64: Introduce helpers for page table enties with
    contiguous bit
  KVM: arm/arm64: Re-factor building the stage2 page table entries
  KVM: arm/arm64: Support dirty page tracking for contiguous hugepages
  KVM: arm/arm64: Add support for creating PTE contiguous hugepages at
    stage2
  KVM: arm/arm64: Add support for creating PMD contiguous hugepages at
    stage2

 arch/arm/include/asm/kvm_mmu.h       |  22 +++
 arch/arm/include/asm/pgtable-hwdef.h |   8 +
 arch/arm64/include/asm/kvm_mmu.h     |  20 +++
 virt/kvm/arm/mmu.c                   | 299 ++++++++++++++++++++++++++++++-----
 4 files changed, 312 insertions(+), 37 deletions(-)

-- 
1.8.3.1


_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/5] KVM: arm/arm64: Introduce helpers for page table enties with contiguous bit
  2019-05-01  9:44 [RFC PATCH 0/5] KVM: arm64: Add support for contiguous PTE/PMD hugepages at stage2 Zenghui Yu
  2019-05-01  9:44 ` Zenghui Yu
@ 2019-05-01  9:44 ` Zenghui Yu
  2019-05-01  9:44   ` Zenghui Yu
  2019-05-01  9:44 ` [PATCH 2/5] KVM: arm/arm64: Re-factor building the stage2 page table entries Zenghui Yu
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Zenghui Yu @ 2019-05-01  9:44 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel, kvm
  Cc: marc.zyngier, catalin.marinas, will.deacon, linux

Introduce helpers to manipulate stage2 page table entries - set contiguous
bit in the entry and say whether this entry points to a contiguous block.

The helpers are introduced in preparation for supporting contiguous
hugepages at stage2.

Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
---
 arch/arm/include/asm/kvm_mmu.h   | 22 ++++++++++++++++++++++
 arch/arm64/include/asm/kvm_mmu.h | 20 ++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 31de4ab..80d73ae 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -143,6 +143,28 @@ static inline bool kvm_s2pud_young(pud_t pud)
 	return false;
 }
 
+static inline pte_t kvm_s2pte_mkcont(pte_t pte)
+{
+	BUG();
+	return pte;
+}
+
+static inline bool kvm_s2pte_cont(pte_t pte)
+{
+	return false;
+}
+
+static inline pmd_t kvm_s2pmd_mkcont(pmd_t pmd)
+{
+	BUG();
+	return pmd;
+}
+
+static inline bool kvm_s2pmd_cont(pmd_t pmd)
+{
+	return false;
+}
+
 static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
 {
 	pte_val(pte) |= L_PTE_S2_RDWR;
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index ebeefcf..4afdad9 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -295,6 +295,26 @@ static inline bool kvm_s2pud_young(pud_t pud)
 	return pud_young(pud);
 }
 
+static inline pte_t kvm_s2pte_mkcont(pte_t pte)
+{
+	return pte_mkcont(pte);
+}
+
+static inline bool kvm_s2pte_cont(pte_t pte)
+{
+	return pte_cont(pte);
+}
+
+static inline pmd_t kvm_s2pmd_mkcont(pmd_t pmd)
+{
+	return pmd_mkcont(pmd);
+}
+
+static inline bool kvm_s2pmd_cont(pmd_t pmd)
+{
+	return !!(pmd_val(pmd) & PMD_SECT_CONT);
+}
+
 #define hyp_pte_table_empty(ptep) kvm_page_empty(ptep)
 
 #ifdef __PAGETABLE_PMD_FOLDED
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 1/5] KVM: arm/arm64: Introduce helpers for page table enties with contiguous bit
  2019-05-01  9:44 ` [PATCH 1/5] KVM: arm/arm64: Introduce helpers for page table enties with contiguous bit Zenghui Yu
@ 2019-05-01  9:44   ` Zenghui Yu
  0 siblings, 0 replies; 12+ messages in thread
From: Zenghui Yu @ 2019-05-01  9:44 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel, kvm
  Cc: marc.zyngier, catalin.marinas, will.deacon, linux

Introduce helpers to manipulate stage2 page table entries - set contiguous
bit in the entry and say whether this entry points to a contiguous block.

The helpers are introduced in preparation for supporting contiguous
hugepages at stage2.

Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
---
 arch/arm/include/asm/kvm_mmu.h   | 22 ++++++++++++++++++++++
 arch/arm64/include/asm/kvm_mmu.h | 20 ++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 31de4ab..80d73ae 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -143,6 +143,28 @@ static inline bool kvm_s2pud_young(pud_t pud)
 	return false;
 }
 
+static inline pte_t kvm_s2pte_mkcont(pte_t pte)
+{
+	BUG();
+	return pte;
+}
+
+static inline bool kvm_s2pte_cont(pte_t pte)
+{
+	return false;
+}
+
+static inline pmd_t kvm_s2pmd_mkcont(pmd_t pmd)
+{
+	BUG();
+	return pmd;
+}
+
+static inline bool kvm_s2pmd_cont(pmd_t pmd)
+{
+	return false;
+}
+
 static inline pte_t kvm_s2pte_mkwrite(pte_t pte)
 {
 	pte_val(pte) |= L_PTE_S2_RDWR;
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index ebeefcf..4afdad9 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -295,6 +295,26 @@ static inline bool kvm_s2pud_young(pud_t pud)
 	return pud_young(pud);
 }
 
+static inline pte_t kvm_s2pte_mkcont(pte_t pte)
+{
+	return pte_mkcont(pte);
+}
+
+static inline bool kvm_s2pte_cont(pte_t pte)
+{
+	return pte_cont(pte);
+}
+
+static inline pmd_t kvm_s2pmd_mkcont(pmd_t pmd)
+{
+	return pmd_mkcont(pmd);
+}
+
+static inline bool kvm_s2pmd_cont(pmd_t pmd)
+{
+	return !!(pmd_val(pmd) & PMD_SECT_CONT);
+}
+
 #define hyp_pte_table_empty(ptep) kvm_page_empty(ptep)
 
 #ifdef __PAGETABLE_PMD_FOLDED
-- 
1.8.3.1


_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/5] KVM: arm/arm64: Re-factor building the stage2 page table entries
  2019-05-01  9:44 [RFC PATCH 0/5] KVM: arm64: Add support for contiguous PTE/PMD hugepages at stage2 Zenghui Yu
  2019-05-01  9:44 ` Zenghui Yu
  2019-05-01  9:44 ` [PATCH 1/5] KVM: arm/arm64: Introduce helpers for page table enties with contiguous bit Zenghui Yu
@ 2019-05-01  9:44 ` Zenghui Yu
  2019-05-01  9:44   ` Zenghui Yu
  2019-05-01  9:44 ` [PATCH 3/5] KVM: arm/arm64: Support dirty page tracking for contiguous hugepages Zenghui Yu
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Zenghui Yu @ 2019-05-01  9:44 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel, kvm
  Cc: marc.zyngier, catalin.marinas, will.deacon, linux

As we're going to support creating CONT_{PTE,PMD}_SIZE huge mappings in
user_mem_abort(), the logic to check vma_pagesize and build page table
entries will become longer, and looks almost the same (but actually they
dont). Refactor this part to make it a bit cleaner.

Add contiguous as a parameter of stage2_build_{pmd,pte}, to indicate
if we're creating contiguous huge mappings.

Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
---
 virt/kvm/arm/mmu.c | 81 ++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 57 insertions(+), 24 deletions(-)

diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 27c9583..cf8b035 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -1616,6 +1616,56 @@ static void kvm_send_hwpoison_signal(unsigned long address,
 	send_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, current);
 }
 
+static pud_t stage2_build_pud(kvm_pfn_t pfn, pgprot_t mem_type, bool writable,
+			      bool needs_exec)
+{
+	pud_t new_pud = kvm_pfn_pud(pfn, mem_type);
+
+	new_pud = kvm_pud_mkhuge(new_pud);
+	if (writable)
+		new_pud = kvm_s2pud_mkwrite(new_pud);
+
+	if (needs_exec)
+		new_pud = kvm_s2pud_mkexec(new_pud);
+
+	return new_pud;
+}
+
+static pmd_t stage2_build_pmd(kvm_pfn_t pfn, pgprot_t mem_type, bool writable,
+			      bool needs_exec, bool contiguous)
+{
+	pmd_t new_pmd = kvm_pfn_pmd(pfn, mem_type);
+
+	new_pmd = kvm_pmd_mkhuge(new_pmd);
+	if (writable)
+		new_pmd = kvm_s2pmd_mkwrite(new_pmd);
+
+	if (needs_exec)
+		new_pmd = kvm_s2pmd_mkexec(new_pmd);
+
+	if (contiguous)
+		new_pmd = kvm_s2pmd_mkcont(new_pmd);
+
+	return new_pmd;
+}
+
+static pte_t stage2_build_pte(kvm_pfn_t pfn, pgprot_t mem_type, bool writable,
+			      bool needs_exec, bool contiguous)
+{
+	pte_t new_pte = kvm_pfn_pte(pfn, mem_type);
+
+	if (writable)
+		new_pte = kvm_s2pte_mkwrite(new_pte);
+
+	if (needs_exec)
+		new_pte = kvm_s2pte_mkexec(new_pte);
+
+	if (contiguous)
+		new_pte = kvm_s2pte_mkcont(new_pte);
+
+	return new_pte;
+}
+
 static bool fault_supports_stage2_huge_mapping(struct kvm_memory_slot *memslot,
 					       unsigned long hva,
 					       unsigned long map_size)
@@ -1807,38 +1857,21 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 		(fault_status == FSC_PERM && stage2_is_exec(kvm, fault_ipa));
 
 	if (vma_pagesize == PUD_SIZE) {
-		pud_t new_pud = kvm_pfn_pud(pfn, mem_type);
-
-		new_pud = kvm_pud_mkhuge(new_pud);
-		if (writable)
-			new_pud = kvm_s2pud_mkwrite(new_pud);
-
-		if (needs_exec)
-			new_pud = kvm_s2pud_mkexec(new_pud);
+		pud_t new_pud = stage2_build_pud(pfn, mem_type, writable,
+						 needs_exec);
 
 		ret = stage2_set_pud_huge(kvm, memcache, fault_ipa, &new_pud);
 	} else if (vma_pagesize == PMD_SIZE) {
-		pmd_t new_pmd = kvm_pfn_pmd(pfn, mem_type);
-
-		new_pmd = kvm_pmd_mkhuge(new_pmd);
-
-		if (writable)
-			new_pmd = kvm_s2pmd_mkwrite(new_pmd);
-
-		if (needs_exec)
-			new_pmd = kvm_s2pmd_mkexec(new_pmd);
+		pmd_t new_pmd = stage2_build_pmd(pfn, mem_type, writable,
+						 needs_exec, false);
 
 		ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd);
 	} else {
-		pte_t new_pte = kvm_pfn_pte(pfn, mem_type);
+		pte_t new_pte = stage2_build_pte(pfn, mem_type, writable,
+						 needs_exec, false);
 
-		if (writable) {
-			new_pte = kvm_s2pte_mkwrite(new_pte);
+		if (writable)
 			mark_page_dirty(kvm, gfn);
-		}
-
-		if (needs_exec)
-			new_pte = kvm_s2pte_mkexec(new_pte);
 
 		ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, flags);
 	}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/5] KVM: arm/arm64: Re-factor building the stage2 page table entries
  2019-05-01  9:44 ` [PATCH 2/5] KVM: arm/arm64: Re-factor building the stage2 page table entries Zenghui Yu
@ 2019-05-01  9:44   ` Zenghui Yu
  0 siblings, 0 replies; 12+ messages in thread
From: Zenghui Yu @ 2019-05-01  9:44 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel, kvm
  Cc: marc.zyngier, catalin.marinas, will.deacon, linux

As we're going to support creating CONT_{PTE,PMD}_SIZE huge mappings in
user_mem_abort(), the logic to check vma_pagesize and build page table
entries will become longer, and looks almost the same (but actually they
dont). Refactor this part to make it a bit cleaner.

Add contiguous as a parameter of stage2_build_{pmd,pte}, to indicate
if we're creating contiguous huge mappings.

Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
---
 virt/kvm/arm/mmu.c | 81 ++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 57 insertions(+), 24 deletions(-)

diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 27c9583..cf8b035 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -1616,6 +1616,56 @@ static void kvm_send_hwpoison_signal(unsigned long address,
 	send_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, current);
 }
 
+static pud_t stage2_build_pud(kvm_pfn_t pfn, pgprot_t mem_type, bool writable,
+			      bool needs_exec)
+{
+	pud_t new_pud = kvm_pfn_pud(pfn, mem_type);
+
+	new_pud = kvm_pud_mkhuge(new_pud);
+	if (writable)
+		new_pud = kvm_s2pud_mkwrite(new_pud);
+
+	if (needs_exec)
+		new_pud = kvm_s2pud_mkexec(new_pud);
+
+	return new_pud;
+}
+
+static pmd_t stage2_build_pmd(kvm_pfn_t pfn, pgprot_t mem_type, bool writable,
+			      bool needs_exec, bool contiguous)
+{
+	pmd_t new_pmd = kvm_pfn_pmd(pfn, mem_type);
+
+	new_pmd = kvm_pmd_mkhuge(new_pmd);
+	if (writable)
+		new_pmd = kvm_s2pmd_mkwrite(new_pmd);
+
+	if (needs_exec)
+		new_pmd = kvm_s2pmd_mkexec(new_pmd);
+
+	if (contiguous)
+		new_pmd = kvm_s2pmd_mkcont(new_pmd);
+
+	return new_pmd;
+}
+
+static pte_t stage2_build_pte(kvm_pfn_t pfn, pgprot_t mem_type, bool writable,
+			      bool needs_exec, bool contiguous)
+{
+	pte_t new_pte = kvm_pfn_pte(pfn, mem_type);
+
+	if (writable)
+		new_pte = kvm_s2pte_mkwrite(new_pte);
+
+	if (needs_exec)
+		new_pte = kvm_s2pte_mkexec(new_pte);
+
+	if (contiguous)
+		new_pte = kvm_s2pte_mkcont(new_pte);
+
+	return new_pte;
+}
+
 static bool fault_supports_stage2_huge_mapping(struct kvm_memory_slot *memslot,
 					       unsigned long hva,
 					       unsigned long map_size)
@@ -1807,38 +1857,21 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 		(fault_status == FSC_PERM && stage2_is_exec(kvm, fault_ipa));
 
 	if (vma_pagesize == PUD_SIZE) {
-		pud_t new_pud = kvm_pfn_pud(pfn, mem_type);
-
-		new_pud = kvm_pud_mkhuge(new_pud);
-		if (writable)
-			new_pud = kvm_s2pud_mkwrite(new_pud);
-
-		if (needs_exec)
-			new_pud = kvm_s2pud_mkexec(new_pud);
+		pud_t new_pud = stage2_build_pud(pfn, mem_type, writable,
+						 needs_exec);
 
 		ret = stage2_set_pud_huge(kvm, memcache, fault_ipa, &new_pud);
 	} else if (vma_pagesize == PMD_SIZE) {
-		pmd_t new_pmd = kvm_pfn_pmd(pfn, mem_type);
-
-		new_pmd = kvm_pmd_mkhuge(new_pmd);
-
-		if (writable)
-			new_pmd = kvm_s2pmd_mkwrite(new_pmd);
-
-		if (needs_exec)
-			new_pmd = kvm_s2pmd_mkexec(new_pmd);
+		pmd_t new_pmd = stage2_build_pmd(pfn, mem_type, writable,
+						 needs_exec, false);
 
 		ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd);
 	} else {
-		pte_t new_pte = kvm_pfn_pte(pfn, mem_type);
+		pte_t new_pte = stage2_build_pte(pfn, mem_type, writable,
+						 needs_exec, false);
 
-		if (writable) {
-			new_pte = kvm_s2pte_mkwrite(new_pte);
+		if (writable)
 			mark_page_dirty(kvm, gfn);
-		}
-
-		if (needs_exec)
-			new_pte = kvm_s2pte_mkexec(new_pte);
 
 		ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte, flags);
 	}
-- 
1.8.3.1


_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/5] KVM: arm/arm64: Support dirty page tracking for contiguous hugepages
  2019-05-01  9:44 [RFC PATCH 0/5] KVM: arm64: Add support for contiguous PTE/PMD hugepages at stage2 Zenghui Yu
                   ` (2 preceding siblings ...)
  2019-05-01  9:44 ` [PATCH 2/5] KVM: arm/arm64: Re-factor building the stage2 page table entries Zenghui Yu
@ 2019-05-01  9:44 ` Zenghui Yu
  2019-05-01  9:44   ` Zenghui Yu
  2019-05-01  9:44 ` [PATCH 4/5] KVM: arm/arm64: Add support for creating PTE contiguous hugepages at stage2 Zenghui Yu
  2019-05-01  9:44 ` [PATCH 5/5] KVM: arm/arm64: Add support for creating PMD " Zenghui Yu
  5 siblings, 1 reply; 12+ messages in thread
From: Zenghui Yu @ 2019-05-01  9:44 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel, kvm
  Cc: marc.zyngier, christoffer.dall, linux, catalin.marinas,
	will.deacon, james.morse, julien.thierry, suzuki.poulose,
	steve.capper, wanghaibin.wang, Zenghui Yu

When logging is enabled, we should keep tracking of normal size pages.
If the memslot is backed by contiguous hugepages, we should dissolve
the contiguous hugepages - clear the whole contiguous range and flush
corresponding TLB entry.

Move kvm_set_{pte,pmd} to the front of stage2_dissolve_cont_{pte,pmd}s
to avoid one more declaration.

Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
---
 arch/arm/include/asm/pgtable-hwdef.h |  8 ++++
 virt/kvm/arm/mmu.c                   | 76 ++++++++++++++++++++++++++++++------
 2 files changed, 72 insertions(+), 12 deletions(-)

diff --git a/arch/arm/include/asm/pgtable-hwdef.h b/arch/arm/include/asm/pgtable-hwdef.h
index 8426229..41f4633 100644
--- a/arch/arm/include/asm/pgtable-hwdef.h
+++ b/arch/arm/include/asm/pgtable-hwdef.h
@@ -16,4 +16,12 @@
 #include <asm/pgtable-2level-hwdef.h>
 #endif
 
+/* dummy definition */
+#define CONT_PTES		(0)
+#define CONT_PTE_SIZE		(0)
+#define CONT_PTE_MASK		(0)
+#define CONT_PMDS		(0)
+#define CONT_PMD_SIZE		(0)
+#define CONT_PMD_MASK		(0)
+
 #endif
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index cf8b035..36c863f 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -96,6 +96,58 @@ static bool kvm_is_device_pfn(unsigned long pfn)
 	return !pfn_valid(pfn);
 }
 
+static inline void kvm_set_pte(pte_t *ptep, pte_t new_pte)
+{
+	WRITE_ONCE(*ptep, new_pte);
+	dsb(ishst);
+}
+
+static inline void kvm_set_pmd(pmd_t *pmdp, pmd_t new_pmd)
+{
+	WRITE_ONCE(*pmdp, new_pmd);
+	dsb(ishst);
+}
+
+static void stage2_dissolve_cont_ptes(struct kvm *kvm, phys_addr_t addr,
+				      pte_t *pte)
+{
+	phys_addr_t addrp;
+	pte_t *ptep;
+	int i;
+
+	if (!kvm_s2pte_cont(*pte))
+		return;
+
+	/* Start with the first pte */
+	addrp = addr & CONT_PTE_MASK;
+	ptep = pte - (addr - addrp) / PAGE_SIZE;
+
+	for (i = 0; i < CONT_PTES; i++, ptep++, addrp += PAGE_SIZE) {
+		kvm_set_pte(ptep, __pte(0));
+		kvm_tlb_flush_vmid_ipa(kvm, addrp);
+		put_page(virt_to_page(ptep));
+	}
+}
+
+static void stage2_dissolve_cont_pmds(struct kvm *kvm, phys_addr_t addr,
+				      pmd_t *pmd)
+{
+	phys_addr_t addrp;
+	pmd_t *pmdp;
+	int i;
+
+	/* Start with the first pmd */
+	addr &= PMD_MASK;
+	addrp = addr & CONT_PMD_MASK;
+	pmdp = pmd - (addr - addrp) / PMD_SIZE;
+
+	for (i = 0; i < CONT_PMDS; i++, pmdp++, addrp += PMD_SIZE) {
+		pmd_clear(pmdp);
+		kvm_tlb_flush_vmid_ipa(kvm, addrp);
+		put_page(virt_to_page(pmdp));
+	}
+}
+
 /**
  * stage2_dissolve_pmd() - clear and flush huge PMD entry
  * @kvm:	pointer to kvm structure.
@@ -109,6 +161,11 @@ static void stage2_dissolve_pmd(struct kvm *kvm, phys_addr_t addr, pmd_t *pmd)
 	if (!pmd_thp_or_huge(*pmd))
 		return;
 
+	if (kvm_s2pmd_cont(*pmd)) {
+		stage2_dissolve_cont_pmds(kvm, addr, pmd);
+		return;
+	}
+
 	pmd_clear(pmd);
 	kvm_tlb_flush_vmid_ipa(kvm, addr);
 	put_page(virt_to_page(pmd));
@@ -193,18 +250,6 @@ static void clear_stage2_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr
 	put_page(virt_to_page(pmd));
 }
 
-static inline void kvm_set_pte(pte_t *ptep, pte_t new_pte)
-{
-	WRITE_ONCE(*ptep, new_pte);
-	dsb(ishst);
-}
-
-static inline void kvm_set_pmd(pmd_t *pmdp, pmd_t new_pmd)
-{
-	WRITE_ONCE(*pmdp, new_pmd);
-	dsb(ishst);
-}
-
 static inline void kvm_pmd_populate(pmd_t *pmdp, pte_t *ptep)
 {
 	kvm_set_pmd(pmdp, kvm_mk_pmd(ptep));
@@ -1289,6 +1334,13 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
 
 	pte = pte_offset_kernel(pmd, addr);
 
+	/*
+	 * While dirty page logging - dissolve contiguous PTE pages, then
+	 * continue on to allocate page.
+	 */
+	if (logging_active)
+		stage2_dissolve_cont_ptes(kvm, addr, pte);
+
 	if (iomap && pte_present(*pte))
 		return -EFAULT;
 
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/5] KVM: arm/arm64: Support dirty page tracking for contiguous hugepages
  2019-05-01  9:44 ` [PATCH 3/5] KVM: arm/arm64: Support dirty page tracking for contiguous hugepages Zenghui Yu
@ 2019-05-01  9:44   ` Zenghui Yu
  0 siblings, 0 replies; 12+ messages in thread
From: Zenghui Yu @ 2019-05-01  9:44 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel, kvm
  Cc: marc.zyngier, catalin.marinas, will.deacon, linux

When logging is enabled, we should keep tracking of normal size pages.
If the memslot is backed by contiguous hugepages, we should dissolve
the contiguous hugepages - clear the whole contiguous range and flush
corresponding TLB entry.

Move kvm_set_{pte,pmd} to the front of stage2_dissolve_cont_{pte,pmd}s
to avoid one more declaration.

Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
---
 arch/arm/include/asm/pgtable-hwdef.h |  8 ++++
 virt/kvm/arm/mmu.c                   | 76 ++++++++++++++++++++++++++++++------
 2 files changed, 72 insertions(+), 12 deletions(-)

diff --git a/arch/arm/include/asm/pgtable-hwdef.h b/arch/arm/include/asm/pgtable-hwdef.h
index 8426229..41f4633 100644
--- a/arch/arm/include/asm/pgtable-hwdef.h
+++ b/arch/arm/include/asm/pgtable-hwdef.h
@@ -16,4 +16,12 @@
 #include <asm/pgtable-2level-hwdef.h>
 #endif
 
+/* dummy definition */
+#define CONT_PTES		(0)
+#define CONT_PTE_SIZE		(0)
+#define CONT_PTE_MASK		(0)
+#define CONT_PMDS		(0)
+#define CONT_PMD_SIZE		(0)
+#define CONT_PMD_MASK		(0)
+
 #endif
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index cf8b035..36c863f 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -96,6 +96,58 @@ static bool kvm_is_device_pfn(unsigned long pfn)
 	return !pfn_valid(pfn);
 }
 
+static inline void kvm_set_pte(pte_t *ptep, pte_t new_pte)
+{
+	WRITE_ONCE(*ptep, new_pte);
+	dsb(ishst);
+}
+
+static inline void kvm_set_pmd(pmd_t *pmdp, pmd_t new_pmd)
+{
+	WRITE_ONCE(*pmdp, new_pmd);
+	dsb(ishst);
+}
+
+static void stage2_dissolve_cont_ptes(struct kvm *kvm, phys_addr_t addr,
+				      pte_t *pte)
+{
+	phys_addr_t addrp;
+	pte_t *ptep;
+	int i;
+
+	if (!kvm_s2pte_cont(*pte))
+		return;
+
+	/* Start with the first pte */
+	addrp = addr & CONT_PTE_MASK;
+	ptep = pte - (addr - addrp) / PAGE_SIZE;
+
+	for (i = 0; i < CONT_PTES; i++, ptep++, addrp += PAGE_SIZE) {
+		kvm_set_pte(ptep, __pte(0));
+		kvm_tlb_flush_vmid_ipa(kvm, addrp);
+		put_page(virt_to_page(ptep));
+	}
+}
+
+static void stage2_dissolve_cont_pmds(struct kvm *kvm, phys_addr_t addr,
+				      pmd_t *pmd)
+{
+	phys_addr_t addrp;
+	pmd_t *pmdp;
+	int i;
+
+	/* Start with the first pmd */
+	addr &= PMD_MASK;
+	addrp = addr & CONT_PMD_MASK;
+	pmdp = pmd - (addr - addrp) / PMD_SIZE;
+
+	for (i = 0; i < CONT_PMDS; i++, pmdp++, addrp += PMD_SIZE) {
+		pmd_clear(pmdp);
+		kvm_tlb_flush_vmid_ipa(kvm, addrp);
+		put_page(virt_to_page(pmdp));
+	}
+}
+
 /**
  * stage2_dissolve_pmd() - clear and flush huge PMD entry
  * @kvm:	pointer to kvm structure.
@@ -109,6 +161,11 @@ static void stage2_dissolve_pmd(struct kvm *kvm, phys_addr_t addr, pmd_t *pmd)
 	if (!pmd_thp_or_huge(*pmd))
 		return;
 
+	if (kvm_s2pmd_cont(*pmd)) {
+		stage2_dissolve_cont_pmds(kvm, addr, pmd);
+		return;
+	}
+
 	pmd_clear(pmd);
 	kvm_tlb_flush_vmid_ipa(kvm, addr);
 	put_page(virt_to_page(pmd));
@@ -193,18 +250,6 @@ static void clear_stage2_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr
 	put_page(virt_to_page(pmd));
 }
 
-static inline void kvm_set_pte(pte_t *ptep, pte_t new_pte)
-{
-	WRITE_ONCE(*ptep, new_pte);
-	dsb(ishst);
-}
-
-static inline void kvm_set_pmd(pmd_t *pmdp, pmd_t new_pmd)
-{
-	WRITE_ONCE(*pmdp, new_pmd);
-	dsb(ishst);
-}
-
 static inline void kvm_pmd_populate(pmd_t *pmdp, pte_t *ptep)
 {
 	kvm_set_pmd(pmdp, kvm_mk_pmd(ptep));
@@ -1289,6 +1334,13 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
 
 	pte = pte_offset_kernel(pmd, addr);
 
+	/*
+	 * While dirty page logging - dissolve contiguous PTE pages, then
+	 * continue on to allocate page.
+	 */
+	if (logging_active)
+		stage2_dissolve_cont_ptes(kvm, addr, pte);
+
 	if (iomap && pte_present(*pte))
 		return -EFAULT;
 
-- 
1.8.3.1


_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/5] KVM: arm/arm64: Add support for creating PTE contiguous hugepages at stage2
  2019-05-01  9:44 [RFC PATCH 0/5] KVM: arm64: Add support for contiguous PTE/PMD hugepages at stage2 Zenghui Yu
                   ` (3 preceding siblings ...)
  2019-05-01  9:44 ` [PATCH 3/5] KVM: arm/arm64: Support dirty page tracking for contiguous hugepages Zenghui Yu
@ 2019-05-01  9:44 ` Zenghui Yu
  2019-05-01  9:44   ` Zenghui Yu
  2019-05-01  9:44 ` [PATCH 5/5] KVM: arm/arm64: Add support for creating PMD " Zenghui Yu
  5 siblings, 1 reply; 12+ messages in thread
From: Zenghui Yu @ 2019-05-01  9:44 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel, kvm
  Cc: marc.zyngier, catalin.marinas, will.deacon, linux

Extend the stage2 fault handling to map in PTE contiguous hugepages first.
With this patch, we now support additional following page size at stage2:

                CONT PTE
                --------
 4K granule:      64K
16K granule:       2M
64K granule:       2M

The PMD contiguous huge mapping is still not supported yet and will be
simply fall back to a PTE mapping.

Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
---
 virt/kvm/arm/mmu.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 36c863f..fdd6314 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -1104,6 +1104,27 @@ static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache
 	return stage2_pmd_offset(kvm, pud, addr);
 }
 
+static pte_t *stage2_get_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
+			     phys_addr_t addr)
+{
+	pmd_t *pmd;
+	pte_t *pte;
+
+	pmd = stage2_get_pmd(kvm, cache, addr);
+	if (!pmd || pmd_thp_or_huge(*pmd))
+		return NULL;
+
+	if (pmd_none(*pmd)) {
+		if (!cache)
+			return NULL;
+		pte = mmu_memory_cache_alloc(cache);
+		kvm_pmd_populate(pmd, pte);
+		get_page(virt_to_page(pmd));
+	}
+
+	return pte_offset_kernel(pmd, addr);
+}
+
 static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache
 			       *cache, phys_addr_t addr, const pmd_t *new_pmd)
 {
@@ -1270,6 +1291,54 @@ static bool stage2_is_exec(struct kvm *kvm, phys_addr_t addr)
 		return kvm_s2pte_exec(ptep);
 }
 
+/* This code is borrowed from arch/arm64/mm/hugetlbpage.c */
+static inline pgprot_t pte_pgprot(pte_t pte)
+{
+	unsigned long pfn = pte_pfn(pte);
+
+	return __pgprot(pte_val(pfn_pte(pfn, __pgprot(0))) ^ pte_val(pte));
+}
+
+static int stage2_set_cont_ptes(struct kvm *kvm, struct kvm_mmu_memory_cache
+				*cache, phys_addr_t addr, const pte_t *new_pte)
+{
+	pte_t *pte, old_pte;
+	unsigned long pfn, dpfn;
+	int i;
+	pgprot_t hugeprot;
+
+	/*
+	 * Make sure we start manipulating the first pte
+	 * within CONT_PTES ptes.
+	 */
+	addr &= CONT_PTE_MASK;
+	pfn = pte_pfn(*new_pte);
+	dpfn = PAGE_SIZE >> PAGE_SHIFT;
+	hugeprot = pte_pgprot(*new_pte);
+
+	pte = stage2_get_pte(kvm, cache, addr);
+	VM_BUG_ON(!pte);
+
+	old_pte = *pte;
+
+	/* Skip page table update if there is no change */
+	if (pte_val(old_pte) == pte_val(*new_pte))
+		return 0;
+
+	for (i = 0; i < CONT_PTES; i++, pte++, addr += PAGE_SIZE, pfn += dpfn) {
+		if (pte_present(old_pte)) {
+			kvm_set_pte(pte, __pte(0));
+			kvm_tlb_flush_vmid_ipa(kvm, addr);
+		} else {
+			get_page(virt_to_page(pte));
+		}
+
+		kvm_set_pte(pte, kvm_pfn_pte(pfn, hugeprot));
+	}
+
+	return 0;
+}
+
 static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
 			  phys_addr_t addr, const pte_t *new_pte,
 			  unsigned long flags)
@@ -1824,7 +1893,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	 * As for PUD huge maps, we must make sure that we have at least
 	 * 3 levels, i.e, PMD is not folded.
 	 */
-	if (vma_pagesize == PMD_SIZE ||
+	if (vma_pagesize == CONT_PTE_SIZE || vma_pagesize == PMD_SIZE ||
 	    (vma_pagesize == PUD_SIZE && kvm_stage2_has_pmd(kvm)))
 		gfn = (fault_ipa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT;
 	up_read(&current->mm->mmap_sem);
@@ -1918,6 +1987,11 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 						 needs_exec, false);
 
 		ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd);
+	} else if (vma_pagesize == CONT_PTE_SIZE) {
+		pte_t new_pte = stage2_build_pte(pfn, mem_type, writable,
+						 needs_exec, true);
+
+		ret = stage2_set_cont_ptes(kvm, memcache, fault_ipa, &new_pte);
 	} else {
 		pte_t new_pte = stage2_build_pte(pfn, mem_type, writable,
 						 needs_exec, false);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/5] KVM: arm/arm64: Add support for creating PTE contiguous hugepages at stage2
  2019-05-01  9:44 ` [PATCH 4/5] KVM: arm/arm64: Add support for creating PTE contiguous hugepages at stage2 Zenghui Yu
@ 2019-05-01  9:44   ` Zenghui Yu
  0 siblings, 0 replies; 12+ messages in thread
From: Zenghui Yu @ 2019-05-01  9:44 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel, kvm
  Cc: marc.zyngier, catalin.marinas, will.deacon, linux

Extend the stage2 fault handling to map in PTE contiguous hugepages first.
With this patch, we now support additional following page size at stage2:

                CONT PTE
                --------
 4K granule:      64K
16K granule:       2M
64K granule:       2M

The PMD contiguous huge mapping is still not supported yet and will be
simply fall back to a PTE mapping.

Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
---
 virt/kvm/arm/mmu.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 36c863f..fdd6314 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -1104,6 +1104,27 @@ static pmd_t *stage2_get_pmd(struct kvm *kvm, struct kvm_mmu_memory_cache *cache
 	return stage2_pmd_offset(kvm, pud, addr);
 }
 
+static pte_t *stage2_get_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
+			     phys_addr_t addr)
+{
+	pmd_t *pmd;
+	pte_t *pte;
+
+	pmd = stage2_get_pmd(kvm, cache, addr);
+	if (!pmd || pmd_thp_or_huge(*pmd))
+		return NULL;
+
+	if (pmd_none(*pmd)) {
+		if (!cache)
+			return NULL;
+		pte = mmu_memory_cache_alloc(cache);
+		kvm_pmd_populate(pmd, pte);
+		get_page(virt_to_page(pmd));
+	}
+
+	return pte_offset_kernel(pmd, addr);
+}
+
 static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache
 			       *cache, phys_addr_t addr, const pmd_t *new_pmd)
 {
@@ -1270,6 +1291,54 @@ static bool stage2_is_exec(struct kvm *kvm, phys_addr_t addr)
 		return kvm_s2pte_exec(ptep);
 }
 
+/* This code is borrowed from arch/arm64/mm/hugetlbpage.c */
+static inline pgprot_t pte_pgprot(pte_t pte)
+{
+	unsigned long pfn = pte_pfn(pte);
+
+	return __pgprot(pte_val(pfn_pte(pfn, __pgprot(0))) ^ pte_val(pte));
+}
+
+static int stage2_set_cont_ptes(struct kvm *kvm, struct kvm_mmu_memory_cache
+				*cache, phys_addr_t addr, const pte_t *new_pte)
+{
+	pte_t *pte, old_pte;
+	unsigned long pfn, dpfn;
+	int i;
+	pgprot_t hugeprot;
+
+	/*
+	 * Make sure we start manipulating the first pte
+	 * within CONT_PTES ptes.
+	 */
+	addr &= CONT_PTE_MASK;
+	pfn = pte_pfn(*new_pte);
+	dpfn = PAGE_SIZE >> PAGE_SHIFT;
+	hugeprot = pte_pgprot(*new_pte);
+
+	pte = stage2_get_pte(kvm, cache, addr);
+	VM_BUG_ON(!pte);
+
+	old_pte = *pte;
+
+	/* Skip page table update if there is no change */
+	if (pte_val(old_pte) == pte_val(*new_pte))
+		return 0;
+
+	for (i = 0; i < CONT_PTES; i++, pte++, addr += PAGE_SIZE, pfn += dpfn) {
+		if (pte_present(old_pte)) {
+			kvm_set_pte(pte, __pte(0));
+			kvm_tlb_flush_vmid_ipa(kvm, addr);
+		} else {
+			get_page(virt_to_page(pte));
+		}
+
+		kvm_set_pte(pte, kvm_pfn_pte(pfn, hugeprot));
+	}
+
+	return 0;
+}
+
 static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
 			  phys_addr_t addr, const pte_t *new_pte,
 			  unsigned long flags)
@@ -1824,7 +1893,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	 * As for PUD huge maps, we must make sure that we have at least
 	 * 3 levels, i.e, PMD is not folded.
 	 */
-	if (vma_pagesize == PMD_SIZE ||
+	if (vma_pagesize == CONT_PTE_SIZE || vma_pagesize == PMD_SIZE ||
 	    (vma_pagesize == PUD_SIZE && kvm_stage2_has_pmd(kvm)))
 		gfn = (fault_ipa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT;
 	up_read(&current->mm->mmap_sem);
@@ -1918,6 +1987,11 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 						 needs_exec, false);
 
 		ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd);
+	} else if (vma_pagesize == CONT_PTE_SIZE) {
+		pte_t new_pte = stage2_build_pte(pfn, mem_type, writable,
+						 needs_exec, true);
+
+		ret = stage2_set_cont_ptes(kvm, memcache, fault_ipa, &new_pte);
 	} else {
 		pte_t new_pte = stage2_build_pte(pfn, mem_type, writable,
 						 needs_exec, false);
-- 
1.8.3.1


_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/5] KVM: arm/arm64: Add support for creating PMD contiguous hugepages at stage2
  2019-05-01  9:44 [RFC PATCH 0/5] KVM: arm64: Add support for contiguous PTE/PMD hugepages at stage2 Zenghui Yu
                   ` (4 preceding siblings ...)
  2019-05-01  9:44 ` [PATCH 4/5] KVM: arm/arm64: Add support for creating PTE contiguous hugepages at stage2 Zenghui Yu
@ 2019-05-01  9:44 ` Zenghui Yu
  2019-05-01  9:44   ` Zenghui Yu
  5 siblings, 1 reply; 12+ messages in thread
From: Zenghui Yu @ 2019-05-01  9:44 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel, kvm
  Cc: marc.zyngier, catalin.marinas, will.deacon, linux

With this patch, we now support PMD contiguous hugepages at stage2, with
following additional page size at stage2:

                CONT PMD
                --------
 4K granule:      32M
16K granule:       1G
64K granule:      16G

Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
---
 virt/kvm/arm/mmu.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index fdd6314..7173589 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -1125,6 +1125,66 @@ static pte_t *stage2_get_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache
 	return pte_offset_kernel(pmd, addr);
 }
 
+static inline pgprot_t pmd_pgprot(pmd_t pmd)
+{
+	unsigned long pfn = pmd_pfn(pmd);
+
+	return __pgprot(pmd_val(pfn_pmd(pfn, __pgprot(0))) ^ pmd_val(pmd));
+}
+
+static int stage2_set_cont_pmds(struct kvm *kvm, struct kvm_mmu_memory_cache
+				*cache, phys_addr_t addr, const pmd_t *new_pmd)
+{
+	pmd_t *pmd, old_pmd;
+	unsigned long pfn, dpfn;
+	int i;
+	pgprot_t hugeprot;
+	phys_addr_t baddr;
+
+	/* Start with the first pmd. */
+	addr &= CONT_PMD_MASK;
+	pfn = pmd_pfn(*new_pmd);
+	dpfn = PMD_SIZE >> PAGE_SHIFT;
+	hugeprot = pmd_pgprot(*new_pmd);
+
+retry:
+	pmd = stage2_get_pmd(kvm, cache, addr);
+	VM_BUG_ON(!pmd);
+
+	old_pmd = *pmd;
+
+	/* Skip page table update if there is no change */
+	if (pmd_val(old_pmd) == pmd_val(*new_pmd))
+		return 0;
+
+	/*
+	 * baddr and the following loop is for only one scenario:
+	 * logging cancel ... Can we do it better?
+	 */
+	baddr = addr;
+	for (i = 0; i < CONT_PMDS; i++, pmd++, baddr += PMD_SIZE) {
+		if (pmd_present(*pmd) && !pmd_thp_or_huge(*pmd)) {
+			unmap_stage2_range(kvm, baddr, S2_PMD_SIZE);
+			goto retry;
+		}
+	}
+
+	pmd = stage2_get_pmd(kvm, cache, addr);
+
+	for (i = 0; i < CONT_PMDS; i++, pmd++, addr += PMD_SIZE, pfn += dpfn) {
+		if (pmd_present(old_pmd)) {
+			pmd_clear(pmd);
+			kvm_tlb_flush_vmid_ipa(kvm, addr);
+		} else {
+			get_page(virt_to_page(pmd));
+		}
+
+		kvm_set_pmd(pmd, pfn_pmd(pfn, hugeprot));
+	}
+
+	return 0;
+}
+
 static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache
 			       *cache, phys_addr_t addr, const pmd_t *new_pmd)
 {
@@ -1894,6 +1954,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	 * 3 levels, i.e, PMD is not folded.
 	 */
 	if (vma_pagesize == CONT_PTE_SIZE || vma_pagesize == PMD_SIZE ||
+	    vma_pagesize == CONT_PMD_SIZE ||
 	    (vma_pagesize == PUD_SIZE && kvm_stage2_has_pmd(kvm)))
 		gfn = (fault_ipa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT;
 	up_read(&current->mm->mmap_sem);
@@ -1982,6 +2043,11 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 						 needs_exec);
 
 		ret = stage2_set_pud_huge(kvm, memcache, fault_ipa, &new_pud);
+	} else if (vma_pagesize == CONT_PMD_SIZE) {
+		pmd_t new_pmd = stage2_build_pmd(pfn, mem_type, writable,
+						 needs_exec, true);
+
+		ret = stage2_set_cont_pmds(kvm, memcache, fault_ipa, &new_pmd);
 	} else if (vma_pagesize == PMD_SIZE) {
 		pmd_t new_pmd = stage2_build_pmd(pfn, mem_type, writable,
 						 needs_exec, false);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/5] KVM: arm/arm64: Add support for creating PMD contiguous hugepages at stage2
  2019-05-01  9:44 ` [PATCH 5/5] KVM: arm/arm64: Add support for creating PMD " Zenghui Yu
@ 2019-05-01  9:44   ` Zenghui Yu
  0 siblings, 0 replies; 12+ messages in thread
From: Zenghui Yu @ 2019-05-01  9:44 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, linux-kernel, kvm
  Cc: marc.zyngier, catalin.marinas, will.deacon, linux

With this patch, we now support PMD contiguous hugepages at stage2, with
following additional page size at stage2:

                CONT PMD
                --------
 4K granule:      32M
16K granule:       1G
64K granule:      16G

Signed-off-by: Zenghui Yu <yuzenghui@huawei.com>
---
 virt/kvm/arm/mmu.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index fdd6314..7173589 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -1125,6 +1125,66 @@ static pte_t *stage2_get_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache
 	return pte_offset_kernel(pmd, addr);
 }
 
+static inline pgprot_t pmd_pgprot(pmd_t pmd)
+{
+	unsigned long pfn = pmd_pfn(pmd);
+
+	return __pgprot(pmd_val(pfn_pmd(pfn, __pgprot(0))) ^ pmd_val(pmd));
+}
+
+static int stage2_set_cont_pmds(struct kvm *kvm, struct kvm_mmu_memory_cache
+				*cache, phys_addr_t addr, const pmd_t *new_pmd)
+{
+	pmd_t *pmd, old_pmd;
+	unsigned long pfn, dpfn;
+	int i;
+	pgprot_t hugeprot;
+	phys_addr_t baddr;
+
+	/* Start with the first pmd. */
+	addr &= CONT_PMD_MASK;
+	pfn = pmd_pfn(*new_pmd);
+	dpfn = PMD_SIZE >> PAGE_SHIFT;
+	hugeprot = pmd_pgprot(*new_pmd);
+
+retry:
+	pmd = stage2_get_pmd(kvm, cache, addr);
+	VM_BUG_ON(!pmd);
+
+	old_pmd = *pmd;
+
+	/* Skip page table update if there is no change */
+	if (pmd_val(old_pmd) == pmd_val(*new_pmd))
+		return 0;
+
+	/*
+	 * baddr and the following loop is for only one scenario:
+	 * logging cancel ... Can we do it better?
+	 */
+	baddr = addr;
+	for (i = 0; i < CONT_PMDS; i++, pmd++, baddr += PMD_SIZE) {
+		if (pmd_present(*pmd) && !pmd_thp_or_huge(*pmd)) {
+			unmap_stage2_range(kvm, baddr, S2_PMD_SIZE);
+			goto retry;
+		}
+	}
+
+	pmd = stage2_get_pmd(kvm, cache, addr);
+
+	for (i = 0; i < CONT_PMDS; i++, pmd++, addr += PMD_SIZE, pfn += dpfn) {
+		if (pmd_present(old_pmd)) {
+			pmd_clear(pmd);
+			kvm_tlb_flush_vmid_ipa(kvm, addr);
+		} else {
+			get_page(virt_to_page(pmd));
+		}
+
+		kvm_set_pmd(pmd, pfn_pmd(pfn, hugeprot));
+	}
+
+	return 0;
+}
+
 static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache
 			       *cache, phys_addr_t addr, const pmd_t *new_pmd)
 {
@@ -1894,6 +1954,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	 * 3 levels, i.e, PMD is not folded.
 	 */
 	if (vma_pagesize == CONT_PTE_SIZE || vma_pagesize == PMD_SIZE ||
+	    vma_pagesize == CONT_PMD_SIZE ||
 	    (vma_pagesize == PUD_SIZE && kvm_stage2_has_pmd(kvm)))
 		gfn = (fault_ipa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT;
 	up_read(&current->mm->mmap_sem);
@@ -1982,6 +2043,11 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 						 needs_exec);
 
 		ret = stage2_set_pud_huge(kvm, memcache, fault_ipa, &new_pud);
+	} else if (vma_pagesize == CONT_PMD_SIZE) {
+		pmd_t new_pmd = stage2_build_pmd(pfn, mem_type, writable,
+						 needs_exec, true);
+
+		ret = stage2_set_cont_pmds(kvm, memcache, fault_ipa, &new_pmd);
 	} else if (vma_pagesize == PMD_SIZE) {
 		pmd_t new_pmd = stage2_build_pmd(pfn, mem_type, writable,
 						 needs_exec, false);
-- 
1.8.3.1


_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2019-05-01  9:48 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-01  9:44 [RFC PATCH 0/5] KVM: arm64: Add support for contiguous PTE/PMD hugepages at stage2 Zenghui Yu
2019-05-01  9:44 ` Zenghui Yu
2019-05-01  9:44 ` [PATCH 1/5] KVM: arm/arm64: Introduce helpers for page table enties with contiguous bit Zenghui Yu
2019-05-01  9:44   ` Zenghui Yu
2019-05-01  9:44 ` [PATCH 2/5] KVM: arm/arm64: Re-factor building the stage2 page table entries Zenghui Yu
2019-05-01  9:44   ` Zenghui Yu
2019-05-01  9:44 ` [PATCH 3/5] KVM: arm/arm64: Support dirty page tracking for contiguous hugepages Zenghui Yu
2019-05-01  9:44   ` Zenghui Yu
2019-05-01  9:44 ` [PATCH 4/5] KVM: arm/arm64: Add support for creating PTE contiguous hugepages at stage2 Zenghui Yu
2019-05-01  9:44   ` Zenghui Yu
2019-05-01  9:44 ` [PATCH 5/5] KVM: arm/arm64: Add support for creating PMD " Zenghui Yu
2019-05-01  9:44   ` Zenghui Yu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).