| From 1b09878ba96f8bd861ad6024e1e7e0c9830c5da2 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 21 Apr 2020 19:59:46 +0800 |
| Subject: MIPS: Make sparse_init() using top-down allocation |
| |
| From: Tiezhu Yang <yangtiezhu@loongson.cn> |
| |
| [ 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 | 10 ++++++++++ |
| 1 file changed, 10 insertions(+) |
| |
| diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c |
| index 8fa30516f39d..33f5aeaf0024 100644 |
| --- a/arch/mips/kernel/setup.c |
| +++ b/arch/mips/kernel/setup.c |
| @@ -769,7 +769,17 @@ static void __init arch_mem_init(char **cmdline_p) |
| BOOTMEM_DEFAULT); |
| #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(); |
| paging_init(); |
| |
| -- |
| 2.25.1 |
| |