linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/7] arm64: Use contigous PTE bit for the kernel linear mapping
@ 2015-09-16 19:02 Jeremy Linton
  2015-09-16 19:03 ` [PATCH 1/7] arm64: Add contiguous page flag shifts and constants Jeremy Linton
                   ` (6 more replies)
  0 siblings, 7 replies; 13+ messages in thread
From: Jeremy Linton @ 2015-09-16 19:02 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: catalin.marinas, will.deacon, linux-kernel, dwoods, steve.capper,
	shijie.huang, Jeremy Linton

When running 64k pages it became apparent that it was possible that the
kernel could create more TLB pressure in certain circumstances when
compared to the 4k page kernel. This is due to the fact that large
portions of the 4k kernel can be mapped with 2M blocks.
While the larger block size for 64k pages is 512M, it 
frequently won't be used for assorted reasons.

ARMv8 has a contiguous PTE bit that allows the TLBs to map a range larger
than a single PTE if the range is physically contiguous. So its
a good idea to use this where appropriate for the kernel mapping.

This patch adds the definitions for the contiguous bit, updates the kernel
page range dump to understand them (and block translations),
and updates the code in mmu.c to use the contiguous bit where appropriate
for the kernel linear mapping.

Jeremy Linton (7):
  arm64: Add contiguous page flag shifts and constants
  arm64: Shorten lines which exceed 80 characters
  arm64: PTE/PMD contiguous bit definition
  arm64: Macros to check/set/unset the contiguous bit
  arm64: Default kernel pages should be contiguous
  arm64: Make the kernel page dump utility aware of the CONT bit
  arm64: Mark kernel page ranges contiguous

 arch/arm64/include/asm/page.h          |  8 +++-
 arch/arm64/include/asm/pgtable-hwdef.h | 25 ++++++++----
 arch/arm64/include/asm/pgtable.h       | 13 +++++++
 arch/arm64/mm/dump.c                   | 18 ++++++++-
 arch/arm64/mm/mmu.c                    | 70 ++++++++++++++++++++++++++++++----
 5 files changed, 116 insertions(+), 18 deletions(-)

-- 
2.4.3



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

* [PATCH 1/7] arm64: Add contiguous page flag shifts and constants
  2015-09-16 19:02 [PATCH 0/7] arm64: Use contigous PTE bit for the kernel linear mapping Jeremy Linton
@ 2015-09-16 19:03 ` Jeremy Linton
  2015-09-16 19:03 ` [PATCH 2/7] arm64: Shorten lines which exceed 80 characters Jeremy Linton
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Jeremy Linton @ 2015-09-16 19:03 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: catalin.marinas, will.deacon, linux-kernel, dwoods, steve.capper,
	shijie.huang, Jeremy Linton

Add the number of pages required to form a contiguous range,
as well as some supporting constants.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/include/asm/page.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h
index 7d9c7e4..33892ef 100644
--- a/arch/arm64/include/asm/page.h
+++ b/arch/arm64/include/asm/page.h
@@ -20,14 +20,20 @@
 #define __ASM_PAGE_H
 
 /* PAGE_SHIFT determines the page size */
+/* CONT_SHIFT determines the number of pages which can be tracked together  */
 #ifdef CONFIG_ARM64_64K_PAGES
 #define PAGE_SHIFT		16
+#define CONT_SHIFT		5
 #else
 #define PAGE_SHIFT		12
+#define CONT_SHIFT		4
 #endif
-#define PAGE_SIZE		(_AC(1,UL) << PAGE_SHIFT)
+#define PAGE_SIZE		(_AC(1, UL) << PAGE_SHIFT)
 #define PAGE_MASK		(~(PAGE_SIZE-1))
 
