[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