xref: /openbmc/linux/arch/riscv/mm/init.c (revision 0651c263)
176d2a049SPalmer Dabbelt /*
276d2a049SPalmer Dabbelt  * Copyright (C) 2012 Regents of the University of California
376d2a049SPalmer Dabbelt  *
476d2a049SPalmer Dabbelt  *   This program is free software; you can redistribute it and/or
576d2a049SPalmer Dabbelt  *   modify it under the terms of the GNU General Public License
676d2a049SPalmer Dabbelt  *   as published by the Free Software Foundation, version 2.
776d2a049SPalmer Dabbelt  *
876d2a049SPalmer Dabbelt  *   This program is distributed in the hope that it will be useful,
976d2a049SPalmer Dabbelt  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
1076d2a049SPalmer Dabbelt  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1176d2a049SPalmer Dabbelt  *   GNU General Public License for more details.
1276d2a049SPalmer Dabbelt  */
1376d2a049SPalmer Dabbelt 
1476d2a049SPalmer Dabbelt #include <linux/init.h>
1576d2a049SPalmer Dabbelt #include <linux/mm.h>
1676d2a049SPalmer Dabbelt #include <linux/memblock.h>
1757c8a661SMike Rapoport #include <linux/initrd.h>
1876d2a049SPalmer Dabbelt #include <linux/swap.h>
195ec9c4ffSChristoph Hellwig #include <linux/sizes.h>
200651c263SAnup Patel #include <linux/of_fdt.h>
2176d2a049SPalmer Dabbelt 
2276d2a049SPalmer Dabbelt #include <asm/tlbflush.h>
2376d2a049SPalmer Dabbelt #include <asm/sections.h>
2476d2a049SPalmer Dabbelt #include <asm/pgtable.h>
2576d2a049SPalmer Dabbelt #include <asm/io.h>
2676d2a049SPalmer Dabbelt 
2776d2a049SPalmer Dabbelt static void __init zone_sizes_init(void)
2876d2a049SPalmer Dabbelt {
295ec9c4ffSChristoph Hellwig 	unsigned long max_zone_pfns[MAX_NR_ZONES] = { 0, };
3076d2a049SPalmer Dabbelt 
31d5fad48cSZong Li #ifdef CONFIG_ZONE_DMA32
3228198c46SGuo Ren 	max_zone_pfns[ZONE_DMA32] = PFN_DOWN(min(4UL * SZ_1G,
3328198c46SGuo Ren 			(unsigned long) PFN_PHYS(max_low_pfn)));
34d5fad48cSZong Li #endif
355ec9c4ffSChristoph Hellwig 	max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
365ec9c4ffSChristoph Hellwig 
375ec9c4ffSChristoph Hellwig 	free_area_init_nodes(max_zone_pfns);
3876d2a049SPalmer Dabbelt }
3976d2a049SPalmer Dabbelt 
4076d2a049SPalmer Dabbelt void setup_zero_page(void)
4176d2a049SPalmer Dabbelt {
4276d2a049SPalmer Dabbelt 	memset((void *)empty_zero_page, 0, PAGE_SIZE);
4376d2a049SPalmer Dabbelt }
4476d2a049SPalmer Dabbelt 
4576d2a049SPalmer Dabbelt void __init paging_init(void)
4676d2a049SPalmer Dabbelt {
4776d2a049SPalmer Dabbelt 	setup_zero_page();
4876d2a049SPalmer Dabbelt 	local_flush_tlb_all();
4976d2a049SPalmer Dabbelt 	zone_sizes_init();
5076d2a049SPalmer Dabbelt }
5176d2a049SPalmer Dabbelt 
5276d2a049SPalmer Dabbelt void __init mem_init(void)
5376d2a049SPalmer Dabbelt {
5476d2a049SPalmer Dabbelt #ifdef CONFIG_FLATMEM
5576d2a049SPalmer Dabbelt 	BUG_ON(!mem_map);
5676d2a049SPalmer Dabbelt #endif /* CONFIG_FLATMEM */
5776d2a049SPalmer Dabbelt 
5876d2a049SPalmer Dabbelt 	high_memory = (void *)(__va(PFN_PHYS(max_low_pfn)));
59c6ffc5caSMike Rapoport 	memblock_free_all();
6076d2a049SPalmer Dabbelt 
6176d2a049SPalmer Dabbelt 	mem_init_print_info(NULL);
6276d2a049SPalmer Dabbelt }
6376d2a049SPalmer Dabbelt 
6476d2a049SPalmer Dabbelt void free_initmem(void)
6576d2a049SPalmer Dabbelt {
6676d2a049SPalmer Dabbelt 	free_initmem_default(0);
6776d2a049SPalmer Dabbelt }
6876d2a049SPalmer Dabbelt 
6976d2a049SPalmer Dabbelt #ifdef CONFIG_BLK_DEV_INITRD
700651c263SAnup Patel static void __init setup_initrd(void)
710651c263SAnup Patel {
720651c263SAnup Patel 	unsigned long size;
730651c263SAnup Patel 
740651c263SAnup Patel 	if (initrd_start >= initrd_end) {
750651c263SAnup Patel 		pr_info("initrd not found or empty");
760651c263SAnup Patel 		goto disable;
770651c263SAnup Patel 	}
780651c263SAnup Patel 	if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) {
790651c263SAnup Patel 		pr_err("initrd extends beyond end of memory");
800651c263SAnup Patel 		goto disable;
810651c263SAnup Patel 	}
820651c263SAnup Patel 
830651c263SAnup Patel 	size = initrd_end - initrd_start;
840651c263SAnup Patel 	memblock_reserve(__pa(initrd_start), size);
850651c263SAnup Patel 	initrd_below_start_ok = 1;
860651c263SAnup Patel 
870651c263SAnup Patel 	pr_info("Initial ramdisk at: 0x%p (%lu bytes)\n",
880651c263SAnup Patel 		(void *)(initrd_start), size);
890651c263SAnup Patel 	return;
900651c263SAnup Patel disable:
910651c263SAnup Patel 	pr_cont(" - disabling initrd\n");
920651c263SAnup Patel 	initrd_start = 0;
930651c263SAnup Patel 	initrd_end = 0;
940651c263SAnup Patel }
950651c263SAnup Patel 
9676d2a049SPalmer Dabbelt void free_initrd_mem(unsigned long start, unsigned long end)
9776d2a049SPalmer Dabbelt {
9876d2a049SPalmer Dabbelt }
9976d2a049SPalmer Dabbelt #endif /* CONFIG_BLK_DEV_INITRD */
1000651c263SAnup Patel 
1010651c263SAnup Patel void __init setup_bootmem(void)
1020651c263SAnup Patel {
1030651c263SAnup Patel 	struct memblock_region *reg;
1040651c263SAnup Patel 	phys_addr_t mem_size = 0;
1050651c263SAnup Patel 
1060651c263SAnup Patel 	/* Find the memory region containing the kernel */
1070651c263SAnup Patel 	for_each_memblock(memory, reg) {
1080651c263SAnup Patel 		phys_addr_t vmlinux_end = __pa(_end);
1090651c263SAnup Patel 		phys_addr_t end = reg->base + reg->size;
1100651c263SAnup Patel 
1110651c263SAnup Patel 		if (reg->base <= vmlinux_end && vmlinux_end <= end) {
1120651c263SAnup Patel 			/*
1130651c263SAnup Patel 			 * Reserve from the start of the region to the end of
1140651c263SAnup Patel 			 * the kernel
1150651c263SAnup Patel 			 */
1160651c263SAnup Patel 			memblock_reserve(reg->base, vmlinux_end - reg->base);
1170651c263SAnup Patel 			mem_size = min(reg->size, (phys_addr_t)-PAGE_OFFSET);
1180651c263SAnup Patel 		}
1190651c263SAnup Patel 	}
1200651c263SAnup Patel 	BUG_ON(mem_size == 0);
1210651c263SAnup Patel 
1220651c263SAnup Patel 	set_max_mapnr(PFN_DOWN(mem_size));
1230651c263SAnup Patel 	max_low_pfn = PFN_DOWN(memblock_end_of_DRAM());
1240651c263SAnup Patel 
1250651c263SAnup Patel #ifdef CONFIG_BLK_DEV_INITRD
1260651c263SAnup Patel 	setup_initrd();
1270651c263SAnup Patel #endif /* CONFIG_BLK_DEV_INITRD */
1280651c263SAnup Patel 
1290651c263SAnup Patel 	early_init_fdt_reserve_self();
1300651c263SAnup Patel 	early_init_fdt_scan_reserved_mem();
1310651c263SAnup Patel 	memblock_allow_resize();
1320651c263SAnup Patel 	memblock_dump_all();
1330651c263SAnup Patel 
1340651c263SAnup Patel 	for_each_memblock(memory, reg) {
1350651c263SAnup Patel 		unsigned long start_pfn = memblock_region_memory_base_pfn(reg);
1360651c263SAnup Patel 		unsigned long end_pfn = memblock_region_memory_end_pfn(reg);
1370651c263SAnup Patel 
1380651c263SAnup Patel 		memblock_set_node(PFN_PHYS(start_pfn),
1390651c263SAnup Patel 				  PFN_PHYS(end_pfn - start_pfn),
1400651c263SAnup Patel 				  &memblock.memory, 0);
1410651c263SAnup Patel 	}
1420651c263SAnup Patel }
143