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