diff mbox

[RFC,v3] powerpc: Loading kernels over 8Mbytes without CONFIG_PIN_TLB

Message ID 20131215150957.1F5C143E5B@localhost.localdomain (mailing list archive)
State Changes Requested
Delegated to: Scott Wood
Headers show

Commit Message

Christophe Leroy Dec. 15, 2013, 3:09 p.m. UTC
Hereunder is a try to implement the sizing of the initial memory size based on
initial-mapped-area size given by uboot in r7.
As this has an impact on all powerpc platforms due to the need to provide the
info up to function setup_initial_memory_limit(), I'm not completly sure of the
proper implementation.
Thanks to provide comments.

Today on the 8xx, the only way to load kernels whose size is greater than
8Mbytes is to activate CONFIG_PIN_TLB. Otherwise, the physical memory initially
mapped is limited to 8Mbytes. This patch uses the size of initial memory mapped
by the bootloader and given to the kernel through register r7.
This is done regardless of whether CONFIG_PIN_TLB is active or not. It allows to
load "big" kernels (for instance when activating CONFIG_LOCKDEP_SUPPORT) without
having to activate CONFIG_PIN_TLB.

Not-yet-signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>


---
Ce courrier électronique ne contient aucun virus ou logiciel malveillant parce que la protection avast! Antivirus est active.
http://www.avast.com

Comments

Scott Wood March 19, 2014, 8:42 p.m. UTC | #1
On Sun, Dec 15, 2013 at 04:09:57PM +0100, LEROY Christophe wrote:
> Hereunder is a try to implement the sizing of the initial memory size based on
> initial-mapped-area size given by uboot in r7.
> As this has an impact on all powerpc platforms due to the need to provide the
> info up to function setup_initial_memory_limit(), I'm not completly sure of the
> proper implementation.
> Thanks to provide comments.
> 
> Today on the 8xx, the only way to load kernels whose size is greater than
> 8Mbytes is to activate CONFIG_PIN_TLB. Otherwise, the physical memory initially
> mapped is limited to 8Mbytes. This patch uses the size of initial memory mapped
> by the bootloader and given to the kernel through register r7.
> This is done regardless of whether CONFIG_PIN_TLB is active or not. It allows to
> load "big" kernels (for instance when activating CONFIG_LOCKDEP_SUPPORT) without
> having to activate CONFIG_PIN_TLB.
> 
> Not-yet-signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
> 
> ---
> Ce courrier électronique ne contient aucun virus ou logiciel malveillant parce que la protection avast! Antivirus est active.
> http://www.avast.com
> 
> Index: linux/arch/powerpc/include/asm/mmu.h
> ===================================================================
> --- linux/arch/powerpc/include/asm/mmu.h	(revision 5484)
> +++ linux/arch/powerpc/include/asm/mmu.h	(copie de travail)
> @@ -138,7 +138,8 @@
>  extern void early_init_mmu_secondary(void);
>  
>  extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
> -				       phys_addr_t first_memblock_size);
> +				       phys_addr_t first_memblock_size,
> +				       u64 init_mem_size);

What is the difference between first_memblock_size and init_mem_size, in
terms of what you expect setup_initial_memory_limit to do with them?

Can you just pass in min(first_memblock_size, init_mem_size), with the
non-ePAPR fallback handled in head_8xx.S (just load r30 with 8M instead
of zero)?

>  #ifdef CONFIG_PPC64
>  /* This is our real memory area size on ppc64 server, on embedded, we
> Index: linux/arch/powerpc/kernel/head_8xx.S
> ===================================================================
> --- linux/arch/powerpc/kernel/head_8xx.S	(revision 5484)
> +++ linux/arch/powerpc/kernel/head_8xx.S	(copie de travail)
> @@ -31,6 +31,8 @@
>  #include <asm/asm-offsets.h>
>  #include <asm/ptrace.h>
>  
> +#define EPAPR_MAGIC	0x65504150
> +
>  /* Macro to make the code more readable. */
>  #ifdef CONFIG_8xx_CPU6
>  #define DO_8xx_CPU6(val, reg)	\
> @@ -77,10 +79,19 @@
>  	.globl	__start
>  __start:
>  	mr	r31,r3			/* save device tree ptr */
> +	li	r30,0
>  
> +	lis	r8,EPAPR_MAGIC@h
> +	ori	r8,r8, EPAPR_MAGIC@l
> +	cmpw	cr0,r8, r6

Whitespace

