xref: /openbmc/linux/arch/riscv/mm/init.c (revision d32fd6bb9f2bc8178cdd65ebec1ad670a8bfa241)
150acfb2bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
276d2a049SPalmer Dabbelt /*
376d2a049SPalmer Dabbelt  * Copyright (C) 2012 Regents of the University of California
4671f9a3eSAnup Patel  * Copyright (C) 2019 Western Digital Corporation or its affiliates.
5e53d2818SNick Kossifidis  * Copyright (C) 2020 FORTH-ICS/CARV
6e53d2818SNick Kossifidis  *  Nick Kossifidis <mick@ics.forth.gr>
776d2a049SPalmer Dabbelt  */
876d2a049SPalmer Dabbelt 
976d2a049SPalmer Dabbelt #include <linux/init.h>
1076d2a049SPalmer Dabbelt #include <linux/mm.h>
1176d2a049SPalmer Dabbelt #include <linux/memblock.h>
1257c8a661SMike Rapoport #include <linux/initrd.h>
1376d2a049SPalmer Dabbelt #include <linux/swap.h>
14ce3aca04SKefeng Wang #include <linux/swiotlb.h>
155ec9c4ffSChristoph Hellwig #include <linux/sizes.h>
160651c263SAnup Patel #include <linux/of_fdt.h>
1756409750SNick Kossifidis #include <linux/of_reserved_mem.h>
18922b0375SAlbert Ou #include <linux/libfdt.h>
19d27c3c90SZong Li #include <linux/set_memory.h>
20da815582SKefeng Wang #include <linux/dma-map-ops.h>
21e53d2818SNick Kossifidis #include <linux/crash_dump.h>
228ba1a8b7SKefeng Wang #include <linux/hugetlb.h>
2339b33072SAlexandre Ghiti #ifdef CONFIG_RELOCATABLE
2439b33072SAlexandre Ghiti #include <linux/elf.h>
2539b33072SAlexandre Ghiti #endif
2625abe0dbSAlexandre Ghiti #include <linux/kfence.h>
2776d2a049SPalmer Dabbelt 
28f2c17aabSAnup Patel #include <asm/fixmap.h>
29d2402048SNick Desaulniers #include <asm/io.h>
30d2402048SNick Desaulniers #include <asm/numa.h>
31d2402048SNick Desaulniers #include <asm/pgtable.h>
32d2402048SNick Desaulniers #include <asm/ptdump.h>
3376d2a049SPalmer Dabbelt #include <asm/sections.h>
342d268251SPalmer Dabbelt #include <asm/soc.h>
35*a4a7ac3dSXu Lu #include <asm/sparsemem.h>
36d2402048SNick Desaulniers #include <asm/tlbflush.h>
3776d2a049SPalmer Dabbelt 
38ffaee272SPaul Walmsley #include "../kernel/head.h"
39ffaee272SPaul Walmsley 
40658e2c51SAlexandre Ghiti struct kernel_mapping kernel_map __ro_after_init;
41658e2c51SAlexandre Ghiti EXPORT_SYMBOL(kernel_map);
4244c92257SVitaly Wool #ifdef CONFIG_XIP_KERNEL
43658e2c51SAlexandre Ghiti #define kernel_map	(*(struct kernel_mapping *)XIP_FIXUP(&kernel_map))
44658e2c51SAlexandre Ghiti #endif
45658e2c51SAlexandre Ghiti 
46e8a62cc2SAlexandre Ghiti #ifdef CONFIG_64BIT
479195c294SPalmer Dabbelt u64 satp_mode __ro_after_init = !IS_ENABLED(CONFIG_XIP_KERNEL) ? SATP_MODE_57 : SATP_MODE_39;
48e8a62cc2SAlexandre Ghiti #else
4967ff2f26SJisheng Zhang u64 satp_mode __ro_after_init = SATP_MODE_32;
50e8a62cc2SAlexandre Ghiti #endif
51e8a62cc2SAlexandre Ghiti EXPORT_SYMBOL(satp_mode);
52e8a62cc2SAlexandre Ghiti 
5320aa4954Skernel test robot bool pgtable_l4_enabled = IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_XIP_KERNEL);
54011f09d1SQinglin Pan bool pgtable_l5_enabled = IS_ENABLED(CONFIG_64BIT) && !IS_ENABLED(CONFIG_XIP_KERNEL);
55e8a62cc2SAlexandre Ghiti EXPORT_SYMBOL(pgtable_l4_enabled);
56d10efa21SQinglin Pan EXPORT_SYMBOL(pgtable_l5_enabled);
57e8a62cc2SAlexandre Ghiti 
586d7f91d9SAlexandre Ghiti phys_addr_t phys_ram_base __ro_after_init;
596d7f91d9SAlexandre Ghiti EXPORT_SYMBOL(phys_ram_base);
606d7f91d9SAlexandre Ghiti 
61*a4a7ac3dSXu Lu #ifdef CONFIG_SPARSEMEM_VMEMMAP
62*a4a7ac3dSXu Lu #define VMEMMAP_ADDR_ALIGN	(1ULL << SECTION_SIZE_BITS)
63*a4a7ac3dSXu Lu 
64*a4a7ac3dSXu Lu unsigned long vmemmap_start_pfn __ro_after_init;
65*a4a7ac3dSXu Lu EXPORT_SYMBOL(vmemmap_start_pfn);
66*a4a7ac3dSXu Lu #endif
67*a4a7ac3dSXu Lu 
68387181dcSAnup Patel unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]
69387181dcSAnup Patel 							__page_aligned_bss;
70387181dcSAnup Patel EXPORT_SYMBOL(empty_zero_page);
71387181dcSAnup Patel 
72d90d45d7SAnup Patel extern char _start[];
7344c92257SVitaly Wool void *_dtb_early_va __initdata;
7444c92257SVitaly Wool uintptr_t _dtb_early_pa __initdata;
75d90d45d7SAnup Patel 
7601062356SJisheng Zhang static phys_addr_t dma32_phys_limit __initdata;
77da815582SKefeng Wang 
zone_sizes_init(void)7876d2a049SPalmer Dabbelt static void __init zone_sizes_init(void)
7976d2a049SPalmer Dabbelt {
805ec9c4ffSChristoph Hellwig 	unsigned long max_zone_pfns[MAX_NR_ZONES] = { 0, };
8176d2a049SPalmer Dabbelt 
82d5fad48cSZong Li #ifdef CONFIG_ZONE_DMA32
83da815582SKefeng Wang 	max_zone_pfns[ZONE_DMA32] = PFN_DOWN(dma32_phys_limit);
84d5fad48cSZong Li #endif
855ec9c4ffSChristoph Hellwig 	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
865ec9c4ffSChristoph Hellwig 
879691a071SMike Rapoport 	free_area_init(max_zone_pfns);
8876d2a049SPalmer Dabbelt }
8976d2a049SPalmer Dabbelt 
908fa3cdffSKefeng Wang #if defined(CONFIG_MMU) && defined(CONFIG_DEBUG_VM)
9126b8f69eSAlexandre Ghiti 
9226b8f69eSAlexandre Ghiti #define LOG2_SZ_1K  ilog2(SZ_1K)
9326b8f69eSAlexandre Ghiti #define LOG2_SZ_1M  ilog2(SZ_1M)
9426b8f69eSAlexandre Ghiti #define LOG2_SZ_1G  ilog2(SZ_1G)
9526b8f69eSAlexandre Ghiti #define LOG2_SZ_1T  ilog2(SZ_1T)
9626b8f69eSAlexandre Ghiti 
print_mlk(char * name,unsigned long b,unsigned long t)972cc6c4a0SYash Shah static inline void print_mlk(char *name, unsigned long b, unsigned long t)
982cc6c4a0SYash Shah {
992cc6c4a0SYash Shah 	pr_notice("%12s : 0x%08lx - 0x%08lx   (%4ld kB)\n", name, b, t,
10026b8f69eSAlexandre Ghiti 		  (((t) - (b)) >> LOG2_SZ_1K));
1012cc6c4a0SYash Shah }
1022cc6c4a0SYash Shah 
print_mlm(char * name,unsigned long b,unsigned long t)1032cc6c4a0SYash Shah static inline void print_mlm(char *name, unsigned long b, unsigned long t)
1042cc6c4a0SYash Shah {
1052cc6c4a0SYash Shah 	pr_notice("%12s : 0x%08lx - 0x%08lx   (%4ld MB)\n", name, b, t,
10626b8f69eSAlexandre Ghiti 		  (((t) - (b)) >> LOG2_SZ_1M));
10726b8f69eSAlexandre Ghiti }
10826b8f69eSAlexandre Ghiti 
print_mlg(char * name,unsigned long b,unsigned long t)10926b8f69eSAlexandre Ghiti static inline void print_mlg(char *name, unsigned long b, unsigned long t)
11026b8f69eSAlexandre Ghiti {
11126b8f69eSAlexandre Ghiti 	pr_notice("%12s : 0x%08lx - 0x%08lx   (%4ld GB)\n", name, b, t,
11226b8f69eSAlexandre Ghiti 		   (((t) - (b)) >> LOG2_SZ_1G));
11326b8f69eSAlexandre Ghiti }
11426b8f69eSAlexandre Ghiti 
11526b8f69eSAlexandre Ghiti #ifdef CONFIG_64BIT
print_mlt(char * name,unsigned long b,unsigned long t)11626b8f69eSAlexandre Ghiti static inline void print_mlt(char *name, unsigned long b, unsigned long t)
11726b8f69eSAlexandre Ghiti {
11826b8f69eSAlexandre Ghiti 	pr_notice("%12s : 0x%08lx - 0x%08lx   (%4ld TB)\n", name, b, t,
11926b8f69eSAlexandre Ghiti 		   (((t) - (b)) >> LOG2_SZ_1T));
12026b8f69eSAlexandre Ghiti }
12126b8f69eSAlexandre Ghiti #else
12226b8f69eSAlexandre Ghiti #define print_mlt(n, b, t) do {} while (0)
12326b8f69eSAlexandre Ghiti #endif
12426b8f69eSAlexandre Ghiti 
print_ml(char * name,unsigned long b,unsigned long t)12526b8f69eSAlexandre Ghiti static inline void print_ml(char *name, unsigned long b, unsigned long t)
12626b8f69eSAlexandre Ghiti {
12726b8f69eSAlexandre Ghiti 	unsigned long diff = t - b;
12826b8f69eSAlexandre Ghiti 
12926b8f69eSAlexandre Ghiti 	if (IS_ENABLED(CONFIG_64BIT) && (diff >> LOG2_SZ_1T) >= 10)
13026b8f69eSAlexandre Ghiti 		print_mlt(name, b, t);
13126b8f69eSAlexandre Ghiti 	else if ((diff >> LOG2_SZ_1G) >= 10)
13226b8f69eSAlexandre Ghiti 		print_mlg(name, b, t);
13326b8f69eSAlexandre Ghiti 	else if ((diff >> LOG2_SZ_1M) >= 10)
13426b8f69eSAlexandre Ghiti 		print_mlm(name, b, t);
13526b8f69eSAlexandre Ghiti 	else
13626b8f69eSAlexandre Ghiti 		print_mlk(name, b, t);
1372cc6c4a0SYash Shah }
1382cc6c4a0SYash Shah 
print_vm_layout(void)1391987501bSJisheng Zhang static void __init print_vm_layout(void)
1402cc6c4a0SYash Shah {
1412cc6c4a0SYash Shah 	pr_notice("Virtual kernel memory layout:\n");
14226b8f69eSAlexandre Ghiti 	print_ml("fixmap", (unsigned long)FIXADDR_START,
1432cc6c4a0SYash Shah 		(unsigned long)FIXADDR_TOP);
14426b8f69eSAlexandre Ghiti 	print_ml("pci io", (unsigned long)PCI_IO_START,
1452cc6c4a0SYash Shah 		(unsigned long)PCI_IO_END);
14626b8f69eSAlexandre Ghiti 	print_ml("vmemmap", (unsigned long)VMEMMAP_START,
1472cc6c4a0SYash Shah 		(unsigned long)VMEMMAP_END);
14826b8f69eSAlexandre Ghiti 	print_ml("vmalloc", (unsigned long)VMALLOC_START,
1492cc6c4a0SYash Shah 		(unsigned long)VMALLOC_END);
150f9293ad4SXianting Tian #ifdef CONFIG_64BIT
151f9293ad4SXianting Tian 	print_ml("modules", (unsigned long)MODULES_VADDR,
152f9293ad4SXianting Tian 		(unsigned long)MODULES_END);
153f9293ad4SXianting Tian #endif
15426b8f69eSAlexandre Ghiti 	print_ml("lowmem", (unsigned long)PAGE_OFFSET,
1552cc6c4a0SYash Shah 		(unsigned long)high_memory);
1560c34e79eSPalmer Dabbelt 	if (IS_ENABLED(CONFIG_64BIT)) {
157f7ae0233SAlexandre Ghiti #ifdef CONFIG_KASAN
15826b8f69eSAlexandre Ghiti 		print_ml("kasan", KASAN_SHADOW_START, KASAN_SHADOW_END);
159f7ae0233SAlexandre Ghiti #endif
1600c34e79eSPalmer Dabbelt 
16139b33072SAlexandre Ghiti 		print_ml("kernel", (unsigned long)kernel_map.virt_addr,
1622bfc6cd8SAlexandre Ghiti 			 (unsigned long)ADDRESS_SPACE_END);
1632cc6c4a0SYash Shah 	}
1642cc6c4a0SYash Shah }
1652cc6c4a0SYash Shah #else
print_vm_layout(void)1662cc6c4a0SYash Shah static void print_vm_layout(void) { }
1672cc6c4a0SYash Shah #endif /* CONFIG_DEBUG_VM */
1682cc6c4a0SYash Shah 
mem_init(void)16976d2a049SPalmer Dabbelt void __init mem_init(void)
17076d2a049SPalmer Dabbelt {
17176d2a049SPalmer Dabbelt #ifdef CONFIG_FLATMEM
17276d2a049SPalmer Dabbelt 	BUG_ON(!mem_map);
17376d2a049SPalmer Dabbelt #endif /* CONFIG_FLATMEM */
17476d2a049SPalmer Dabbelt 
175c6af2aa9SChristoph Hellwig 	swiotlb_init(max_pfn > PFN_DOWN(dma32_phys_limit), SWIOTLB_VERBOSE);
176c6ffc5caSMike Rapoport 	memblock_free_all();
17776d2a049SPalmer Dabbelt 
1782cc6c4a0SYash Shah 	print_vm_layout();
17976d2a049SPalmer Dabbelt }
18076d2a049SPalmer Dabbelt 
181f7ae0233SAlexandre Ghiti /* Limit the memory size via mem. */
182f7ae0233SAlexandre Ghiti static phys_addr_t memory_limit;
183e792a03dSFrederik Haxel #ifdef CONFIG_XIP_KERNEL
184e792a03dSFrederik Haxel #define memory_limit	(*(phys_addr_t *)XIP_FIXUP(&memory_limit))
185e792a03dSFrederik Haxel #endif /* CONFIG_XIP_KERNEL */
186c9811e37SKefeng Wang 
early_mem(char * p)187c9811e37SKefeng Wang static int __init early_mem(char *p)
188c9811e37SKefeng Wang {
189c9811e37SKefeng Wang 	u64 size;
190c9811e37SKefeng Wang 
191c9811e37SKefeng Wang 	if (!p)
192c9811e37SKefeng Wang 		return 1;
193c9811e37SKefeng Wang 
194c9811e37SKefeng Wang 	size = memparse(p, &p) & PAGE_MASK;
195c9811e37SKefeng Wang 	memory_limit = min_t(u64, size, memory_limit);
196c9811e37SKefeng Wang 
197c9811e37SKefeng Wang 	pr_notice("Memory limited to %lldMB\n", (u64)memory_limit >> 20);
198c9811e37SKefeng Wang 
199c9811e37SKefeng Wang 	return 0;
200c9811e37SKefeng Wang }
201c9811e37SKefeng Wang early_param("mem", early_mem);
202c9811e37SKefeng Wang 
setup_bootmem(void)203f842f5ffSKefeng Wang static void __init setup_bootmem(void)
2040651c263SAnup Patel {
205ac51e005SZong Li 	phys_addr_t vmlinux_end = __pa_symbol(&_end);
20607aabe8fSJisheng Zhang 	phys_addr_t max_mapped_addr;
207fe036db7SJisheng Zhang 	phys_addr_t phys_ram_end, vmlinux_start;
2080651c263SAnup Patel 
209fe036db7SJisheng Zhang 	if (IS_ENABLED(CONFIG_XIP_KERNEL))
21044c92257SVitaly Wool 		vmlinux_start = __pa_symbol(&_sdata);
211fe036db7SJisheng Zhang 	else
212fe036db7SJisheng Zhang 		vmlinux_start = __pa_symbol(&_start);
21344c92257SVitaly Wool 
214c9811e37SKefeng Wang 	memblock_enforce_memory_limit(memory_limit);
2150651c263SAnup Patel 
2162bfc6cd8SAlexandre Ghiti 	/*
2178db6f937SGeert Uytterhoeven 	 * Make sure we align the reservation on PMD_SIZE since we will
2182bfc6cd8SAlexandre Ghiti 	 * map the kernel in the linear mapping as read-only: we do not want
2192bfc6cd8SAlexandre Ghiti 	 * any allocation to happen between _end and the next pmd aligned page.
2202bfc6cd8SAlexandre Ghiti 	 */
22107aabe8fSJisheng Zhang 	if (IS_ENABLED(CONFIG_64BIT) && IS_ENABLED(CONFIG_STRICT_KERNEL_RWX))
2228db6f937SGeert Uytterhoeven 		vmlinux_end = (vmlinux_end + PMD_SIZE - 1) & PMD_MASK;
22307aabe8fSJisheng Zhang 	/*
22407aabe8fSJisheng Zhang 	 * Reserve from the start of the kernel to the end of the kernel
22507aabe8fSJisheng Zhang 	 */
2268db6f937SGeert Uytterhoeven 	memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
227d90d45d7SAnup Patel 
228c3bcc65dSAlexandre Ghiti 	/*
229c3bcc65dSAlexandre Ghiti 	 * Make sure we align the start of the memory on a PMD boundary so that
230c3bcc65dSAlexandre Ghiti 	 * at worst, we map the linear mapping with PMD mappings.
231c3bcc65dSAlexandre Ghiti 	 */
232*a4a7ac3dSXu Lu 	if (!IS_ENABLED(CONFIG_XIP_KERNEL)) {
233c3bcc65dSAlexandre Ghiti 		phys_ram_base = memblock_start_of_DRAM() & PMD_MASK;
234*a4a7ac3dSXu Lu #ifdef CONFIG_SPARSEMEM_VMEMMAP
235*a4a7ac3dSXu Lu 		vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT;
236*a4a7ac3dSXu Lu #endif
237*a4a7ac3dSXu Lu 	}
2383335068fSAlexandre Ghiti 
2393335068fSAlexandre Ghiti 	/*
2403335068fSAlexandre Ghiti 	 * In 64-bit, any use of __va/__pa before this point is wrong as we
2413335068fSAlexandre Ghiti 	 * did not know the start of DRAM before.
2423335068fSAlexandre Ghiti 	 */
243b008e327SSamuel Holland 	if (IS_ENABLED(CONFIG_64BIT) && IS_ENABLED(CONFIG_MMU))
2443335068fSAlexandre Ghiti 		kernel_map.va_pa_offset = PAGE_OFFSET - phys_ram_base;
2453335068fSAlexandre Ghiti 
246abb8e86bSAtish Patra 	/*
24740208cdbSStuart Menefy 	 * The size of the linear page mapping may restrict the amount of
24840208cdbSStuart Menefy 	 * usable RAM.
24940208cdbSStuart Menefy 	 */
250bd29d845SAlexandre Ghiti 	if (IS_ENABLED(CONFIG_64BIT) && IS_ENABLED(CONFIG_MMU)) {
25140208cdbSStuart Menefy 		max_mapped_addr = __pa(PAGE_OFFSET) + KERN_VIRT_SIZE;
25240208cdbSStuart Menefy 		memblock_cap_memory_range(phys_ram_base,
25340208cdbSStuart Menefy 					  max_mapped_addr - phys_ram_base);
25440208cdbSStuart Menefy 	}
25540208cdbSStuart Menefy 
25640208cdbSStuart Menefy 	/*
257d63e501aSNam Cao 	 * Reserve physical address space that would be mapped to virtual
258d63e501aSNam Cao 	 * addresses greater than (void *)(-PAGE_SIZE) because:
259d63e501aSNam Cao 	 *  - This memory would overlap with ERR_PTR
260d63e501aSNam Cao 	 *  - This memory belongs to high memory, which is not supported
261d63e501aSNam Cao 	 *
262d63e501aSNam Cao 	 * This is not applicable to 64-bit kernel, because virtual addresses
263d63e501aSNam Cao 	 * after (void *)(-PAGE_SIZE) are not linearly mapped: they are
264d63e501aSNam Cao 	 * occupied by kernel mapping. Also it is unrealistic for high memory
265d63e501aSNam Cao 	 * to exist on 64-bit platforms.
266abb8e86bSAtish Patra 	 */
26707aabe8fSJisheng Zhang 	if (!IS_ENABLED(CONFIG_64BIT)) {
268d63e501aSNam Cao 		max_mapped_addr = __va_to_pa_nodebug(-PAGE_SIZE);
269d63e501aSNam Cao 		memblock_reserve(max_mapped_addr, (phys_addr_t)-max_mapped_addr);
27007aabe8fSJisheng Zhang 	}
271abb8e86bSAtish Patra 
27240208cdbSStuart Menefy 	phys_ram_end = memblock_end_of_DRAM();
2736d7f91d9SAlexandre Ghiti 	min_low_pfn = PFN_UP(phys_ram_base);
2746d7f91d9SAlexandre Ghiti 	max_low_pfn = max_pfn = PFN_DOWN(phys_ram_end);
275625e24a5SAlexandre Ghiti 	high_memory = (void *)(__va(PFN_PHYS(max_low_pfn)));
276f6e5aedfSKefeng Wang 
277da815582SKefeng Wang 	dma32_phys_limit = min(4UL * SZ_1G, (unsigned long)PFN_PHYS(max_low_pfn));
278336e8eb2SGuo Ren 	set_max_mapnr(max_low_pfn - ARCH_PFN_OFFSET);
2790651c263SAnup Patel 
280aec33b54SKefeng Wang 	reserve_initrd_mem();
281ef69d255SAlexandre Ghiti 
282ef69d255SAlexandre Ghiti 	/*
283ef69d255SAlexandre Ghiti 	 * No allocation should be done before reserving the memory as defined
284ef69d255SAlexandre Ghiti 	 * in the device tree, otherwise the allocation could end up in a
285ef69d255SAlexandre Ghiti 	 * reserved region.
286ef69d255SAlexandre Ghiti 	 */
287ef69d255SAlexandre Ghiti 	early_init_fdt_scan_reserved_mem();
288ef69d255SAlexandre Ghiti 
289922b0375SAlbert Ou 	/*
290f105aa94SVitaly Wool 	 * If DTB is built in, no need to reserve its memblock.
291f105aa94SVitaly Wool 	 * Otherwise, do reserve it but avoid using
292f105aa94SVitaly Wool 	 * early_init_fdt_reserve_self() since __pa() does
293922b0375SAlbert Ou 	 * not work for DTB pointers that are fixmap addresses
294922b0375SAlbert Ou 	 */
2951b50f956SAlexandre Ghiti 	if (!IS_ENABLED(CONFIG_BUILTIN_DTB))
296922b0375SAlbert Ou 		memblock_reserve(dtb_early_pa, fdt_totalsize(dtb_early_va));
297922b0375SAlbert Ou 
298da815582SKefeng Wang 	dma_contiguous_reserve(dma32_phys_limit);
2998ba1a8b7SKefeng Wang 	if (IS_ENABLED(CONFIG_64BIT))
3008ba1a8b7SKefeng Wang 		hugetlb_cma_reserve(PUD_SHIFT - PAGE_SHIFT);
3010651c263SAnup Patel }
3026f1e9e94SAnup Patel 
3036bd33e1eSChristoph Hellwig #ifdef CONFIG_MMU
3040c34e79eSPalmer Dabbelt struct pt_alloc_ops pt_ops __initdata;
30544c92257SVitaly Wool 
3066f1e9e94SAnup Patel pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
307671f9a3eSAnup Patel pgd_t trampoline_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
30801062356SJisheng Zhang static pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss;
309671f9a3eSAnup Patel 
310671f9a3eSAnup Patel pgd_t early_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
311f2c17aabSAnup Patel 
31244c92257SVitaly Wool #ifdef CONFIG_XIP_KERNEL
313805a3ebeSJisheng Zhang #define pt_ops			(*(struct pt_alloc_ops *)XIP_FIXUP(&pt_ops))
31444c92257SVitaly Wool #define trampoline_pg_dir      ((pgd_t *)XIP_FIXUP(trampoline_pg_dir))
31544c92257SVitaly Wool #define fixmap_pte             ((pte_t *)XIP_FIXUP(fixmap_pte))
31644c92257SVitaly Wool #define early_pg_dir           ((pgd_t *)XIP_FIXUP(early_pg_dir))
31744c92257SVitaly Wool #endif /* CONFIG_XIP_KERNEL */
31844c92257SVitaly Wool 
3194147b5e2SAnshuman Khandual static const pgprot_t protection_map[16] = {
3204147b5e2SAnshuman Khandual 	[VM_NONE]					= PAGE_NONE,
3214147b5e2SAnshuman Khandual 	[VM_READ]					= PAGE_READ,
3224147b5e2SAnshuman Khandual 	[VM_WRITE]					= PAGE_COPY,
3234147b5e2SAnshuman Khandual 	[VM_WRITE | VM_READ]				= PAGE_COPY,
3244147b5e2SAnshuman Khandual 	[VM_EXEC]					= PAGE_EXEC,
3254147b5e2SAnshuman Khandual 	[VM_EXEC | VM_READ]				= PAGE_READ_EXEC,
3264147b5e2SAnshuman Khandual 	[VM_EXEC | VM_WRITE]				= PAGE_COPY_EXEC,
3276569fc12SHsieh-Tseng Shen 	[VM_EXEC | VM_WRITE | VM_READ]			= PAGE_COPY_EXEC,
3284147b5e2SAnshuman Khandual 	[VM_SHARED]					= PAGE_NONE,
3294147b5e2SAnshuman Khandual 	[VM_SHARED | VM_READ]				= PAGE_READ,
3304147b5e2SAnshuman Khandual 	[VM_SHARED | VM_WRITE]				= PAGE_SHARED,
3314147b5e2SAnshuman Khandual 	[VM_SHARED | VM_WRITE | VM_READ]		= PAGE_SHARED,
3324147b5e2SAnshuman Khandual 	[VM_SHARED | VM_EXEC]				= PAGE_EXEC,
3334147b5e2SAnshuman Khandual 	[VM_SHARED | VM_EXEC | VM_READ]			= PAGE_READ_EXEC,
3344147b5e2SAnshuman Khandual 	[VM_SHARED | VM_EXEC | VM_WRITE]		= PAGE_SHARED_EXEC,
3354147b5e2SAnshuman Khandual 	[VM_SHARED | VM_EXEC | VM_WRITE | VM_READ]	= PAGE_SHARED_EXEC
3364147b5e2SAnshuman Khandual };
3374147b5e2SAnshuman Khandual DECLARE_VM_GET_PAGE_PROT
3384147b5e2SAnshuman Khandual 
__set_fixmap(enum fixed_addresses idx,phys_addr_t phys,pgprot_t prot)339f2c17aabSAnup Patel void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
340f2c17aabSAnup Patel {
341f2c17aabSAnup Patel 	unsigned long addr = __fix_to_virt(idx);
342f2c17aabSAnup Patel 	pte_t *ptep;
343f2c17aabSAnup Patel 
344f2c17aabSAnup Patel 	BUG_ON(idx <= FIX_HOLE || idx >= __end_of_fixed_addresses);
345f2c17aabSAnup Patel 
346f2c17aabSAnup Patel 	ptep = &fixmap_pte[pte_index(addr)];
347f2c17aabSAnup Patel 
34821190b74SGreentime Hu 	if (pgprot_val(prot))
349f2c17aabSAnup Patel 		set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
35021190b74SGreentime Hu 	else
351f2c17aabSAnup Patel 		pte_clear(&init_mm, addr, ptep);
352f2c17aabSAnup Patel 	local_flush_tlb_page(addr);
353f2c17aabSAnup Patel }
354f2c17aabSAnup Patel 
get_pte_virt_early(phys_addr_t pa)355e8dcb61fSAtish Patra static inline pte_t *__init get_pte_virt_early(phys_addr_t pa)
356671f9a3eSAnup Patel {
357671f9a3eSAnup Patel 	return (pte_t *)((uintptr_t)pa);
358671f9a3eSAnup Patel }
359e8dcb61fSAtish Patra 
get_pte_virt_fixmap(phys_addr_t pa)360e8dcb61fSAtish Patra static inline pte_t *__init get_pte_virt_fixmap(phys_addr_t pa)
361e8dcb61fSAtish Patra {
362e8dcb61fSAtish Patra 	clear_fixmap(FIX_PTE);
363e8dcb61fSAtish Patra 	return (pte_t *)set_fixmap_offset(FIX_PTE, pa);
364671f9a3eSAnup Patel }
365671f9a3eSAnup Patel 
get_pte_virt_late(phys_addr_t pa)36601062356SJisheng Zhang static inline pte_t *__init get_pte_virt_late(phys_addr_t pa)
367e8dcb61fSAtish Patra {
368e8dcb61fSAtish Patra 	return (pte_t *) __va(pa);
369e8dcb61fSAtish Patra }
370e8dcb61fSAtish Patra 
alloc_pte_early(uintptr_t va)371e8dcb61fSAtish Patra static inline phys_addr_t __init alloc_pte_early(uintptr_t va)
372671f9a3eSAnup Patel {
373671f9a3eSAnup Patel 	/*
374671f9a3eSAnup Patel 	 * We only create PMD or PGD early mappings so we
375671f9a3eSAnup Patel 	 * should never reach here with MMU disabled.
376671f9a3eSAnup Patel 	 */
377e8dcb61fSAtish Patra 	BUG();
378e8dcb61fSAtish Patra }
379671f9a3eSAnup Patel 
alloc_pte_fixmap(uintptr_t va)380e8dcb61fSAtish Patra static inline phys_addr_t __init alloc_pte_fixmap(uintptr_t va)
381e8dcb61fSAtish Patra {
382671f9a3eSAnup Patel 	return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
383671f9a3eSAnup Patel }
384671f9a3eSAnup Patel 
alloc_pte_late(uintptr_t va)38501062356SJisheng Zhang static phys_addr_t __init alloc_pte_late(uintptr_t va)
386e8dcb61fSAtish Patra {
387380f2c1aSVishal Moola (Oracle) 	struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL & ~__GFP_HIGHMEM, 0);
388e8dcb61fSAtish Patra 
389380f2c1aSVishal Moola (Oracle) 	BUG_ON(!ptdesc || !pagetable_pte_ctor(ptdesc));
390380f2c1aSVishal Moola (Oracle) 	return __pa((pte_t *)ptdesc_address(ptdesc));
391e8dcb61fSAtish Patra }
392e8dcb61fSAtish Patra 
create_pte_mapping(pte_t * ptep,uintptr_t va,phys_addr_t pa,phys_addr_t sz,pgprot_t prot)393671f9a3eSAnup Patel static void __init create_pte_mapping(pte_t *ptep,
394671f9a3eSAnup Patel 				      uintptr_t va, phys_addr_t pa,
395671f9a3eSAnup Patel 				      phys_addr_t sz, pgprot_t prot)
396671f9a3eSAnup Patel {
397974b9b2cSMike Rapoport 	uintptr_t pte_idx = pte_index(va);
398671f9a3eSAnup Patel 
399671f9a3eSAnup Patel 	BUG_ON(sz != PAGE_SIZE);
400671f9a3eSAnup Patel 
401974b9b2cSMike Rapoport 	if (pte_none(ptep[pte_idx]))
402974b9b2cSMike Rapoport 		ptep[pte_idx] = pfn_pte(PFN_DOWN(pa), prot);
403671f9a3eSAnup Patel }
404671f9a3eSAnup Patel 
405671f9a3eSAnup Patel #ifndef __PAGETABLE_PMD_FOLDED
406671f9a3eSAnup Patel 
40701062356SJisheng Zhang static pmd_t trampoline_pmd[PTRS_PER_PMD] __page_aligned_bss;
40801062356SJisheng Zhang static pmd_t fixmap_pmd[PTRS_PER_PMD] __page_aligned_bss;
40901062356SJisheng Zhang static pmd_t early_pmd[PTRS_PER_PMD] __initdata __aligned(PAGE_SIZE);
410671f9a3eSAnup Patel 
41144c92257SVitaly Wool #ifdef CONFIG_XIP_KERNEL
41244c92257SVitaly Wool #define trampoline_pmd ((pmd_t *)XIP_FIXUP(trampoline_pmd))
41344c92257SVitaly Wool #define fixmap_pmd     ((pmd_t *)XIP_FIXUP(fixmap_pmd))
41444c92257SVitaly Wool #define early_pmd      ((pmd_t *)XIP_FIXUP(early_pmd))
41544c92257SVitaly Wool #endif /* CONFIG_XIP_KERNEL */
41644c92257SVitaly Wool 
417677b9eb8SQinglin Pan static p4d_t trampoline_p4d[PTRS_PER_P4D] __page_aligned_bss;
418677b9eb8SQinglin Pan static p4d_t fixmap_p4d[PTRS_PER_P4D] __page_aligned_bss;
419677b9eb8SQinglin Pan static p4d_t early_p4d[PTRS_PER_P4D] __initdata __aligned(PAGE_SIZE);
420677b9eb8SQinglin Pan 
421677b9eb8SQinglin Pan #ifdef CONFIG_XIP_KERNEL
422677b9eb8SQinglin Pan #define trampoline_p4d ((p4d_t *)XIP_FIXUP(trampoline_p4d))
423677b9eb8SQinglin Pan #define fixmap_p4d     ((p4d_t *)XIP_FIXUP(fixmap_p4d))
424677b9eb8SQinglin Pan #define early_p4d      ((p4d_t *)XIP_FIXUP(early_p4d))
425677b9eb8SQinglin Pan #endif /* CONFIG_XIP_KERNEL */
426677b9eb8SQinglin Pan 
427e8a62cc2SAlexandre Ghiti static pud_t trampoline_pud[PTRS_PER_PUD] __page_aligned_bss;
428e8a62cc2SAlexandre Ghiti static pud_t fixmap_pud[PTRS_PER_PUD] __page_aligned_bss;
429e8a62cc2SAlexandre Ghiti static pud_t early_pud[PTRS_PER_PUD] __initdata __aligned(PAGE_SIZE);
430e8a62cc2SAlexandre Ghiti 
431e8a62cc2SAlexandre Ghiti #ifdef CONFIG_XIP_KERNEL
432e8a62cc2SAlexandre Ghiti #define trampoline_pud ((pud_t *)XIP_FIXUP(trampoline_pud))
433e8a62cc2SAlexandre Ghiti #define fixmap_pud     ((pud_t *)XIP_FIXUP(fixmap_pud))
434e8a62cc2SAlexandre Ghiti #define early_pud      ((pud_t *)XIP_FIXUP(early_pud))
435e8a62cc2SAlexandre Ghiti #endif /* CONFIG_XIP_KERNEL */
436e8a62cc2SAlexandre Ghiti 
get_pmd_virt_early(phys_addr_t pa)437e8dcb61fSAtish Patra static pmd_t *__init get_pmd_virt_early(phys_addr_t pa)
438671f9a3eSAnup Patel {
439e8dcb61fSAtish Patra 	/* Before MMU is enabled */
440671f9a3eSAnup Patel 	return (pmd_t *)((uintptr_t)pa);
441671f9a3eSAnup Patel }
442e8dcb61fSAtish Patra 
get_pmd_virt_fixmap(phys_addr_t pa)443e8dcb61fSAtish Patra static pmd_t *__init get_pmd_virt_fixmap(phys_addr_t pa)
444e8dcb61fSAtish Patra {
445e8dcb61fSAtish Patra 	clear_fixmap(FIX_PMD);
446e8dcb61fSAtish Patra 	return (pmd_t *)set_fixmap_offset(FIX_PMD, pa);
447671f9a3eSAnup Patel }
448671f9a3eSAnup Patel 
get_pmd_virt_late(phys_addr_t pa)44901062356SJisheng Zhang static pmd_t *__init get_pmd_virt_late(phys_addr_t pa)
450e8dcb61fSAtish Patra {
451e8dcb61fSAtish Patra 	return (pmd_t *) __va(pa);
452e8dcb61fSAtish Patra }
453e8dcb61fSAtish Patra 
alloc_pmd_early(uintptr_t va)454e8dcb61fSAtish Patra static phys_addr_t __init alloc_pmd_early(uintptr_t va)
455671f9a3eSAnup Patel {
456e8a62cc2SAlexandre Ghiti 	BUG_ON((va - kernel_map.virt_addr) >> PUD_SHIFT);
457671f9a3eSAnup Patel 
4580f02de44SAlexandre Ghiti 	return (uintptr_t)early_pmd;
459671f9a3eSAnup Patel }
460671f9a3eSAnup Patel 
alloc_pmd_fixmap(uintptr_t va)461e8dcb61fSAtish Patra static phys_addr_t __init alloc_pmd_fixmap(uintptr_t va)
462e8dcb61fSAtish Patra {
463e8dcb61fSAtish Patra 	return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
464e8dcb61fSAtish Patra }
465e8dcb61fSAtish Patra 
alloc_pmd_late(uintptr_t va)46601062356SJisheng Zhang static phys_addr_t __init alloc_pmd_late(uintptr_t va)
467e8dcb61fSAtish Patra {
468380f2c1aSVishal Moola (Oracle) 	struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL & ~__GFP_HIGHMEM, 0);
469e8dcb61fSAtish Patra 
470380f2c1aSVishal Moola (Oracle) 	BUG_ON(!ptdesc || !pagetable_pmd_ctor(ptdesc));
471380f2c1aSVishal Moola (Oracle) 	return __pa((pmd_t *)ptdesc_address(ptdesc));
472e8dcb61fSAtish Patra }
473e8dcb61fSAtish Patra 
create_pmd_mapping(pmd_t * pmdp,uintptr_t va,phys_addr_t pa,phys_addr_t sz,pgprot_t prot)474671f9a3eSAnup Patel static void __init create_pmd_mapping(pmd_t *pmdp,
475671f9a3eSAnup Patel 				      uintptr_t va, phys_addr_t pa,
476671f9a3eSAnup Patel 				      phys_addr_t sz, pgprot_t prot)
477671f9a3eSAnup Patel {
478671f9a3eSAnup Patel 	pte_t *ptep;
479671f9a3eSAnup Patel 	phys_addr_t pte_phys;
480974b9b2cSMike Rapoport 	uintptr_t pmd_idx = pmd_index(va);
481671f9a3eSAnup Patel 
482671f9a3eSAnup Patel 	if (sz == PMD_SIZE) {
483974b9b2cSMike Rapoport 		if (pmd_none(pmdp[pmd_idx]))
484974b9b2cSMike Rapoport 			pmdp[pmd_idx] = pfn_pmd(PFN_DOWN(pa), prot);
485671f9a3eSAnup Patel 		return;
486671f9a3eSAnup Patel 	}
487671f9a3eSAnup Patel 
488974b9b2cSMike Rapoport 	if (pmd_none(pmdp[pmd_idx])) {
489e8dcb61fSAtish Patra 		pte_phys = pt_ops.alloc_pte(va);
490974b9b2cSMike Rapoport 		pmdp[pmd_idx] = pfn_pmd(PFN_DOWN(pte_phys), PAGE_TABLE);
491e8dcb61fSAtish Patra 		ptep = pt_ops.get_pte_virt(pte_phys);
492671f9a3eSAnup Patel 		memset(ptep, 0, PAGE_SIZE);
493671f9a3eSAnup Patel 	} else {
494974b9b2cSMike Rapoport 		pte_phys = PFN_PHYS(_pmd_pfn(pmdp[pmd_idx]));
495e8dcb61fSAtish Patra 		ptep = pt_ops.get_pte_virt(pte_phys);
496671f9a3eSAnup Patel 	}
497671f9a3eSAnup Patel 
498671f9a3eSAnup Patel 	create_pte_mapping(ptep, va, pa, sz, prot);
499671f9a3eSAnup Patel }
500671f9a3eSAnup Patel 
get_pud_virt_early(phys_addr_t pa)501e8a62cc2SAlexandre Ghiti static pud_t *__init get_pud_virt_early(phys_addr_t pa)
502e8a62cc2SAlexandre Ghiti {
503e8a62cc2SAlexandre Ghiti 	return (pud_t *)((uintptr_t)pa);
504e8a62cc2SAlexandre Ghiti }
505e8a62cc2SAlexandre Ghiti 
get_pud_virt_fixmap(phys_addr_t pa)506e8a62cc2SAlexandre Ghiti static pud_t *__init get_pud_virt_fixmap(phys_addr_t pa)
507e8a62cc2SAlexandre Ghiti {
508e8a62cc2SAlexandre Ghiti 	clear_fixmap(FIX_PUD);
509e8a62cc2SAlexandre Ghiti 	return (pud_t *)set_fixmap_offset(FIX_PUD, pa);
510e8a62cc2SAlexandre Ghiti }
511e8a62cc2SAlexandre Ghiti 
get_pud_virt_late(phys_addr_t pa)512e8a62cc2SAlexandre Ghiti static pud_t *__init get_pud_virt_late(phys_addr_t pa)
513e8a62cc2SAlexandre Ghiti {
514e8a62cc2SAlexandre Ghiti 	return (pud_t *)__va(pa);
515e8a62cc2SAlexandre Ghiti }
516e8a62cc2SAlexandre Ghiti 
alloc_pud_early(uintptr_t va)517e8a62cc2SAlexandre Ghiti static phys_addr_t __init alloc_pud_early(uintptr_t va)
518e8a62cc2SAlexandre Ghiti {
519e8a62cc2SAlexandre Ghiti 	/* Only one PUD is available for early mapping */
520e8a62cc2SAlexandre Ghiti 	BUG_ON((va - kernel_map.virt_addr) >> PGDIR_SHIFT);
521e8a62cc2SAlexandre Ghiti 
522e8a62cc2SAlexandre Ghiti 	return (uintptr_t)early_pud;
523e8a62cc2SAlexandre Ghiti }
524e8a62cc2SAlexandre Ghiti 
alloc_pud_fixmap(uintptr_t va)525e8a62cc2SAlexandre Ghiti static phys_addr_t __init alloc_pud_fixmap(uintptr_t va)
526e8a62cc2SAlexandre Ghiti {
527e8a62cc2SAlexandre Ghiti 	return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
528e8a62cc2SAlexandre Ghiti }
529e8a62cc2SAlexandre Ghiti 
alloc_pud_late(uintptr_t va)530e8a62cc2SAlexandre Ghiti static phys_addr_t alloc_pud_late(uintptr_t va)
531e8a62cc2SAlexandre Ghiti {
532e8a62cc2SAlexandre Ghiti 	unsigned long vaddr;
533e8a62cc2SAlexandre Ghiti 
534e8a62cc2SAlexandre Ghiti 	vaddr = __get_free_page(GFP_KERNEL);
535e8a62cc2SAlexandre Ghiti 	BUG_ON(!vaddr);
536e8a62cc2SAlexandre Ghiti 	return __pa(vaddr);
537e8a62cc2SAlexandre Ghiti }
538e8a62cc2SAlexandre Ghiti 
get_p4d_virt_early(phys_addr_t pa)539677b9eb8SQinglin Pan static p4d_t *__init get_p4d_virt_early(phys_addr_t pa)
540677b9eb8SQinglin Pan {
541677b9eb8SQinglin Pan 	return (p4d_t *)((uintptr_t)pa);
542677b9eb8SQinglin Pan }
543677b9eb8SQinglin Pan 
get_p4d_virt_fixmap(phys_addr_t pa)544677b9eb8SQinglin Pan static p4d_t *__init get_p4d_virt_fixmap(phys_addr_t pa)
545677b9eb8SQinglin Pan {
546677b9eb8SQinglin Pan 	clear_fixmap(FIX_P4D);
547677b9eb8SQinglin Pan 	return (p4d_t *)set_fixmap_offset(FIX_P4D, pa);
548677b9eb8SQinglin Pan }
549677b9eb8SQinglin Pan 
get_p4d_virt_late(phys_addr_t pa)550677b9eb8SQinglin Pan static p4d_t *__init get_p4d_virt_late(phys_addr_t pa)
551677b9eb8SQinglin Pan {
552677b9eb8SQinglin Pan 	return (p4d_t *)__va(pa);
553677b9eb8SQinglin Pan }
554677b9eb8SQinglin Pan 
alloc_p4d_early(uintptr_t va)555677b9eb8SQinglin Pan static phys_addr_t __init alloc_p4d_early(uintptr_t va)
556677b9eb8SQinglin Pan {
557677b9eb8SQinglin Pan 	/* Only one P4D is available for early mapping */
558677b9eb8SQinglin Pan 	BUG_ON((va - kernel_map.virt_addr) >> PGDIR_SHIFT);
559677b9eb8SQinglin Pan 
560677b9eb8SQinglin Pan 	return (uintptr_t)early_p4d;
561677b9eb8SQinglin Pan }
562677b9eb8SQinglin Pan 
alloc_p4d_fixmap(uintptr_t va)563677b9eb8SQinglin Pan static phys_addr_t __init alloc_p4d_fixmap(uintptr_t va)
564677b9eb8SQinglin Pan {
565677b9eb8SQinglin Pan 	return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
566677b9eb8SQinglin Pan }
567677b9eb8SQinglin Pan 
alloc_p4d_late(uintptr_t va)568677b9eb8SQinglin Pan static phys_addr_t alloc_p4d_late(uintptr_t va)
569677b9eb8SQinglin Pan {
570677b9eb8SQinglin Pan 	unsigned long vaddr;
571677b9eb8SQinglin Pan 
572677b9eb8SQinglin Pan 	vaddr = __get_free_page(GFP_KERNEL);
573677b9eb8SQinglin Pan 	BUG_ON(!vaddr);
574677b9eb8SQinglin Pan 	return __pa(vaddr);
575677b9eb8SQinglin Pan }
576677b9eb8SQinglin Pan 
create_pud_mapping(pud_t * pudp,uintptr_t va,phys_addr_t pa,phys_addr_t sz,pgprot_t prot)577e8a62cc2SAlexandre Ghiti static void __init create_pud_mapping(pud_t *pudp,
578e8a62cc2SAlexandre Ghiti 				      uintptr_t va, phys_addr_t pa,
579e8a62cc2SAlexandre Ghiti 				      phys_addr_t sz, pgprot_t prot)
580e8a62cc2SAlexandre Ghiti {
581e8a62cc2SAlexandre Ghiti 	pmd_t *nextp;
582e8a62cc2SAlexandre Ghiti 	phys_addr_t next_phys;
583e8a62cc2SAlexandre Ghiti 	uintptr_t pud_index = pud_index(va);
584e8a62cc2SAlexandre Ghiti 
585e8a62cc2SAlexandre Ghiti 	if (sz == PUD_SIZE) {
586e8a62cc2SAlexandre Ghiti 		if (pud_val(pudp[pud_index]) == 0)
587e8a62cc2SAlexandre Ghiti 			pudp[pud_index] = pfn_pud(PFN_DOWN(pa), prot);
588e8a62cc2SAlexandre Ghiti 		return;
589e8a62cc2SAlexandre Ghiti 	}
590e8a62cc2SAlexandre Ghiti 
591e8a62cc2SAlexandre Ghiti 	if (pud_val(pudp[pud_index]) == 0) {
592e8a62cc2SAlexandre Ghiti 		next_phys = pt_ops.alloc_pmd(va);
593e8a62cc2SAlexandre Ghiti 		pudp[pud_index] = pfn_pud(PFN_DOWN(next_phys), PAGE_TABLE);
594e8a62cc2SAlexandre Ghiti 		nextp = pt_ops.get_pmd_virt(next_phys);
595e8a62cc2SAlexandre Ghiti 		memset(nextp, 0, PAGE_SIZE);
596e8a62cc2SAlexandre Ghiti 	} else {
597e8a62cc2SAlexandre Ghiti 		next_phys = PFN_PHYS(_pud_pfn(pudp[pud_index]));
598e8a62cc2SAlexandre Ghiti 		nextp = pt_ops.get_pmd_virt(next_phys);
599e8a62cc2SAlexandre Ghiti 	}
600e8a62cc2SAlexandre Ghiti 
601e8a62cc2SAlexandre Ghiti 	create_pmd_mapping(nextp, va, pa, sz, prot);
602e8a62cc2SAlexandre Ghiti }
603e8a62cc2SAlexandre Ghiti 
create_p4d_mapping(p4d_t * p4dp,uintptr_t va,phys_addr_t pa,phys_addr_t sz,pgprot_t prot)604677b9eb8SQinglin Pan static void __init create_p4d_mapping(p4d_t *p4dp,
605677b9eb8SQinglin Pan 				      uintptr_t va, phys_addr_t pa,
606677b9eb8SQinglin Pan 				      phys_addr_t sz, pgprot_t prot)
607677b9eb8SQinglin Pan {
608677b9eb8SQinglin Pan 	pud_t *nextp;
609677b9eb8SQinglin Pan 	phys_addr_t next_phys;
610677b9eb8SQinglin Pan 	uintptr_t p4d_index = p4d_index(va);
611677b9eb8SQinglin Pan 
612677b9eb8SQinglin Pan 	if (sz == P4D_SIZE) {
613677b9eb8SQinglin Pan 		if (p4d_val(p4dp[p4d_index]) == 0)
614677b9eb8SQinglin Pan 			p4dp[p4d_index] = pfn_p4d(PFN_DOWN(pa), prot);
615677b9eb8SQinglin Pan 		return;
616677b9eb8SQinglin Pan 	}
617677b9eb8SQinglin Pan 
618677b9eb8SQinglin Pan 	if (p4d_val(p4dp[p4d_index]) == 0) {
619677b9eb8SQinglin Pan 		next_phys = pt_ops.alloc_pud(va);
620677b9eb8SQinglin Pan 		p4dp[p4d_index] = pfn_p4d(PFN_DOWN(next_phys), PAGE_TABLE);
621677b9eb8SQinglin Pan 		nextp = pt_ops.get_pud_virt(next_phys);
622677b9eb8SQinglin Pan 		memset(nextp, 0, PAGE_SIZE);
623677b9eb8SQinglin Pan 	} else {
624677b9eb8SQinglin Pan 		next_phys = PFN_PHYS(_p4d_pfn(p4dp[p4d_index]));
625677b9eb8SQinglin Pan 		nextp = pt_ops.get_pud_virt(next_phys);
626677b9eb8SQinglin Pan 	}
627677b9eb8SQinglin Pan 
628677b9eb8SQinglin Pan 	create_pud_mapping(nextp, va, pa, sz, prot);
629677b9eb8SQinglin Pan }
630677b9eb8SQinglin Pan 
631677b9eb8SQinglin Pan #define pgd_next_t		p4d_t
632677b9eb8SQinglin Pan #define alloc_pgd_next(__va)	(pgtable_l5_enabled ?			\
633677b9eb8SQinglin Pan 		pt_ops.alloc_p4d(__va) : (pgtable_l4_enabled ?		\
634677b9eb8SQinglin Pan 		pt_ops.alloc_pud(__va) : pt_ops.alloc_pmd(__va)))
635677b9eb8SQinglin Pan #define get_pgd_next_virt(__pa)	(pgtable_l5_enabled ?			\
636677b9eb8SQinglin Pan 		pt_ops.get_p4d_virt(__pa) : (pgd_next_t *)(pgtable_l4_enabled ?	\
637677b9eb8SQinglin Pan 		pt_ops.get_pud_virt(__pa) : (pud_t *)pt_ops.get_pmd_virt(__pa)))
638671f9a3eSAnup Patel #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot)	\
639677b9eb8SQinglin Pan 				(pgtable_l5_enabled ?			\
640677b9eb8SQinglin Pan 		create_p4d_mapping(__nextp, __va, __pa, __sz, __prot) : \
641e8a62cc2SAlexandre Ghiti 				(pgtable_l4_enabled ?			\
642677b9eb8SQinglin Pan 		create_pud_mapping((pud_t *)__nextp, __va, __pa, __sz, __prot) :	\
643677b9eb8SQinglin Pan 		create_pmd_mapping((pmd_t *)__nextp, __va, __pa, __sz, __prot)))
644677b9eb8SQinglin Pan #define fixmap_pgd_next		(pgtable_l5_enabled ?			\
645677b9eb8SQinglin Pan 		(uintptr_t)fixmap_p4d : (pgtable_l4_enabled ?		\
646677b9eb8SQinglin Pan 		(uintptr_t)fixmap_pud : (uintptr_t)fixmap_pmd))
647677b9eb8SQinglin Pan #define trampoline_pgd_next	(pgtable_l5_enabled ?			\
648677b9eb8SQinglin Pan 		(uintptr_t)trampoline_p4d : (pgtable_l4_enabled ?	\
649677b9eb8SQinglin Pan 		(uintptr_t)trampoline_pud : (uintptr_t)trampoline_pmd))
650671f9a3eSAnup Patel #else
651671f9a3eSAnup Patel #define pgd_next_t		pte_t
652e8dcb61fSAtish Patra #define alloc_pgd_next(__va)	pt_ops.alloc_pte(__va)
653e8dcb61fSAtish Patra #define get_pgd_next_virt(__pa)	pt_ops.get_pte_virt(__pa)
654671f9a3eSAnup Patel #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot)	\
655671f9a3eSAnup Patel 	create_pte_mapping(__nextp, __va, __pa, __sz, __prot)
656e8a62cc2SAlexandre Ghiti #define fixmap_pgd_next		((uintptr_t)fixmap_pte)
657f83050a8SPalmer Dabbelt #define create_p4d_mapping(__pmdp, __va, __pa, __sz, __prot) do {} while(0)
658f83050a8SPalmer Dabbelt #define create_pud_mapping(__pmdp, __va, __pa, __sz, __prot) do {} while(0)
659f83050a8SPalmer Dabbelt #define create_pmd_mapping(__pmdp, __va, __pa, __sz, __prot) do {} while(0)
660e8a62cc2SAlexandre Ghiti #endif /* __PAGETABLE_PMD_FOLDED */
661671f9a3eSAnup Patel 
create_pgd_mapping(pgd_t * pgdp,uintptr_t va,phys_addr_t pa,phys_addr_t sz,pgprot_t prot)662b91540d5SAtish Patra void __init create_pgd_mapping(pgd_t *pgdp,
663671f9a3eSAnup Patel 				      uintptr_t va, phys_addr_t pa,
664671f9a3eSAnup Patel 				      phys_addr_t sz, pgprot_t prot)
665671f9a3eSAnup Patel {
666671f9a3eSAnup Patel 	pgd_next_t *nextp;
667671f9a3eSAnup Patel 	phys_addr_t next_phys;
668974b9b2cSMike Rapoport 	uintptr_t pgd_idx = pgd_index(va);
669671f9a3eSAnup Patel 
670671f9a3eSAnup Patel 	if (sz == PGDIR_SIZE) {
671974b9b2cSMike Rapoport 		if (pgd_val(pgdp[pgd_idx]) == 0)
672974b9b2cSMike Rapoport 			pgdp[pgd_idx] = pfn_pgd(PFN_DOWN(pa), prot);
673671f9a3eSAnup Patel 		return;
674671f9a3eSAnup Patel 	}
675671f9a3eSAnup Patel 
676974b9b2cSMike Rapoport 	if (pgd_val(pgdp[pgd_idx]) == 0) {
677671f9a3eSAnup Patel 		next_phys = alloc_pgd_next(va);
678974b9b2cSMike Rapoport 		pgdp[pgd_idx] = pfn_pgd(PFN_DOWN(next_phys), PAGE_TABLE);
679671f9a3eSAnup Patel 		nextp = get_pgd_next_virt(next_phys);
680671f9a3eSAnup Patel 		memset(nextp, 0, PAGE_SIZE);
681671f9a3eSAnup Patel 	} else {
682974b9b2cSMike Rapoport 		next_phys = PFN_PHYS(_pgd_pfn(pgdp[pgd_idx]));
683671f9a3eSAnup Patel 		nextp = get_pgd_next_virt(next_phys);
684671f9a3eSAnup Patel 	}
685671f9a3eSAnup Patel 
686671f9a3eSAnup Patel 	create_pgd_next_mapping(nextp, va, pa, sz, prot);
687671f9a3eSAnup Patel }
688671f9a3eSAnup Patel 
best_map_size(phys_addr_t pa,uintptr_t va,phys_addr_t size)68949a0a373SAlexandre Ghiti static uintptr_t __init best_map_size(phys_addr_t pa, uintptr_t va,
69049a0a373SAlexandre Ghiti 				      phys_addr_t size)
691671f9a3eSAnup Patel {
69205f263c1SNam Cao 	if (debug_pagealloc_enabled())
69305f263c1SNam Cao 		return PAGE_SIZE;
69405f263c1SNam Cao 
6955f03d4f2SAlexandre Ghiti 	if (pgtable_l5_enabled &&
6965f03d4f2SAlexandre Ghiti 	    !(pa & (P4D_SIZE - 1)) && !(va & (P4D_SIZE - 1)) && size >= P4D_SIZE)
6973335068fSAlexandre Ghiti 		return P4D_SIZE;
6983335068fSAlexandre Ghiti 
6995f03d4f2SAlexandre Ghiti 	if (pgtable_l4_enabled &&
7005f03d4f2SAlexandre Ghiti 	    !(pa & (PUD_SIZE - 1)) && !(va & (PUD_SIZE - 1)) && size >= PUD_SIZE)
7013335068fSAlexandre Ghiti 		return PUD_SIZE;
7023335068fSAlexandre Ghiti 
7035f03d4f2SAlexandre Ghiti 	if (IS_ENABLED(CONFIG_64BIT) &&
7045f03d4f2SAlexandre Ghiti 	    !(pa & (PMD_SIZE - 1)) && !(va & (PMD_SIZE - 1)) && size >= PMD_SIZE)
7050fdc636cSZong Li 		return PMD_SIZE;
7066ff8ca3fSQinglin Pan 
7076ff8ca3fSQinglin Pan 	return PAGE_SIZE;
708671f9a3eSAnup Patel }
709671f9a3eSAnup Patel 
71044c92257SVitaly Wool #ifdef CONFIG_XIP_KERNEL
7114b1c70aaSPalmer Dabbelt #define phys_ram_base  (*(phys_addr_t *)XIP_FIXUP(&phys_ram_base))
712805a3ebeSJisheng Zhang extern char _xiprom[], _exiprom[], __data_loc;
713805a3ebeSJisheng Zhang 
71444c92257SVitaly Wool /* called from head.S with MMU off */
__copy_data(void)71544c92257SVitaly Wool asmlinkage void __init __copy_data(void)
71644c92257SVitaly Wool {
717f9ace4edSVitaly Wool 	void *from = (void *)(&__data_loc);
71844c92257SVitaly Wool 	void *to = (void *)CONFIG_PHYS_RAM_BASE;
719f9ace4edSVitaly Wool 	size_t sz = (size_t)((uintptr_t)(&_end) - (uintptr_t)(&_sdata));
72044c92257SVitaly Wool 
72144c92257SVitaly Wool 	memcpy(to, from, sz);
72244c92257SVitaly Wool }
72344c92257SVitaly Wool #endif
72444c92257SVitaly Wool 
725e5c35fa0SAlexandre Ghiti #ifdef CONFIG_STRICT_KERNEL_RWX
pgprot_from_va(uintptr_t va)726e5c35fa0SAlexandre Ghiti static __init pgprot_t pgprot_from_va(uintptr_t va)
727e5c35fa0SAlexandre Ghiti {
728e5c35fa0SAlexandre Ghiti 	if (is_va_kernel_text(va))
729e5c35fa0SAlexandre Ghiti 		return PAGE_KERNEL_READ_EXEC;
730e5c35fa0SAlexandre Ghiti 
731e5c35fa0SAlexandre Ghiti 	/*
732e5c35fa0SAlexandre Ghiti 	 * In 64-bit kernel, the kernel mapping is outside the linear mapping so
733e5c35fa0SAlexandre Ghiti 	 * we must protect its linear mapping alias from being executed and
734e5c35fa0SAlexandre Ghiti 	 * written.
735e5c35fa0SAlexandre Ghiti 	 * And rodata section is marked readonly in mark_rodata_ro.
736e5c35fa0SAlexandre Ghiti 	 */
737e5c35fa0SAlexandre Ghiti 	if (IS_ENABLED(CONFIG_64BIT) && is_va_kernel_lm_alias_text(va))
738e5c35fa0SAlexandre Ghiti 		return PAGE_KERNEL_READ;
739e5c35fa0SAlexandre Ghiti 
740e5c35fa0SAlexandre Ghiti 	return PAGE_KERNEL;
741e5c35fa0SAlexandre Ghiti }
742e5c35fa0SAlexandre Ghiti 
mark_rodata_ro(void)743e5c35fa0SAlexandre Ghiti void mark_rodata_ro(void)
744e5c35fa0SAlexandre Ghiti {
745e5c35fa0SAlexandre Ghiti 	set_kernel_memory(__start_rodata, _data, set_memory_ro);
746e5c35fa0SAlexandre Ghiti 	if (IS_ENABLED(CONFIG_64BIT))
747e5c35fa0SAlexandre Ghiti 		set_kernel_memory(lm_alias(__start_rodata), lm_alias(_data),
748e5c35fa0SAlexandre Ghiti 				  set_memory_ro);
749e5c35fa0SAlexandre Ghiti 
750e5c35fa0SAlexandre Ghiti 	debug_checkwx();
751e5c35fa0SAlexandre Ghiti }
752e5c35fa0SAlexandre Ghiti #else
pgprot_from_va(uintptr_t va)753e5c35fa0SAlexandre Ghiti static __init pgprot_t pgprot_from_va(uintptr_t va)
754e5c35fa0SAlexandre Ghiti {
755e5c35fa0SAlexandre Ghiti 	if (IS_ENABLED(CONFIG_64BIT) && !is_kernel_mapping(va))
756e5c35fa0SAlexandre Ghiti 		return PAGE_KERNEL;
757e5c35fa0SAlexandre Ghiti 
758e5c35fa0SAlexandre Ghiti 	return PAGE_KERNEL_EXEC;
759e5c35fa0SAlexandre Ghiti }
760e5c35fa0SAlexandre Ghiti #endif /* CONFIG_STRICT_KERNEL_RWX */
761e5c35fa0SAlexandre Ghiti 
762d9e418d0SPalmer Dabbelt #if defined(CONFIG_64BIT) && !defined(CONFIG_XIP_KERNEL)
76326e7aacbSAlexandre Ghiti u64 __pi_set_satp_mode_from_cmdline(uintptr_t dtb_pa);
76426e7aacbSAlexandre Ghiti 
disable_pgtable_l5(void)765011f09d1SQinglin Pan static void __init disable_pgtable_l5(void)
766011f09d1SQinglin Pan {
767011f09d1SQinglin Pan 	pgtable_l5_enabled = false;
768011f09d1SQinglin Pan 	kernel_map.page_offset = PAGE_OFFSET_L4;
769011f09d1SQinglin Pan 	satp_mode = SATP_MODE_48;
770011f09d1SQinglin Pan }
771011f09d1SQinglin Pan 
disable_pgtable_l4(void)772e8a62cc2SAlexandre Ghiti static void __init disable_pgtable_l4(void)
773e8a62cc2SAlexandre Ghiti {
774e8a62cc2SAlexandre Ghiti 	pgtable_l4_enabled = false;
775e8a62cc2SAlexandre Ghiti 	kernel_map.page_offset = PAGE_OFFSET_L3;
776e8a62cc2SAlexandre Ghiti 	satp_mode = SATP_MODE_39;
777e8a62cc2SAlexandre Ghiti }
778e8a62cc2SAlexandre Ghiti 
print_no4lvl(char * p)77926e7aacbSAlexandre Ghiti static int __init print_no4lvl(char *p)
78026e7aacbSAlexandre Ghiti {
78126e7aacbSAlexandre Ghiti 	pr_info("Disabled 4-level and 5-level paging");
78226e7aacbSAlexandre Ghiti 	return 0;
78326e7aacbSAlexandre Ghiti }
78426e7aacbSAlexandre Ghiti early_param("no4lvl", print_no4lvl);
78526e7aacbSAlexandre Ghiti 
print_no5lvl(char * p)78626e7aacbSAlexandre Ghiti static int __init print_no5lvl(char *p)
78726e7aacbSAlexandre Ghiti {
78826e7aacbSAlexandre Ghiti 	pr_info("Disabled 5-level paging");
78926e7aacbSAlexandre Ghiti 	return 0;
79026e7aacbSAlexandre Ghiti }
79126e7aacbSAlexandre Ghiti early_param("no5lvl", print_no5lvl);
79226e7aacbSAlexandre Ghiti 
793e8a62cc2SAlexandre Ghiti /*
794e8a62cc2SAlexandre Ghiti  * There is a simple way to determine if 4-level is supported by the
795e8a62cc2SAlexandre Ghiti  * underlying hardware: establish 1:1 mapping in 4-level page table mode
796e8a62cc2SAlexandre Ghiti  * then read SATP to see if the configuration was taken into account
797e8a62cc2SAlexandre Ghiti  * meaning sv48 is supported.
798e8a62cc2SAlexandre Ghiti  */
set_satp_mode(uintptr_t dtb_pa)79926e7aacbSAlexandre Ghiti static __init void set_satp_mode(uintptr_t dtb_pa)
800e8a62cc2SAlexandre Ghiti {
801e8a62cc2SAlexandre Ghiti 	u64 identity_satp, hw_satp;
802011f09d1SQinglin Pan 	uintptr_t set_satp_mode_pmd = ((unsigned long)set_satp_mode) & PMD_MASK;
80326e7aacbSAlexandre Ghiti 	u64 satp_mode_cmdline = __pi_set_satp_mode_from_cmdline(dtb_pa);
80426e7aacbSAlexandre Ghiti 
80526e7aacbSAlexandre Ghiti 	if (satp_mode_cmdline == SATP_MODE_57) {
80626e7aacbSAlexandre Ghiti 		disable_pgtable_l5();
80726e7aacbSAlexandre Ghiti 	} else if (satp_mode_cmdline == SATP_MODE_48) {
80826e7aacbSAlexandre Ghiti 		disable_pgtable_l5();
80926e7aacbSAlexandre Ghiti 		disable_pgtable_l4();
81026e7aacbSAlexandre Ghiti 		return;
81126e7aacbSAlexandre Ghiti 	}
812e8a62cc2SAlexandre Ghiti 
813011f09d1SQinglin Pan 	create_p4d_mapping(early_p4d,
814e8a62cc2SAlexandre Ghiti 			set_satp_mode_pmd, (uintptr_t)early_pud,
815011f09d1SQinglin Pan 			P4D_SIZE, PAGE_TABLE);
816e8a62cc2SAlexandre Ghiti 	create_pud_mapping(early_pud,
817e8a62cc2SAlexandre Ghiti 			   set_satp_mode_pmd, (uintptr_t)early_pmd,
818e8a62cc2SAlexandre Ghiti 			   PUD_SIZE, PAGE_TABLE);
819e8a62cc2SAlexandre Ghiti 	/* Handle the case where set_satp_mode straddles 2 PMDs */
820e8a62cc2SAlexandre Ghiti 	create_pmd_mapping(early_pmd,
821e8a62cc2SAlexandre Ghiti 			   set_satp_mode_pmd, set_satp_mode_pmd,
822e8a62cc2SAlexandre Ghiti 			   PMD_SIZE, PAGE_KERNEL_EXEC);
823e8a62cc2SAlexandre Ghiti 	create_pmd_mapping(early_pmd,
824e8a62cc2SAlexandre Ghiti 			   set_satp_mode_pmd + PMD_SIZE,
825e8a62cc2SAlexandre Ghiti 			   set_satp_mode_pmd + PMD_SIZE,
826e8a62cc2SAlexandre Ghiti 			   PMD_SIZE, PAGE_KERNEL_EXEC);
827011f09d1SQinglin Pan retry:
828011f09d1SQinglin Pan 	create_pgd_mapping(early_pg_dir,
829011f09d1SQinglin Pan 			   set_satp_mode_pmd,
83026e7aacbSAlexandre Ghiti 			   pgtable_l5_enabled ?
83126e7aacbSAlexandre Ghiti 				(uintptr_t)early_p4d : (uintptr_t)early_pud,
832011f09d1SQinglin Pan 			   PGDIR_SIZE, PAGE_TABLE);
833e8a62cc2SAlexandre Ghiti 
834e8a62cc2SAlexandre Ghiti 	identity_satp = PFN_DOWN((uintptr_t)&early_pg_dir) | satp_mode;
835e8a62cc2SAlexandre Ghiti 
836e8a62cc2SAlexandre Ghiti 	local_flush_tlb_all();
837e8a62cc2SAlexandre Ghiti 	csr_write(CSR_SATP, identity_satp);
838e8a62cc2SAlexandre Ghiti 	hw_satp = csr_swap(CSR_SATP, 0ULL);
839e8a62cc2SAlexandre Ghiti 	local_flush_tlb_all();
840e8a62cc2SAlexandre Ghiti 
841011f09d1SQinglin Pan 	if (hw_satp != identity_satp) {
84226e7aacbSAlexandre Ghiti 		if (pgtable_l5_enabled) {
843011f09d1SQinglin Pan 			disable_pgtable_l5();
844d5fdade9SAnup Patel 			memset(early_pg_dir, 0, PAGE_SIZE);
845011f09d1SQinglin Pan 			goto retry;
846011f09d1SQinglin Pan 		}
847e8a62cc2SAlexandre Ghiti 		disable_pgtable_l4();
848011f09d1SQinglin Pan 	}
849e8a62cc2SAlexandre Ghiti 
850e8a62cc2SAlexandre Ghiti 	memset(early_pg_dir, 0, PAGE_SIZE);
851011f09d1SQinglin Pan 	memset(early_p4d, 0, PAGE_SIZE);
852e8a62cc2SAlexandre Ghiti 	memset(early_pud, 0, PAGE_SIZE);
853e8a62cc2SAlexandre Ghiti 	memset(early_pmd, 0, PAGE_SIZE);
854e8a62cc2SAlexandre Ghiti }
855e8a62cc2SAlexandre Ghiti #endif
856e8a62cc2SAlexandre Ghiti 
857387181dcSAnup Patel /*
858387181dcSAnup Patel  * setup_vm() is called from head.S with MMU-off.
859387181dcSAnup Patel  *
860387181dcSAnup Patel  * Following requirements should be honoured for setup_vm() to work
861387181dcSAnup Patel  * correctly:
862387181dcSAnup Patel  * 1) It should use PC-relative addressing for accessing kernel symbols.
863387181dcSAnup Patel  *    To achieve this we always use GCC cmodel=medany.
864387181dcSAnup Patel  * 2) The compiler instrumentation for FTRACE will not work for setup_vm()
865387181dcSAnup Patel  *    so disable compiler instrumentation when FTRACE is enabled.
866387181dcSAnup Patel  *
867387181dcSAnup Patel  * Currently, the above requirements are honoured by using custom CFLAGS
868387181dcSAnup Patel  * for init.o in mm/Makefile.
869387181dcSAnup Patel  */
870387181dcSAnup Patel 
871387181dcSAnup Patel #ifndef __riscv_cmodel_medany
8726a527b67SPaul Walmsley #error "setup_vm() is called from head.S before relocate so it should not use absolute addressing."
873387181dcSAnup Patel #endif
874387181dcSAnup Patel 
87539b33072SAlexandre Ghiti #ifdef CONFIG_RELOCATABLE
87639b33072SAlexandre Ghiti extern unsigned long __rela_dyn_start, __rela_dyn_end;
87739b33072SAlexandre Ghiti 
relocate_kernel(void)87839b33072SAlexandre Ghiti static void __init relocate_kernel(void)
87939b33072SAlexandre Ghiti {
88039b33072SAlexandre Ghiti 	Elf64_Rela *rela = (Elf64_Rela *)&__rela_dyn_start;
88139b33072SAlexandre Ghiti 	/*
88239b33072SAlexandre Ghiti 	 * This holds the offset between the linked virtual address and the
88339b33072SAlexandre Ghiti 	 * relocated virtual address.
88439b33072SAlexandre Ghiti 	 */
88539b33072SAlexandre Ghiti 	uintptr_t reloc_offset = kernel_map.virt_addr - KERNEL_LINK_ADDR;
88639b33072SAlexandre Ghiti 	/*
88739b33072SAlexandre Ghiti 	 * This holds the offset between kernel linked virtual address and
88839b33072SAlexandre Ghiti 	 * physical address.
88939b33072SAlexandre Ghiti 	 */
89039b33072SAlexandre Ghiti 	uintptr_t va_kernel_link_pa_offset = KERNEL_LINK_ADDR - kernel_map.phys_addr;
89139b33072SAlexandre Ghiti 
89239b33072SAlexandre Ghiti 	for ( ; rela < (Elf64_Rela *)&__rela_dyn_end; rela++) {
89339b33072SAlexandre Ghiti 		Elf64_Addr addr = (rela->r_offset - va_kernel_link_pa_offset);
89439b33072SAlexandre Ghiti 		Elf64_Addr relocated_addr = rela->r_addend;
89539b33072SAlexandre Ghiti 
89639b33072SAlexandre Ghiti 		if (rela->r_info != R_RISCV_RELATIVE)
89739b33072SAlexandre Ghiti 			continue;
89839b33072SAlexandre Ghiti 
89939b33072SAlexandre Ghiti 		/*
90039b33072SAlexandre Ghiti 		 * Make sure to not relocate vdso symbols like rt_sigreturn
90139b33072SAlexandre Ghiti 		 * which are linked from the address 0 in vmlinux since
90239b33072SAlexandre Ghiti 		 * vdso symbol addresses are actually used as an offset from
90339b33072SAlexandre Ghiti 		 * mm->context.vdso in VDSO_OFFSET macro.
90439b33072SAlexandre Ghiti 		 */
90539b33072SAlexandre Ghiti 		if (relocated_addr >= KERNEL_LINK_ADDR)
90639b33072SAlexandre Ghiti 			relocated_addr += reloc_offset;
90739b33072SAlexandre Ghiti 
90839b33072SAlexandre Ghiti 		*(Elf64_Addr *)addr = relocated_addr;
90939b33072SAlexandre Ghiti 	}
91039b33072SAlexandre Ghiti }
91139b33072SAlexandre Ghiti #endif /* CONFIG_RELOCATABLE */
91239b33072SAlexandre Ghiti 
91344c92257SVitaly Wool #ifdef CONFIG_XIP_KERNEL
create_kernel_page_table(pgd_t * pgdir,__always_unused bool early)914526f83dfSAlexandre Ghiti static void __init create_kernel_page_table(pgd_t *pgdir,
915e5c35fa0SAlexandre Ghiti 					    __always_unused bool early)
91644c92257SVitaly Wool {
91744c92257SVitaly Wool 	uintptr_t va, end_va;
91844c92257SVitaly Wool 
91944c92257SVitaly Wool 	/* Map the flash resident part */
920658e2c51SAlexandre Ghiti 	end_va = kernel_map.virt_addr + kernel_map.xiprom_sz;
921526f83dfSAlexandre Ghiti 	for (va = kernel_map.virt_addr; va < end_va; va += PMD_SIZE)
92244c92257SVitaly Wool 		create_pgd_mapping(pgdir, va,
923658e2c51SAlexandre Ghiti 				   kernel_map.xiprom + (va - kernel_map.virt_addr),
924526f83dfSAlexandre Ghiti 				   PMD_SIZE, PAGE_KERNEL_EXEC);
92544c92257SVitaly Wool 
92644c92257SVitaly Wool 	/* Map the data in RAM */
92736ebafdaSNam Cao 	end_va = kernel_map.virt_addr + kernel_map.size;
928526f83dfSAlexandre Ghiti 	for (va = kernel_map.virt_addr + XIP_OFFSET; va < end_va; va += PMD_SIZE)
92944c92257SVitaly Wool 		create_pgd_mapping(pgdir, va,
930658e2c51SAlexandre Ghiti 				   kernel_map.phys_addr + (va - (kernel_map.virt_addr + XIP_OFFSET)),
931526f83dfSAlexandre Ghiti 				   PMD_SIZE, PAGE_KERNEL);
93244c92257SVitaly Wool }
93344c92257SVitaly Wool #else
create_kernel_page_table(pgd_t * pgdir,bool early)934526f83dfSAlexandre Ghiti static void __init create_kernel_page_table(pgd_t *pgdir, bool early)
9352bfc6cd8SAlexandre Ghiti {
9362bfc6cd8SAlexandre Ghiti 	uintptr_t va, end_va;
9372bfc6cd8SAlexandre Ghiti 
938658e2c51SAlexandre Ghiti 	end_va = kernel_map.virt_addr + kernel_map.size;
939526f83dfSAlexandre Ghiti 	for (va = kernel_map.virt_addr; va < end_va; va += PMD_SIZE)
9402bfc6cd8SAlexandre Ghiti 		create_pgd_mapping(pgdir, va,
941658e2c51SAlexandre Ghiti 				   kernel_map.phys_addr + (va - kernel_map.virt_addr),
942526f83dfSAlexandre Ghiti 				   PMD_SIZE,
943e5c35fa0SAlexandre Ghiti 				   early ?
944e5c35fa0SAlexandre Ghiti 					PAGE_KERNEL_EXEC : pgprot_from_va(va));
9452bfc6cd8SAlexandre Ghiti }
94644c92257SVitaly Wool #endif
9472bfc6cd8SAlexandre Ghiti 
948fe45ffa4SAlexandre Ghiti /*
949fe45ffa4SAlexandre Ghiti  * Setup a 4MB mapping that encompasses the device tree: for 64-bit kernel,
950fe45ffa4SAlexandre Ghiti  * this means 2 PMD entries whereas for 32-bit kernel, this is only 1 PGDIR
951fe45ffa4SAlexandre Ghiti  * entry.
952fe45ffa4SAlexandre Ghiti  */
create_fdt_early_page_table(uintptr_t fix_fdt_va,uintptr_t dtb_pa)953e4ef93edSSong Shuai static void __init create_fdt_early_page_table(uintptr_t fix_fdt_va,
954ef69d255SAlexandre Ghiti 					       uintptr_t dtb_pa)
955fe45ffa4SAlexandre Ghiti {
95633d418daSAlexandre Ghiti #ifndef CONFIG_BUILTIN_DTB
957fe45ffa4SAlexandre Ghiti 	uintptr_t pa = dtb_pa & ~(PMD_SIZE - 1);
958fe45ffa4SAlexandre Ghiti 
959ef69d255SAlexandre Ghiti 	/* Make sure the fdt fixmap address is always aligned on PMD size */
960ef69d255SAlexandre Ghiti 	BUILD_BUG_ON(FIX_FDT % (PMD_SIZE / PAGE_SIZE));
961fe45ffa4SAlexandre Ghiti 
962ef69d255SAlexandre Ghiti 	/* In 32-bit only, the fdt lies in its own PGD */
963ef69d255SAlexandre Ghiti 	if (!IS_ENABLED(CONFIG_64BIT)) {
964ef69d255SAlexandre Ghiti 		create_pgd_mapping(early_pg_dir, fix_fdt_va,
965ef69d255SAlexandre Ghiti 				   pa, MAX_FDT_SIZE, PAGE_KERNEL);
966ef69d255SAlexandre Ghiti 	} else {
967ef69d255SAlexandre Ghiti 		create_pmd_mapping(fixmap_pmd, fix_fdt_va,
968fe45ffa4SAlexandre Ghiti 				   pa, PMD_SIZE, PAGE_KERNEL);
969ef69d255SAlexandre Ghiti 		create_pmd_mapping(fixmap_pmd, fix_fdt_va + PMD_SIZE,
970fe45ffa4SAlexandre Ghiti 				   pa + PMD_SIZE, PMD_SIZE, PAGE_KERNEL);
971fe45ffa4SAlexandre Ghiti 	}
972fe45ffa4SAlexandre Ghiti 
973ef69d255SAlexandre Ghiti 	dtb_early_va = (void *)fix_fdt_va + (dtb_pa & (PMD_SIZE - 1));
974fe45ffa4SAlexandre Ghiti #else
975fe45ffa4SAlexandre Ghiti 	/*
976fe45ffa4SAlexandre Ghiti 	 * For 64-bit kernel, __va can't be used since it would return a linear
977fe45ffa4SAlexandre Ghiti 	 * mapping address whereas dtb_early_va will be used before
978fe45ffa4SAlexandre Ghiti 	 * setup_vm_final installs the linear mapping. For 32-bit kernel, as the
979fe45ffa4SAlexandre Ghiti 	 * kernel is mapped in the linear mapping, that makes no difference.
980fe45ffa4SAlexandre Ghiti 	 */
981e792a03dSFrederik Haxel 	dtb_early_va = kernel_mapping_pa_to_va(dtb_pa);
982fe45ffa4SAlexandre Ghiti #endif
983fe45ffa4SAlexandre Ghiti 
984fe45ffa4SAlexandre Ghiti 	dtb_early_pa = dtb_pa;
985fe45ffa4SAlexandre Ghiti }
986fe45ffa4SAlexandre Ghiti 
987840125a9SAlexandre Ghiti /*
988840125a9SAlexandre Ghiti  * MMU is not enabled, the page tables are allocated directly using
989840125a9SAlexandre Ghiti  * early_pmd/pud/p4d and the address returned is the physical one.
990840125a9SAlexandre Ghiti  */
pt_ops_set_early(void)9919c375cfcSJisheng Zhang static void __init pt_ops_set_early(void)
992840125a9SAlexandre Ghiti {
993840125a9SAlexandre Ghiti 	pt_ops.alloc_pte = alloc_pte_early;
994840125a9SAlexandre Ghiti 	pt_ops.get_pte_virt = get_pte_virt_early;
995840125a9SAlexandre Ghiti #ifndef __PAGETABLE_PMD_FOLDED
996840125a9SAlexandre Ghiti 	pt_ops.alloc_pmd = alloc_pmd_early;
997840125a9SAlexandre Ghiti 	pt_ops.get_pmd_virt = get_pmd_virt_early;
998e8a62cc2SAlexandre Ghiti 	pt_ops.alloc_pud = alloc_pud_early;
999e8a62cc2SAlexandre Ghiti 	pt_ops.get_pud_virt = get_pud_virt_early;
1000677b9eb8SQinglin Pan 	pt_ops.alloc_p4d = alloc_p4d_early;
1001677b9eb8SQinglin Pan 	pt_ops.get_p4d_virt = get_p4d_virt_early;
1002840125a9SAlexandre Ghiti #endif
1003840125a9SAlexandre Ghiti }
1004840125a9SAlexandre Ghiti 
1005840125a9SAlexandre Ghiti /*
1006840125a9SAlexandre Ghiti  * MMU is enabled but page table setup is not complete yet.
1007840125a9SAlexandre Ghiti  * fixmap page table alloc functions must be used as a means to temporarily
1008840125a9SAlexandre Ghiti  * map the allocated physical pages since the linear mapping does not exist yet.
1009840125a9SAlexandre Ghiti  *
1010840125a9SAlexandre Ghiti  * Note that this is called with MMU disabled, hence kernel_mapping_pa_to_va,
1011840125a9SAlexandre Ghiti  * but it will be used as described above.
1012840125a9SAlexandre Ghiti  */
pt_ops_set_fixmap(void)10139c375cfcSJisheng Zhang static void __init pt_ops_set_fixmap(void)
1014840125a9SAlexandre Ghiti {
1015583286e2SSamuel Holland 	pt_ops.alloc_pte = kernel_mapping_pa_to_va(alloc_pte_fixmap);
1016583286e2SSamuel Holland 	pt_ops.get_pte_virt = kernel_mapping_pa_to_va(get_pte_virt_fixmap);
1017840125a9SAlexandre Ghiti #ifndef __PAGETABLE_PMD_FOLDED
1018583286e2SSamuel Holland 	pt_ops.alloc_pmd = kernel_mapping_pa_to_va(alloc_pmd_fixmap);
1019583286e2SSamuel Holland 	pt_ops.get_pmd_virt = kernel_mapping_pa_to_va(get_pmd_virt_fixmap);
1020583286e2SSamuel Holland 	pt_ops.alloc_pud = kernel_mapping_pa_to_va(alloc_pud_fixmap);
1021583286e2SSamuel Holland 	pt_ops.get_pud_virt = kernel_mapping_pa_to_va(get_pud_virt_fixmap);
1022583286e2SSamuel Holland 	pt_ops.alloc_p4d = kernel_mapping_pa_to_va(alloc_p4d_fixmap);
1023583286e2SSamuel Holland 	pt_ops.get_p4d_virt = kernel_mapping_pa_to_va(get_p4d_virt_fixmap);
1024840125a9SAlexandre Ghiti #endif
1025840125a9SAlexandre Ghiti }
1026840125a9SAlexandre Ghiti 
1027840125a9SAlexandre Ghiti /*
1028840125a9SAlexandre Ghiti  * MMU is enabled and page table setup is complete, so from now, we can use
1029840125a9SAlexandre Ghiti  * generic page allocation functions to setup page table.
1030840125a9SAlexandre Ghiti  */
pt_ops_set_late(void)10319c375cfcSJisheng Zhang static void __init pt_ops_set_late(void)
1032840125a9SAlexandre Ghiti {
1033840125a9SAlexandre Ghiti 	pt_ops.alloc_pte = alloc_pte_late;
1034840125a9SAlexandre Ghiti 	pt_ops.get_pte_virt = get_pte_virt_late;
1035840125a9SAlexandre Ghiti #ifndef __PAGETABLE_PMD_FOLDED
1036840125a9SAlexandre Ghiti 	pt_ops.alloc_pmd = alloc_pmd_late;
1037840125a9SAlexandre Ghiti 	pt_ops.get_pmd_virt = get_pmd_virt_late;
1038e8a62cc2SAlexandre Ghiti 	pt_ops.alloc_pud = alloc_pud_late;
1039e8a62cc2SAlexandre Ghiti 	pt_ops.get_pud_virt = get_pud_virt_late;
1040677b9eb8SQinglin Pan 	pt_ops.alloc_p4d = alloc_p4d_late;
1041677b9eb8SQinglin Pan 	pt_ops.get_p4d_virt = get_p4d_virt_late;
1042840125a9SAlexandre Ghiti #endif
1043840125a9SAlexandre Ghiti }
1044840125a9SAlexandre Ghiti 
104584fe419dSAlexandre Ghiti #ifdef CONFIG_RANDOMIZE_BASE
104684fe419dSAlexandre Ghiti extern bool __init __pi_set_nokaslr_from_cmdline(uintptr_t dtb_pa);
104784fe419dSAlexandre Ghiti extern u64 __init __pi_get_kaslr_seed(uintptr_t dtb_pa);
104884fe419dSAlexandre Ghiti 
print_nokaslr(char * p)104984fe419dSAlexandre Ghiti static int __init print_nokaslr(char *p)
105084fe419dSAlexandre Ghiti {
105184fe419dSAlexandre Ghiti 	pr_info("Disabled KASLR");
105284fe419dSAlexandre Ghiti 	return 0;
105384fe419dSAlexandre Ghiti }
105484fe419dSAlexandre Ghiti early_param("nokaslr", print_nokaslr);
105584fe419dSAlexandre Ghiti 
kaslr_offset(void)105684fe419dSAlexandre Ghiti unsigned long kaslr_offset(void)
105784fe419dSAlexandre Ghiti {
105884fe419dSAlexandre Ghiti 	return kernel_map.virt_offset;
105984fe419dSAlexandre Ghiti }
106084fe419dSAlexandre Ghiti #endif
106184fe419dSAlexandre Ghiti 
setup_vm(uintptr_t dtb_pa)1062671f9a3eSAnup Patel asmlinkage void __init setup_vm(uintptr_t dtb_pa)
10636f1e9e94SAnup Patel {
10646f3e5fd2SAlexandre Ghiti 	pmd_t __maybe_unused fix_bmap_spmd, fix_bmap_epmd;
10656f1e9e94SAnup Patel 
106684fe419dSAlexandre Ghiti #ifdef CONFIG_RANDOMIZE_BASE
106784fe419dSAlexandre Ghiti 	if (!__pi_set_nokaslr_from_cmdline(dtb_pa)) {
106884fe419dSAlexandre Ghiti 		u64 kaslr_seed = __pi_get_kaslr_seed(dtb_pa);
106984fe419dSAlexandre Ghiti 		u32 kernel_size = (uintptr_t)(&_end) - (uintptr_t)(&_start);
107084fe419dSAlexandre Ghiti 		u32 nr_pos;
107184fe419dSAlexandre Ghiti 
107284fe419dSAlexandre Ghiti 		/*
107384fe419dSAlexandre Ghiti 		 * Compute the number of positions available: we are limited
107484fe419dSAlexandre Ghiti 		 * by the early page table that only has one PUD and we must
107584fe419dSAlexandre Ghiti 		 * be aligned on PMD_SIZE.
107684fe419dSAlexandre Ghiti 		 */
107784fe419dSAlexandre Ghiti 		nr_pos = (PUD_SIZE - kernel_size) / PMD_SIZE;
107884fe419dSAlexandre Ghiti 
107984fe419dSAlexandre Ghiti 		kernel_map.virt_offset = (kaslr_seed % nr_pos) * PMD_SIZE;
108084fe419dSAlexandre Ghiti 	}
108184fe419dSAlexandre Ghiti #endif
108284fe419dSAlexandre Ghiti 
108384fe419dSAlexandre Ghiti 	kernel_map.virt_addr = KERNEL_LINK_ADDR + kernel_map.virt_offset;
1084658e2c51SAlexandre Ghiti 
108544c92257SVitaly Wool #ifdef CONFIG_XIP_KERNEL
1086b73ffafaSAlexandre Ghiti #ifdef CONFIG_64BIT
1087e792a03dSFrederik Haxel 	kernel_map.page_offset = PAGE_OFFSET_L3;
1088b73ffafaSAlexandre Ghiti #else
1089b73ffafaSAlexandre Ghiti 	kernel_map.page_offset = _AC(CONFIG_PAGE_OFFSET, UL);
1090b73ffafaSAlexandre Ghiti #endif
1091658e2c51SAlexandre Ghiti 	kernel_map.xiprom = (uintptr_t)CONFIG_XIP_PHYS_ADDR;
1092658e2c51SAlexandre Ghiti 	kernel_map.xiprom_sz = (uintptr_t)(&_exiprom) - (uintptr_t)(&_xiprom);
109344c92257SVitaly Wool 
10946d7f91d9SAlexandre Ghiti 	phys_ram_base = CONFIG_PHYS_RAM_BASE;
1095*a4a7ac3dSXu Lu #ifdef CONFIG_SPARSEMEM_VMEMMAP
1096*a4a7ac3dSXu Lu 	vmemmap_start_pfn = round_down(phys_ram_base, VMEMMAP_ADDR_ALIGN) >> PAGE_SHIFT;
1097*a4a7ac3dSXu Lu #endif
1098658e2c51SAlexandre Ghiti 	kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE;
109936ebafdaSNam Cao 	kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_start);
110044c92257SVitaly Wool 
1101658e2c51SAlexandre Ghiti 	kernel_map.va_kernel_xip_pa_offset = kernel_map.virt_addr - kernel_map.xiprom;
110244c92257SVitaly Wool #else
1103e792a03dSFrederik Haxel 	kernel_map.page_offset = _AC(CONFIG_PAGE_OFFSET, UL);
1104658e2c51SAlexandre Ghiti 	kernel_map.phys_addr = (uintptr_t)(&_start);
1105658e2c51SAlexandre Ghiti 	kernel_map.size = (uintptr_t)(&_end) - kernel_map.phys_addr;
110644c92257SVitaly Wool #endif
1107e8a62cc2SAlexandre Ghiti 
1108e8a62cc2SAlexandre Ghiti #if defined(CONFIG_64BIT) && !defined(CONFIG_XIP_KERNEL)
110926e7aacbSAlexandre Ghiti 	set_satp_mode(dtb_pa);
1110e8a62cc2SAlexandre Ghiti #endif
1111e8a62cc2SAlexandre Ghiti 
11123335068fSAlexandre Ghiti 	/*
11133335068fSAlexandre Ghiti 	 * In 64-bit, we defer the setup of va_pa_offset to setup_bootmem,
11143335068fSAlexandre Ghiti 	 * where we have the system memory layout: this allows us to align
11153335068fSAlexandre Ghiti 	 * the physical and virtual mappings and then make use of PUD/P4D/PGD
11163335068fSAlexandre Ghiti 	 * for the linear mapping. This is only possible because the kernel
11173335068fSAlexandre Ghiti 	 * mapping lies outside the linear mapping.
11183335068fSAlexandre Ghiti 	 * In 32-bit however, as the kernel resides in the linear mapping,
11193335068fSAlexandre Ghiti 	 * setup_vm_final can not change the mapping established here,
11203335068fSAlexandre Ghiti 	 * otherwise the same kernel addresses would get mapped to different
11213335068fSAlexandre Ghiti 	 * physical addresses (if the start of dram is different from the
11223335068fSAlexandre Ghiti 	 * kernel physical address start).
11233335068fSAlexandre Ghiti 	 */
11243335068fSAlexandre Ghiti 	kernel_map.va_pa_offset = IS_ENABLED(CONFIG_64BIT) ?
11253335068fSAlexandre Ghiti 				0UL : PAGE_OFFSET - kernel_map.phys_addr;
1126658e2c51SAlexandre Ghiti 	kernel_map.va_kernel_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr;
11272bfc6cd8SAlexandre Ghiti 
1128f7ae0233SAlexandre Ghiti 	/*
1129f7ae0233SAlexandre Ghiti 	 * The default maximal physical memory size is KERN_VIRT_SIZE for 32-bit
1130f7ae0233SAlexandre Ghiti 	 * kernel, whereas for 64-bit kernel, the end of the virtual address
1131f7ae0233SAlexandre Ghiti 	 * space is occupied by the modules/BPF/kernel mappings which reduces
1132f7ae0233SAlexandre Ghiti 	 * the available size of the linear mapping.
1133f7ae0233SAlexandre Ghiti 	 */
1134f7ae0233SAlexandre Ghiti 	memory_limit = KERN_VIRT_SIZE - (IS_ENABLED(CONFIG_64BIT) ? SZ_4G : 0);
1135f7ae0233SAlexandre Ghiti 
11366f1e9e94SAnup Patel 	/* Sanity check alignment and size */
11376f1e9e94SAnup Patel 	BUG_ON((PAGE_OFFSET % PGDIR_SIZE) != 0);
1138526f83dfSAlexandre Ghiti 	BUG_ON((kernel_map.phys_addr % PMD_SIZE) != 0);
1139671f9a3eSAnup Patel 
1140db6b84a3SAlexandre Ghiti #ifdef CONFIG_64BIT
1141db6b84a3SAlexandre Ghiti 	/*
1142db6b84a3SAlexandre Ghiti 	 * The last 4K bytes of the addressable memory can not be mapped because
1143db6b84a3SAlexandre Ghiti 	 * of IS_ERR_VALUE macro.
1144db6b84a3SAlexandre Ghiti 	 */
1145db6b84a3SAlexandre Ghiti 	BUG_ON((kernel_map.virt_addr + kernel_map.size) > ADDRESS_SPACE_END - SZ_4K);
1146e8dcb61fSAtish Patra #endif
1147671f9a3eSAnup Patel 
114839b33072SAlexandre Ghiti #ifdef CONFIG_RELOCATABLE
114939b33072SAlexandre Ghiti 	/*
115039b33072SAlexandre Ghiti 	 * Early page table uses only one PUD, which makes it possible
115139b33072SAlexandre Ghiti 	 * to map PUD_SIZE aligned on PUD_SIZE: if the relocation offset
115239b33072SAlexandre Ghiti 	 * makes the kernel cross over a PUD_SIZE boundary, raise a bug
115339b33072SAlexandre Ghiti 	 * since a part of the kernel would not get mapped.
115439b33072SAlexandre Ghiti 	 */
115539b33072SAlexandre Ghiti 	BUG_ON(PUD_SIZE - (kernel_map.virt_addr & (PUD_SIZE - 1)) < kernel_map.size);
115639b33072SAlexandre Ghiti 	relocate_kernel();
115739b33072SAlexandre Ghiti #endif
115839b33072SAlexandre Ghiti 
1159a35707c3SHeiko Stuebner 	apply_early_boot_alternatives();
1160840125a9SAlexandre Ghiti 	pt_ops_set_early();
1161840125a9SAlexandre Ghiti 
11626f1e9e94SAnup Patel 	/* Setup early PGD for fixmap */
11636f1e9e94SAnup Patel 	create_pgd_mapping(early_pg_dir, FIXADDR_START,
1164e8a62cc2SAlexandre Ghiti 			   fixmap_pgd_next, PGDIR_SIZE, PAGE_TABLE);
11656f1e9e94SAnup Patel 
11666f1e9e94SAnup Patel #ifndef __PAGETABLE_PMD_FOLDED
1167677b9eb8SQinglin Pan 	/* Setup fixmap P4D and PUD */
1168677b9eb8SQinglin Pan 	if (pgtable_l5_enabled)
1169677b9eb8SQinglin Pan 		create_p4d_mapping(fixmap_p4d, FIXADDR_START,
1170677b9eb8SQinglin Pan 				   (uintptr_t)fixmap_pud, P4D_SIZE, PAGE_TABLE);
1171e8a62cc2SAlexandre Ghiti 	/* Setup fixmap PUD and PMD */
1172e8a62cc2SAlexandre Ghiti 	if (pgtable_l4_enabled)
1173e8a62cc2SAlexandre Ghiti 		create_pud_mapping(fixmap_pud, FIXADDR_START,
1174e8a62cc2SAlexandre Ghiti 				   (uintptr_t)fixmap_pmd, PUD_SIZE, PAGE_TABLE);
1175671f9a3eSAnup Patel 	create_pmd_mapping(fixmap_pmd, FIXADDR_START,
1176671f9a3eSAnup Patel 			   (uintptr_t)fixmap_pte, PMD_SIZE, PAGE_TABLE);
1177671f9a3eSAnup Patel 	/* Setup trampoline PGD and PMD */
1178658e2c51SAlexandre Ghiti 	create_pgd_mapping(trampoline_pg_dir, kernel_map.virt_addr,
1179e8a62cc2SAlexandre Ghiti 			   trampoline_pgd_next, PGDIR_SIZE, PAGE_TABLE);
1180677b9eb8SQinglin Pan 	if (pgtable_l5_enabled)
1181677b9eb8SQinglin Pan 		create_p4d_mapping(trampoline_p4d, kernel_map.virt_addr,
1182677b9eb8SQinglin Pan 				   (uintptr_t)trampoline_pud, P4D_SIZE, PAGE_TABLE);
1183e8a62cc2SAlexandre Ghiti 	if (pgtable_l4_enabled)
1184e8a62cc2SAlexandre Ghiti 		create_pud_mapping(trampoline_pud, kernel_map.virt_addr,
1185e8a62cc2SAlexandre Ghiti 				   (uintptr_t)trampoline_pmd, PUD_SIZE, PAGE_TABLE);
118644c92257SVitaly Wool #ifdef CONFIG_XIP_KERNEL
1187658e2c51SAlexandre Ghiti 	create_pmd_mapping(trampoline_pmd, kernel_map.virt_addr,
1188658e2c51SAlexandre Ghiti 			   kernel_map.xiprom, PMD_SIZE, PAGE_KERNEL_EXEC);
118944c92257SVitaly Wool #else
1190658e2c51SAlexandre Ghiti 	create_pmd_mapping(trampoline_pmd, kernel_map.virt_addr,
1191658e2c51SAlexandre Ghiti 			   kernel_map.phys_addr, PMD_SIZE, PAGE_KERNEL_EXEC);
119244c92257SVitaly Wool #endif
11936f1e9e94SAnup Patel #else
1194671f9a3eSAnup Patel 	/* Setup trampoline PGD */
1195658e2c51SAlexandre Ghiti 	create_pgd_mapping(trampoline_pg_dir, kernel_map.virt_addr,
1196658e2c51SAlexandre Ghiti 			   kernel_map.phys_addr, PGDIR_SIZE, PAGE_KERNEL_EXEC);
1197671f9a3eSAnup Patel #endif
11986f1e9e94SAnup Patel 
1199671f9a3eSAnup Patel 	/*
12002bfc6cd8SAlexandre Ghiti 	 * Setup early PGD covering entire kernel which will allow
1201671f9a3eSAnup Patel 	 * us to reach paging_init(). We map all memory banks later
1202671f9a3eSAnup Patel 	 * in setup_vm_final() below.
1203671f9a3eSAnup Patel 	 */
1204526f83dfSAlexandre Ghiti 	create_kernel_page_table(early_pg_dir, true);
1205f2c17aabSAnup Patel 
1206fe45ffa4SAlexandre Ghiti 	/* Setup early mapping for FDT early scan */
1207e4ef93edSSong Shuai 	create_fdt_early_page_table(__fix_to_virt(FIX_FDT), dtb_pa);
12086262f661SAtish Patra 
12096262f661SAtish Patra 	/*
12106262f661SAtish Patra 	 * Bootime fixmap only can handle PMD_SIZE mapping. Thus, boot-ioremap
12116262f661SAtish Patra 	 * range can not span multiple pmds.
12126262f661SAtish Patra 	 */
1213e8a62cc2SAlexandre Ghiti 	BUG_ON((__fix_to_virt(FIX_BTMAP_BEGIN) >> PMD_SHIFT)
12146262f661SAtish Patra 		     != (__fix_to_virt(FIX_BTMAP_END) >> PMD_SHIFT));
12156262f661SAtish Patra 
12166262f661SAtish Patra #ifndef __PAGETABLE_PMD_FOLDED
12176262f661SAtish Patra 	/*
12186262f661SAtish Patra 	 * Early ioremap fixmap is already created as it lies within first 2MB
12196262f661SAtish Patra 	 * of fixmap region. We always map PMD_SIZE. Thus, both FIX_BTMAP_END
12206262f661SAtish Patra 	 * FIX_BTMAP_BEGIN should lie in the same pmd. Verify that and warn
12216262f661SAtish Patra 	 * the user if not.
12226262f661SAtish Patra 	 */
12236262f661SAtish Patra 	fix_bmap_spmd = fixmap_pmd[pmd_index(__fix_to_virt(FIX_BTMAP_BEGIN))];
12246262f661SAtish Patra 	fix_bmap_epmd = fixmap_pmd[pmd_index(__fix_to_virt(FIX_BTMAP_END))];
12256262f661SAtish Patra 	if (pmd_val(fix_bmap_spmd) != pmd_val(fix_bmap_epmd)) {
12266262f661SAtish Patra 		WARN_ON(1);
12276262f661SAtish Patra 		pr_warn("fixmap btmap start [%08lx] != end [%08lx]\n",
12286262f661SAtish Patra 			pmd_val(fix_bmap_spmd), pmd_val(fix_bmap_epmd));
12296262f661SAtish Patra 		pr_warn("fix_to_virt(FIX_BTMAP_BEGIN): %08lx\n",
12306262f661SAtish Patra 			fix_to_virt(FIX_BTMAP_BEGIN));
12316262f661SAtish Patra 		pr_warn("fix_to_virt(FIX_BTMAP_END):   %08lx\n",
12326262f661SAtish Patra 			fix_to_virt(FIX_BTMAP_END));
12336262f661SAtish Patra 
12346262f661SAtish Patra 		pr_warn("FIX_BTMAP_END:       %d\n", FIX_BTMAP_END);
12356262f661SAtish Patra 		pr_warn("FIX_BTMAP_BEGIN:     %d\n", FIX_BTMAP_BEGIN);
12366262f661SAtish Patra 	}
12376262f661SAtish Patra #endif
1238840125a9SAlexandre Ghiti 
1239840125a9SAlexandre Ghiti 	pt_ops_set_fixmap();
12406f1e9e94SAnup Patel }
1241f2c17aabSAnup Patel 
create_linear_mapping_range(phys_addr_t start,phys_addr_t end,uintptr_t fixed_map_size)12428589e346SAlexandre Ghiti static void __init create_linear_mapping_range(phys_addr_t start,
124325abe0dbSAlexandre Ghiti 					       phys_addr_t end,
124425abe0dbSAlexandre Ghiti 					       uintptr_t fixed_map_size)
1245671f9a3eSAnup Patel {
12468589e346SAlexandre Ghiti 	phys_addr_t pa;
1247671f9a3eSAnup Patel 	uintptr_t va, map_size;
1248671f9a3eSAnup Patel 
12498589e346SAlexandre Ghiti 	for (pa = start; pa < end; pa += map_size) {
12508589e346SAlexandre Ghiti 		va = (uintptr_t)__va(pa);
125125abe0dbSAlexandre Ghiti 		map_size = fixed_map_size ? fixed_map_size :
125249a0a373SAlexandre Ghiti 					    best_map_size(pa, va, end - pa);
12538589e346SAlexandre Ghiti 
12548589e346SAlexandre Ghiti 		create_pgd_mapping(swapper_pg_dir, va, pa, map_size,
12558589e346SAlexandre Ghiti 				   pgprot_from_va(va));
12568589e346SAlexandre Ghiti 	}
12578589e346SAlexandre Ghiti }
12588589e346SAlexandre Ghiti 
create_linear_mapping_page_table(void)12598589e346SAlexandre Ghiti static void __init create_linear_mapping_page_table(void)
12608589e346SAlexandre Ghiti {
12618589e346SAlexandre Ghiti 	phys_addr_t start, end;
126225abe0dbSAlexandre Ghiti 	phys_addr_t kfence_pool __maybe_unused;
1263671f9a3eSAnup Patel 	u64 i;
1264671f9a3eSAnup Patel 
12653335068fSAlexandre Ghiti #ifdef CONFIG_STRICT_KERNEL_RWX
12663335068fSAlexandre Ghiti 	phys_addr_t ktext_start = __pa_symbol(_start);
12673335068fSAlexandre Ghiti 	phys_addr_t ktext_size = __init_data_begin - _start;
12683335068fSAlexandre Ghiti 	phys_addr_t krodata_start = __pa_symbol(__start_rodata);
12693335068fSAlexandre Ghiti 	phys_addr_t krodata_size = _data - __start_rodata;
12703335068fSAlexandre Ghiti 
12713335068fSAlexandre Ghiti 	/* Isolate kernel text and rodata so they don't get mapped with a PUD */
12723335068fSAlexandre Ghiti 	memblock_mark_nomap(ktext_start,  ktext_size);
12733335068fSAlexandre Ghiti 	memblock_mark_nomap(krodata_start, krodata_size);
12743335068fSAlexandre Ghiti #endif
12753335068fSAlexandre Ghiti 
127625abe0dbSAlexandre Ghiti #ifdef CONFIG_KFENCE
127725abe0dbSAlexandre Ghiti 	/*
127825abe0dbSAlexandre Ghiti 	 *  kfence pool must be backed by PAGE_SIZE mappings, so allocate it
127925abe0dbSAlexandre Ghiti 	 *  before we setup the linear mapping so that we avoid using hugepages
128025abe0dbSAlexandre Ghiti 	 *  for this region.
128125abe0dbSAlexandre Ghiti 	 */
128225abe0dbSAlexandre Ghiti 	kfence_pool = memblock_phys_alloc(KFENCE_POOL_SIZE, PAGE_SIZE);
128325abe0dbSAlexandre Ghiti 	BUG_ON(!kfence_pool);
128425abe0dbSAlexandre Ghiti 
128525abe0dbSAlexandre Ghiti 	memblock_mark_nomap(kfence_pool, KFENCE_POOL_SIZE);
128625abe0dbSAlexandre Ghiti 	__kfence_pool = __va(kfence_pool);
128725abe0dbSAlexandre Ghiti #endif
128825abe0dbSAlexandre Ghiti 
12892bfc6cd8SAlexandre Ghiti 	/* Map all memory banks in the linear mapping */
1290b10d6bcaSMike Rapoport 	for_each_mem_range(i, &start, &end) {
1291671f9a3eSAnup Patel 		if (start >= end)
1292671f9a3eSAnup Patel 			break;
1293671f9a3eSAnup Patel 		if (start <= __pa(PAGE_OFFSET) &&
1294671f9a3eSAnup Patel 		    __pa(PAGE_OFFSET) < end)
1295671f9a3eSAnup Patel 			start = __pa(PAGE_OFFSET);
1296671f9a3eSAnup Patel 
129725abe0dbSAlexandre Ghiti 		create_linear_mapping_range(start, end, 0);
12988589e346SAlexandre Ghiti 	}
12993335068fSAlexandre Ghiti 
13003335068fSAlexandre Ghiti #ifdef CONFIG_STRICT_KERNEL_RWX
130125abe0dbSAlexandre Ghiti 	create_linear_mapping_range(ktext_start, ktext_start + ktext_size, 0);
13023335068fSAlexandre Ghiti 	create_linear_mapping_range(krodata_start,
130325abe0dbSAlexandre Ghiti 				    krodata_start + krodata_size, 0);
13043335068fSAlexandre Ghiti 
13053335068fSAlexandre Ghiti 	memblock_clear_nomap(ktext_start,  ktext_size);
13063335068fSAlexandre Ghiti 	memblock_clear_nomap(krodata_start, krodata_size);
13073335068fSAlexandre Ghiti #endif
130825abe0dbSAlexandre Ghiti 
130925abe0dbSAlexandre Ghiti #ifdef CONFIG_KFENCE
131025abe0dbSAlexandre Ghiti 	create_linear_mapping_range(kfence_pool,
131125abe0dbSAlexandre Ghiti 				    kfence_pool + KFENCE_POOL_SIZE,
131225abe0dbSAlexandre Ghiti 				    PAGE_SIZE);
131325abe0dbSAlexandre Ghiti 
131425abe0dbSAlexandre Ghiti 	memblock_clear_nomap(kfence_pool, KFENCE_POOL_SIZE);
131525abe0dbSAlexandre Ghiti #endif
13168589e346SAlexandre Ghiti }
13172bfc6cd8SAlexandre Ghiti 
setup_vm_final(void)13188589e346SAlexandre Ghiti static void __init setup_vm_final(void)
13198589e346SAlexandre Ghiti {
1320671f9a3eSAnup Patel 	/* Setup swapper PGD for fixmap */
1321ef69d255SAlexandre Ghiti #if !defined(CONFIG_64BIT)
1322ef69d255SAlexandre Ghiti 	/*
1323ef69d255SAlexandre Ghiti 	 * In 32-bit, the device tree lies in a pgd entry, so it must be copied
1324ef69d255SAlexandre Ghiti 	 * directly in swapper_pg_dir in addition to the pgd entry that points
1325ef69d255SAlexandre Ghiti 	 * to fixmap_pte.
1326ef69d255SAlexandre Ghiti 	 */
1327ef69d255SAlexandre Ghiti 	unsigned long idx = pgd_index(__fix_to_virt(FIX_FDT));
1328ef69d255SAlexandre Ghiti 
1329ef69d255SAlexandre Ghiti 	set_pgd(&swapper_pg_dir[idx], early_pg_dir[idx]);
1330ef69d255SAlexandre Ghiti #endif
1331671f9a3eSAnup Patel 	create_pgd_mapping(swapper_pg_dir, FIXADDR_START,
1332671f9a3eSAnup Patel 			   __pa_symbol(fixmap_pgd_next),
1333671f9a3eSAnup Patel 			   PGDIR_SIZE, PAGE_TABLE);
1334671f9a3eSAnup Patel 
13358589e346SAlexandre Ghiti 	/* Map the linear mapping */
13368589e346SAlexandre Ghiti 	create_linear_mapping_page_table();
1337671f9a3eSAnup Patel 
13382bfc6cd8SAlexandre Ghiti 	/* Map the kernel */
133907aabe8fSJisheng Zhang 	if (IS_ENABLED(CONFIG_64BIT))
1340526f83dfSAlexandre Ghiti 		create_kernel_page_table(swapper_pg_dir, false);
13412bfc6cd8SAlexandre Ghiti 
13422efad17eSAlexandre Ghiti #ifdef CONFIG_KASAN
13432efad17eSAlexandre Ghiti 	kasan_swapper_init();
13442efad17eSAlexandre Ghiti #endif
13452efad17eSAlexandre Ghiti 
1346671f9a3eSAnup Patel 	/* Clear fixmap PTE and PMD mappings */
1347671f9a3eSAnup Patel 	clear_fixmap(FIX_PTE);
1348671f9a3eSAnup Patel 	clear_fixmap(FIX_PMD);
1349e8a62cc2SAlexandre Ghiti 	clear_fixmap(FIX_PUD);
1350677b9eb8SQinglin Pan 	clear_fixmap(FIX_P4D);
1351671f9a3eSAnup Patel 
1352671f9a3eSAnup Patel 	/* Move to swapper page table */
1353e8a62cc2SAlexandre Ghiti 	csr_write(CSR_SATP, PFN_DOWN(__pa_symbol(swapper_pg_dir)) | satp_mode);
1354671f9a3eSAnup Patel 	local_flush_tlb_all();
1355e8dcb61fSAtish Patra 
1356840125a9SAlexandre Ghiti 	pt_ops_set_late();
1357671f9a3eSAnup Patel }
13586bd33e1eSChristoph Hellwig #else
setup_vm(uintptr_t dtb_pa)13596bd33e1eSChristoph Hellwig asmlinkage void __init setup_vm(uintptr_t dtb_pa)
13606bd33e1eSChristoph Hellwig {
13616bd33e1eSChristoph Hellwig 	dtb_early_va = (void *)dtb_pa;
1362a78c6f59SAtish Patra 	dtb_early_pa = dtb_pa;
13636bd33e1eSChristoph Hellwig }
13646bd33e1eSChristoph Hellwig 
setup_vm_final(void)13656bd33e1eSChristoph Hellwig static inline void setup_vm_final(void)
13666bd33e1eSChristoph Hellwig {
13676bd33e1eSChristoph Hellwig }
13686bd33e1eSChristoph Hellwig #endif /* CONFIG_MMU */
1369671f9a3eSAnup Patel 
13705882e5acSChen Jiahao /* Reserve 128M low memory by default for swiotlb buffer */
13715882e5acSChen Jiahao #define DEFAULT_CRASH_KERNEL_LOW_SIZE	(128UL << 20)
13725882e5acSChen Jiahao 
reserve_crashkernel_low(unsigned long long low_size)13735882e5acSChen Jiahao static int __init reserve_crashkernel_low(unsigned long long low_size)
13745882e5acSChen Jiahao {
13755882e5acSChen Jiahao 	unsigned long long low_base;
13765882e5acSChen Jiahao 
13775882e5acSChen Jiahao 	low_base = memblock_phys_alloc_range(low_size, PMD_SIZE, 0, dma32_phys_limit);
13785882e5acSChen Jiahao 	if (!low_base) {
13795882e5acSChen Jiahao 		pr_err("cannot allocate crashkernel low memory (size:0x%llx).\n", low_size);
13805882e5acSChen Jiahao 		return -ENOMEM;
13815882e5acSChen Jiahao 	}
13825882e5acSChen Jiahao 
13835882e5acSChen Jiahao 	pr_info("crashkernel low memory reserved: 0x%016llx - 0x%016llx (%lld MB)\n",
13845882e5acSChen Jiahao 		low_base, low_base + low_size, low_size >> 20);
13855882e5acSChen Jiahao 
13865882e5acSChen Jiahao 	crashk_low_res.start = low_base;
13875882e5acSChen Jiahao 	crashk_low_res.end = low_base + low_size - 1;
13885882e5acSChen Jiahao 
13895882e5acSChen Jiahao 	return 0;
13905882e5acSChen Jiahao }
13915882e5acSChen Jiahao 
1392e53d2818SNick Kossifidis /*
1393e53d2818SNick Kossifidis  * reserve_crashkernel() - reserves memory for crash kernel
1394e53d2818SNick Kossifidis  *
1395e53d2818SNick Kossifidis  * This function reserves memory area given in "crashkernel=" kernel command
1396e53d2818SNick Kossifidis  * line parameter. The memory reserved is used by dump capture kernel when
1397e53d2818SNick Kossifidis  * primary kernel is crashing.
1398e53d2818SNick Kossifidis  */
reserve_crashkernel(void)1399e53d2818SNick Kossifidis static void __init reserve_crashkernel(void)
1400e53d2818SNick Kossifidis {
1401e53d2818SNick Kossifidis 	unsigned long long crash_base = 0;
1402e53d2818SNick Kossifidis 	unsigned long long crash_size = 0;
14035882e5acSChen Jiahao 	unsigned long long crash_low_size = 0;
1404e53d2818SNick Kossifidis 	unsigned long search_start = memblock_start_of_DRAM();
14055882e5acSChen Jiahao 	unsigned long search_end = (unsigned long)dma32_phys_limit;
14065882e5acSChen Jiahao 	char *cmdline = boot_command_line;
14075882e5acSChen Jiahao 	bool fixed_base = false;
14085882e5acSChen Jiahao 	bool high = false;
1409e53d2818SNick Kossifidis 
1410e53d2818SNick Kossifidis 	int ret = 0;
1411e53d2818SNick Kossifidis 
1412d414cb37SJisheng Zhang 	if (!IS_ENABLED(CONFIG_KEXEC_CORE))
1413d414cb37SJisheng Zhang 		return;
141456409750SNick Kossifidis 	/*
141556409750SNick Kossifidis 	 * Don't reserve a region for a crash kernel on a crash kernel
141656409750SNick Kossifidis 	 * since it doesn't make much sense and we have limited memory
141756409750SNick Kossifidis 	 * resources.
141856409750SNick Kossifidis 	 */
141956409750SNick Kossifidis 	if (is_kdump_kernel()) {
142056409750SNick Kossifidis 		pr_info("crashkernel: ignoring reservation request\n");
142156409750SNick Kossifidis 		return;
142256409750SNick Kossifidis 	}
142356409750SNick Kossifidis 
14245882e5acSChen Jiahao 	ret = parse_crashkernel(cmdline, memblock_phys_mem_size(),
1425e53d2818SNick Kossifidis 				&crash_size, &crash_base);
14265882e5acSChen Jiahao 	if (ret == -ENOENT) {
14275882e5acSChen Jiahao 		/* Fallback to crashkernel=X,[high,low] */
14285882e5acSChen Jiahao 		ret = parse_crashkernel_high(cmdline, 0, &crash_size, &crash_base);
1429e53d2818SNick Kossifidis 		if (ret || !crash_size)
1430e53d2818SNick Kossifidis 			return;
1431e53d2818SNick Kossifidis 
14325882e5acSChen Jiahao 		/*
14335882e5acSChen Jiahao 		 * crashkernel=Y,low is valid only when crashkernel=X,high
14345882e5acSChen Jiahao 		 * is passed.
14355882e5acSChen Jiahao 		 */
14365882e5acSChen Jiahao 		ret = parse_crashkernel_low(cmdline, 0, &crash_low_size, &crash_base);
14375882e5acSChen Jiahao 		if (ret == -ENOENT)
14385882e5acSChen Jiahao 			crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
14395882e5acSChen Jiahao 		else if (ret)
14405882e5acSChen Jiahao 			return;
14415882e5acSChen Jiahao 
14425882e5acSChen Jiahao 		search_start = (unsigned long)dma32_phys_limit;
14435882e5acSChen Jiahao 		search_end = memblock_end_of_DRAM();
14445882e5acSChen Jiahao 		high = true;
14455882e5acSChen Jiahao 	} else if (ret || !crash_size) {
14465882e5acSChen Jiahao 		/* Invalid argument value specified */
14475882e5acSChen Jiahao 		return;
14485882e5acSChen Jiahao 	}
14495882e5acSChen Jiahao 
1450e53d2818SNick Kossifidis 	crash_size = PAGE_ALIGN(crash_size);
1451e53d2818SNick Kossifidis 
1452a7259df7SMike Rapoport 	if (crash_base) {
14535882e5acSChen Jiahao 		fixed_base = true;
1454a7259df7SMike Rapoport 		search_start = crash_base;
1455a7259df7SMike Rapoport 		search_end = crash_base + crash_size;
1456a7259df7SMike Rapoport 	}
1457a7259df7SMike Rapoport 
1458e53d2818SNick Kossifidis 	/*
1459e53d2818SNick Kossifidis 	 * Current riscv boot protocol requires 2MB alignment for
1460e53d2818SNick Kossifidis 	 * RV64 and 4MB alignment for RV32 (hugepage size)
1461decf89f8SNick Kossifidis 	 *
1462decf89f8SNick Kossifidis 	 * Try to alloc from 32bit addressible physical memory so that
1463decf89f8SNick Kossifidis 	 * swiotlb can work on the crash kernel.
1464e53d2818SNick Kossifidis 	 */
1465a7259df7SMike Rapoport 	crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE,
14665882e5acSChen Jiahao 					       search_start, search_end);
1467decf89f8SNick Kossifidis 	if (crash_base == 0) {
14685882e5acSChen Jiahao 		/*
14695882e5acSChen Jiahao 		 * For crashkernel=size[KMG]@offset[KMG], print out failure
14705882e5acSChen Jiahao 		 * message if can't reserve the specified region.
14715882e5acSChen Jiahao 		 */
14725882e5acSChen Jiahao 		if (fixed_base) {
14735882e5acSChen Jiahao 			pr_warn("crashkernel: allocating failed with given size@offset\n");
14745882e5acSChen Jiahao 			return;
14755882e5acSChen Jiahao 		}
14765882e5acSChen Jiahao 
14775882e5acSChen Jiahao 		if (high) {
14785882e5acSChen Jiahao 			/*
14795882e5acSChen Jiahao 			 * For crashkernel=size[KMG],high, if the first attempt was
14805882e5acSChen Jiahao 			 * for high memory, fall back to low memory.
14815882e5acSChen Jiahao 			 */
14825882e5acSChen Jiahao 			search_start = memblock_start_of_DRAM();
14835882e5acSChen Jiahao 			search_end = (unsigned long)dma32_phys_limit;
14845882e5acSChen Jiahao 		} else {
14855882e5acSChen Jiahao 			/*
14865882e5acSChen Jiahao 			 * For crashkernel=size[KMG], if the first attempt was for
14875882e5acSChen Jiahao 			 * low memory, fall back to high memory, the minimum required
14885882e5acSChen Jiahao 			 * low memory will be reserved later.
14895882e5acSChen Jiahao 			 */
14905882e5acSChen Jiahao 			search_start = (unsigned long)dma32_phys_limit;
14915882e5acSChen Jiahao 			search_end = memblock_end_of_DRAM();
14925882e5acSChen Jiahao 			crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
14935882e5acSChen Jiahao 		}
14945882e5acSChen Jiahao 
1495decf89f8SNick Kossifidis 		crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE,
1496a7259df7SMike Rapoport 						       search_start, search_end);
1497e53d2818SNick Kossifidis 		if (crash_base == 0) {
1498e53d2818SNick Kossifidis 			pr_warn("crashkernel: couldn't allocate %lldKB\n",
1499e53d2818SNick Kossifidis 				crash_size >> 10);
1500e53d2818SNick Kossifidis 			return;
1501e53d2818SNick Kossifidis 		}
1502decf89f8SNick Kossifidis 	}
1503e53d2818SNick Kossifidis 
15045882e5acSChen Jiahao 	if ((crash_base >= dma32_phys_limit) && crash_low_size &&
15055882e5acSChen Jiahao 	     reserve_crashkernel_low(crash_low_size)) {
15065882e5acSChen Jiahao 		memblock_phys_free(crash_base, crash_size);
15075882e5acSChen Jiahao 		return;
15085882e5acSChen Jiahao 	}
15095882e5acSChen Jiahao 
1510e53d2818SNick Kossifidis 	pr_info("crashkernel: reserved 0x%016llx - 0x%016llx (%lld MB)\n",
1511e53d2818SNick Kossifidis 		crash_base, crash_base + crash_size, crash_size >> 20);
1512e53d2818SNick Kossifidis 
1513e53d2818SNick Kossifidis 	crashk_res.start = crash_base;
1514e53d2818SNick Kossifidis 	crashk_res.end = crash_base + crash_size - 1;
1515e53d2818SNick Kossifidis }
1516e53d2818SNick Kossifidis 
paging_init(void)1517671f9a3eSAnup Patel void __init paging_init(void)
1518671f9a3eSAnup Patel {
1519f842f5ffSKefeng Wang 	setup_bootmem();
1520671f9a3eSAnup Patel 	setup_vm_final();
152185fadc0dSWoody Zhang 
152285fadc0dSWoody Zhang 	/* Depend on that Linear Mapping is ready */
152385fadc0dSWoody Zhang 	memblock_allow_resize();
1524cbd34f4bSAtish Patra }
1525cbd34f4bSAtish Patra 
misc_mem_init(void)1526cbd34f4bSAtish Patra void __init misc_mem_init(void)
1527cbd34f4bSAtish Patra {
1528f6e5aedfSKefeng Wang 	early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT);
15294f0e8eefSAtish Patra 	arch_numa_init();
1530cbd34f4bSAtish Patra 	sparse_init();
1531d3770844SVincent Chen #ifdef CONFIG_SPARSEMEM_VMEMMAP
1532d3770844SVincent Chen 	/* The entire VMEMMAP region has been populated. Flush TLB for this region */
1533d3770844SVincent Chen 	local_flush_tlb_kernel_range(VMEMMAP_START, VMEMMAP_END);
1534d3770844SVincent Chen #endif
1535671f9a3eSAnup Patel 	zone_sizes_init();
1536e53d2818SNick Kossifidis 	reserve_crashkernel();
15374f0e8eefSAtish Patra 	memblock_dump_all();
15386f1e9e94SAnup Patel }
1539d95f1a54SLogan Gunthorpe 
15409fe57d8cSKefeng Wang #ifdef CONFIG_SPARSEMEM_VMEMMAP
vmemmap_populate(unsigned long start,unsigned long end,int node,struct vmem_altmap * altmap)1541d95f1a54SLogan Gunthorpe int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
1542d95f1a54SLogan Gunthorpe 			       struct vmem_altmap *altmap)
1543d95f1a54SLogan Gunthorpe {
15441d9cfee7SAnshuman Khandual 	return vmemmap_populate_basepages(start, end, node, NULL);
1545d95f1a54SLogan Gunthorpe }
1546d95f1a54SLogan Gunthorpe #endif
15477d3332beSBjörn Töpel 
15487d3332beSBjörn Töpel #if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
15497d3332beSBjörn Töpel /*
15507d3332beSBjörn Töpel  * Pre-allocates page-table pages for a specific area in the kernel
15517d3332beSBjörn Töpel  * page-table. Only the level which needs to be synchronized between
15527d3332beSBjörn Töpel  * all page-tables is allocated because the synchronization can be
15537d3332beSBjörn Töpel  * expensive.
15547d3332beSBjörn Töpel  */
preallocate_pgd_pages_range(unsigned long start,unsigned long end,const char * area)15557d3332beSBjörn Töpel static void __init preallocate_pgd_pages_range(unsigned long start, unsigned long end,
15567d3332beSBjörn Töpel 					       const char *area)
15577d3332beSBjörn Töpel {
15587d3332beSBjörn Töpel 	unsigned long addr;
15597d3332beSBjörn Töpel 	const char *lvl;
15607d3332beSBjörn Töpel 
15617d3332beSBjörn Töpel 	for (addr = start; addr < end && addr >= start; addr = ALIGN(addr + 1, PGDIR_SIZE)) {
15627d3332beSBjörn Töpel 		pgd_t *pgd = pgd_offset_k(addr);
15637d3332beSBjörn Töpel 		p4d_t *p4d;
15647d3332beSBjörn Töpel 		pud_t *pud;
15657d3332beSBjörn Töpel 		pmd_t *pmd;
15667d3332beSBjörn Töpel 
15677d3332beSBjörn Töpel 		lvl = "p4d";
15687d3332beSBjörn Töpel 		p4d = p4d_alloc(&init_mm, pgd, addr);
15697d3332beSBjörn Töpel 		if (!p4d)
15707d3332beSBjörn Töpel 			goto failed;
15717d3332beSBjörn Töpel 
15727d3332beSBjörn Töpel 		if (pgtable_l5_enabled)
15737d3332beSBjörn Töpel 			continue;
15747d3332beSBjörn Töpel 
15757d3332beSBjörn Töpel 		lvl = "pud";
15767d3332beSBjörn Töpel 		pud = pud_alloc(&init_mm, p4d, addr);
15777d3332beSBjörn Töpel 		if (!pud)
15787d3332beSBjörn Töpel 			goto failed;
15797d3332beSBjörn Töpel 
15807d3332beSBjörn Töpel 		if (pgtable_l4_enabled)
15817d3332beSBjörn Töpel 			continue;
15827d3332beSBjörn Töpel 
15837d3332beSBjörn Töpel 		lvl = "pmd";
15847d3332beSBjörn Töpel 		pmd = pmd_alloc(&init_mm, pud, addr);
15857d3332beSBjörn Töpel 		if (!pmd)
15867d3332beSBjörn Töpel 			goto failed;
15877d3332beSBjörn Töpel 	}
15887d3332beSBjörn Töpel 	return;
15897d3332beSBjörn Töpel 
15907d3332beSBjörn Töpel failed:
15917d3332beSBjörn Töpel 	/*
15927d3332beSBjörn Töpel 	 * The pages have to be there now or they will be missing in
15937d3332beSBjörn Töpel 	 * process page-tables later.
15947d3332beSBjörn Töpel 	 */
15957d3332beSBjörn Töpel 	panic("Failed to pre-allocate %s pages for %s area\n", lvl, area);
15967d3332beSBjörn Töpel }
15977d3332beSBjörn Töpel 
pgtable_cache_init(void)15987d3332beSBjörn Töpel void __init pgtable_cache_init(void)
15997d3332beSBjörn Töpel {
16007d3332beSBjörn Töpel 	preallocate_pgd_pages_range(VMALLOC_START, VMALLOC_END, "vmalloc");
16017d3332beSBjörn Töpel 	if (IS_ENABLED(CONFIG_MODULES))
16027d3332beSBjörn Töpel 		preallocate_pgd_pages_range(MODULES_VADDR, MODULES_END, "bpf/modules");
16037d3332beSBjörn Töpel }
16047d3332beSBjörn Töpel #endif
1605