+#define CONT_SIZE		(_AC(1, UL) << (CONT_SHIFT + PAGE_SHIFT))
+#define CONT_MASK		(~(CONT_SIZE-1))
+
 /*
  * The idmap and swapper page tables need some space reserved in the kernel
  * image. Both require pgd, pud (4 levels only) and pmd tables to (section)
-- 
2.4.3



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

* [PATCH 2/7] arm64: Shorten lines which exceed 80 characters
  2015-09-16 19:02 [PATCH 0/7] arm64: Use contigous PTE bit for the kernel linear mapping Jeremy Linton
  2015-09-16 19:03 ` [PATCH 1/7] arm64: Add contiguous page flag shifts and constants Jeremy Linton
@ 2015-09-16 19:03 ` Jeremy Linton
  2015-09-17  9:45   ` Catalin Marinas
  2015-09-16 19:03 ` [PATCH 3/7] arm64: PTE/PMD contiguous bit definition Jeremy Linton
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Jeremy Linton @ 2015-09-16 19:03 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: catalin.marinas, will.deacon, linux-kernel, dwoods, steve.capper,
	shijie.huang, Jeremy Linton

PTE definitions in this file exceed 80 characters

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/include/asm/pgtable-hwdef.h | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 24154b0..4489cf6 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -99,14 +99,14 @@
 #define PTE_TYPE_FAULT		(_AT(pteval_t, 0) << 0)
 #define PTE_TYPE_PAGE		(_AT(pteval_t, 3) << 0)
 #define PTE_TABLE_BIT		(_AT(pteval_t, 1) << 1)
-#define PTE_USER		(_AT(pteval_t, 1) << 6)		/* AP[1] */
-#define PTE_RDONLY		(_AT(pteval_t, 1) << 7)		/* AP[2] */
-#define PTE_SHARED		(_AT(pteval_t, 3) << 8)		/* SH[1:0], inner shareable */
-#define PTE_AF			(_AT(pteval_t, 1) << 10)	/* Access Flag */
-#define PTE_NG			(_AT(pteval_t, 1) << 11)	/* nG */
-#define PTE_DBM			(_AT(pteval_t, 1) << 51)	/* Dirty Bit Management */
-#define PTE_PXN			(_AT(pteval_t, 1) << 53)	/* Privileged XN */
-#define PTE_UXN			(_AT(pteval_t, 1) << 54)	/* User XN */
+#define PTE_USER		(_AT(pteval_t, 1) << 6)  /* AP[1] */
+#define PTE_RDONLY		(_AT(pteval_t, 1) << 7)  /* AP[2] */
+#define PTE_SHARED		(_AT(pteval_t, 3) << 8)  /* inner shareable */
+#define PTE_AF			(_AT(pteval_t, 1) << 10) /* Access Flag */
+#define PTE_NG			(_AT(pteval_t, 1) << 11) /* nG */
+#define PTE_DBM			(_AT(pteval_t, 1) << 51) /* Dirty Bit Mgmt */
+#define PTE_PXN			(_AT(pteval_t, 1) << 53) /* Privileged XN */
+#define PTE_UXN			(_AT(pteval_t, 1) << 54) /* User XN */
 
 /*
  * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
-- 
2.4.3



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

* [PATCH 3/7] arm64: PTE/PMD contiguous bit definition
  2015-09-16 19:02 [PATCH 0/7] arm64: Use contigous PTE bit for the kernel linear mapping Jeremy Linton
  2015-09-16 19:03 ` [PATCH 1/7] arm64: Add contiguous page flag shifts and constants Jeremy Linton
  2015-09-16 19:03 ` [PATCH 2/7] arm64: Shorten lines which exceed 80 characters Jeremy Linton
@ 2015-09-16 19:03 ` Jeremy Linton
  2015-09-16 19:03 ` [PATCH 4/7] arm64: Macros to check/set/unset the contiguous bit Jeremy Linton
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Jeremy Linton @ 2015-09-16 19:03 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: catalin.marinas, will.deacon, linux-kernel, dwoods, steve.capper,
	shijie.huang, Jeremy Linton

Define the bit positions in the PTE and PMD for the
contiguous bit.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/include/asm/pgtable-hwdef.h | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 4489cf6..80eeebf 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -55,6 +55,13 @@
 #define SECTION_MASK		(~(SECTION_SIZE-1))
 
 /*
+ * Contiguous page definitions.
+ */
+#define CONT_RANGE		(_AC(1, UL) << CONT_SHIFT)
+#define CONT_RANGE_MASK	((CONT_RANGE-1) << PAGE_SHIFT)
+#define CONT_RANGE_OFFSET(addr) (((addr)>>PAGE_SHIFT)&(CONT_RANGE-1))
+
+/*
  * Hardware page table definitions.
  *
  * Level 1 descriptor (PUD).
@@ -83,6 +90,7 @@
 #define PMD_SECT_S		(_AT(pmdval_t, 3) << 8)
 #define PMD_SECT_AF		(_AT(pmdval_t, 1) << 10)
 #define PMD_SECT_NG		(_AT(pmdval_t, 1) << 11)
+#define PMD_SECT_CONT		(_AT(pmdval_t, 1) << 52)
 #define PMD_SECT_PXN		(_AT(pmdval_t, 1) << 53)
 #define PMD_SECT_UXN		(_AT(pmdval_t, 1) << 54)
 
@@ -105,6 +113,7 @@
 #define PTE_AF			(_AT(pteval_t, 1) << 10) /* Access Flag */
 #define PTE_NG			(_AT(pteval_t, 1) << 11) /* nG */
 #define PTE_DBM			(_AT(pteval_t, 1) << 51) /* Dirty Bit Mgmt */
+#define PTE_CONT		(_AT(pteval_t, 1) << 52) /* Contiguous range */
 #define PTE_PXN			(_AT(pteval_t, 1) << 53) /* Privileged XN */
 #define PTE_UXN			(_AT(pteval_t, 1) << 54) /* User XN */
 