> +	bne	1f
> +
> +	mr	r30,r7			/* save initial ram size */
> +
>  	/* We have to turn on the MMU right away so we get cache modes
>  	 * set correctly.
>  	 */
> +1:
>  	bl	initial_mmu
>  
>  /* We now have the lower 8 Meg mapped into TLB entries, and the caches
> @@ -717,6 +728,8 @@
>   */
>  	li	r3,0
>  	mr	r4,r31
> +	li	r5,0
> +	mr	r6,r30
>  	bl	machine_init
>  	bl	MMU_init
>  
> @@ -841,11 +854,17 @@
>  	ori	r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
>  	mtspr	SPRN_MD_RPN, r8
>  
> +	/* Map two more 8M kernel data pages if needed
> +	 * We check how much memory is mapped by the bootloader
> +	*/

Whitespace

> Index: linux/arch/powerpc/kernel/prom.c
> ===================================================================
> --- linux/arch/powerpc/kernel/prom.c	(revision 5484)
> +++ linux/arch/powerpc/kernel/prom.c	(copie de travail)
> @@ -649,7 +649,7 @@
>  	}
>  }
>  
> -void __init early_init_devtree(void *params)
> +void __init early_init_devtree(void *params, u64 init_mem_size)
>  {
>  	phys_addr_t limit;
>  
> @@ -697,7 +697,7 @@
>  	/* make sure we've parsed cmdline for mem= before this */
>  	if (memory_limit)
>  		first_memblock_size = min_t(u64, first_memblock_size, memory_limit);
> -	setup_initial_memory_limit(memstart_addr, first_memblock_size);
> +	setup_initial_memory_limit(memstart_addr, first_memblock_size, init_mem_size);

Line length.
Yes, I know there's an existing violation on the previous line. :-)

> Index: linux/arch/powerpc/mm/init_32.c
> ===================================================================
> --- linux/arch/powerpc/mm/init_32.c	(revision 5484)
> +++ linux/arch/powerpc/mm/init_32.c	(copie de travail)
> @@ -206,19 +206,16 @@
>  
>  #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
>  void setup_initial_memory_limit(phys_addr_t first_memblock_base,
> -				phys_addr_t first_memblock_size)
> +				phys_addr_t first_memblock_size,
> +				u64 init_mem_size)
>  {
>  	/* We don't currently support the first MEMBLOCK not mapping 0
>  	 * physical on those processors
>  	 */
>  	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
> +	if (!init_mem_size)
> +		init_mem_size = 0x00800000;
> +	memblock_set_current_limit(min_t(u64, first_memblock_size, init_mem_size));

Line length

>  }
>  #endif /* CONFIG_8xx */
> Index: linux/arch/powerpc/mm/ppc_mmu_32.c
> ===================================================================
> --- linux/arch/powerpc/mm/ppc_mmu_32.c	(revision 5484)
> +++ linux/arch/powerpc/mm/ppc_mmu_32.c	(copie de travail)
> @@ -273,7 +273,8 @@
>  }
>  
>  void setup_initial_memory_limit(phys_addr_t first_memblock_base,
> -				phys_addr_t first_memblock_size)
> +				phys_addr_t first_memblock_size,
> +				u64 init_mem_size)
>  {
>  	/* We don't currently support the first MEMBLOCK not mapping 0
>  	 * physical on those processors
> Index: linux/arch/powerpc/mm/tlb_nohash.c
> ===================================================================
> --- linux/arch/powerpc/mm/tlb_nohash.c	(revision 5484)
> +++ linux/arch/powerpc/mm/tlb_nohash.c	(copie de travail)
> @@ -654,7 +654,8 @@
>  }
>  
>  void setup_initial_memory_limit(phys_addr_t first_memblock_base,
> -				phys_addr_t first_memblock_size)
> +				phys_addr_t first_memblock_size,
> +				u64 init_mem_size)
>  {
>  	/* On non-FSL Embedded 64-bit, we adjust the RMA size to match
>  	 * the bolted TLB entry. We know for now that only 1G

It seems a bit odd for this function to take init_mem_size on these other
platforms, but not use it.

-Scott
diff mbox

Patch

Index: linux/arch/powerpc/include/asm/mmu.h
===================================================================
--- linux/arch/powerpc/include/asm/mmu.h	(revision 5484)
+++ linux/arch/powerpc/include/asm/mmu.h	(copie de travail)
@@ -138,7 +138,8 @@ 
 extern void early_init_mmu_secondary(void);
 
 extern void setup_initial_memory_limit(phys_addr_t first_memblock_base,
-				       phys_addr_t first_memblock_size);
+				       phys_addr_t first_memblock_size,
+				       u64 init_mem_size);
 
 #ifdef CONFIG_PPC64
 /* This is our real memory area size on ppc64 server, on embedded, we
Index: linux/arch/powerpc/kernel/head_8xx.S
===================================================================
--- linux/arch/powerpc/kernel/head_8xx.S	(revision 5484)
+++ linux/arch/powerpc/kernel/head_8xx.S	(copie de travail)
@@ -31,6 +31,8 @@ 
 #include <asm/asm-offsets.h>
 #include <asm/ptrace.h>
 
+#define EPAPR_MAGIC	0x65504150
+
 /* Macro to make the code more readable. */
 #ifdef CONFIG_8xx_CPU6
 #define DO_8xx_CPU6(val, reg)	\
@@ -77,10 +79,19 @@ 
 	.globl	__start
 __start:
 	mr	r31,r3			/* save device tree ptr */
+	li	r30,0
 
+	lis	r8,EPAPR_MAGIC@h
+	ori	r8,r8, EPAPR_MAGIC@l
+	cmpw	cr0,r8, r6
+	bne	1f
+
+	mr	r30,r7			/* save initial ram size */
+
 	/* We have to turn on the MMU right away so we get cache modes
 	 * set correctly.
 	 */
+1:
 	bl	initial_mmu
 
 /* We now have the lower 8 Meg mapped into TLB entries, and the caches
@@ -717,6 +728,8 @@ 
  */
 	li	r3,0
 	mr	r4,r31
+	li	r5,0
+	mr	r6,r30
 	bl	machine_init
 	bl	MMU_init
 
@@ -841,11 +854,17 @@ 
 	ori	r8, r8, MI_BOOTINIT|0x2 /* Inhibit cache -- Cort */
 	mtspr	SPRN_MD_RPN, r8
 
+	/* Map two more 8M kernel data pages if needed
+	 * We check how much memory is mapped by the bootloader
+	*/
+	lis	r8, 0x0100
+	cmplw	cr0, r8, r30
+	blt	2f
+
 #ifdef CONFIG_PIN_TLB
-	/* Map two more 8M kernel data pages.
-	*/
 	addi	r10, r10, 0x0100
 	mtspr	SPRN_MD_CTR, r10
+#endif
 
 	lis	r8, KERNELBASE@h	/* Create vaddr for TLB */
 	addis	r8, r8, 0x0080		/* Add 8M */
@@ -858,20 +877,26 @@ 
 	addis	r11, r11, 0x0080	/* Add 8M */
 	mtspr	SPRN_MD_RPN, r11
 
+	lis	r8, 0x0180
+	cmplw	cr0, r8, r30
+	blt	2f
+
+#ifdef CONFIG_PIN_TLB
 	addi	r10, r10, 0x0100
 	mtspr	SPRN_MD_CTR, r10
+#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.
 	 */
+2:
 	lis	r8, IDC_INVALL@h
 	mtspr	SPRN_IC_CST, r8
 	mtspr	SPRN_DC_CST, r8
Index: linux/arch/powerpc/kernel/prom.c
===================================================================
--- linux/arch/powerpc/kernel/prom.c	(revision 5484)
+++ linux/arch/powerpc/kernel/prom.c	(copie de travail)
@@ -649,7 +649,7 @@ 
 	}
 }
 
