MIPS: Make sparse_init() using top-down allocation
authorTiezhu Yang <yangtiezhu@loongson.cn>
Tue, 21 Apr 2020 11:59:46 +0000 (19:59 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 22 Jun 2020 07:30:59 +0000 (09:30 +0200)
[ Upstream commit 269b3a9ac538c4ae87f84be640b9fa89914a2489 ]

In the current code, if CONFIG_SWIOTLB is set, when failed to get IO TLB
memory from the low pages by plat_swiotlb_setup(), it may lead to the boot
process failed with kernel panic.

(1) On the Loongson and SiByte platform
arch/mips/loongson64/dma.c
arch/mips/sibyte/common/dma.c
void __init plat_swiotlb_setup(void)
{
swiotlb_init(1);
}

kernel/dma/swiotlb.c
void  __init
swiotlb_init(int verbose)
{
...
vstart = memblock_alloc_low(PAGE_ALIGN(bytes), PAGE_SIZE);
if (vstart && !swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose))
return;
...
pr_warn("Cannot allocate buffer");
no_iotlb_memory = true;
}

phys_addr_t swiotlb_tbl_map_single()
{
...
if (no_iotlb_memory)
panic("Can not allocate SWIOTLB buffer earlier ...");
...
}

(2) On the Cavium OCTEON platform
arch/mips/cavium-octeon/dma-octeon.c
void __init plat_swiotlb_setup(void)
{
...
octeon_swiotlb = memblock_alloc_low(swiotlbsize, PAGE_SIZE);
if (!octeon_swiotlb)
panic("%s: Failed to allocate %zu bytes align=%lx\n",
      __func__, swiotlbsize, PAGE_SIZE);
...
}

Because IO_TLB_DEFAULT_SIZE is 64M, if the rest size of low memory is less
than 64M when call plat_swiotlb_setup(), we can easily reproduce the panic
case.

In order to reduce the possibility of kernel panic when failed to get IO
TLB memory under CONFIG_SWIOTLB, it is better to allocate low memory as
small as possible before plat_swiotlb_setup(), so make sparse_init() using
top-down allocation.

Reported-by: Juxin Gao <gaojuxin@loongson.cn>
Co-developed-by: Juxin Gao <gaojuxin@loongson.cn>
Signed-off-by: Juxin Gao <gaojuxin@loongson.cn>
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/mips/kernel/setup.c

index 5eec13b..7b06e6e 100644 (file)
@@ -653,7 +653,17 @@ static void __init arch_mem_init(char **cmdline_p)
                                 crashk_res.end - crashk_res.start + 1);
 #endif
        device_tree_init();
+
+       /*
+        * In order to reduce the possibility of kernel panic when failed to
+        * get IO TLB memory under CONFIG_SWIOTLB, it is better to allocate
+        * low memory as small as possible before plat_swiotlb_setup(), so
+        * make sparse_init() using top-down allocation.
+        */
+       memblock_set_bottom_up(false);
        sparse_init();
+       memblock_set_bottom_up(true);
+
        plat_swiotlb_setup();
 
        dma_contiguous_reserve(PFN_PHYS(max_low_pfn));