-- 
2.4.3



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

* [PATCH 4/7] arm64: Macros to check/set/unset the contiguous bit
  2015-09-16 19:02 [PATCH 0/7] arm64: Use contigous PTE bit for the kernel linear mapping Jeremy Linton
                   ` (2 preceding siblings ...)
  2015-09-16 19:03 ` [PATCH 3/7] arm64: PTE/PMD contiguous bit definition Jeremy Linton
@ 2015-09-16 19:03 ` Jeremy Linton
  2015-09-16 19:03 ` [PATCH 5/7] arm64: Default kernel pages should be contiguous Jeremy Linton
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Jeremy Linton @ 2015-09-16 19:03 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: catalin.marinas, will.deacon, linux-kernel, dwoods, steve.capper,
	shijie.huang, Jeremy Linton

Add the supporting macros to check if the contiguous bit
is set, set the bit, or clear it in a PTE entry.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/include/asm/pgtable.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 6900b2d9..d43e1d1 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -144,6 +144,7 @@ extern struct page *empty_zero_page;
 #define pte_special(pte)	(!!(pte_val(pte) & PTE_SPECIAL))
 #define pte_write(pte)		(!!(pte_val(pte) & PTE_WRITE))
 #define pte_exec(pte)		(!(pte_val(pte) & PTE_UXN))
+#define pte_cont(pte)		(!!(pte_val(pte) & PTE_CONT))
 
 #ifdef CONFIG_ARM64_HW_AFDBM
 #define pte_hw_dirty(pte)	(!(pte_val(pte) & PTE_RDONLY))
@@ -206,6 +207,16 @@ static inline pte_t pte_mkspecial(pte_t pte)
 	return set_pte_bit(pte, __pgprot(PTE_SPECIAL));
 }
 
