[PATCH v2 00/15] powerpc/32s: Use BATs/LTLBs for STRICT_KERNEL_RWX

Christophe Leroy christophe.leroy at c-s.fr
Wed Jan 16 17:55:29 AEDT 2019



Le 16/01/2019 à 01:35, Jonathan Neuschäfer a écrit :
> On Tue, Jan 15, 2019 at 07:51:01AM +0100, Christophe Leroy wrote:
>> Le 15/01/2019 à 01:33, Jonathan Neuschäfer a écrit :
> [...]
>>> I've checked it patch-by-patch now (with STRICT_KERNEL_RWX):
>>>
>>> - patches 1 and 2 build and boot fine
>>> - patches 3 to 6 build, but fail to boot with this error:
>>
>> The bug is in patch 2, mmu_mapin_ram() should return base instead of
>> returning 0 when __map_without_bats is set.
> 
> Indeed, with this change, I can boot up to patch 11.
> 
>>> - patches 12 to 15 build but fail to boot with this error:
>>
>> Thats the one we need to really understand.
>>
>> Do you have modules ? If so, can you try without ?
> 
> I don't use any modules in my test setup, but I have module support
> enabled. Disabling CONFIG_MODULES makes no difference, as far as I can
> see (I get the same backtrace with memblock_alloc_base+0x34/0x44).
> 
>>> 	[    0.000000] [c0f1ff30] [c00280f0] panic+0x144/0x324 (unreliable)
>>> 	[    0.000000] [c0f1ff90] [c0c18a34] memblock_alloc_base+0x34/0x44
>>> 	[    0.000000] [c0f1ffa0] [c0c071e0] MMU_init_hw+0xcc/0x300
>>> 	[    0.000000] [c0f1ffd0] [c0c06554] MMU_init+0x12c/0x198
>>> 	[    0.000000] [c0f1fff0] [c0003418] start_here+0x40/0x78
> 
> With a few printks[1], I traced this error, and got the following
> result:
> 
> [    0.000000] __memblock_find_range_top_down(1000:1800000, 100000:100000, ffffffff, 0)
> [    0.000000] __memblock_find_range_top_down: in loop, 10000000:13f00000
> [    0.000000] __memblock_find_range_top_down: in loop, 179962d:1800000
> [    0.000000] __memblock_find_range_top_down: in loop, 1676000:17987a0
> [    0.000000] __memblock_find_range_top_down: nothing found :(
> 
> The limit of 0x1800000 comes from setup_initial_memory_limit, which only
> considers the first memblock, but the second memblock starts at 256MiB,
> so it wouldn't be usable anyway, according to the comment in
> setup_initial_memory_limit.

Yes, initial_bats() in head_32.S sets one 256Mb BAT for initial booting:

/*
  * On 601, we use 3 BATs to map up to 24M of RAM at _PAGE_OFFSET
  * (we keep one for debugging) and on others, we use one 256M BAT.
  */
initial_bats:
	lis	r11,PAGE_OFFSET at h
	mfspr	r9,SPRN_PVR
	rlwinm	r9,r9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
	cmpwi	0,r9,1
	bne	4f
...
4:	tophys(r8,r11)
#ifdef CONFIG_SMP
	ori	r8,r8,0x12		/* R/W access, M=1 */
#else
	ori	r8,r8,2			/* R/W access */
#endif /* CONFIG_SMP */
	ori	r11,r11,BL_256M<<2|0x2	/* set up BAT registers for 604 */

	mtspr	SPRN_DBAT0L,r8		/* N.B. 6xx (not 601) have valid */
	mtspr	SPRN_DBAT0U,r11		/* bit in upper BAT register */
	mtspr	SPRN_IBAT0L,r8
	mtspr	SPRN_IBAT0U,r11
	isync
	blr


> 
> Thinning the kernel down a bit actually makes it boot again. Ooops...!
> Maybe enabling CONFIG_STRICT_KERNEL_RWX has made it just large enough to
> fail the hash table allocation, but there may have been other factors
> involved (I'm not sure exactly).  Sorry for the confusion!

Ok, that must be the reason. Thanks for testing.

What about the following modification which maps a second 256Mb BAT, 
does it helps ?



diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index c2f564690778..ea574596de37 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -1160,6 +1160,14 @@ initial_bats:
  	mtspr	SPRN_DBAT0U,r11		/* bit in upper BAT register */
  	mtspr	SPRN_IBAT0L,r8
  	mtspr	SPRN_IBAT0U,r11
+#ifdef CONFIG_WII
+	addis	r11,r11,0x10000000 at h
+	addis	r8,r8,0x10000000 at h
+	mtspr	SPRN_DBAT2L,r8
+	mtspr	SPRN_DBAT2U,r11
+	mtspr	SPRN_IBAT2L,r8
+	mtspr	SPRN_IBAT2U,r11
+#endif
  	isync
  	blr

diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index 3f4193201ee7..a334fd5210a8 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -259,6 +259,8 @@ void setup_initial_memory_limit(phys_addr_t 
first_memblock_base,
  	/* 601 can only access 16MB at the moment */
  	if (PVR_VER(mfspr(SPRN_PVR)) == 1)
  		memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01000000));
+	else if (IS_ENABLED(CONFIG_WII))
+		memblock_set_current_limit(min_t(u64, first_memblock_size, 0x20000000));
  	else /* Anything else has 256M mapped */
  		memblock_set_current_limit(min_t(u64, first_memblock_size, 0x10000000));
  }


Christophe

> 
> 
> Jonathan
> 
> [1]:
> diff --git a/mm/memblock.c b/mm/memblock.c
> index 022d4cbb3618..66d588e08487 100644
> --- a/mm/memblock.c
> +++ b/mm/memblock.c
> @@ -215,8 +215,11 @@ __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
>   	phys_addr_t this_start, this_end, cand;
>   	u64 i;
>   
> +	printk("%s(%x:%x, %x:%x, %x, %x)\n", __func__, start, end, size, align, nid, flags);
> +
>   	for_each_free_mem_range_reverse(i, nid, flags, &this_start, &this_end,
>   					NULL) {
> +		printk("%s: in loop, %x:%x\n", __func__, this_start, this_end);
>   		this_start = clamp(this_start, start, end);
>   		this_end = clamp(this_end, start, end);
>   
> @@ -228,6 +231,7 @@ __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
>   			return cand;
>   	}
>   
> +	printk("%s: nothing found :(\n", __func__);
>   	return 0;
>   }
>   
> 


More information about the Linuxppc-dev mailing list