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@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@h
+       addis   r8,r8,0x10000000@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;
  }

Reply via email to