+static inline pte_t pte_mkcont(pte_t pte)
+{
+	return set_pte_bit(pte, __pgprot(PTE_CONT));
+}
+
+static inline pte_t pte_mknoncont(pte_t pte)
+{
+	return clear_pte_bit(pte, __pgprot(PTE_CONT));
+}
+
 static inline void set_pte(pte_t *ptep, pte_t pte)
 {
 	*ptep = pte;
-- 
2.4.3



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

* [PATCH 5/7] arm64: Default kernel pages should be contiguous
  2015-09-16 19:02 [PATCH 0/7] arm64: Use contigous PTE bit for the kernel linear mapping Jeremy Linton
                   ` (3 preceding siblings ...)
  2015-09-16 19:03 ` [PATCH 4/7] arm64: Macros to check/set/unset the contiguous bit Jeremy Linton
@ 2015-09-16 19:03 ` Jeremy Linton
  2015-09-16 19:03 ` [PATCH 6/7] arm64: Make the kernel page dump utility aware of the CONT bit Jeremy Linton
  2015-09-16 19:03 ` [PATCH 7/7] arm64: Mark kernel page ranges contiguous Jeremy Linton
  6 siblings, 0 replies; 13+ messages in thread
From: Jeremy Linton @ 2015-09-16 19:03 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: catalin.marinas, will.deacon, linux-kernel, dwoods, steve.capper,
	shijie.huang, Jeremy Linton

The default page attributes for a PMD being broken should have the CONT bit
set. Create a new definition for an early boot range of PTE's that are
contiguous.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/include/asm/pgtable.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index d43e1d1..252499e 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -76,6 +76,8 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
 
 #define PAGE_KERNEL		__pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE)
 #define PAGE_KERNEL_EXEC	__pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE)
+#define PAGE_KERNEL_EXEC_CONT	__pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | \
+					 PTE_WRITE | PTE_CONT)
 
 #define PAGE_HYP		__pgprot(_PAGE_DEFAULT | PTE_HYP)
 #define PAGE_HYP_DEVICE		__pgprot(PROT_DEVICE_nGnRE | PTE_HYP)
-- 
2.4.3



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

* [PATCH 6/7] arm64: Make the kernel page dump utility aware of the CONT bit
  2015-09-16 19:02 [PATCH 0/7] arm64: Use contigous PTE bit for the kernel linear mapping Jeremy Linton
                   ` (4 preceding siblings ...)
  2015-09-16 19:03 ` [PATCH 5/7] arm64: Default kernel pages should be contiguous Jeremy Linton
@ 2015-09-16 19:03 ` Jeremy Linton
  2015-09-18  7:02   ` Huang Shijie
  2015-09-18  8:35   ` Huang Shijie
  2015-09-16 19:03 ` [PATCH 7/7] arm64: Mark kernel page ranges contiguous Jeremy Linton
  6 siblings, 2 replies; 13+ messages in thread
From: Jeremy Linton @ 2015-09-16 19:03 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: catalin.marinas, will.deacon, linux-kernel, dwoods, steve.capper,
	shijie.huang, Jeremy Linton

The kernel page dump utility needs to be aware of the CONT bit before
it will break up pages ranges for display.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/mm/dump.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
index f3d6221..5a22a11 100644
--- a/arch/arm64/mm/dump.c
+++ b/arch/arm64/mm/dump.c
@@ -67,6 +67,12 @@ static struct addr_marker address_markers[] = {
 	{ -1,			NULL },
 };
 
+/*
+ * The page dumper groups page table entries of the same type into a single
+ * description. It uses pg_state to track the range information while
+ * iterating over the pte entries. When the continuity is broken it then
+ * dumps out a description of the range.
+ */
 struct pg_state {
 	struct seq_file *seq;
 	const struct addr_marker *marker;
@@ -114,6 +120,16 @@ static const struct prot_bits pte_bits[] = {
 		.set	= "NG",
 		.clear	= "  ",
 	}, {
+		.mask	= PTE_CONT,
+		.val	= PTE_CONT,
+		.set	= "CON",
+		.clear	= "   ",
+	}, {
+		.mask	= PTE_TABLE_BIT,
+		.val	= PTE_TABLE_BIT,
+		.set	= "   ",
+		.clear	= "BLK",
+	}, {
 		.mask	= PTE_UXN,
 		.val	= PTE_UXN,
 		.set	= "UXN",
@@ -198,7 +214,7 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
 		unsigned long delta;
 
 		if (st->current_prot) {
-			seq_printf(st->seq, "0x%16lx-0x%16lx   ",
+			seq_printf(st->seq, "0x%016lx-0x%016lx   ",
 				   st->start_address, addr);
 
 			delta = (addr - st->start_address) >> 10;
-- 
2.4.3



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

* [PATCH 7/7] arm64: Mark kernel page ranges contiguous
  2015-09-16 19:02 [PATCH 0/7] arm64: Use contigous PTE bit for the kernel linear mapping Jeremy Linton
                   ` (5 preceding siblings ...)
  2015-09-16 19:03 ` [PATCH 6/7] arm64: Make the kernel page dump utility aware of the CONT bit Jeremy Linton
@ 2015-09-16 19:03 ` Jeremy Linton
  2015-09-17 17:23   ` Steve Capper
  6 siblings, 1 reply; 13+ messages in thread
From: Jeremy Linton @ 2015-09-16 19:03 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: catalin.marinas, will.deacon, linux-kernel, dwoods, steve.capper,
	shijie.huang, Jeremy Linton

With 64k pages, the next larger segment size is 512M. The linux
kernel also uses different protection flags to cover its code and data.
Because of this requirement, the vast majority of the kernel code and
data structures end up being mapped with 64k pages instead of the larger
pages common with a 4k page kernel.

Recent ARM processors support a contiguous bit in the
page tables which allows the a TLB to cover a range larger than a
single PTE if that range is mapped into physically contiguous
ram.

So, for the kernel its a good idea to set this flag. Some basic
micro benchmarks show it can significantly reduce the number of
L1 dTLB refills.

Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
---
 arch/arm64/mm/mmu.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 62 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 9211b85..c7abbcc 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -80,19 +80,55 @@ static void split_pmd(pmd_t *pmd, pte_t *pte)
 	do {
 		/*
 		 * Need to have the least restrictive permissions available
-		 * permissions will be fixed up later
+		 * permissions will be fixed up later. Default the new page
+		 * range as contiguous ptes.
 		 */
-		set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
+		set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC_CONT));
 		pfn++;
 	} while (pte++, i++, i < PTRS_PER_PTE);
 }
 
+/*
+ * Given a PTE with the CONT bit set, determine where the CONT range
+ * starts, and clear the entire range of PTE CONT bits.
+ */
+static void clear_cont_pte_range(pte_t *pte, unsigned long addr)
+{
+	int i;
+
+	pte -= CONT_RANGE_OFFSET(addr);
+	for (i = 0; i < CONT_RANGE; i++) {
+		set_pte(pte, pte_mknoncont(*pte));
+		pte++;
+	}
+	flush_tlb_all();
+}
+
+/*
+ * Given a range of PTEs set the pfn and provided page protection flags
+ */
+static void __populate_init_pte(pte_t *pte, unsigned long addr,
+				unsigned long end, phys_addr_t phys,
+				pgprot_t prot)
+{
+	unsigned long pfn = __phys_to_pfn(phys);
+
+	do {
+		/* clear all the bits except the pfn, then apply the prot */
+		set_pte(pte, pfn_pte(pfn, prot));
+		pte++;
+		pfn++;
+		addr += PAGE_SIZE;
+	} while (addr != end);
+}
+
 static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
-				  unsigned long end, unsigned long pfn,
+				  unsigned long end, phys_addr_t phys,
 				  pgprot_t prot,
 				  void *(*alloc)(unsigned long size))
 {
 	pte_t *pte;
+	unsigned long next;
 
 	if (pmd_none(*pmd) || pmd_sect(*pmd)) {
 		pte = alloc(PTRS_PER_PTE * sizeof(pte_t));
@@ -105,9 +141,28 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
 
 	pte = pte_offset_kernel(pmd, addr);
 	do {
-		set_pte(pte, pfn_pte(pfn, prot));
-		pfn++;
-	} while (pte++, addr += PAGE_SIZE, addr != end);
+		next = min(end, (addr + CONT_SIZE) & CONT_MASK);
+		if (((addr | next | phys) & CONT_RANGE_MASK) == 0) {
+			/* a block of CONT_RANGE_SIZE PTEs */
+			__populate_init_pte(pte, addr, next, phys,
+					    prot | __pgprot(PTE_CONT));
+			pte += CONT_RANGE;
+		} else {
+			/*
+			 * If the range being split is already inside of a
+			 * contiguous range but this PTE isn't going to be
+			 * contiguous, then we want to unmark the adjacent
+			 * ranges, then update the portion of the range we
+			 * are interrested in.
+			 */
+			 clear_cont_pte_range(pte, addr);
+			 __populate_init_pte(pte, addr, next, phys, prot);
+			 pte += CONT_RANGE_OFFSET(next - addr);
+		}
+
+		phys += next - addr;
+		addr = next;
+	} while (addr != end);
 }
 
 void split_pud(pud_t *old_pud, pmd_t *pmd)
@@ -168,8 +223,7 @@ static void alloc_init_pmd(struct mm_struct *mm, pud_t *pud,
 				}
 			}
 		} else {
-			alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
-				       prot, alloc);
+			alloc_init_pte(pmd, addr, next, phys, prot, alloc);
 		}
 		phys += next - addr;
 	} while (pmd++, addr = next, addr != end);
-- 
2.4.3



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

* Re: [PATCH 2/7] arm64: Shorten lines which exceed 80 characters
  2015-09-16 19:03 ` [PATCH 2/7] arm64: Shorten lines which exceed 80 characters Jeremy Linton
@ 2015-09-17  9:45   ` Catalin Marinas
  0 siblings, 0 replies; 13+ messages in thread
From: Catalin Marinas @ 2015-09-17  9:45 UTC (permalink / raw)
  To: Jeremy Linton
  Cc: linux-arm-kernel, steve.capper, dwoods, linux-kernel,
	will.deacon, shijie.huang

On Wed, Sep 16, 2015 at 02:03:01PM -0500, Jeremy Linton wrote:
> PTE definitions in this file exceed 80 characters
> 
> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
> ---
>  arch/arm64/include/asm/pgtable-hwdef.h | 16 ++++++++--------
>  1 file changed, 8 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
> index 24154b0..4489cf6 100644
> --- a/arch/arm64/include/asm/pgtable-hwdef.h
> +++ b/arch/arm64/include/asm/pgtable-hwdef.h
> @@ -99,14 +99,14 @@
>  #define PTE_TYPE_FAULT		(_AT(pteval_t, 0) << 0)
>  #define PTE_TYPE_PAGE		(_AT(pteval_t, 3) << 0)
>  #define PTE_TABLE_BIT		(_AT(pteval_t, 1) << 1)
> -#define PTE_USER		(_AT(pteval_t, 1) << 6)		/* AP[1] */
> -#define PTE_RDONLY		(_AT(pteval_t, 1) << 7)		/* AP[2] */
> -#define PTE_SHARED		(_AT(pteval_t, 3) << 8)		/* SH[1:0], inner shareable */
> -#define PTE_AF			(_AT(pteval_t, 1) << 10)	/* Access Flag */
> -#define PTE_NG			(_AT(pteval_t, 1) << 11)	/* nG */
> -#define PTE_DBM			(_AT(pteval_t, 1) << 51)	/* Dirty Bit Management */
> -#define PTE_PXN			(_AT(pteval_t, 1) << 53)	/* Privileged XN */
> -#define PTE_UXN			(_AT(pteval_t, 1) << 54)	/* User XN */
> +#define PTE_USER		(_AT(pteval_t, 1) << 6)  /* AP[1] */
> +#define PTE_RDONLY		(_AT(pteval_t, 1) << 7)  /* AP[2] */
> +#define PTE_SHARED		(_AT(pteval_t, 3) << 8)  /* inner shareable */
> +#define PTE_AF			(_AT(pteval_t, 1) << 10) /* Access Flag */
> +#define PTE_NG			(_AT(pteval_t, 1) << 11) /* nG */
> +#define PTE_DBM			(_AT(pteval_t, 1) << 51) /* Dirty Bit Mgmt */
> +#define PTE_PXN			(_AT(pteval_t, 1) << 53) /* Privileged XN */
> +#define PTE_UXN			(_AT(pteval_t, 1) << 54) /* User XN */

I told you already ;), I'm not taking this patch. Some (of my) rules for
checkpatch usage:

1. Don't run it on existing code with the aim of fixing it
2. Existing coding style takes precedence over checkpatch warnings

(I have another rule but I don't want to impose it on anyone: I never
run checkpatch)

-- 
Catalin

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

* Re: [PATCH 7/7] arm64: Mark kernel page ranges contiguous
  2015-09-16 19:03 ` [PATCH 7/7] arm64: Mark kernel page ranges contiguous Jeremy Linton
@ 2015-09-17 17:23   ` Steve Capper
  2015-09-17 17:33     ` Jeremy Linton
  0 siblings, 1 reply; 13+ messages in thread
From: Steve Capper @ 2015-09-17 17:23 UTC (permalink / raw)
  To: Jeremy Linton
  Cc: linux-arm-kernel, Steve Capper, Catalin Marinas, dwoods,
	linux-kernel, Will Deacon, shijie.huang

Hi Jeremy,
One quick comment for now below.
I ran into a problem testing this on my Seattle board, and needed the fix below.

Cheers,
--
Steve

On 16 September 2015 at 20:03, Jeremy Linton <jeremy.linton@arm.com> wrote:
> With 64k pages, the next larger segment size is 512M. The linux
> kernel also uses different protection flags to cover its code and data.
> Because of this requirement, the vast majority of the kernel code and
> data structures end up being mapped with 64k pages instead of the larger
> pages common with a 4k page kernel.
>
> Recent ARM processors support a contiguous bit in the
> page tables which allows the a TLB to cover a range larger than a
> single PTE if that range is mapped into physically contiguous
> ram.
>
> So, for the kernel its a good idea to set this flag. Some basic
> micro benchmarks show it can significantly reduce the number of
> L1 dTLB refills.
>
> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
> ---
>  arch/arm64/mm/mmu.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 62 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> index 9211b85..c7abbcc 100644
> --- a/arch/arm64/mm/mmu.c
> +++ b/arch/arm64/mm/mmu.c
> @@ -80,19 +80,55 @@ static void split_pmd(pmd_t *pmd, pte_t *pte)
>         do {
>                 /*
>                  * Need to have the least restrictive permissions available
> -                * permissions will be fixed up later
> +                * permissions will be fixed up later. Default the new page
> +                * range as contiguous ptes.
>                  */
> -               set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
> +               set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC_CONT));
>                 pfn++;
>         } while (pte++, i++, i < PTRS_PER_PTE);
>  }
>
> +/*
> + * Given a PTE with the CONT bit set, determine where the CONT range
> + * starts, and clear the entire range of PTE CONT bits.
> + */
> +static void clear_cont_pte_range(pte_t *pte, unsigned long addr)
> +{
> +       int i;
> +
> +       pte -= CONT_RANGE_OFFSET(addr);
> +       for (i = 0; i < CONT_RANGE; i++) {
> +               set_pte(pte, pte_mknoncont(*pte));
> +               pte++;
> +       }
> +       flush_tlb_all();
> +}
> +
> +/*
> + * Given a range of PTEs set the pfn and provided page protection flags
> + */
> +static void __populate_init_pte(pte_t *pte, unsigned long addr,
> +                               unsigned long end, phys_addr_t phys,
> +                               pgprot_t prot)
> +{
> +       unsigned long pfn = __phys_to_pfn(phys);
> +
> +       do {
> +               /* clear all the bits except the pfn, then apply the prot */
> +               set_pte(pte, pfn_pte(pfn, prot));
> +               pte++;
> +               pfn++;
> +               addr += PAGE_SIZE;
> +       } while (addr != end);
> +}
> +
>  static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
> -                                 unsigned long end, unsigned long pfn,
> +                                 unsigned long end, phys_addr_t phys,
>                                   pgprot_t prot,
>                                   void *(*alloc)(unsigned long size))
>  {
>         pte_t *pte;
> +       unsigned long next;
>
>         if (pmd_none(*pmd) || pmd_sect(*pmd)) {
>                 pte = alloc(PTRS_PER_PTE * sizeof(pte_t));
> @@ -105,9 +141,28 @@ static void alloc_init_pte(pmd_t *pmd, unsigned long addr,
>
>         pte = pte_offset_kernel(pmd, addr);
>         do {
> -               set_pte(pte, pfn_pte(pfn, prot));
> -               pfn++;
> -       } while (pte++, addr += PAGE_SIZE, addr != end);
> +               next = min(end, (addr + CONT_SIZE) & CONT_MASK);
> +               if (((addr | next | phys) & CONT_RANGE_MASK) == 0) {
> +                       /* a block of CONT_RANGE_SIZE PTEs */
> +                       __populate_init_pte(pte, addr, next, phys,
> +                                           prot | __pgprot(PTE_CONT));
> +                       pte += CONT_RANGE;
> +               } else {
> +                       /*
> +                        * If the range being split is already inside of a
> +                        * contiguous range but this PTE isn't going to be
> +                        * contiguous, then we want to unmark the adjacent
> +                        * ranges, then update the portion of the range we
> +                        * are interrested in.
> +                        */
> +                        clear_cont_pte_range(pte, addr);
> +                        __populate_init_pte(pte, addr, next, phys, prot);
> +                        pte += CONT_RANGE_OFFSET(next - addr);

I think this should instead be:
pte += (next - addr) >> PAGE_SHIFT;

Without the above change, I get panics on boot with my Seattle board
when efi_rtc is initialised.
(I think the EFI runtime stuff exacerbates the non-contiguous code
path hence I notice it on my system).

> +               }
> +
> +               phys += next - addr;
> +               addr = next;
> +       } while (addr != end);
>  }
>
>  void split_pud(pud_t *old_pud, pmd_t *pmd)
> @@ -168,8 +223,7 @@ static void alloc_init_pmd(struct mm_struct *mm, pud_t *pud,
>                                 }
>                         }
>                 } else {
> -                       alloc_init_pte(pmd, addr, next, __phys_to_pfn(phys),
> -                                      prot, alloc);
> +                       alloc_init_pte(pmd, addr, next, phys, prot, alloc);
>                 }
>                 phys += next - addr;
>         } while (pmd++, addr = next, addr != end);
> --
> 2.4.3
>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* RE: [PATCH 7/7] arm64: Mark kernel page ranges contiguous
  2015-09-17 17:23   ` Steve Capper
@ 2015-09-17 17:33     ` Jeremy Linton
  0 siblings, 0 replies; 13+ messages in thread
