1 // SPDX-License-Identifier: GPL-2.0-only 1 2 /* 3 * Copyright (C) 2004, 2007-2010, 2011-2012 Sy 4 */ 5 6 #include <linux/kernel.h> 7 #include <linux/mm.h> 8 #include <linux/memblock.h> 9 #ifdef CONFIG_BLK_DEV_INITRD 10 #include <linux/initrd.h> 11 #endif 12 #include <linux/of_fdt.h> 13 #include <linux/swap.h> 14 #include <linux/module.h> 15 #include <linux/highmem.h> 16 #include <asm/page.h> 17 #include <asm/sections.h> 18 #include <asm/setup.h> 19 #include <asm/arcregs.h> 20 21 pgd_t swapper_pg_dir[PTRS_PER_PGD] __aligned(P 22 char empty_zero_page[PAGE_SIZE] __aligned(PAGE 23 EXPORT_SYMBOL(empty_zero_page); 24 25 static const unsigned long low_mem_start = CON 26 static unsigned long low_mem_sz; 27 28 #ifdef CONFIG_HIGHMEM 29 static unsigned long min_high_pfn, max_high_pf 30 static phys_addr_t high_mem_start; 31 static phys_addr_t high_mem_sz; 32 unsigned long arch_pfn_offset; 33 EXPORT_SYMBOL(arch_pfn_offset); 34 #endif 35 36 long __init arc_get_mem_sz(void) 37 { 38 return low_mem_sz; 39 } 40 41 /* User can over-ride above with "mem=nnn[KkMm 42 static int __init setup_mem_sz(char *str) 43 { 44 low_mem_sz = memparse(str, NULL) & PAG 45 46 /* early console might not be setup ye 47 pr_info("\"mem=%s\": mem sz set to %ld 48 49 return 0; 50 } 51 early_param("mem", setup_mem_sz); 52 53 void __init early_init_dt_add_memory_arch(u64 54 { 55 int in_use = 0; 56 57 if (!low_mem_sz) { 58 if (base != low_mem_start) 59 panic("CONFIG_LINUX_RA 60 61 low_mem_sz = size; 62 in_use = 1; 63 memblock_add_node(base, size, 64 } else { 65 #ifdef CONFIG_HIGHMEM 66 high_mem_start = base; 67 high_mem_sz = size; 68 in_use = 1; 69 memblock_add_node(base, size, 70 memblock_reserve(base, size); 71 #endif 72 } 73 74 pr_info("Memory @ %llx [%lldM] %s\n", 75 base, TO_MB(size), !in_use ? " 76 } 77 78 /* 79 * First memory setup routine called from setu 80 * 1. setup swapper's mm @init_mm 81 * 2. Count the pages we have and setup bootme 82 * 3. zone setup 83 */ 84 void __init setup_arch_memory(void) 85 { 86 unsigned long max_zone_pfn[MAX_NR_ZONE 87 88 setup_initial_init_mm(_text, _etext, _ 89 90 /* first page of system - kernel .vect 91 min_low_pfn = virt_to_pfn((void *)CONF 92 93 /* Last usable page of low mem */ 94 max_low_pfn = max_pfn = PFN_DOWN(low_m 95 96 /*------------- bootmem allocator setu 97 98 /* 99 * seed the bootmem allocator after an 100 * "mem=xxx" cmdline overrides have po 101 * 102 * Only low mem is added, otherwise we 103 * mem_map[] itself. NO_BOOTMEM alloca 104 * avail memory, ending in highmem wit 105 * it then tries to memset it with a t 106 * the crash 107 */ 108 109 memblock_reserve(CONFIG_LINUX_LINK_BAS 110 __pa(_end) - CONFIG_L 111 112 #ifdef CONFIG_BLK_DEV_INITRD 113 if (phys_initrd_size) { 114 memblock_reserve(phys_initrd_s 115 initrd_start = (unsigned long) 116 initrd_end = initrd_start + ph 117 } 118 #endif 119 120 early_init_fdt_reserve_self(); 121 early_init_fdt_scan_reserved_mem(); 122 123 memblock_dump_all(); 124 125 /*----------------- node/zones setup - 126 max_zone_pfn[ZONE_NORMAL] = max_low_pf 127 128 #ifdef CONFIG_HIGHMEM 129 /* 130 * On ARC (w/o PAE) HIGHMEM addresses 131 * than addresses in normal aka low me 132 * Even with PAE, the huge peripheral 133 * mem with single contiguous mem_map[ 134 * Thus when HIGHMEM on ARC is enabled 135 * to the hole is freed and ARC specif 136 * handles the hole in the memory map. 137 */ 138 139 min_high_pfn = PFN_DOWN(high_mem_start 140 max_high_pfn = PFN_DOWN(high_mem_start 141 142 /* 143 * max_high_pfn should be ok here for 144 * For HIGHMEM without PAE max_high_pf 145 * min_low_pfn to guarantee that these 146 * For PAE case highmem is greater tha 147 * to use max_high_pfn. 148 * 149 * In both cases, holes should be hand 150 */ 151 max_zone_pfn[ZONE_HIGHMEM] = max_high_ 152 153 high_memory = (void *)(min_high_pfn << 154 155 arch_pfn_offset = min(min_low_pfn, min 156 kmap_init(); 157 158 #else /* CONFIG_HIGHMEM */ 159 /* pfn_valid() uses this when FLATMEM= 160 max_mapnr = max_low_pfn - min_low_pfn; 161 162 #endif /* CONFIG_HIGHMEM */ 163 164 free_area_init(max_zone_pfn); 165 } 166 167 static void __init highmem_init(void) 168 { 169 #ifdef CONFIG_HIGHMEM 170 unsigned long tmp; 171 172 memblock_phys_free(high_mem_start, hig 173 for (tmp = min_high_pfn; tmp < max_hig 174 free_highmem_page(pfn_to_page( 175 #endif 176 } 177 178 /* 179 * mem_init - initializes memory 180 * 181 * Frees up bootmem 182 * Calculates and displays memory available/us 183 */ 184 void __init mem_init(void) 185 { 186 memblock_free_all(); 187 highmem_init(); 188 189 BUILD_BUG_ON((PTRS_PER_PGD * sizeof(pg 190 BUILD_BUG_ON((PTRS_PER_PUD * sizeof(pu 191 BUILD_BUG_ON((PTRS_PER_PMD * sizeof(pm 192 BUILD_BUG_ON((PTRS_PER_PTE * sizeof(pt 193 } 194 195 #ifdef CONFIG_HIGHMEM 196 int pfn_valid(unsigned long pfn) 197 { 198 return (pfn >= min_high_pfn && pfn <= 199 (pfn >= min_low_pfn && pfn <= 200 } 201 EXPORT_SYMBOL(pfn_valid); 202 #endif 203
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.