at v4.19 12 kB view raw
1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Discontiguous memory support, Kanoj Sarcar, SGI, Nov 1999 4 */ 5#ifndef _LINUX_BOOTMEM_H 6#define _LINUX_BOOTMEM_H 7 8#include <linux/mmzone.h> 9#include <linux/mm_types.h> 10#include <asm/dma.h> 11#include <asm/processor.h> 12 13/* 14 * simple boot-time physical memory area allocator. 15 */ 16 17extern unsigned long max_low_pfn; 18extern unsigned long min_low_pfn; 19 20/* 21 * highest page 22 */ 23extern unsigned long max_pfn; 24/* 25 * highest possible page 26 */ 27extern unsigned long long max_possible_pfn; 28 29#ifndef CONFIG_NO_BOOTMEM 30/** 31 * struct bootmem_data - per-node information used by the bootmem allocator 32 * @node_min_pfn: the starting physical address of the node's memory 33 * @node_low_pfn: the end physical address of the directly addressable memory 34 * @node_bootmem_map: is a bitmap pointer - the bits represent all physical 35 * memory pages (including holes) on the node. 36 * @last_end_off: the offset within the page of the end of the last allocation; 37 * if 0, the page used is full 38 * @hint_idx: the PFN of the page used with the last allocation; 39 * together with using this with the @last_end_offset field, 40 * a test can be made to see if allocations can be merged 41 * with the page used for the last allocation rather than 42 * using up a full new page. 43 * @list: list entry in the linked list ordered by the memory addresses 44 */ 45typedef struct bootmem_data { 46 unsigned long node_min_pfn; 47 unsigned long node_low_pfn; 48 void *node_bootmem_map; 49 unsigned long last_end_off; 50 unsigned long hint_idx; 51 struct list_head list; 52} bootmem_data_t; 53 54extern bootmem_data_t bootmem_node_data[]; 55#endif 56 57extern unsigned long bootmem_bootmap_pages(unsigned long); 58 59extern unsigned long init_bootmem_node(pg_data_t *pgdat, 60 unsigned long freepfn, 61 unsigned long startpfn, 62 unsigned long endpfn); 63extern unsigned long init_bootmem(unsigned long addr, unsigned long memend); 64 65extern unsigned long free_all_bootmem(void); 66extern void reset_node_managed_pages(pg_data_t *pgdat); 67extern void reset_all_zones_managed_pages(void); 68 69extern void free_bootmem_node(pg_data_t *pgdat, 70 unsigned long addr, 71 unsigned long size); 72extern void free_bootmem(unsigned long physaddr, unsigned long size); 73extern void free_bootmem_late(unsigned long physaddr, unsigned long size); 74 75/* 76 * Flags for reserve_bootmem (also if CONFIG_HAVE_ARCH_BOOTMEM_NODE, 77 * the architecture-specific code should honor this). 78 * 79 * If flags is BOOTMEM_DEFAULT, then the return value is always 0 (success). 80 * If flags contains BOOTMEM_EXCLUSIVE, then -EBUSY is returned if the memory 81 * already was reserved. 82 */ 83#define BOOTMEM_DEFAULT 0 84#define BOOTMEM_EXCLUSIVE (1<<0) 85 86extern int reserve_bootmem(unsigned long addr, 87 unsigned long size, 88 int flags); 89extern int reserve_bootmem_node(pg_data_t *pgdat, 90 unsigned long physaddr, 91 unsigned long size, 92 int flags); 93 94extern void *__alloc_bootmem(unsigned long size, 95 unsigned long align, 96 unsigned long goal); 97extern void *__alloc_bootmem_nopanic(unsigned long size, 98 unsigned long align, 99 unsigned long goal) __malloc; 100extern void *__alloc_bootmem_node(pg_data_t *pgdat, 101 unsigned long size, 102 unsigned long align, 103 unsigned long goal) __malloc; 104void *__alloc_bootmem_node_high(pg_data_t *pgdat, 105 unsigned long size, 106 unsigned long align, 107 unsigned long goal) __malloc; 108extern void *__alloc_bootmem_node_nopanic(pg_data_t *pgdat, 109 unsigned long size, 110 unsigned long align, 111 unsigned long goal) __malloc; 112void *___alloc_bootmem_node_nopanic(pg_data_t *pgdat, 113 unsigned long size, 114 unsigned long align, 115 unsigned long goal, 116 unsigned long limit) __malloc; 117extern void *__alloc_bootmem_low(unsigned long size, 118 unsigned long align, 119 unsigned long goal) __malloc; 120void *__alloc_bootmem_low_nopanic(unsigned long size, 121 unsigned long align, 122 unsigned long goal) __malloc; 123extern void *__alloc_bootmem_low_node(pg_data_t *pgdat, 124 unsigned long size, 125 unsigned long align, 126 unsigned long goal) __malloc; 127 128#ifdef CONFIG_NO_BOOTMEM 129/* We are using top down, so it is safe to use 0 here */ 130#define BOOTMEM_LOW_LIMIT 0 131#else 132#define BOOTMEM_LOW_LIMIT __pa(MAX_DMA_ADDRESS) 133#endif 134 135#ifndef ARCH_LOW_ADDRESS_LIMIT 136#define ARCH_LOW_ADDRESS_LIMIT 0xffffffffUL 137#endif 138 139#define alloc_bootmem(x) \ 140 __alloc_bootmem(x, SMP_CACHE_BYTES, BOOTMEM_LOW_LIMIT) 141#define alloc_bootmem_align(x, align) \ 142 __alloc_bootmem(x, align, BOOTMEM_LOW_LIMIT) 143#define alloc_bootmem_nopanic(x) \ 144 __alloc_bootmem_nopanic(x, SMP_CACHE_BYTES, BOOTMEM_LOW_LIMIT) 145#define alloc_bootmem_pages(x) \ 146 __alloc_bootmem(x, PAGE_SIZE, BOOTMEM_LOW_LIMIT) 147#define alloc_bootmem_pages_nopanic(x) \ 148 __alloc_bootmem_nopanic(x, PAGE_SIZE, BOOTMEM_LOW_LIMIT) 149#define alloc_bootmem_node(pgdat, x) \ 150 __alloc_bootmem_node(pgdat, x, SMP_CACHE_BYTES, BOOTMEM_LOW_LIMIT) 151#define alloc_bootmem_node_nopanic(pgdat, x) \ 152 __alloc_bootmem_node_nopanic(pgdat, x, SMP_CACHE_BYTES, BOOTMEM_LOW_LIMIT) 153#define alloc_bootmem_pages_node(pgdat, x) \ 154 __alloc_bootmem_node(pgdat, x, PAGE_SIZE, BOOTMEM_LOW_LIMIT) 155#define alloc_bootmem_pages_node_nopanic(pgdat, x) \ 156 __alloc_bootmem_node_nopanic(pgdat, x, PAGE_SIZE, BOOTMEM_LOW_LIMIT) 157 158#define alloc_bootmem_low(x) \ 159 __alloc_bootmem_low(x, SMP_CACHE_BYTES, 0) 160#define alloc_bootmem_low_pages_nopanic(x) \ 161 __alloc_bootmem_low_nopanic(x, PAGE_SIZE, 0) 162#define alloc_bootmem_low_pages(x) \ 163 __alloc_bootmem_low(x, PAGE_SIZE, 0) 164#define alloc_bootmem_low_pages_node(pgdat, x) \ 165 __alloc_bootmem_low_node(pgdat, x, PAGE_SIZE, 0) 166 167 168#if defined(CONFIG_HAVE_MEMBLOCK) && defined(CONFIG_NO_BOOTMEM) 169 170/* FIXME: use MEMBLOCK_ALLOC_* variants here */ 171#define BOOTMEM_ALLOC_ACCESSIBLE 0 172#define BOOTMEM_ALLOC_ANYWHERE (~(phys_addr_t)0) 173 174/* FIXME: Move to memblock.h at a point where we remove nobootmem.c */ 175void *memblock_virt_alloc_try_nid_raw(phys_addr_t size, phys_addr_t align, 176 phys_addr_t min_addr, 177 phys_addr_t max_addr, int nid); 178void *memblock_virt_alloc_try_nid_nopanic(phys_addr_t size, 179 phys_addr_t align, phys_addr_t min_addr, 180 phys_addr_t max_addr, int nid); 181void *memblock_virt_alloc_try_nid(phys_addr_t size, phys_addr_t align, 182 phys_addr_t min_addr, phys_addr_t max_addr, int nid); 183void __memblock_free_early(phys_addr_t base, phys_addr_t size); 184void __memblock_free_late(phys_addr_t base, phys_addr_t size); 185 186static inline void * __init memblock_virt_alloc( 187 phys_addr_t size, phys_addr_t align) 188{ 189 return memblock_virt_alloc_try_nid(size, align, BOOTMEM_LOW_LIMIT, 190 BOOTMEM_ALLOC_ACCESSIBLE, 191 NUMA_NO_NODE); 192} 193 194static inline void * __init memblock_virt_alloc_raw( 195 phys_addr_t size, phys_addr_t align) 196{ 197 return memblock_virt_alloc_try_nid_raw(size, align, BOOTMEM_LOW_LIMIT, 198 BOOTMEM_ALLOC_ACCESSIBLE, 199 NUMA_NO_NODE); 200} 201 202static inline void * __init memblock_virt_alloc_nopanic( 203 phys_addr_t size, phys_addr_t align) 204{ 205 return memblock_virt_alloc_try_nid_nopanic(size, align, 206 BOOTMEM_LOW_LIMIT, 207 BOOTMEM_ALLOC_ACCESSIBLE, 208 NUMA_NO_NODE); 209} 210 211static inline void * __init memblock_virt_alloc_low( 212 phys_addr_t size, phys_addr_t align) 213{ 214 return memblock_virt_alloc_try_nid(size, align, 215 BOOTMEM_LOW_LIMIT, 216 ARCH_LOW_ADDRESS_LIMIT, 217 NUMA_NO_NODE); 218} 219static inline void * __init memblock_virt_alloc_low_nopanic( 220 phys_addr_t size, phys_addr_t align) 221{ 222 return memblock_virt_alloc_try_nid_nopanic(size, align, 223 BOOTMEM_LOW_LIMIT, 224 ARCH_LOW_ADDRESS_LIMIT, 225 NUMA_NO_NODE); 226} 227 228static inline void * __init memblock_virt_alloc_from_nopanic( 229 phys_addr_t size, phys_addr_t align, phys_addr_t min_addr) 230{ 231 return memblock_virt_alloc_try_nid_nopanic(size, align, min_addr, 232 BOOTMEM_ALLOC_ACCESSIBLE, 233 NUMA_NO_NODE); 234} 235 236static inline void * __init memblock_virt_alloc_node( 237 phys_addr_t size, int nid) 238{ 239 return memblock_virt_alloc_try_nid(size, 0, BOOTMEM_LOW_LIMIT, 240 BOOTMEM_ALLOC_ACCESSIBLE, nid); 241} 242 243static inline void * __init memblock_virt_alloc_node_nopanic( 244 phys_addr_t size, int nid) 245{ 246 return memblock_virt_alloc_try_nid_nopanic(size, 0, BOOTMEM_LOW_LIMIT, 247 BOOTMEM_ALLOC_ACCESSIBLE, 248 nid); 249} 250 251static inline void __init memblock_free_early( 252 phys_addr_t base, phys_addr_t size) 253{ 254 __memblock_free_early(base, size); 255} 256 257static inline void __init memblock_free_early_nid( 258 phys_addr_t base, phys_addr_t size, int nid) 259{ 260 __memblock_free_early(base, size); 261} 262 263static inline void __init memblock_free_late( 264 phys_addr_t base, phys_addr_t size) 265{ 266 __memblock_free_late(base, size); 267} 268 269#else 270 271#define BOOTMEM_ALLOC_ACCESSIBLE 0 272 273 274/* Fall back to all the existing bootmem APIs */ 275static inline void * __init memblock_virt_alloc( 276 phys_addr_t size, phys_addr_t align) 277{ 278 if (!align) 279 align = SMP_CACHE_BYTES; 280 return __alloc_bootmem(size, align, BOOTMEM_LOW_LIMIT); 281} 282 283static inline void * __init memblock_virt_alloc_raw( 284 phys_addr_t size, phys_addr_t align) 285{ 286 if (!align) 287 align = SMP_CACHE_BYTES; 288 return __alloc_bootmem_nopanic(size, align, BOOTMEM_LOW_LIMIT); 289} 290 291static inline void * __init memblock_virt_alloc_nopanic( 292 phys_addr_t size, phys_addr_t align) 293{ 294 if (!align) 295 align = SMP_CACHE_BYTES; 296 return __alloc_bootmem_nopanic(size, align, BOOTMEM_LOW_LIMIT); 297} 298 299static inline void * __init memblock_virt_alloc_low( 300 phys_addr_t size, phys_addr_t align) 301{ 302 if (!align) 303 align = SMP_CACHE_BYTES; 304 return __alloc_bootmem_low(size, align, 0); 305} 306 307static inline void * __init memblock_virt_alloc_low_nopanic( 308 phys_addr_t size, phys_addr_t align) 309{ 310 if (!align) 311 align = SMP_CACHE_BYTES; 312 return __alloc_bootmem_low_nopanic(size, align, 0); 313} 314 315static inline void * __init memblock_virt_alloc_from_nopanic( 316 phys_addr_t size, phys_addr_t align, phys_addr_t min_addr) 317{ 318 return __alloc_bootmem_nopanic(size, align, min_addr); 319} 320 321static inline void * __init memblock_virt_alloc_node( 322 phys_addr_t size, int nid) 323{ 324 return __alloc_bootmem_node(NODE_DATA(nid), size, SMP_CACHE_BYTES, 325 BOOTMEM_LOW_LIMIT); 326} 327 328static inline void * __init memblock_virt_alloc_node_nopanic( 329 phys_addr_t size, int nid) 330{ 331 return __alloc_bootmem_node_nopanic(NODE_DATA(nid), size, 332 SMP_CACHE_BYTES, 333 BOOTMEM_LOW_LIMIT); 334} 335 336static inline void * __init memblock_virt_alloc_try_nid(phys_addr_t size, 337 phys_addr_t align, phys_addr_t min_addr, phys_addr_t max_addr, int nid) 338{ 339 return __alloc_bootmem_node_high(NODE_DATA(nid), size, align, 340 min_addr); 341} 342 343static inline void * __init memblock_virt_alloc_try_nid_raw( 344 phys_addr_t size, phys_addr_t align, 345 phys_addr_t min_addr, phys_addr_t max_addr, int nid) 346{ 347 return ___alloc_bootmem_node_nopanic(NODE_DATA(nid), size, align, 348 min_addr, max_addr); 349} 350 351static inline void * __init memblock_virt_alloc_try_nid_nopanic( 352 phys_addr_t size, phys_addr_t align, 353 phys_addr_t min_addr, phys_addr_t max_addr, int nid) 354{ 355 return ___alloc_bootmem_node_nopanic(NODE_DATA(nid), size, align, 356 min_addr, max_addr); 357} 358 359static inline void __init memblock_free_early( 360 phys_addr_t base, phys_addr_t size) 361{ 362 free_bootmem(base, size); 363} 364 365static inline void __init memblock_free_early_nid( 366 phys_addr_t base, phys_addr_t size, int nid) 367{ 368 free_bootmem_node(NODE_DATA(nid), base, size); 369} 370 371static inline void __init memblock_free_late( 372 phys_addr_t base, phys_addr_t size) 373{ 374 free_bootmem_late(base, size); 375} 376#endif /* defined(CONFIG_HAVE_MEMBLOCK) && defined(CONFIG_NO_BOOTMEM) */ 377 378extern void *alloc_large_system_hash(const char *tablename, 379 unsigned long bucketsize, 380 unsigned long numentries, 381 int scale, 382 int flags, 383 unsigned int *_hash_shift, 384 unsigned int *_hash_mask, 385 unsigned long low_limit, 386 unsigned long high_limit); 387 388#define HASH_EARLY 0x00000001 /* Allocating during early boot? */ 389#define HASH_SMALL 0x00000002 /* sub-page allocation allowed, min 390 * shift passed via *_hash_shift */ 391#define HASH_ZERO 0x00000004 /* Zero allocated hash table */ 392 393/* Only NUMA needs hash distribution. 64bit NUMA architectures have 394 * sufficient vmalloc space. 395 */ 396#ifdef CONFIG_NUMA 397#define HASHDIST_DEFAULT IS_ENABLED(CONFIG_64BIT) 398extern int hashdist; /* Distribute hashes across NUMA nodes? */ 399#else 400#define hashdist (0) 401#endif 402 403 404#endif /* _LINUX_BOOTMEM_H */