Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0-or-later */
2 : #ifndef _LINUX_MEMBLOCK_H
3 : #define _LINUX_MEMBLOCK_H
4 :
5 : /*
6 : * Logical memory blocks.
7 : *
8 : * Copyright (C) 2001 Peter Bergner, IBM Corp.
9 : */
10 :
11 : #include <linux/init.h>
12 : #include <linux/mm.h>
13 : #include <asm/dma.h>
14 :
15 : extern unsigned long max_low_pfn;
16 : extern unsigned long min_low_pfn;
17 :
18 : /*
19 : * highest page
20 : */
21 : extern unsigned long max_pfn;
22 : /*
23 : * highest possible page
24 : */
25 : extern unsigned long long max_possible_pfn;
26 :
27 : /**
28 : * enum memblock_flags - definition of memory region attributes
29 : * @MEMBLOCK_NONE: no special request
30 : * @MEMBLOCK_HOTPLUG: memory region indicated in the firmware-provided memory
31 : * map during early boot as hot(un)pluggable system RAM (e.g., memory range
32 : * that might get hotunplugged later). With "movable_node" set on the kernel
33 : * commandline, try keeping this memory region hotunpluggable. Does not apply
34 : * to memblocks added ("hotplugged") after early boot.
35 : * @MEMBLOCK_MIRROR: mirrored region
36 : * @MEMBLOCK_NOMAP: don't add to kernel direct mapping and treat as
37 : * reserved in the memory map; refer to memblock_mark_nomap() description
38 : * for further details
39 : * @MEMBLOCK_DRIVER_MANAGED: memory region that is always detected and added
40 : * via a driver, and never indicated in the firmware-provided memory map as
41 : * system RAM. This corresponds to IORESOURCE_SYSRAM_DRIVER_MANAGED in the
42 : * kernel resource tree.
43 : */
44 : enum memblock_flags {
45 : MEMBLOCK_NONE = 0x0, /* No special request */
46 : MEMBLOCK_HOTPLUG = 0x1, /* hotpluggable region */
47 : MEMBLOCK_MIRROR = 0x2, /* mirrored region */
48 : MEMBLOCK_NOMAP = 0x4, /* don't add to kernel direct mapping */
49 : MEMBLOCK_DRIVER_MANAGED = 0x8, /* always detected via a driver */
50 : };
51 :
52 : /**
53 : * struct memblock_region - represents a memory region
54 : * @base: base address of the region
55 : * @size: size of the region
56 : * @flags: memory region attributes
57 : * @nid: NUMA node id
58 : */
59 : struct memblock_region {
60 : phys_addr_t base;
61 : phys_addr_t size;
62 : enum memblock_flags flags;
63 : #ifdef CONFIG_NUMA
64 : int nid;
65 : #endif
66 : };
67 :
68 : /**
69 : * struct memblock_type - collection of memory regions of certain type
70 : * @cnt: number of regions
71 : * @max: size of the allocated array
72 : * @total_size: size of all regions
73 : * @regions: array of regions
74 : * @name: the memory type symbolic name
75 : */
76 : struct memblock_type {
77 : unsigned long cnt;
78 : unsigned long max;
79 : phys_addr_t total_size;
80 : struct memblock_region *regions;
81 : char *name;
82 : };
83 :
84 : /**
85 : * struct memblock - memblock allocator metadata
86 : * @bottom_up: is bottom up direction?
87 : * @current_limit: physical address of the current allocation limit
88 : * @memory: usable memory regions
89 : * @reserved: reserved memory regions
90 : */
91 : struct memblock {
92 : bool bottom_up; /* is bottom up direction? */
93 : phys_addr_t current_limit;
94 : struct memblock_type memory;
95 : struct memblock_type reserved;
96 : };
97 :
98 : extern struct memblock memblock;
99 :
100 : #ifndef CONFIG_ARCH_KEEP_MEMBLOCK
101 : #define __init_memblock __meminit
102 : #define __initdata_memblock __meminitdata
103 : void memblock_discard(void);
104 : #else
105 : #define __init_memblock
106 : #define __initdata_memblock
107 : static inline void memblock_discard(void) {}
108 : #endif
109 :
110 : void memblock_allow_resize(void);
111 : int memblock_add_node(phys_addr_t base, phys_addr_t size, int nid,
112 : enum memblock_flags flags);
113 : int memblock_add(phys_addr_t base, phys_addr_t size);
114 : int memblock_remove(phys_addr_t base, phys_addr_t size);
115 : int memblock_phys_free(phys_addr_t base, phys_addr_t size);
116 : int memblock_reserve(phys_addr_t base, phys_addr_t size);
117 : #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
118 : int memblock_physmem_add(phys_addr_t base, phys_addr_t size);
119 : #endif
120 : void memblock_trim_memory(phys_addr_t align);
121 : bool memblock_overlaps_region(struct memblock_type *type,
122 : phys_addr_t base, phys_addr_t size);
123 : int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
124 : int memblock_clear_hotplug(phys_addr_t base, phys_addr_t size);
125 : int memblock_mark_mirror(phys_addr_t base, phys_addr_t size);
126 : int memblock_mark_nomap(phys_addr_t base, phys_addr_t size);
127 : int memblock_clear_nomap(phys_addr_t base, phys_addr_t size);
128 :
129 : void memblock_free_all(void);
130 : void memblock_free(void *ptr, size_t size);
131 : void reset_node_managed_pages(pg_data_t *pgdat);
132 : void reset_all_zones_managed_pages(void);
133 :
134 : /* Low level functions */
135 : void __next_mem_range(u64 *idx, int nid, enum memblock_flags flags,
136 : struct memblock_type *type_a,
137 : struct memblock_type *type_b, phys_addr_t *out_start,
138 : phys_addr_t *out_end, int *out_nid);
139 :
140 : void __next_mem_range_rev(u64 *idx, int nid, enum memblock_flags flags,
141 : struct memblock_type *type_a,
142 : struct memblock_type *type_b, phys_addr_t *out_start,
143 : phys_addr_t *out_end, int *out_nid);
144 :
145 : void memblock_free_late(phys_addr_t base, phys_addr_t size);
146 :
147 : #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
148 : static inline void __next_physmem_range(u64 *idx, struct memblock_type *type,
149 : phys_addr_t *out_start,
150 : phys_addr_t *out_end)
151 : {
152 : extern struct memblock_type physmem;
153 :
154 : __next_mem_range(idx, NUMA_NO_NODE, MEMBLOCK_NONE, &physmem, type,
155 : out_start, out_end, NULL);
156 : }
157 :
158 : /**
159 : * for_each_physmem_range - iterate through physmem areas not included in type.
160 : * @i: u64 used as loop variable
161 : * @type: ptr to memblock_type which excludes from the iteration, can be %NULL
162 : * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
163 : * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
164 : */
165 : #define for_each_physmem_range(i, type, p_start, p_end) \
166 : for (i = 0, __next_physmem_range(&i, type, p_start, p_end); \
167 : i != (u64)ULLONG_MAX; \
168 : __next_physmem_range(&i, type, p_start, p_end))
169 : #endif /* CONFIG_HAVE_MEMBLOCK_PHYS_MAP */
170 :
171 : /**
172 : * __for_each_mem_range - iterate through memblock areas from type_a and not
173 : * included in type_b. Or just type_a if type_b is NULL.
174 : * @i: u64 used as loop variable
175 : * @type_a: ptr to memblock_type to iterate
176 : * @type_b: ptr to memblock_type which excludes from the iteration
177 : * @nid: node selector, %NUMA_NO_NODE for all nodes
178 : * @flags: pick from blocks based on memory attributes
179 : * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
180 : * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
181 : * @p_nid: ptr to int for nid of the range, can be %NULL
182 : */
183 : #define __for_each_mem_range(i, type_a, type_b, nid, flags, \
184 : p_start, p_end, p_nid) \
185 : for (i = 0, __next_mem_range(&i, nid, flags, type_a, type_b, \
186 : p_start, p_end, p_nid); \
187 : i != (u64)ULLONG_MAX; \
188 : __next_mem_range(&i, nid, flags, type_a, type_b, \
189 : p_start, p_end, p_nid))
190 :
191 : /**
192 : * __for_each_mem_range_rev - reverse iterate through memblock areas from
193 : * type_a and not included in type_b. Or just type_a if type_b is NULL.
194 : * @i: u64 used as loop variable
195 : * @type_a: ptr to memblock_type to iterate
196 : * @type_b: ptr to memblock_type which excludes from the iteration
197 : * @nid: node selector, %NUMA_NO_NODE for all nodes
198 : * @flags: pick from blocks based on memory attributes
199 : * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
200 : * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
201 : * @p_nid: ptr to int for nid of the range, can be %NULL
202 : */
203 : #define __for_each_mem_range_rev(i, type_a, type_b, nid, flags, \
204 : p_start, p_end, p_nid) \
205 : for (i = (u64)ULLONG_MAX, \
206 : __next_mem_range_rev(&i, nid, flags, type_a, type_b, \
207 : p_start, p_end, p_nid); \
208 : i != (u64)ULLONG_MAX; \
209 : __next_mem_range_rev(&i, nid, flags, type_a, type_b, \
210 : p_start, p_end, p_nid))
211 :
212 : /**
213 : * for_each_mem_range - iterate through memory areas.
214 : * @i: u64 used as loop variable
215 : * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
216 : * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
217 : */
218 : #define for_each_mem_range(i, p_start, p_end) \
219 : __for_each_mem_range(i, &memblock.memory, NULL, NUMA_NO_NODE, \
220 : MEMBLOCK_HOTPLUG | MEMBLOCK_DRIVER_MANAGED, \
221 : p_start, p_end, NULL)
222 :
223 : /**
224 : * for_each_mem_range_rev - reverse iterate through memblock areas from
225 : * type_a and not included in type_b. Or just type_a if type_b is NULL.
226 : * @i: u64 used as loop variable
227 : * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
228 : * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
229 : */
230 : #define for_each_mem_range_rev(i, p_start, p_end) \
231 : __for_each_mem_range_rev(i, &memblock.memory, NULL, NUMA_NO_NODE, \
232 : MEMBLOCK_HOTPLUG | MEMBLOCK_DRIVER_MANAGED,\
233 : p_start, p_end, NULL)
234 :
235 : /**
236 : * for_each_reserved_mem_range - iterate over all reserved memblock areas
237 : * @i: u64 used as loop variable
238 : * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
239 : * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
240 : *
241 : * Walks over reserved areas of memblock. Available as soon as memblock
242 : * is initialized.
243 : */
244 : #define for_each_reserved_mem_range(i, p_start, p_end) \
245 : __for_each_mem_range(i, &memblock.reserved, NULL, NUMA_NO_NODE, \
246 : MEMBLOCK_NONE, p_start, p_end, NULL)
247 :
248 : static inline bool memblock_is_hotpluggable(struct memblock_region *m)
249 : {
250 : return m->flags & MEMBLOCK_HOTPLUG;
251 : }
252 :
253 : static inline bool memblock_is_mirror(struct memblock_region *m)
254 : {
255 0 : return m->flags & MEMBLOCK_MIRROR;
256 : }
257 :
258 : static inline bool memblock_is_nomap(struct memblock_region *m)
259 : {
260 107 : return m->flags & MEMBLOCK_NOMAP;
261 : }
262 :
263 : static inline bool memblock_is_driver_managed(struct memblock_region *m)
264 : {
265 106 : return m->flags & MEMBLOCK_DRIVER_MANAGED;
266 : }
267 :
268 : int memblock_search_pfn_nid(unsigned long pfn, unsigned long *start_pfn,
269 : unsigned long *end_pfn);
270 : void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
271 : unsigned long *out_end_pfn, int *out_nid);
272 :
273 : /**
274 : * for_each_mem_pfn_range - early memory pfn range iterator
275 : * @i: an integer used as loop variable
276 : * @nid: node selector, %MAX_NUMNODES for all nodes
277 : * @p_start: ptr to ulong for start pfn of the range, can be %NULL
278 : * @p_end: ptr to ulong for end pfn of the range, can be %NULL
279 : * @p_nid: ptr to int for nid of the range, can be %NULL
280 : *
281 : * Walks over configured memory ranges.
282 : */
283 : #define for_each_mem_pfn_range(i, nid, p_start, p_end, p_nid) \
284 : for (i = -1, __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid); \
285 : i >= 0; __next_mem_pfn_range(&i, nid, p_start, p_end, p_nid))
286 :
287 : #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
288 : void __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone,
289 : unsigned long *out_spfn,
290 : unsigned long *out_epfn);
291 : /**
292 : * for_each_free_mem_pfn_range_in_zone - iterate through zone specific free
293 : * memblock areas
294 : * @i: u64 used as loop variable
295 : * @zone: zone in which all of the memory blocks reside
296 : * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
297 : * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
298 : *
299 : * Walks over free (memory && !reserved) areas of memblock in a specific
300 : * zone. Available once memblock and an empty zone is initialized. The main
301 : * assumption is that the zone start, end, and pgdat have been associated.
302 : * This way we can use the zone to determine NUMA node, and if a given part
303 : * of the memblock is valid for the zone.
304 : */
305 : #define for_each_free_mem_pfn_range_in_zone(i, zone, p_start, p_end) \
306 : for (i = 0, \
307 : __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end); \
308 : i != U64_MAX; \
309 : __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end))
310 :
311 : /**
312 : * for_each_free_mem_pfn_range_in_zone_from - iterate through zone specific
313 : * free memblock areas from a given point
314 : * @i: u64 used as loop variable
315 : * @zone: zone in which all of the memory blocks reside
316 : * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
317 : * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
318 : *
319 : * Walks over free (memory && !reserved) areas of memblock in a specific
320 : * zone, continuing from current position. Available as soon as memblock is
321 : * initialized.
322 : */
323 : #define for_each_free_mem_pfn_range_in_zone_from(i, zone, p_start, p_end) \
324 : for (; i != U64_MAX; \
325 : __next_mem_pfn_range_in_zone(&i, zone, p_start, p_end))
326 :
327 : int __init deferred_page_init_max_threads(const struct cpumask *node_cpumask);
328 :
329 : #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
330 :
331 : /**
332 : * for_each_free_mem_range - iterate through free memblock areas
333 : * @i: u64 used as loop variable
334 : * @nid: node selector, %NUMA_NO_NODE for all nodes
335 : * @flags: pick from blocks based on memory attributes
336 : * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
337 : * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
338 : * @p_nid: ptr to int for nid of the range, can be %NULL
339 : *
340 : * Walks over free (memory && !reserved) areas of memblock. Available as
341 : * soon as memblock is initialized.
342 : */
343 : #define for_each_free_mem_range(i, nid, flags, p_start, p_end, p_nid) \
344 : __for_each_mem_range(i, &memblock.memory, &memblock.reserved, \
345 : nid, flags, p_start, p_end, p_nid)
346 :
347 : /**
348 : * for_each_free_mem_range_reverse - rev-iterate through free memblock areas
349 : * @i: u64 used as loop variable
350 : * @nid: node selector, %NUMA_NO_NODE for all nodes
351 : * @flags: pick from blocks based on memory attributes
352 : * @p_start: ptr to phys_addr_t for start address of the range, can be %NULL
353 : * @p_end: ptr to phys_addr_t for end address of the range, can be %NULL
354 : * @p_nid: ptr to int for nid of the range, can be %NULL
355 : *
356 : * Walks over free (memory && !reserved) areas of memblock in reverse
357 : * order. Available as soon as memblock is initialized.
358 : */
359 : #define for_each_free_mem_range_reverse(i, nid, flags, p_start, p_end, \
360 : p_nid) \
361 : __for_each_mem_range_rev(i, &memblock.memory, &memblock.reserved, \
362 : nid, flags, p_start, p_end, p_nid)
363 :
364 : int memblock_set_node(phys_addr_t base, phys_addr_t size,
365 : struct memblock_type *type, int nid);
366 :
367 : #ifdef CONFIG_NUMA
368 : static inline void memblock_set_region_node(struct memblock_region *r, int nid)
369 : {
370 : r->nid = nid;
371 : }
372 :
373 : static inline int memblock_get_region_node(const struct memblock_region *r)
374 : {
375 : return r->nid;
376 : }
377 : #else
378 : static inline void memblock_set_region_node(struct memblock_region *r, int nid)
379 : {
380 : }
381 :
382 : static inline int memblock_get_region_node(const struct memblock_region *r)
383 : {
384 : return 0;
385 : }
386 : #endif /* CONFIG_NUMA */
387 :
388 : /* Flags for memblock allocation APIs */
389 : #define MEMBLOCK_ALLOC_ANYWHERE (~(phys_addr_t)0)
390 : #define MEMBLOCK_ALLOC_ACCESSIBLE 0
391 : #define MEMBLOCK_ALLOC_NOLEAKTRACE 1
392 :
393 : /* We are using top down, so it is safe to use 0 here */
394 : #define MEMBLOCK_LOW_LIMIT 0
395 :
396 : #ifndef ARCH_LOW_ADDRESS_LIMIT
397 : #define ARCH_LOW_ADDRESS_LIMIT 0xffffffffUL
398 : #endif
399 :
400 : phys_addr_t memblock_phys_alloc_range(phys_addr_t size, phys_addr_t align,
401 : phys_addr_t start, phys_addr_t end);
402 : phys_addr_t memblock_alloc_range_nid(phys_addr_t size,
403 : phys_addr_t align, phys_addr_t start,
404 : phys_addr_t end, int nid, bool exact_nid);
405 : phys_addr_t memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid);
406 :
407 : static __always_inline phys_addr_t memblock_phys_alloc(phys_addr_t size,
408 : phys_addr_t align)
409 : {
410 : return memblock_phys_alloc_range(size, align, 0,
411 : MEMBLOCK_ALLOC_ACCESSIBLE);
412 : }
413 :
414 : void *memblock_alloc_exact_nid_raw(phys_addr_t size, phys_addr_t align,
415 : phys_addr_t min_addr, phys_addr_t max_addr,
416 : int nid);
417 : void *memblock_alloc_try_nid_raw(phys_addr_t size, phys_addr_t align,
418 : phys_addr_t min_addr, phys_addr_t max_addr,
419 : int nid);
420 : void *memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align,
421 : phys_addr_t min_addr, phys_addr_t max_addr,
422 : int nid);
423 :
424 : static __always_inline void *memblock_alloc(phys_addr_t size, phys_addr_t align)
425 : {
426 15 : return memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT,
427 : MEMBLOCK_ALLOC_ACCESSIBLE, NUMA_NO_NODE);
428 : }
429 :
430 : static inline void *memblock_alloc_raw(phys_addr_t size,
431 : phys_addr_t align)
432 : {
433 0 : return memblock_alloc_try_nid_raw(size, align, MEMBLOCK_LOW_LIMIT,
434 : MEMBLOCK_ALLOC_ACCESSIBLE,
435 : NUMA_NO_NODE);
436 : }
437 :
438 : static inline void *memblock_alloc_from(phys_addr_t size,
439 : phys_addr_t align,
440 : phys_addr_t min_addr)
441 : {
442 1 : return memblock_alloc_try_nid(size, align, min_addr,
443 : MEMBLOCK_ALLOC_ACCESSIBLE, NUMA_NO_NODE);
444 : }
445 :
446 : static inline void *memblock_alloc_low(phys_addr_t size,
447 : phys_addr_t align)
448 : {
449 3 : return memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT,
450 : ARCH_LOW_ADDRESS_LIMIT, NUMA_NO_NODE);
451 : }
452 :
453 : static inline void *memblock_alloc_node(phys_addr_t size,
454 : phys_addr_t align, int nid)
455 : {
456 1 : return memblock_alloc_try_nid(size, align, MEMBLOCK_LOW_LIMIT,
457 : MEMBLOCK_ALLOC_ACCESSIBLE, nid);
458 : }
459 :
460 : /*
461 : * Set the allocation direction to bottom-up or top-down.
462 : */
463 : static inline __init_memblock void memblock_set_bottom_up(bool enable)
464 : {
465 : memblock.bottom_up = enable;
466 : }
467 :
468 : /*
469 : * Check if the allocation direction is bottom-up or not.
470 : * if this is true, that said, memblock will allocate memory
471 : * in bottom-up direction.
472 : */
473 : static inline __init_memblock bool memblock_bottom_up(void)
474 : {
475 21 : return memblock.bottom_up;
476 : }
477 :
478 : phys_addr_t memblock_phys_mem_size(void);
479 : phys_addr_t memblock_reserved_size(void);
480 : phys_addr_t memblock_start_of_DRAM(void);
481 : phys_addr_t memblock_end_of_DRAM(void);
482 : void memblock_enforce_memory_limit(phys_addr_t memory_limit);
483 : void memblock_cap_memory_range(phys_addr_t base, phys_addr_t size);
484 : void memblock_mem_limit_remove_map(phys_addr_t limit);
485 : bool memblock_is_memory(phys_addr_t addr);
486 : bool memblock_is_map_memory(phys_addr_t addr);
487 : bool memblock_is_region_memory(phys_addr_t base, phys_addr_t size);
488 : bool memblock_is_reserved(phys_addr_t addr);
489 : bool memblock_is_region_reserved(phys_addr_t base, phys_addr_t size);
490 :
491 : void memblock_dump_all(void);
492 :
493 : /**
494 : * memblock_set_current_limit - Set the current allocation limit to allow
495 : * limiting allocations to what is currently
496 : * accessible during boot
497 : * @limit: New limit value (physical address)
498 : */
499 : void memblock_set_current_limit(phys_addr_t limit);
500 :
501 :
502 : phys_addr_t memblock_get_current_limit(void);
503 :
504 : /*
505 : * pfn conversion functions
506 : *
507 : * While the memory MEMBLOCKs should always be page aligned, the reserved
508 : * MEMBLOCKs may not be. This accessor attempt to provide a very clear
509 : * idea of what they return for such non aligned MEMBLOCKs.
510 : */
511 :
512 : /**
513 : * memblock_region_memory_base_pfn - get the lowest pfn of the memory region
514 : * @reg: memblock_region structure
515 : *
516 : * Return: the lowest pfn intersecting with the memory region
517 : */
518 : static inline unsigned long memblock_region_memory_base_pfn(const struct memblock_region *reg)
519 : {
520 0 : return PFN_UP(reg->base);
521 : }
522 :
523 : /**
524 : * memblock_region_memory_end_pfn - get the end pfn of the memory region
525 : * @reg: memblock_region structure
526 : *
527 : * Return: the end_pfn of the reserved region
528 : */
529 : static inline unsigned long memblock_region_memory_end_pfn(const struct memblock_region *reg)
530 : {
531 0 : return PFN_DOWN(reg->base + reg->size);
532 : }
533 :
534 : /**
535 : * memblock_region_reserved_base_pfn - get the lowest pfn of the reserved region
536 : * @reg: memblock_region structure
537 : *
538 : * Return: the lowest pfn intersecting with the reserved region
539 : */
540 : static inline unsigned long memblock_region_reserved_base_pfn(const struct memblock_region *reg)
541 : {
542 : return PFN_DOWN(reg->base);
543 : }
544 :
545 : /**
546 : * memblock_region_reserved_end_pfn - get the end pfn of the reserved region
547 : * @reg: memblock_region structure
548 : *
549 : * Return: the end_pfn of the reserved region
550 : */
551 : static inline unsigned long memblock_region_reserved_end_pfn(const struct memblock_region *reg)
552 : {
553 : return PFN_UP(reg->base + reg->size);
554 : }
555 :
556 : /**
557 : * for_each_mem_region - itereate over memory regions
558 : * @region: loop variable
559 : */
560 : #define for_each_mem_region(region) \
561 : for (region = memblock.memory.regions; \
562 : region < (memblock.memory.regions + memblock.memory.cnt); \
563 : region++)
564 :
565 : /**
566 : * for_each_reserved_mem_region - itereate over reserved memory regions
567 : * @region: loop variable
568 : */
569 : #define for_each_reserved_mem_region(region) \
570 : for (region = memblock.reserved.regions; \
571 : region < (memblock.reserved.regions + memblock.reserved.cnt); \
572 : region++)
573 :
574 : extern void *alloc_large_system_hash(const char *tablename,
575 : unsigned long bucketsize,
576 : unsigned long numentries,
577 : int scale,
578 : int flags,
579 : unsigned int *_hash_shift,
580 : unsigned int *_hash_mask,
581 : unsigned long low_limit,
582 : unsigned long high_limit);
583 :
584 : #define HASH_EARLY 0x00000001 /* Allocating during early boot? */
585 : #define HASH_SMALL 0x00000002 /* sub-page allocation allowed, min
586 : * shift passed via *_hash_shift */
587 : #define HASH_ZERO 0x00000004 /* Zero allocated hash table */
588 :
589 : /* Only NUMA needs hash distribution. 64bit NUMA architectures have
590 : * sufficient vmalloc space.
591 : */
592 : #ifdef CONFIG_NUMA
593 : #define HASHDIST_DEFAULT IS_ENABLED(CONFIG_64BIT)
594 : extern int hashdist; /* Distribute hashes across NUMA nodes? */
595 : #else
596 : #define hashdist (0)
597 : #endif
598 :
599 : #ifdef CONFIG_MEMTEST
600 : extern void early_memtest(phys_addr_t start, phys_addr_t end);
601 : #else
602 : static inline void early_memtest(phys_addr_t start, phys_addr_t end)
603 : {
604 : }
605 : #endif
606 :
607 :
608 : #endif /* _LINUX_MEMBLOCK_H */
|