From: Jeremy Linton @ 2015-09-17 17:33 UTC (permalink / raw)
  To: Steve Capper
  Cc: linux-arm-kernel, Steve Capper, Catalin Marinas, dwoods,
	linux-kernel, Will Deacon, Shijie Huang

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 2432 bytes --]

|Hi Jeremy,
|One quick comment for now below.
|I ran into a problem testing this on my Seattle board, and needed the fix
|below.
<snip>
|> -       } while (pte++, addr += PAGE_SIZE, addr != end);
|> +               next = min(end, (addr + CONT_SIZE) & CONT_MASK);
|> +               if (((addr | next | phys) & CONT_RANGE_MASK) == 0) {
|> +                       /* a block of CONT_RANGE_SIZE PTEs */
|> +                       __populate_init_pte(pte, addr, next, phys,
|> +                                           prot | __pgprot(PTE_CONT));
|> +                       pte += CONT_RANGE;
|> +               } else {
|> +                       /*
|> +                        * If the range being split is already inside of a
|> +                        * contiguous range but this PTE isn't going to be
|> +                        * contiguous, then we want to unmark the adjacent
|> +                        * ranges, then update the portion of the range we
|> +                        * are interrested in.
|> +                        */
|> +                        clear_cont_pte_range(pte, addr);
|> +                        __populate_init_pte(pte, addr, next, phys, prot);
|> +                        pte += CONT_RANGE_OFFSET(next - addr);
|
|I think this should instead be:
|pte += (next - addr) >> PAGE_SHIFT;
|
|Without the above change, I get panics on boot with my Seattle board when
|efi_rtc is initialised.
|(I think the EFI runtime stuff exacerbates the non-contiguous code path
|hence I notice it on my system).

I think that implies you have linear mappings >= 2M that aren’t aligned. Ok, but that almost sounds like something we want to complain about if we detect it.






-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium.  Thank you.

ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No:  2557590
ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No:  2548782
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

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

* Re: [PATCH 6/7] arm64: Make the kernel page dump utility aware of the CONT bit
  2015-09-16 19:03 ` [PATCH 6/7] arm64: Make the kernel page dump utility aware of the CONT bit Jeremy Linton
@ 2015-09-18  7:02   ` Huang Shijie
  2015-09-18  8:35   ` Huang Shijie
  1 sibling, 0 replies; 13+ messages in thread
From: Huang Shijie @ 2015-09-18  7:02 UTC (permalink / raw)
  To: Jeremy Linton
  Cc: linux-arm-kernel, catalin.marinas, will.deacon, linux-kernel,
	dwoods, steve.capper

On Wed, Sep 16, 2015 at 02:03:05PM -0500, Jeremy Linton wrote:
Hi Jeremy,
> The kernel page dump utility needs to be aware of the CONT bit before
> it will break up pages ranges for display.
> 
> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
> ---
>  arch/arm64/mm/dump.c | 18 +++++++++++++++++-
>  1 file changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
> index f3d6221..5a22a11 100644
> --- a/arch/arm64/mm/dump.c
> +++ b/arch/arm64/mm/dump.c
> @@ -67,6 +67,12 @@ static struct addr_marker address_markers[] = {
>  	{ -1,			NULL },
>  };
>  
> +/*
> + * The page dumper groups page table entries of the same type into a single
> + * description. It uses pg_state to track the range information while
> + * iterating over the pte entries. When the continuity is broken it then
> + * dumps out a description of the range.
> + */
>  struct pg_state {
>  	struct seq_file *seq;
>  	const struct addr_marker *marker;
> @@ -114,6 +120,16 @@ static const struct prot_bits pte_bits[] = {
>  		.set	= "NG",
>  		.clear	= "  ",
>  	}, {
> +		.mask	= PTE_CONT,
> +		.val	= PTE_CONT,
> +		.set	= "CON",
> +		.clear	= "   ",
> +	}, {
> +		.mask	= PTE_TABLE_BIT,
> +		.val	= PTE_TABLE_BIT,
> +		.set	= "   ",
> +		.clear	= "BLK",
Please update the commit message, since your patch also add the TABLE_BIT, not
only the CONT bit.

thanks
Huang Shijie


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

* Re: [PATCH 6/7] arm64: Make the kernel page dump utility aware of the CONT bit
  2015-09-16 19:03 ` [PATCH 6/7] arm64: Make the kernel page dump utility aware of the CONT bit Jeremy Linton
  2015-09-18  7:02   ` Huang Shijie
@ 2015-09-18  8:35   ` Huang Shijie
  1 sibling, 0 replies; 13+ messages in thread
From: Huang Shijie @ 2015-09-18  8:35 UTC (permalink / raw)
  To: Jeremy Linton
  Cc: linux-arm-kernel, catalin.marinas, will.deacon, linux-kernel,
	dwoods, steve.capper

On Wed, Sep 16, 2015 at 02:03:05PM -0500, Jeremy Linton wrote:
> The kernel page dump utility needs to be aware of the CONT bit before
> it will break up pages ranges for display.
> 
> Signed-off-by: Jeremy Linton <jeremy.linton@arm.com>
> ---
>  arch/arm64/mm/dump.c | 18 +++++++++++++++++-
>  1 file changed, 17 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/mm/dump.c b/arch/arm64/mm/dump.c
> index f3d6221..5a22a11 100644
> --- a/arch/arm64/mm/dump.c
> +++ b/arch/arm64/mm/dump.c
> @@ -67,6 +67,12 @@ static struct addr_marker address_markers[] = {
>  	{ -1,			NULL },
>  };
>  
> +/*
> + * The page dumper groups page table entries of the same type into a single
> + * description. It uses pg_state to track the range information while
> + * iterating over the pte entries. When the continuity is broken it then
> + * dumps out a description of the range.
> + */
>  struct pg_state {
>  	struct seq_file *seq;
>  	const struct addr_marker *marker;
> @@ -114,6 +120,16 @@ static const struct prot_bits pte_bits[] = {
>  		.set	= "NG",
>  		.clear	= "  ",
>  	}, {
> +		.mask	= PTE_CONT,
> +		.val	= PTE_CONT,
> +		.set	= "CON",
> +		.clear	= "   ",
> +	}, {
> +		.mask	= PTE_TABLE_BIT,
> +		.val	= PTE_TABLE_BIT,
> +		.set	= "   ",
> +		.clear	= "BLK",
I think the PTE_TABLE_BIT should be not here. Since PTE_TABLE_BIT is in bit 1,
it should be placed before the PTE_USER which is in bit 6.

thanks
Huang Shijie


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

end of thread, other threads:[~2015-09-18  8:35 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-16 19:02 [PATCH 0/7] arm64: Use contigous PTE bit for the kernel linear mapping Jeremy Linton
2015-09-16 19:03 ` [PATCH 1/7] arm64: Add contiguous page flag shifts and constants Jeremy Linton
2015-09-16 19:03 ` [PATCH 2/7] arm64: Shorten lines which exceed 80 characters Jeremy Linton
2015-09-17  9:45   ` Catalin Marinas
2015-09-16 19:03 ` [PATCH 3/7] arm64: PTE/PMD contiguous bit definition Jeremy Linton
2015-09-16 19:03 ` [PATCH 4/7] arm64: Macros to check/set/unset the contiguous bit Jeremy Linton
2015-09-16 19:03 ` [PATCH 5/7] arm64: Default kernel pages should be contiguous Jeremy Linton
2015-09-16 19:03 ` [PATCH 6/7] arm64: Make the kernel page dump utility aware of the CONT bit Jeremy Linton
2015-09-18  7:02   ` Huang Shijie
2015-09-18  8:35   ` Huang Shijie
2015-09-16 19:03 ` [PATCH 7/7] arm64: Mark kernel page ranges contiguous Jeremy Linton
2015-09-17 17:23   ` Steve Capper
2015-09-17 17:33     ` Jeremy Linton

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).