| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 6 | | - * published by the Free Software Foundation. |
|---|
| 7 | 4 | */ |
|---|
| 8 | 5 | |
|---|
| 9 | 6 | #include <linux/kernel.h> |
|---|
| 10 | 7 | #include <linux/mm.h> |
|---|
| 11 | | -#include <linux/bootmem.h> |
|---|
| 12 | 8 | #include <linux/memblock.h> |
|---|
| 13 | 9 | #ifdef CONFIG_BLK_DEV_INITRD |
|---|
| 14 | 10 | #include <linux/initrd.h> |
|---|
| .. | .. |
|---|
| 18 | 14 | #include <linux/module.h> |
|---|
| 19 | 15 | #include <linux/highmem.h> |
|---|
| 20 | 16 | #include <asm/page.h> |
|---|
| 21 | | -#include <asm/pgalloc.h> |
|---|
| 22 | 17 | #include <asm/sections.h> |
|---|
| 23 | 18 | #include <asm/arcregs.h> |
|---|
| 24 | 19 | |
|---|
| .. | .. |
|---|
| 31 | 26 | |
|---|
| 32 | 27 | #ifdef CONFIG_HIGHMEM |
|---|
| 33 | 28 | static unsigned long min_high_pfn, max_high_pfn; |
|---|
| 34 | | -static u64 high_mem_start; |
|---|
| 35 | | -static u64 high_mem_sz; |
|---|
| 29 | +static phys_addr_t high_mem_start; |
|---|
| 30 | +static phys_addr_t high_mem_sz; |
|---|
| 36 | 31 | #endif |
|---|
| 37 | 32 | |
|---|
| 38 | 33 | #ifdef CONFIG_DISCONTIGMEM |
|---|
| .. | .. |
|---|
| 67 | 62 | |
|---|
| 68 | 63 | low_mem_sz = size; |
|---|
| 69 | 64 | in_use = 1; |
|---|
| 65 | + memblock_add_node(base, size, 0); |
|---|
| 70 | 66 | } else { |
|---|
| 71 | 67 | #ifdef CONFIG_HIGHMEM |
|---|
| 72 | 68 | high_mem_start = base; |
|---|
| 73 | 69 | high_mem_sz = size; |
|---|
| 74 | 70 | in_use = 1; |
|---|
| 71 | + memblock_add_node(base, size, 1); |
|---|
| 72 | + memblock_reserve(base, size); |
|---|
| 75 | 73 | #endif |
|---|
| 76 | 74 | } |
|---|
| 77 | 75 | |
|---|
| .. | .. |
|---|
| 79 | 77 | base, TO_MB(size), !in_use ? "Not used":""); |
|---|
| 80 | 78 | } |
|---|
| 81 | 79 | |
|---|
| 82 | | -#ifdef CONFIG_BLK_DEV_INITRD |
|---|
| 83 | | -static int __init early_initrd(char *p) |
|---|
| 80 | +bool arch_has_descending_max_zone_pfns(void) |
|---|
| 84 | 81 | { |
|---|
| 85 | | - unsigned long start, size; |
|---|
| 86 | | - char *endp; |
|---|
| 87 | | - |
|---|
| 88 | | - start = memparse(p, &endp); |
|---|
| 89 | | - if (*endp == ',') { |
|---|
| 90 | | - size = memparse(endp + 1, NULL); |
|---|
| 91 | | - |
|---|
| 92 | | - initrd_start = (unsigned long)__va(start); |
|---|
| 93 | | - initrd_end = (unsigned long)__va(start + size); |
|---|
| 94 | | - } |
|---|
| 95 | | - return 0; |
|---|
| 82 | + return !IS_ENABLED(CONFIG_ARC_HAS_PAE40); |
|---|
| 96 | 83 | } |
|---|
| 97 | | -early_param("initrd", early_initrd); |
|---|
| 98 | | -#endif |
|---|
| 99 | 84 | |
|---|
| 100 | 85 | /* |
|---|
| 101 | 86 | * First memory setup routine called from setup_arch() |
|---|
| .. | .. |
|---|
| 105 | 90 | */ |
|---|
| 106 | 91 | void __init setup_arch_memory(void) |
|---|
| 107 | 92 | { |
|---|
| 108 | | - unsigned long zones_size[MAX_NR_ZONES]; |
|---|
| 109 | | - unsigned long zones_holes[MAX_NR_ZONES]; |
|---|
| 93 | + unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0 }; |
|---|
| 110 | 94 | |
|---|
| 111 | 95 | init_mm.start_code = (unsigned long)_text; |
|---|
| 112 | 96 | init_mm.end_code = (unsigned long)_etext; |
|---|
| .. | .. |
|---|
| 137 | 121 | * the crash |
|---|
| 138 | 122 | */ |
|---|
| 139 | 123 | |
|---|
| 140 | | - memblock_add_node(low_mem_start, low_mem_sz, 0); |
|---|
| 141 | 124 | memblock_reserve(CONFIG_LINUX_LINK_BASE, |
|---|
| 142 | 125 | __pa(_end) - CONFIG_LINUX_LINK_BASE); |
|---|
| 143 | 126 | |
|---|
| 144 | 127 | #ifdef CONFIG_BLK_DEV_INITRD |
|---|
| 145 | | - if (initrd_start) |
|---|
| 146 | | - memblock_reserve(__pa(initrd_start), initrd_end - initrd_start); |
|---|
| 128 | + if (phys_initrd_size) { |
|---|
| 129 | + memblock_reserve(phys_initrd_start, phys_initrd_size); |
|---|
| 130 | + initrd_start = (unsigned long)__va(phys_initrd_start); |
|---|
| 131 | + initrd_end = initrd_start + phys_initrd_size; |
|---|
| 132 | + } |
|---|
| 147 | 133 | #endif |
|---|
| 148 | 134 | |
|---|
| 149 | 135 | early_init_fdt_reserve_self(); |
|---|
| .. | .. |
|---|
| 152 | 138 | memblock_dump_all(); |
|---|
| 153 | 139 | |
|---|
| 154 | 140 | /*----------------- node/zones setup --------------------------*/ |
|---|
| 155 | | - memset(zones_size, 0, sizeof(zones_size)); |
|---|
| 156 | | - memset(zones_holes, 0, sizeof(zones_holes)); |
|---|
| 157 | | - |
|---|
| 158 | | - zones_size[ZONE_NORMAL] = max_low_pfn - min_low_pfn; |
|---|
| 159 | | - zones_holes[ZONE_NORMAL] = 0; |
|---|
| 160 | | - |
|---|
| 161 | | - /* |
|---|
| 162 | | - * We can't use the helper free_area_init(zones[]) because it uses |
|---|
| 163 | | - * PAGE_OFFSET to compute the @min_low_pfn which would be wrong |
|---|
| 164 | | - * when our kernel doesn't start at PAGE_OFFSET, i.e. |
|---|
| 165 | | - * PAGE_OFFSET != CONFIG_LINUX_RAM_BASE |
|---|
| 166 | | - */ |
|---|
| 167 | | - free_area_init_node(0, /* node-id */ |
|---|
| 168 | | - zones_size, /* num pages per zone */ |
|---|
| 169 | | - min_low_pfn, /* first pfn of node */ |
|---|
| 170 | | - zones_holes); /* holes */ |
|---|
| 141 | + max_zone_pfn[ZONE_NORMAL] = max_low_pfn; |
|---|
| 171 | 142 | |
|---|
| 172 | 143 | #ifdef CONFIG_HIGHMEM |
|---|
| 173 | 144 | /* |
|---|
| .. | .. |
|---|
| 187 | 158 | min_high_pfn = PFN_DOWN(high_mem_start); |
|---|
| 188 | 159 | max_high_pfn = PFN_DOWN(high_mem_start + high_mem_sz); |
|---|
| 189 | 160 | |
|---|
| 190 | | - zones_size[ZONE_NORMAL] = 0; |
|---|
| 191 | | - zones_holes[ZONE_NORMAL] = 0; |
|---|
| 192 | | - |
|---|
| 193 | | - zones_size[ZONE_HIGHMEM] = max_high_pfn - min_high_pfn; |
|---|
| 194 | | - zones_holes[ZONE_HIGHMEM] = 0; |
|---|
| 195 | | - |
|---|
| 196 | | - free_area_init_node(1, /* node-id */ |
|---|
| 197 | | - zones_size, /* num pages per zone */ |
|---|
| 198 | | - min_high_pfn, /* first pfn of node */ |
|---|
| 199 | | - zones_holes); /* holes */ |
|---|
| 161 | + /* |
|---|
| 162 | + * max_high_pfn should be ok here for both HIGHMEM and HIGHMEM+PAE. |
|---|
| 163 | + * For HIGHMEM without PAE max_high_pfn should be less than |
|---|
| 164 | + * min_low_pfn to guarantee that these two regions don't overlap. |
|---|
| 165 | + * For PAE case highmem is greater than lowmem, so it is natural |
|---|
| 166 | + * to use max_high_pfn. |
|---|
| 167 | + * |
|---|
| 168 | + * In both cases, holes should be handled by pfn_valid(). |
|---|
| 169 | + */ |
|---|
| 170 | + max_zone_pfn[ZONE_HIGHMEM] = max_high_pfn; |
|---|
| 200 | 171 | |
|---|
| 201 | 172 | high_memory = (void *)(min_high_pfn << PAGE_SHIFT); |
|---|
| 202 | 173 | kmap_init(); |
|---|
| 174 | +#endif |
|---|
| 175 | + |
|---|
| 176 | + free_area_init(max_zone_pfn); |
|---|
| 177 | +} |
|---|
| 178 | + |
|---|
| 179 | +static void __init highmem_init(void) |
|---|
| 180 | +{ |
|---|
| 181 | +#ifdef CONFIG_HIGHMEM |
|---|
| 182 | + unsigned long tmp; |
|---|
| 183 | + |
|---|
| 184 | + memblock_free(high_mem_start, high_mem_sz); |
|---|
| 185 | + for (tmp = min_high_pfn; tmp < max_high_pfn; tmp++) |
|---|
| 186 | + free_highmem_page(pfn_to_page(tmp)); |
|---|
| 203 | 187 | #endif |
|---|
| 204 | 188 | } |
|---|
| 205 | 189 | |
|---|
| .. | .. |
|---|
| 211 | 195 | */ |
|---|
| 212 | 196 | void __init mem_init(void) |
|---|
| 213 | 197 | { |
|---|
| 214 | | -#ifdef CONFIG_HIGHMEM |
|---|
| 215 | | - unsigned long tmp; |
|---|
| 216 | | - |
|---|
| 217 | | - reset_all_zones_managed_pages(); |
|---|
| 218 | | - for (tmp = min_high_pfn; tmp < max_high_pfn; tmp++) |
|---|
| 219 | | - free_highmem_page(pfn_to_page(tmp)); |
|---|
| 220 | | -#endif |
|---|
| 221 | | - |
|---|
| 222 | | - free_all_bootmem(); |
|---|
| 198 | + memblock_free_all(); |
|---|
| 199 | + highmem_init(); |
|---|
| 223 | 200 | mem_init_print_info(NULL); |
|---|
| 224 | 201 | } |
|---|
| 225 | | - |
|---|
| 226 | | -/* |
|---|
| 227 | | - * free_initmem: Free all the __init memory. |
|---|
| 228 | | - */ |
|---|
| 229 | | -void __ref free_initmem(void) |
|---|
| 230 | | -{ |
|---|
| 231 | | - free_initmem_default(-1); |
|---|
| 232 | | -} |
|---|
| 233 | | - |
|---|
| 234 | | -#ifdef CONFIG_BLK_DEV_INITRD |
|---|
| 235 | | -void __init free_initrd_mem(unsigned long start, unsigned long end) |
|---|
| 236 | | -{ |
|---|
| 237 | | - free_reserved_area((void *)start, (void *)end, -1, "initrd"); |
|---|
| 238 | | -} |
|---|
| 239 | | -#endif |
|---|