powerpc/book3s64/radix: Fix boot failure with large amount of guest memory
authorAneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Fri, 28 Aug 2020 10:08:52 +0000 (15:38 +0530)
committerMichael Ellerman <mpe@ellerman.id.au>
Fri, 28 Aug 2020 10:14:45 +0000 (20:14 +1000)
If the hypervisor doesn't support hugepages, the kernel ends up allocating a large
number of page table pages. The early page table allocation was wrongly
setting the max memblock limit to ppc64_rma_size with radix translation
which resulted in boot failure as shown below.

Kernel panic - not syncing:
early_alloc_pgtable: Failed to allocate 16777216 bytes align=0x1000000 nid=-1 from=0x0000000000000000 max_addr=0xffffffffffffffff
 CPU: 0 PID: 0 Comm: swapper Not tainted 5.8.0-24.9-default+ #2
 Call Trace:
 [c0000000016f3d00] [c0000000007c6470] dump_stack+0xc4/0x114 (unreliable)
 [c0000000016f3d40] [c00000000014c78c] panic+0x164/0x418
 [c0000000016f3dd0] [c000000000098890] early_alloc_pgtable+0xe0/0xec
 [c0000000016f3e60] [c0000000010a5440] radix__early_init_mmu+0x360/0x4b4
 [c0000000016f3ef0] [c000000001099bac] early_init_mmu+0x1c/0x3c
 [c0000000016f3f10] [c00000000109a320] early_setup+0x134/0x170

This was because the kernel was checking for the radix feature before we enable the
feature via mmu_features. This resulted in the kernel using hash restrictions on
radix.

Rework the early init code such that the kernel boot with memblock restrictions
as imposed by hash. At that point, the kernel still hasn't finalized the
translation the kernel will end up using.

We have three different ways of detecting radix.

1. dt_cpu_ftrs_scan -> used only in case of PowerNV
2. ibm,pa-features -> Used when we don't use cpu_dt_ftr_scan
3. CAS -> Where we negotiate with hypervisor about the supported translation.

We look at 1 or 2 early in the boot and after that, we look at the CAS vector to
finalize the translation the kernel will use. We also support a kernel command
line option (disable_radix) to switch to hash.

Update the memblock limit after mmu_early_init_devtree() if the kernel is going
to use radix translation. This forces some of the memblock allocations we do before
mmu_early_init_devtree() to be within the RMA limit.

Fixes: 2bfd65e45e87 ("powerpc/mm/radix: Add radix callbacks for early init routines")
Reported-by: Shirisha Ganta <shiganta@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Reviewed-by: Hari Bathini <hbathini@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20200828100852.426575-1-aneesh.kumar@linux.ibm.com
arch/powerpc/include/asm/book3s/64/mmu.h
arch/powerpc/mm/book3s64/radix_pgtable.c
arch/powerpc/mm/init_64.c

index 55442d45c59791e05f828597106265d817a0b636..b392384a3b15089c04eef26f61a73cd7cfef33bf 100644 (file)
@@ -239,14 +239,14 @@ static inline void early_init_mmu_secondary(void)
 
 extern void hash__setup_initial_memory_limit(phys_addr_t first_memblock_base,
                                         phys_addr_t first_memblock_size);
-extern void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
-                                        phys_addr_t first_memblock_size);
 static inline void setup_initial_memory_limit(phys_addr_t first_memblock_base,
                                              phys_addr_t first_memblock_size)
 {
-       if (early_radix_enabled())
-               return radix__setup_initial_memory_limit(first_memblock_base,
-                                                  first_memblock_size);
+       /*
+        * Hash has more strict restrictions. At this point we don't
+        * know which translations we will pick. Hence go with hash
+        * restrictions.
+        */
        return hash__setup_initial_memory_limit(first_memblock_base,
                                           first_memblock_size);
 }
index 28c784976beda540c875c99d2ca041bf2aba548e..d5f0c10d752a37086146ab68c6ce6769d587ed81 100644 (file)
@@ -734,21 +734,6 @@ void radix__mmu_cleanup_all(void)
        }
 }
 
-void radix__setup_initial_memory_limit(phys_addr_t first_memblock_base,
-                               phys_addr_t first_memblock_size)
-{
-       /*
-        * We don't currently support the first MEMBLOCK not mapping 0
-        * physical on those processors
-        */
-       BUG_ON(first_memblock_base != 0);
-
-       /*
-        * Radix mode is not limited by RMA / VRMA addressing.
-        */
-       ppc64_rma_size = ULONG_MAX;
-}
-
 #ifdef CONFIG_MEMORY_HOTPLUG
 static void free_pte_table(pte_t *pte_start, pmd_t *pmd)
 {
index 02e127fa5777c0050e29a2a71f420e33a35670e7..8459056cce671efd7c49171a7b35d1c019c6d29c 100644 (file)
@@ -433,9 +433,16 @@ void __init mmu_early_init_devtree(void)
        if (!(mfmsr() & MSR_HV))
                early_check_vec5();
 
-       if (early_radix_enabled())
+       if (early_radix_enabled()) {
                radix__early_init_devtree();
-       else
+               /*
+                * We have finalized the translation we are going to use by now.
+                * Radix mode is not limited by RMA / VRMA addressing.
+                * Hence don't limit memblock allocations.
+                */
+               ppc64_rma_size = ULONG_MAX;
+               memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
+       } else
                hash__early_init_devtree();
 }
 #endif /* CONFIG_PPC_BOOK3S_64 */