root/arch/unicore32/mm/init.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. find_limits
  2. uc32_bootmem_free
  3. pfn_valid
  4. uc32_memory_present
  5. meminfo_cmp
  6. uc32_memblock_init
  7. bootmem_init
  8. free_memmap
  9. free_unused_memmap
  10. mem_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  *  linux/arch/unicore32/mm/init.c
   4  *
   5  *  Copyright (C) 2010 GUAN Xue-tao
   6  */
   7 #include <linux/kernel.h>
   8 #include <linux/errno.h>
   9 #include <linux/swap.h>
  10 #include <linux/init.h>
  11 #include <linux/memblock.h>
  12 #include <linux/mman.h>
  13 #include <linux/nodemask.h>
  14 #include <linux/initrd.h>
  15 #include <linux/highmem.h>
  16 #include <linux/gfp.h>
  17 #include <linux/sort.h>
  18 #include <linux/dma-mapping.h>
  19 #include <linux/export.h>
  20 
  21 #include <asm/sections.h>
  22 #include <asm/setup.h>
  23 #include <linux/sizes.h>
  24 #include <asm/tlb.h>
  25 #include <asm/memblock.h>
  26 #include <mach/map.h>
  27 
  28 #include "mm.h"
  29 
  30 /*
  31  * This keeps memory configuration data used by a couple memory
  32  * initialization functions, as well as show_mem() for the skipping
  33  * of holes in the memory map.  It is populated by uc32_add_memory().
  34  */
  35 struct meminfo meminfo;
  36 
  37 static void __init find_limits(unsigned long *min, unsigned long *max_low,
  38         unsigned long *max_high)
  39 {
  40         struct meminfo *mi = &meminfo;
  41         int i;
  42 
  43         *min = -1UL;
  44         *max_low = *max_high = 0;
  45 
  46         for_each_bank(i, mi) {
  47                 struct membank *bank = &mi->bank[i];
  48                 unsigned long start, end;
  49 
  50                 start = bank_pfn_start(bank);
  51                 end = bank_pfn_end(bank);
  52 
  53                 if (*min > start)
  54                         *min = start;
  55                 if (*max_high < end)
  56                         *max_high = end;
  57                 if (bank->highmem)
  58                         continue;
  59                 if (*max_low < end)
  60                         *max_low = end;
  61         }
  62 }
  63 
  64 static void __init uc32_bootmem_free(unsigned long min, unsigned long max_low,
  65         unsigned long max_high)
  66 {
  67         unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
  68         struct memblock_region *reg;
  69 
  70         /*
  71          * initialise the zones.
  72          */
  73         memset(zone_size, 0, sizeof(zone_size));
  74 
  75         /*
  76          * The memory size has already been determined.  If we need
  77          * to do anything fancy with the allocation of this memory
  78          * to the zones, now is the time to do it.
  79          */
  80         zone_size[0] = max_low - min;
  81 
  82         /*
  83          * Calculate the size of the holes.
  84          *  holes = node_size - sum(bank_sizes)
  85          */
  86         memcpy(zhole_size, zone_size, sizeof(zhole_size));
  87         for_each_memblock(memory, reg) {
  88                 unsigned long start = memblock_region_memory_base_pfn(reg);
  89                 unsigned long end = memblock_region_memory_end_pfn(reg);
  90 
  91                 if (start < max_low) {
  92                         unsigned long low_end = min(end, max_low);
  93                         zhole_size[0] -= low_end - start;
  94                 }
  95         }
  96 
  97         /*
  98          * Adjust the sizes according to any special requirements for
  99          * this machine type.
 100          */
 101         arch_adjust_zones(zone_size, zhole_size);
 102 
 103         free_area_init_node(0, zone_size, min, zhole_size);
 104 }
 105 
 106 int pfn_valid(unsigned long pfn)
 107 {
 108         return memblock_is_memory(pfn << PAGE_SHIFT);
 109 }
 110 EXPORT_SYMBOL(pfn_valid);
 111 
 112 static void uc32_memory_present(void)
 113 {
 114 }
 115 
 116 static int __init meminfo_cmp(const void *_a, const void *_b)
 117 {
 118         const struct membank *a = _a, *b = _b;
 119         long cmp = bank_pfn_start(a) - bank_pfn_start(b);
 120         return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
 121 }
 122 
 123 void __init uc32_memblock_init(struct meminfo *mi)
 124 {
 125         int i;
 126 
 127         sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]),
 128                 meminfo_cmp, NULL);
 129 
 130         for (i = 0; i < mi->nr_banks; i++)
 131                 memblock_add(mi->bank[i].start, mi->bank[i].size);
 132 
 133         /* Register the kernel text, kernel data and initrd with memblock. */
 134         memblock_reserve(__pa(_text), _end - _text);
 135 
 136 #ifdef CONFIG_BLK_DEV_INITRD
 137         if (!phys_initrd_size) {
 138                 phys_initrd_start = 0x01000000;
 139                 phys_initrd_size = SZ_8M;
 140         }
 141 
 142         if (phys_initrd_size) {
 143                 memblock_reserve(phys_initrd_start, phys_initrd_size);
 144 
 145                 /* Now convert initrd to virtual addresses */
 146                 initrd_start = __phys_to_virt(phys_initrd_start);
 147                 initrd_end = initrd_start + phys_initrd_size;
 148         }
 149 #endif
 150 
 151         uc32_mm_memblock_reserve();
 152 
 153         memblock_allow_resize();
 154         memblock_dump_all();
 155 }
 156 
 157 void __init bootmem_init(void)
 158 {
 159         unsigned long min, max_low, max_high;
 160 
 161         max_low = max_high = 0;
 162 
 163         find_limits(&min, &max_low, &max_high);
 164 
 165         node_set_online(0);
 166 
 167         /*
 168          * Sparsemem tries to allocate bootmem in memory_present(),
 169          * so must be done after the fixed reservations
 170          */
 171         uc32_memory_present();
 172 
 173         /*
 174          * sparse_init() needs the bootmem allocator up and running.
 175          */
 176         sparse_init();
 177 
 178         /*
 179          * Now free the memory - free_area_init_node needs
 180          * the sparse mem_map arrays initialized by sparse_init()
 181          * for memmap_init_zone(), otherwise all PFNs are invalid.
 182          */
 183         uc32_bootmem_free(min, max_low, max_high);
 184 
 185         high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
 186 
 187         /*
 188          * This doesn't seem to be used by the Linux memory manager any
 189          * more, but is used by ll_rw_block.  If we can get rid of it, we
 190          * also get rid of some of the stuff above as well.
 191          *
 192          * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
 193          * the system, not the maximum PFN.
 194          */
 195         max_low_pfn = max_low - PHYS_PFN_OFFSET;
 196         max_pfn = max_high - PHYS_PFN_OFFSET;
 197 }
 198 
 199 static inline void
 200 free_memmap(unsigned long start_pfn, unsigned long end_pfn)
 201 {
 202         struct page *start_pg, *end_pg;
 203         unsigned long pg, pgend;
 204 
 205         /*
 206          * Convert start_pfn/end_pfn to a struct page pointer.
 207          */
 208         start_pg = pfn_to_page(start_pfn - 1) + 1;
 209         end_pg = pfn_to_page(end_pfn);
 210 
 211         /*
 212          * Convert to physical addresses, and
 213          * round start upwards and end downwards.
 214          */
 215         pg = PAGE_ALIGN(__pa(start_pg));
 216         pgend = __pa(end_pg) & PAGE_MASK;
 217 
 218         /*
 219          * If there are free pages between these,
 220          * free the section of the memmap array.
 221          */
 222         if (pg < pgend)
 223                 memblock_free(pg, pgend - pg);
 224 }
 225 
 226 /*
 227  * The mem_map array can get very big.  Free the unused area of the memory map.
 228  */
 229 static void __init free_unused_memmap(struct meminfo *mi)
 230 {
 231         unsigned long bank_start, prev_bank_end = 0;
 232         unsigned int i;
 233 
 234         /*
 235          * This relies on each bank being in address order.
 236          * The banks are sorted previously in bootmem_init().
 237          */
 238         for_each_bank(i, mi) {
 239                 struct membank *bank = &mi->bank[i];
 240 
 241                 bank_start = bank_pfn_start(bank);
 242 
 243                 /*
 244                  * If we had a previous bank, and there is a space
 245                  * between the current bank and the previous, free it.
 246                  */
 247                 if (prev_bank_end && prev_bank_end < bank_start)
 248                         free_memmap(prev_bank_end, bank_start);
 249 
 250                 /*
 251                  * Align up here since the VM subsystem insists that the
 252                  * memmap entries are valid from the bank end aligned to
 253                  * MAX_ORDER_NR_PAGES.
 254                  */
 255                 prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
 256         }
 257 }
 258 
 259 /*
 260  * mem_init() marks the free areas in the mem_map and tells us how much
 261  * memory is free.  This is done after various parts of the system have
 262  * claimed their memory after the kernel image.
 263  */
 264 void __init mem_init(void)
 265 {
 266         max_mapnr   = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
 267 
 268         free_unused_memmap(&meminfo);
 269 
 270         /* this will put all unused low memory onto the freelists */
 271         memblock_free_all();
 272 
 273         mem_init_print_info(NULL);
 274 
 275         BUILD_BUG_ON(TASK_SIZE                          > MODULES_VADDR);
 276         BUG_ON(TASK_SIZE                                > MODULES_VADDR);
 277 
 278         if (PAGE_SIZE >= 16384 && get_num_physpages() <= 128) {
 279                 /*
 280                  * On a machine this small we won't get
 281                  * anywhere without overcommit, so turn
 282                  * it on by default.
 283                  */
 284                 sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
 285         }
 286 }

/* [<][>][^][v][top][bottom][index][help] */