[PATCH v8 10/23] powerpc/8xx: map more RAM at startup when needed

Christophe Leroy christophe.leroy at c-s.fr
Wed Feb 10 03:08:06 AEDT 2016


On recent kernels, with some debug options like for instance
CONFIG_LOCKDEP, the BSS requires more than 8M memory, allthough
the kernel code fits in the first 8M.
Today, it is necessary to activate CONFIG_PIN_TLB to get more than 8M
at startup, allthough pinning TLB is not necessary for that.

This patch adds more pages (up to 24Mb) to the initial mapping if
possible/needed in order to have the necessary mappings regardless of
CONFIG_PIN_TLB.

We could have mapped 16M or 24M inconditionnally but since some
platforms only have 8M memory, we need something a bit more elaborated

Therefore, if the bootloader is compliant with ePAPR standard, we use
r7 to know how much memory was mapped by the bootloader.
Otherwise, we try to determine the required memory size by looking at
the _end symbol and the address of the device tree.

This patch does not modify the behaviour when CONFIG_PIN_TLB is
selected.

Signed-off-by: Christophe Leroy <christophe.leroy at c-s.fr>
---
v2: no change
v3: Automatic detection of available/needed memory instead of allocating 16M for all.
v4: no change
v5: no change
v6: no change
v8: no change

 arch/powerpc/kernel/head_8xx.S | 56 +++++++++++++++++++++++++++++++++++++++---
 arch/powerpc/mm/8xx_mmu.c      | 10 +++-----
 2 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S
index ae721a1..a268cf4 100644
--- a/arch/powerpc/kernel/head_8xx.S
+++ b/arch/powerpc/kernel/head_8xx.S
@@ -72,6 +72,9 @@
 #define RPN_PATTERN	0x00f0
 #endif
 
+/* ePAPR magic value for non BOOK III-E CPUs */
+#define EPAPR_SMAGIC	0x65504150
+
 	__HEAD
 _ENTRY(_stext);
 _ENTRY(_start);
@@ -101,6 +104,38 @@ _ENTRY(_start);
  */
 	.globl	__start
 __start:
+/*
+ * Determine initial RAM size
+ *
+ * If the Bootloader is ePAPR compliant, the size is given in r7
+ * otherwise, we have to determine how much is needed. For that, we have to
+ * check whether _end of kernel and device tree are within the first 8Mb.
+ */
+	lis	r30, 0x00800000 at h	/* 8Mb by default */
+
+	lis	r8, EPAPR_SMAGIC at h
+	ori	r8, r8, EPAPR_SMAGIC at l
+	cmplw	cr0, r8, r6
+	bne	1f
+	lis	r30, 0x01800000 at h	/* 24Mb max */
+	cmplw	cr0, r7, r30
+	bgt	2f
+	mr	r30, r7			/* save initial ram size */
+	b	2f
+1:
+	/* is kernel _end or DTB in the first 8M ? if not map 16M */
+	lis	r8, (_end - PAGE_OFFSET)@h
+	ori	r8, r8, (_end - PAGE_OFFSET)@l
+	addi	r8, r8, -1
+	or	r8, r8, r3
+	cmplw	cr0, r8, r30
+	blt	2f
+	lis	r30, 0x01000000 at h	/* 16Mb */
+	/* is kernel _end or DTB in the first 16M ? if not map 24M */
+	cmplw	cr0, r8, r30
+	blt	2f
+	lis	r30, 0x01800000 at h	/* 24Mb */
+2:
 	mr	r31,r3			/* save device tree ptr */
 
 	/* We have to turn on the MMU right away so we get cache modes
@@ -737,6 +772,8 @@ start_here:
 /*
  * Decide what sort of machine this is and initialize the MMU.
  */
+	lis	r3, initial_memory_size at ha
+	stw	r30, initial_memory_size at l(r3)
 	li	r3,0
 	mr	r4,r31
 	bl	machine_init
@@ -868,10 +905,15 @@ initial_mmu:
 	mtspr	SPRN_MD_RPN, r8
 
 #ifdef CONFIG_PIN_TLB
-	/* Map two more 8M kernel data pages.
-	*/
+	/* Map one more 8M kernel data page. */
 	addi	r10, r10, 0x0100
 	mtspr	SPRN_MD_CTR, r10
+#else
+	/* Map one more 8M kernel data page if needed */
+	lis	r10, 0x00800000 at h
+	cmplw	cr0, r30, r10
+	ble	1f
+#endif
 
 	lis	r8, KERNELBASE at h	/* Create vaddr for TLB */
 	addis	r8, r8, 0x0080		/* Add 8M */
@@ -884,20 +926,28 @@ initial_mmu:
 	addis	r11, r11, 0x0080	/* Add 8M */
 	mtspr	SPRN_MD_RPN, r11
 
+#ifdef CONFIG_PIN_TLB
+	/* Map one more 8M kernel data page. */
 	addi	r10, r10, 0x0100
 	mtspr	SPRN_MD_CTR, r10
+#else
+	/* Map one more 8M kernel data page if needed */
+	lis	r10, 0x01000000 at h
+	cmplw	cr0, r30, r10
+	ble	1f
+#endif
 
 	addis	r8, r8, 0x0080		/* Add 8M */
 	mtspr	SPRN_MD_EPN, r8
 	mtspr	SPRN_MD_TWC, r9
 	addis	r11, r11, 0x0080	/* Add 8M */
 	mtspr	SPRN_MD_RPN, r11
-#endif
 
 	/* Since the cache is enabled according to the information we
 	 * just loaded into the TLB, invalidate and enable the caches here.
 	 * We should probably check/set other modes....later.
 	 */
+1:
 	lis	r8, IDC_INVALL at h
 	mtspr	SPRN_IC_CST, r8
 	mtspr	SPRN_DC_CST, r8
diff --git a/arch/powerpc/mm/8xx_mmu.c b/arch/powerpc/mm/8xx_mmu.c
index f37d5ec..50f17d2 100644
--- a/arch/powerpc/mm/8xx_mmu.c
+++ b/arch/powerpc/mm/8xx_mmu.c
@@ -20,6 +20,7 @@
 #define IMMR_SIZE (__fix_to_virt(FIX_IMMR_TOP) + PAGE_SIZE - VIRT_IMMR_BASE)
 
 extern int __map_without_ltlbs;
+int initial_memory_size; /* size of initial memory mapped by head_8xx.S */
 
 /*
  * Return PA for this VA if it is in IMMR area, or 0
@@ -143,11 +144,6 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base,
 	 */
 	BUG_ON(first_memblock_base != 0);
 
-#ifdef CONFIG_PIN_TLB
-	/* 8xx can only access 24MB at the moment */
-	memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01800000));
-#else
-	/* 8xx can only access 8MB at the moment */
-	memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000));
-#endif
+	memblock_set_current_limit(min_t(u64, first_memblock_size,
+					 initial_memory_size));
 }
-- 
2.1.0



More information about the Linuxppc-dev mailing list