Palmer Dabbelt | 76d2a04 | 2017-07-10 18:00:26 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2012 Regents of the University of California |
| 3 | * |
| 4 | * This program is free software; you can redistribute it and/or |
| 5 | * modify it under the terms of the GNU General Public License |
| 6 | * as published by the Free Software Foundation, version 2. |
| 7 | * |
| 8 | * This program is distributed in the hope that it will be useful, |
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 | * GNU General Public License for more details. |
| 12 | */ |
| 13 | |
| 14 | #include <linux/init.h> |
| 15 | #include <linux/mm.h> |
Palmer Dabbelt | 76d2a04 | 2017-07-10 18:00:26 -0700 | [diff] [blame] | 16 | #include <linux/memblock.h> |
Mike Rapoport | 57c8a66 | 2018-10-30 15:09:49 -0700 | [diff] [blame] | 17 | #include <linux/initrd.h> |
Palmer Dabbelt | 76d2a04 | 2017-07-10 18:00:26 -0700 | [diff] [blame] | 18 | #include <linux/swap.h> |
Christoph Hellwig | 5ec9c4f | 2018-01-16 09:37:50 +0100 | [diff] [blame] | 19 | #include <linux/sizes.h> |
Anup Patel | 0651c26 | 2019-02-21 11:25:49 +0530 | [diff] [blame^] | 20 | #include <linux/of_fdt.h> |
Palmer Dabbelt | 76d2a04 | 2017-07-10 18:00:26 -0700 | [diff] [blame] | 21 | |
| 22 | #include <asm/tlbflush.h> |
| 23 | #include <asm/sections.h> |
| 24 | #include <asm/pgtable.h> |
| 25 | #include <asm/io.h> |
| 26 | |
| 27 | static void __init zone_sizes_init(void) |
| 28 | { |
Christoph Hellwig | 5ec9c4f | 2018-01-16 09:37:50 +0100 | [diff] [blame] | 29 | unsigned long max_zone_pfns[MAX_NR_ZONES] = { 0, }; |
Palmer Dabbelt | 76d2a04 | 2017-07-10 18:00:26 -0700 | [diff] [blame] | 30 | |
Zong Li | d5fad48 | 2018-06-25 16:49:37 +0800 | [diff] [blame] | 31 | #ifdef CONFIG_ZONE_DMA32 |
Guo Ren | 28198c4 | 2019-01-12 16:16:27 +0800 | [diff] [blame] | 32 | max_zone_pfns[ZONE_DMA32] = PFN_DOWN(min(4UL * SZ_1G, |
| 33 | (unsigned long) PFN_PHYS(max_low_pfn))); |
Zong Li | d5fad48 | 2018-06-25 16:49:37 +0800 | [diff] [blame] | 34 | #endif |
Christoph Hellwig | 5ec9c4f | 2018-01-16 09:37:50 +0100 | [diff] [blame] | 35 | max_zone_pfns[ZONE_NORMAL] = max_low_pfn; |
| 36 | |
| 37 | free_area_init_nodes(max_zone_pfns); |
Palmer Dabbelt | 76d2a04 | 2017-07-10 18:00:26 -0700 | [diff] [blame] | 38 | } |
| 39 | |
| 40 | void setup_zero_page(void) |
| 41 | { |
| 42 | memset((void *)empty_zero_page, 0, PAGE_SIZE); |
| 43 | } |
| 44 | |
| 45 | void __init paging_init(void) |
| 46 | { |
Palmer Dabbelt | 76d2a04 | 2017-07-10 18:00:26 -0700 | [diff] [blame] | 47 | setup_zero_page(); |
| 48 | local_flush_tlb_all(); |
| 49 | zone_sizes_init(); |
| 50 | } |
| 51 | |
| 52 | void __init mem_init(void) |
| 53 | { |
| 54 | #ifdef CONFIG_FLATMEM |
| 55 | BUG_ON(!mem_map); |
| 56 | #endif /* CONFIG_FLATMEM */ |
| 57 | |
| 58 | high_memory = (void *)(__va(PFN_PHYS(max_low_pfn))); |
Mike Rapoport | c6ffc5c | 2018-10-30 15:09:30 -0700 | [diff] [blame] | 59 | memblock_free_all(); |
Palmer Dabbelt | 76d2a04 | 2017-07-10 18:00:26 -0700 | [diff] [blame] | 60 | |
| 61 | mem_init_print_info(NULL); |
| 62 | } |
| 63 | |
| 64 | void free_initmem(void) |
| 65 | { |
| 66 | free_initmem_default(0); |
| 67 | } |
| 68 | |
| 69 | #ifdef CONFIG_BLK_DEV_INITRD |
Anup Patel | 0651c26 | 2019-02-21 11:25:49 +0530 | [diff] [blame^] | 70 | static void __init setup_initrd(void) |
| 71 | { |
| 72 | unsigned long size; |
| 73 | |
| 74 | if (initrd_start >= initrd_end) { |
| 75 | pr_info("initrd not found or empty"); |
| 76 | goto disable; |
| 77 | } |
| 78 | if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) { |
| 79 | pr_err("initrd extends beyond end of memory"); |
| 80 | goto disable; |
| 81 | } |
| 82 | |
| 83 | size = initrd_end - initrd_start; |
| 84 | memblock_reserve(__pa(initrd_start), size); |
| 85 | initrd_below_start_ok = 1; |
| 86 | |
| 87 | pr_info("Initial ramdisk at: 0x%p (%lu bytes)\n", |
| 88 | (void *)(initrd_start), size); |
| 89 | return; |
| 90 | disable: |
| 91 | pr_cont(" - disabling initrd\n"); |
| 92 | initrd_start = 0; |
| 93 | initrd_end = 0; |
| 94 | } |
| 95 | |
Palmer Dabbelt | 76d2a04 | 2017-07-10 18:00:26 -0700 | [diff] [blame] | 96 | void free_initrd_mem(unsigned long start, unsigned long end) |
| 97 | { |
| 98 | } |
| 99 | #endif /* CONFIG_BLK_DEV_INITRD */ |
Anup Patel | 0651c26 | 2019-02-21 11:25:49 +0530 | [diff] [blame^] | 100 | |
| 101 | void __init setup_bootmem(void) |
| 102 | { |
| 103 | struct memblock_region *reg; |
| 104 | phys_addr_t mem_size = 0; |
| 105 | |
| 106 | /* Find the memory region containing the kernel */ |
| 107 | for_each_memblock(memory, reg) { |
| 108 | phys_addr_t vmlinux_end = __pa(_end); |
| 109 | phys_addr_t end = reg->base + reg->size; |
| 110 | |
| 111 | if (reg->base <= vmlinux_end && vmlinux_end <= end) { |
| 112 | /* |
| 113 | * Reserve from the start of the region to the end of |
| 114 | * the kernel |
| 115 | */ |
| 116 | memblock_reserve(reg->base, vmlinux_end - reg->base); |
| 117 | mem_size = min(reg->size, (phys_addr_t)-PAGE_OFFSET); |
| 118 | } |
| 119 | } |
| 120 | BUG_ON(mem_size == 0); |
| 121 | |
| 122 | set_max_mapnr(PFN_DOWN(mem_size)); |
| 123 | max_low_pfn = PFN_DOWN(memblock_end_of_DRAM()); |
| 124 | |
| 125 | #ifdef CONFIG_BLK_DEV_INITRD |
| 126 | setup_initrd(); |
| 127 | #endif /* CONFIG_BLK_DEV_INITRD */ |
| 128 | |
| 129 | early_init_fdt_reserve_self(); |
| 130 | early_init_fdt_scan_reserved_mem(); |
| 131 | memblock_allow_resize(); |
| 132 | memblock_dump_all(); |
| 133 | |
| 134 | for_each_memblock(memory, reg) { |
| 135 | unsigned long start_pfn = memblock_region_memory_base_pfn(reg); |
| 136 | unsigned long end_pfn = memblock_region_memory_end_pfn(reg); |
| 137 | |
| 138 | memblock_set_node(PFN_PHYS(start_pfn), |
| 139 | PFN_PHYS(end_pfn - start_pfn), |
| 140 | &memblock.memory, 0); |
| 141 | } |
| 142 | } |