-void __init early_init_devtree(void *params)
+void __init early_init_devtree(void *params, u64 init_mem_size)
 {
 	phys_addr_t limit;
 
@@ -697,7 +697,7 @@ 
 	/* make sure we've parsed cmdline for mem= before this */
 	if (memory_limit)
 		first_memblock_size = min_t(u64, first_memblock_size, memory_limit);
-	setup_initial_memory_limit(memstart_addr, first_memblock_size);
+	setup_initial_memory_limit(memstart_addr, first_memblock_size, init_mem_size);
 	/* Reserve MEMBLOCK regions used by kernel, initrd, dt, etc... */
 	memblock_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
 	/* If relocatable, reserve first 32k for interrupt vectors etc. */
Index: linux/arch/powerpc/kernel/setup_32.c
===================================================================
--- linux/arch/powerpc/kernel/setup_32.c	(revision 5484)
+++ linux/arch/powerpc/kernel/setup_32.c	(copie de travail)
@@ -119,7 +119,7 @@ 
  * This is called very early on the boot process, after a minimal
  * MMU environment has been set up but before MMU_init is called.
  */
-notrace void __init machine_init(u64 dt_ptr)
+notrace void __init machine_init(u64 dt_ptr, u64 init_mem_size)
 {
 	lockdep_init();
 
@@ -127,7 +127,7 @@ 
 	udbg_early_init();
 
 	/* Do some early initialization based on the flat device tree */
-	early_init_devtree(__va(dt_ptr));
+	early_init_devtree(__va(dt_ptr), init_mem_size);
 
 	epapr_paravirt_early_init();
 
Index: linux/arch/powerpc/kernel/setup_64.c
===================================================================
--- linux/arch/powerpc/kernel/setup_64.c	(revision 5484)
+++ linux/arch/powerpc/kernel/setup_64.c	(copie de travail)
@@ -185,7 +185,7 @@ 
  * device-tree is not accessible via normal means at this point.
  */
 
-void __init early_setup(unsigned long dt_ptr)
+void __init early_setup(unsigned long dt_ptr, u64 init_mem_size)
 {
 	static __initdata struct paca_struct boot_paca;
 
@@ -214,7 +214,7 @@ 
 	 * tree, such as retrieving the physical memory map or
 	 * calculating/retrieving the hash table size.
 	 */
-	early_init_devtree(__va(dt_ptr));
+	early_init_devtree(__va(dt_ptr), init_mem_size);
 
 	epapr_paravirt_early_init();
 
Index: linux/arch/powerpc/mm/40x_mmu.c
===================================================================
--- linux/arch/powerpc/mm/40x_mmu.c	(revision 5484)
+++ linux/arch/powerpc/mm/40x_mmu.c	(copie de travail)
@@ -147,7 +147,8 @@ 
 }
 
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
-				phys_addr_t first_memblock_size)
+				phys_addr_t first_memblock_size,
+				u64 init_mem_size)
 {
 	/* We don't currently support the first MEMBLOCK not mapping 0
 	 * physical on those processors
Index: linux/arch/powerpc/mm/44x_mmu.c
===================================================================
--- linux/arch/powerpc/mm/44x_mmu.c	(revision 5484)
+++ linux/arch/powerpc/mm/44x_mmu.c	(copie de travail)
@@ -212,7 +212,8 @@ 
 }
 
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
-				phys_addr_t first_memblock_size)
+				phys_addr_t first_memblock_size,
+				u64 init_mem_size)
 {
 	u64 size;
 
Index: linux/arch/powerpc/mm/fsl_booke_mmu.c
===================================================================
--- linux/arch/powerpc/mm/fsl_booke_mmu.c	(revision 5484)
+++ linux/arch/powerpc/mm/fsl_booke_mmu.c	(copie de travail)
@@ -234,7 +234,8 @@ 
 }
 
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
-				phys_addr_t first_memblock_size)
+				phys_addr_t first_memblock_size,
+				u64 init_mem_size)
 {
 	phys_addr_t limit = first_memblock_base + first_memblock_size;
 
Index: linux/arch/powerpc/mm/hash_utils_64.c
===================================================================
--- linux/arch/powerpc/mm/hash_utils_64.c	(revision 5484)
+++ linux/arch/powerpc/mm/hash_utils_64.c	(copie de travail)
@@ -1416,7 +1416,8 @@ 
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
-				phys_addr_t first_memblock_size)
+				phys_addr_t first_memblock_size,
+				u64 init_mem_size)
 {
 	/* We don't currently support the first MEMBLOCK not mapping 0
 	 * physical on those processors
Index: linux/arch/powerpc/mm/init_32.c
===================================================================
--- linux/arch/powerpc/mm/init_32.c	(revision 5484)
+++ linux/arch/powerpc/mm/init_32.c	(copie de travail)
@@ -206,19 +206,16 @@ 
 
 #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
-				phys_addr_t first_memblock_size)
+				phys_addr_t first_memblock_size,
+				u64 init_mem_size)
 {
 	/* We don't currently support the first MEMBLOCK not mapping 0
 	 * physical on those processors
 	 */
 	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
+	if (!init_mem_size)
+		init_mem_size = 0x00800000;
+	memblock_set_current_limit(min_t(u64, first_memblock_size, init_mem_size));
 }
 #endif /* CONFIG_8xx */
Index: linux/arch/powerpc/mm/ppc_mmu_32.c
===================================================================
--- linux/arch/powerpc/mm/ppc_mmu_32.c	(revision 5484)
+++ linux/arch/powerpc/mm/ppc_mmu_32.c	(copie de travail)
@@ -273,7 +273,8 @@ 
 }
 
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
-				phys_addr_t first_memblock_size)
+				phys_addr_t first_memblock_size,
+				u64 init_mem_size)
 {
 	/* We don't currently support the first MEMBLOCK not mapping 0
 	 * physical on those processors
Index: linux/arch/powerpc/mm/tlb_nohash.c
===================================================================
--- linux/arch/powerpc/mm/tlb_nohash.c	(revision 5484)
+++ linux/arch/powerpc/mm/tlb_nohash.c	(copie de travail)
@@ -654,7 +654,8 @@ 
 }
 
 void setup_initial_memory_limit(phys_addr_t first_memblock_base,
-				phys_addr_t first_memblock_size)
+				phys_addr_t first_memblock_size,
+				u64 init_mem_size)
 {
 	/* On non-FSL Embedded 64-bit, we adjust the RMA size to match
 	 * the bolted TLB entry. We know for now that only 1G