Blame view

mm/memblock.c 56.6 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
95f72d1ed   Yinghai Lu   lmb: rename to me...
2
3
4
5
6
  /*
   * Procedures for maintaining information about logical memory blocks.
   *
   * Peter Bergner, IBM Corp.	June 2001.
   * Copyright (C) 2001 Peter Bergner.
95f72d1ed   Yinghai Lu   lmb: rename to me...
7
8
9
   */
  
  #include <linux/kernel.h>
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
10
  #include <linux/slab.h>
95f72d1ed   Yinghai Lu   lmb: rename to me...
11
12
  #include <linux/init.h>
  #include <linux/bitops.h>
449e8df39   Benjamin Herrenschmidt   memblock: Add deb...
13
  #include <linux/poison.h>
c196f76fd   Benjamin Herrenschmidt   memblock: NUMA al...
14
  #include <linux/pfn.h>
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
15
  #include <linux/debugfs.h>
514c60324   Randy Dunlap   headers: untangle...
16
  #include <linux/kmemleak.h>
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
17
  #include <linux/seq_file.h>
95f72d1ed   Yinghai Lu   lmb: rename to me...
18
  #include <linux/memblock.h>
c4c5ad6b3   Christoph Hellwig   memblock: include...
19
  #include <asm/sections.h>
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
20
21
22
  #include <linux/io.h>
  
  #include "internal.h"
79442ed18   Tang Chen   mm/memblock.c: in...
23

8a5b403d7   Ard Biesheuvel   arm64, mm, efi: A...
24
25
26
27
28
29
  #define INIT_MEMBLOCK_REGIONS			128
  #define INIT_PHYSMEM_REGIONS			4
  
  #ifndef INIT_MEMBLOCK_RESERVED_REGIONS
  # define INIT_MEMBLOCK_RESERVED_REGIONS		INIT_MEMBLOCK_REGIONS
  #endif
3e039c5c0   Mike Rapoport   docs/mm: memblock...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  /**
   * DOC: memblock overview
   *
   * Memblock is a method of managing memory regions during the early
   * boot period when the usual kernel memory allocators are not up and
   * running.
   *
   * Memblock views the system memory as collections of contiguous
   * regions. There are several types of these collections:
   *
   * * ``memory`` - describes the physical memory available to the
   *   kernel; this may differ from the actual physical memory installed
   *   in the system, for instance when the memory is restricted with
   *   ``mem=`` command line parameter
   * * ``reserved`` - describes the regions that were allocated
   * * ``physmap`` - describes the actual physical memory regardless of
   *   the possible restrictions; the ``physmap`` type is only available
   *   on some architectures.
   *
   * Each region is represented by :c:type:`struct memblock_region` that
   * defines the region extents, its attributes and NUMA node id on NUMA
   * systems. Every memory type is described by the :c:type:`struct
   * memblock_type` which contains an array of memory regions along with
   * the allocator metadata. The memory types are nicely wrapped with
   * :c:type:`struct memblock`. This structure is statically initialzed
   * at build time. The region arrays for the "memory" and "reserved"
   * types are initially sized to %INIT_MEMBLOCK_REGIONS and for the
   * "physmap" type to %INIT_PHYSMEM_REGIONS.
   * The :c:func:`memblock_allow_resize` enables automatic resizing of
   * the region arrays during addition of new regions. This feature
   * should be used with care so that memory allocated for the region
   * array will not overlap with areas that should be reserved, for
   * example initrd.
   *
   * The early architecture setup should tell memblock what the physical
   * memory layout is by using :c:func:`memblock_add` or
   * :c:func:`memblock_add_node` functions. The first function does not
   * assign the region to a NUMA node and it is appropriate for UMA
   * systems. Yet, it is possible to use it on NUMA systems as well and
   * assign the region to a NUMA node later in the setup process using
   * :c:func:`memblock_set_node`. The :c:func:`memblock_add_node`
   * performs such an assignment directly.
   *
a2974133b   Mike Rapoport   mm: memblock: upd...
73
74
75
76
77
78
79
80
81
82
83
84
85
   * Once memblock is setup the memory can be allocated using one of the
   * API variants:
   *
   * * :c:func:`memblock_phys_alloc*` - these functions return the
   *   **physical** address of the allocated memory
   * * :c:func:`memblock_alloc*` - these functions return the **virtual**
   *   address of the allocated memory.
   *
   * Note, that both API variants use implict assumptions about allowed
   * memory ranges and the fallback methods. Consult the documentation
   * of :c:func:`memblock_alloc_internal` and
   * :c:func:`memblock_alloc_range_nid` functions for more elaboarte
   * description.
3e039c5c0   Mike Rapoport   docs/mm: memblock...
86
87
88
89
90
   *
   * As the system boot progresses, the architecture specific
   * :c:func:`mem_init` function frees all the memory to the buddy page
   * allocator.
   *
350e88bad   Mike Rapoport   mm: memblock: mak...
91
   * Unless an architecure enables %CONFIG_ARCH_KEEP_MEMBLOCK, the
3e039c5c0   Mike Rapoport   docs/mm: memblock...
92
93
94
   * memblock data structures will be discarded after the system
   * initialization compltes.
   */
bda49a811   Mike Rapoport   mm: remove nobootmem
95
96
97
98
99
100
101
102
103
  #ifndef CONFIG_NEED_MULTIPLE_NODES
  struct pglist_data __refdata contig_page_data;
  EXPORT_SYMBOL(contig_page_data);
  #endif
  
  unsigned long max_low_pfn;
  unsigned long min_low_pfn;
  unsigned long max_pfn;
  unsigned long long max_possible_pfn;
fe091c208   Tejun Heo   memblock: Kill me...
104
  static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
8a5b403d7   Ard Biesheuvel   arm64, mm, efi: A...
105
  static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_RESERVED_REGIONS] __initdata_memblock;
70210ed95   Philipp Hachtmann   mm/memblock: add ...
106
107
108
  #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
  static struct memblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS] __initdata_memblock;
  #endif
fe091c208   Tejun Heo   memblock: Kill me...
109
110
111
112
113
  
  struct memblock memblock __initdata_memblock = {
  	.memory.regions		= memblock_memory_init_regions,
  	.memory.cnt		= 1,	/* empty dummy entry */
  	.memory.max		= INIT_MEMBLOCK_REGIONS,
0262d9c84   Heiko Carstens   memblock: embed m...
114
  	.memory.name		= "memory",
fe091c208   Tejun Heo   memblock: Kill me...
115
116
117
  
  	.reserved.regions	= memblock_reserved_init_regions,
  	.reserved.cnt		= 1,	/* empty dummy entry */
8a5b403d7   Ard Biesheuvel   arm64, mm, efi: A...
118
  	.reserved.max		= INIT_MEMBLOCK_RESERVED_REGIONS,
0262d9c84   Heiko Carstens   memblock: embed m...
119
  	.reserved.name		= "reserved",
fe091c208   Tejun Heo   memblock: Kill me...
120

70210ed95   Philipp Hachtmann   mm/memblock: add ...
121
122
123
124
  #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
  	.physmem.regions	= memblock_physmem_init_regions,
  	.physmem.cnt		= 1,	/* empty dummy entry */
  	.physmem.max		= INIT_PHYSMEM_REGIONS,
0262d9c84   Heiko Carstens   memblock: embed m...
125
  	.physmem.name		= "physmem",
70210ed95   Philipp Hachtmann   mm/memblock: add ...
126
  #endif
79442ed18   Tang Chen   mm/memblock.c: in...
127
  	.bottom_up		= false,
fe091c208   Tejun Heo   memblock: Kill me...
128
129
  	.current_limit		= MEMBLOCK_ALLOC_ANYWHERE,
  };
95f72d1ed   Yinghai Lu   lmb: rename to me...
130

10d064398   Yinghai Lu   memblock: Option ...
131
  int memblock_debug __initdata_memblock;
a3f5bafcc   Tony Luck   mm/memblock: allo...
132
  static bool system_has_some_mirror __initdata_memblock = false;
1aadc0560   Tejun Heo   memblock: s/membl...
133
  static int memblock_can_resize __initdata_memblock;
181eb3942   Gavin Shan   mm/memblock: fix ...
134
135
  static int memblock_memory_in_slab __initdata_memblock = 0;
  static int memblock_reserved_in_slab __initdata_memblock = 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
136

c366ea89f   Mike Rapoport   memblock: make me...
137
  static enum memblock_flags __init_memblock choose_memblock_flags(void)
a3f5bafcc   Tony Luck   mm/memblock: allo...
138
139
140
  {
  	return system_has_some_mirror ? MEMBLOCK_MIRROR : MEMBLOCK_NONE;
  }
eb18f1b5b   Tejun Heo   memblock: Make me...
141
142
143
  /* adjust *@size so that (@base + *@size) doesn't overflow, return new size */
  static inline phys_addr_t memblock_cap_size(phys_addr_t base, phys_addr_t *size)
  {
1c4bc43dd   Stefan Agner   mm/memblock: intr...
144
  	return *size = min(*size, PHYS_ADDR_MAX - base);
eb18f1b5b   Tejun Heo   memblock: Make me...
145
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
146
147
148
  /*
   * Address comparison utilities
   */
10d064398   Yinghai Lu   memblock: Option ...
149
  static unsigned long __init_memblock memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
2898cc4cd   Benjamin Herrenschmidt   memblock: Change ...
150
  				       phys_addr_t base2, phys_addr_t size2)
95f72d1ed   Yinghai Lu   lmb: rename to me...
151
152
153
  {
  	return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
  }
95cf82ecc   Tang Chen   mem-hotplug: hand...
154
  bool __init_memblock memblock_overlaps_region(struct memblock_type *type,
2d7d3eb2b   H Hartley Sweeten   mm/memblock.c: qu...
155
  					phys_addr_t base, phys_addr_t size)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
156
157
  {
  	unsigned long i;
f14516fbf   Alexander Kuleshov   mm/memblock: remo...
158
159
160
  	for (i = 0; i < type->cnt; i++)
  		if (memblock_addrs_overlap(base, size, type->regions[i].base,
  					   type->regions[i].size))
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
161
  			break;
c5c5c9d10   Tang Chen   mm/memblock.c: ma...
162
  	return i < type->cnt;
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
163
  }
47cec4432   Mike Rapoport   docs/mm: memblock...
164
  /**
79442ed18   Tang Chen   mm/memblock.c: in...
165
166
   * __memblock_find_range_bottom_up - find free area utility in bottom-up
   * @start: start of candidate range
47cec4432   Mike Rapoport   docs/mm: memblock...
167
168
   * @end: end of candidate range, can be %MEMBLOCK_ALLOC_ANYWHERE or
   *       %MEMBLOCK_ALLOC_ACCESSIBLE
79442ed18   Tang Chen   mm/memblock.c: in...
169
170
   * @size: size of free area to find
   * @align: alignment of free area to find
b11542335   Grygorii Strashko   mm/memblock: swit...
171
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
fc6daaf93   Tony Luck   mm/memblock: add ...
172
   * @flags: pick from blocks based on memory attributes
79442ed18   Tang Chen   mm/memblock.c: in...
173
174
175
   *
   * Utility called from memblock_find_in_range_node(), find free area bottom-up.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
176
   * Return:
79442ed18   Tang Chen   mm/memblock.c: in...
177
178
179
180
   * Found address on success, 0 on failure.
   */
  static phys_addr_t __init_memblock
  __memblock_find_range_bottom_up(phys_addr_t start, phys_addr_t end,
fc6daaf93   Tony Luck   mm/memblock: add ...
181
  				phys_addr_t size, phys_addr_t align, int nid,
e1720fee2   Mike Rapoport   mm/memblock: add ...
182
  				enum memblock_flags flags)
79442ed18   Tang Chen   mm/memblock.c: in...
183
184
185
  {
  	phys_addr_t this_start, this_end, cand;
  	u64 i;
fc6daaf93   Tony Luck   mm/memblock: add ...
186
  	for_each_free_mem_range(i, nid, flags, &this_start, &this_end, NULL) {
79442ed18   Tang Chen   mm/memblock.c: in...
187
188
189
190
191
192
193
194
195
196
  		this_start = clamp(this_start, start, end);
  		this_end = clamp(this_end, start, end);
  
  		cand = round_up(this_start, align);
  		if (cand < this_end && this_end - cand >= size)
  			return cand;
  	}
  
  	return 0;
  }
7bd0b0f0d   Tejun Heo   memblock: Reimple...
197
  /**
1402899e4   Tang Chen   mm/memblock.c: fa...
198
   * __memblock_find_range_top_down - find free area utility, in top-down
7bd0b0f0d   Tejun Heo   memblock: Reimple...
199
   * @start: start of candidate range
47cec4432   Mike Rapoport   docs/mm: memblock...
200
201
   * @end: end of candidate range, can be %MEMBLOCK_ALLOC_ANYWHERE or
   *       %MEMBLOCK_ALLOC_ACCESSIBLE
7bd0b0f0d   Tejun Heo   memblock: Reimple...
202
203
   * @size: size of free area to find
   * @align: alignment of free area to find
b11542335   Grygorii Strashko   mm/memblock: swit...
204
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
fc6daaf93   Tony Luck   mm/memblock: add ...
205
   * @flags: pick from blocks based on memory attributes
7bd0b0f0d   Tejun Heo   memblock: Reimple...
206
   *
1402899e4   Tang Chen   mm/memblock.c: fa...
207
   * Utility called from memblock_find_in_range_node(), find free area top-down.
7bd0b0f0d   Tejun Heo   memblock: Reimple...
208
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
209
   * Return:
79442ed18   Tang Chen   mm/memblock.c: in...
210
   * Found address on success, 0 on failure.
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
211
   */
1402899e4   Tang Chen   mm/memblock.c: fa...
212
213
  static phys_addr_t __init_memblock
  __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
fc6daaf93   Tony Luck   mm/memblock: add ...
214
  			       phys_addr_t size, phys_addr_t align, int nid,
e1720fee2   Mike Rapoport   mm/memblock: add ...
215
  			       enum memblock_flags flags)
f7210e6c4   Tang Chen   mm/memblock.c: us...
216
217
218
  {
  	phys_addr_t this_start, this_end, cand;
  	u64 i;
fc6daaf93   Tony Luck   mm/memblock: add ...
219
220
  	for_each_free_mem_range_reverse(i, nid, flags, &this_start, &this_end,
  					NULL) {
f7210e6c4   Tang Chen   mm/memblock.c: us...
221
222
223
224
225
226
227
228
229
230
  		this_start = clamp(this_start, start, end);
  		this_end = clamp(this_end, start, end);
  
  		if (this_end < size)
  			continue;
  
  		cand = round_down(this_end - size, align);
  		if (cand >= this_start)
  			return cand;
  	}
1402899e4   Tang Chen   mm/memblock.c: fa...
231

f7210e6c4   Tang Chen   mm/memblock.c: us...
232
233
  	return 0;
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
234

7bd0b0f0d   Tejun Heo   memblock: Reimple...
235
  /**
1402899e4   Tang Chen   mm/memblock.c: fa...
236
   * memblock_find_in_range_node - find free area in given range and node
1402899e4   Tang Chen   mm/memblock.c: fa...
237
238
   * @size: size of free area to find
   * @align: alignment of free area to find
87029ee93   Grygorii Strashko   mm/memblock: reor...
239
   * @start: start of candidate range
47cec4432   Mike Rapoport   docs/mm: memblock...
240
241
   * @end: end of candidate range, can be %MEMBLOCK_ALLOC_ANYWHERE or
   *       %MEMBLOCK_ALLOC_ACCESSIBLE
b11542335   Grygorii Strashko   mm/memblock: swit...
242
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
fc6daaf93   Tony Luck   mm/memblock: add ...
243
   * @flags: pick from blocks based on memory attributes
1402899e4   Tang Chen   mm/memblock.c: fa...
244
245
246
   *
   * Find @size free area aligned to @align in the specified range and node.
   *
79442ed18   Tang Chen   mm/memblock.c: in...
247
248
249
250
251
252
253
254
   * When allocation direction is bottom-up, the @start should be greater
   * than the end of the kernel image. Otherwise, it will be trimmed. The
   * reason is that we want the bottom-up allocation just near the kernel
   * image so it is highly likely that the allocated memory and the kernel
   * will reside in the same node.
   *
   * If bottom-up allocation failed, will try to allocate memory top-down.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
255
   * Return:
79442ed18   Tang Chen   mm/memblock.c: in...
256
   * Found address on success, 0 on failure.
1402899e4   Tang Chen   mm/memblock.c: fa...
257
   */
c366ea89f   Mike Rapoport   memblock: make me...
258
  static phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
87029ee93   Grygorii Strashko   mm/memblock: reor...
259
  					phys_addr_t align, phys_addr_t start,
e1720fee2   Mike Rapoport   mm/memblock: add ...
260
261
  					phys_addr_t end, int nid,
  					enum memblock_flags flags)
1402899e4   Tang Chen   mm/memblock.c: fa...
262
  {
0cfb8f0c3   Tang Chen   memblock, memhotp...
263
  	phys_addr_t kernel_end, ret;
79442ed18   Tang Chen   mm/memblock.c: in...
264

1402899e4   Tang Chen   mm/memblock.c: fa...
265
  	/* pump up @end */
fed84c785   Qian Cai   mm/memblock.c: sk...
266
267
  	if (end == MEMBLOCK_ALLOC_ACCESSIBLE ||
  	    end == MEMBLOCK_ALLOC_KASAN)
1402899e4   Tang Chen   mm/memblock.c: fa...
268
269
270
271
272
  		end = memblock.current_limit;
  
  	/* avoid allocating the first page */
  	start = max_t(phys_addr_t, start, PAGE_SIZE);
  	end = max(start, end);
79442ed18   Tang Chen   mm/memblock.c: in...
273
274
275
276
277
278
279
280
281
282
283
284
285
286
  	kernel_end = __pa_symbol(_end);
  
  	/*
  	 * try bottom-up allocation only when bottom-up mode
  	 * is set and @end is above the kernel image.
  	 */
  	if (memblock_bottom_up() && end > kernel_end) {
  		phys_addr_t bottom_up_start;
  
  		/* make sure we will allocate above the kernel */
  		bottom_up_start = max(start, kernel_end);
  
  		/* ok, try bottom-up allocation first */
  		ret = __memblock_find_range_bottom_up(bottom_up_start, end,
fc6daaf93   Tony Luck   mm/memblock: add ...
287
  						      size, align, nid, flags);
79442ed18   Tang Chen   mm/memblock.c: in...
288
289
290
291
292
293
294
295
296
297
298
299
300
  		if (ret)
  			return ret;
  
  		/*
  		 * we always limit bottom-up allocation above the kernel,
  		 * but top-down allocation doesn't have the limit, so
  		 * retrying top-down allocation may succeed when bottom-up
  		 * allocation failed.
  		 *
  		 * bottom-up allocation is expected to be fail very rarely,
  		 * so we use WARN_ONCE() here to see the stack trace if
  		 * fail happens.
  		 */
e3d301cae   Michal Hocko   mm/memblock.c: do...
301
302
303
  		WARN_ONCE(IS_ENABLED(CONFIG_MEMORY_HOTREMOVE),
  			  "memblock: bottom-up allocation failed, memory hotremove may be affected
  ");
79442ed18   Tang Chen   mm/memblock.c: in...
304
  	}
1402899e4   Tang Chen   mm/memblock.c: fa...
305

fc6daaf93   Tony Luck   mm/memblock: add ...
306
307
  	return __memblock_find_range_top_down(start, end, size, align, nid,
  					      flags);
1402899e4   Tang Chen   mm/memblock.c: fa...
308
309
310
  }
  
  /**
7bd0b0f0d   Tejun Heo   memblock: Reimple...
311
312
   * memblock_find_in_range - find free area in given range
   * @start: start of candidate range
47cec4432   Mike Rapoport   docs/mm: memblock...
313
314
   * @end: end of candidate range, can be %MEMBLOCK_ALLOC_ANYWHERE or
   *       %MEMBLOCK_ALLOC_ACCESSIBLE
7bd0b0f0d   Tejun Heo   memblock: Reimple...
315
316
317
318
319
   * @size: size of free area to find
   * @align: alignment of free area to find
   *
   * Find @size free area aligned to @align in the specified range.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
320
   * Return:
79442ed18   Tang Chen   mm/memblock.c: in...
321
   * Found address on success, 0 on failure.
fc769a8e7   Tejun Heo   memblock: Replace...
322
   */
7bd0b0f0d   Tejun Heo   memblock: Reimple...
323
324
325
  phys_addr_t __init_memblock memblock_find_in_range(phys_addr_t start,
  					phys_addr_t end, phys_addr_t size,
  					phys_addr_t align)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
326
  {
a3f5bafcc   Tony Luck   mm/memblock: allo...
327
  	phys_addr_t ret;
e1720fee2   Mike Rapoport   mm/memblock: add ...
328
  	enum memblock_flags flags = choose_memblock_flags();
a3f5bafcc   Tony Luck   mm/memblock: allo...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
  
  again:
  	ret = memblock_find_in_range_node(size, align, start, end,
  					    NUMA_NO_NODE, flags);
  
  	if (!ret && (flags & MEMBLOCK_MIRROR)) {
  		pr_warn("Could not allocate %pap bytes of mirrored memory
  ",
  			&size);
  		flags &= ~MEMBLOCK_MIRROR;
  		goto again;
  	}
  
  	return ret;
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
343
  }
10d064398   Yinghai Lu   memblock: Option ...
344
  static void __init_memblock memblock_remove_region(struct memblock_type *type, unsigned long r)
95f72d1ed   Yinghai Lu   lmb: rename to me...
345
  {
1440c4e2c   Tejun Heo   memblock: Track t...
346
  	type->total_size -= type->regions[r].size;
7c0caeb86   Tejun Heo   memblock: Add opt...
347
348
  	memmove(&type->regions[r], &type->regions[r + 1],
  		(type->cnt - (r + 1)) * sizeof(type->regions[r]));
e3239ff92   Benjamin Herrenschmidt   memblock: Rename ...
349
  	type->cnt--;
95f72d1ed   Yinghai Lu   lmb: rename to me...
350

8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
351
352
  	/* Special case for empty arrays */
  	if (type->cnt == 0) {
1440c4e2c   Tejun Heo   memblock: Track t...
353
  		WARN_ON(type->total_size != 0);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
354
355
356
  		type->cnt = 1;
  		type->regions[0].base = 0;
  		type->regions[0].size = 0;
66a207572   Tang Chen   memblock, numa: i...
357
  		type->regions[0].flags = 0;
7c0caeb86   Tejun Heo   memblock: Add opt...
358
  		memblock_set_region_node(&type->regions[0], MAX_NUMNODES);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
359
  	}
95f72d1ed   Yinghai Lu   lmb: rename to me...
360
  }
350e88bad   Mike Rapoport   mm: memblock: mak...
361
  #ifndef CONFIG_ARCH_KEEP_MEMBLOCK
3010f8765   Pavel Tatashin   mm: discard membl...
362
  /**
47cec4432   Mike Rapoport   docs/mm: memblock...
363
   * memblock_discard - discard memory and reserved arrays if they were allocated
3010f8765   Pavel Tatashin   mm: discard membl...
364
365
   */
  void __init memblock_discard(void)
5e270e254   Philipp Hachtmann   mm: free memblock...
366
  {
3010f8765   Pavel Tatashin   mm: discard membl...
367
  	phys_addr_t addr, size;
5e270e254   Philipp Hachtmann   mm: free memblock...
368

3010f8765   Pavel Tatashin   mm: discard membl...
369
370
371
372
373
374
  	if (memblock.reserved.regions != memblock_reserved_init_regions) {
  		addr = __pa(memblock.reserved.regions);
  		size = PAGE_ALIGN(sizeof(struct memblock_region) *
  				  memblock.reserved.max);
  		__memblock_free_late(addr, size);
  	}
5e270e254   Philipp Hachtmann   mm: free memblock...
375

91b540f98   Pavel Tatashin   mm/memblock.c: re...
376
  	if (memblock.memory.regions != memblock_memory_init_regions) {
3010f8765   Pavel Tatashin   mm: discard membl...
377
378
379
380
381
  		addr = __pa(memblock.memory.regions);
  		size = PAGE_ALIGN(sizeof(struct memblock_region) *
  				  memblock.memory.max);
  		__memblock_free_late(addr, size);
  	}
5e270e254   Philipp Hachtmann   mm: free memblock...
382
  }
5e270e254   Philipp Hachtmann   mm: free memblock...
383
  #endif
48c3b583b   Greg Pearson   mm/memblock: fix ...
384
385
386
387
388
389
390
391
  /**
   * memblock_double_array - double the size of the memblock regions array
   * @type: memblock type of the regions array being doubled
   * @new_area_start: starting address of memory range to avoid overlap with
   * @new_area_size: size of memory range to avoid overlap with
   *
   * Double the size of the @type regions array. If memblock is being used to
   * allocate memory for a new reserved regions array and there is a previously
47cec4432   Mike Rapoport   docs/mm: memblock...
392
   * allocated memory range [@new_area_start, @new_area_start + @new_area_size]
48c3b583b   Greg Pearson   mm/memblock: fix ...
393
394
395
   * waiting to be reserved, ensure the memory used by the new array does
   * not overlap.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
396
   * Return:
48c3b583b   Greg Pearson   mm/memblock: fix ...
397
398
399
400
401
   * 0 on success, -1 on failure.
   */
  static int __init_memblock memblock_double_array(struct memblock_type *type,
  						phys_addr_t new_area_start,
  						phys_addr_t new_area_size)
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
402
403
  {
  	struct memblock_region *new_array, *old_array;
29f673860   Yinghai Lu   memblock: free al...
404
  	phys_addr_t old_alloc_size, new_alloc_size;
a36aab890   Mike Rapoport   mm/memblock.c: re...
405
  	phys_addr_t old_size, new_size, addr, new_end;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
406
  	int use_slab = slab_is_available();
181eb3942   Gavin Shan   mm/memblock: fix ...
407
  	int *in_slab;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
408
409
410
411
412
413
  
  	/* We don't allow resizing until we know about the reserved regions
  	 * of memory that aren't suitable for allocation
  	 */
  	if (!memblock_can_resize)
  		return -1;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
414
415
416
  	/* Calculate new doubled size */
  	old_size = type->max * sizeof(struct memblock_region);
  	new_size = old_size << 1;
29f673860   Yinghai Lu   memblock: free al...
417
418
419
420
421
422
  	/*
  	 * We need to allocated new one align to PAGE_SIZE,
  	 *   so we can free them completely later.
  	 */
  	old_alloc_size = PAGE_ALIGN(old_size);
  	new_alloc_size = PAGE_ALIGN(new_size);
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
423

181eb3942   Gavin Shan   mm/memblock: fix ...
424
425
426
427
428
  	/* Retrieve the slab flag */
  	if (type == &memblock.memory)
  		in_slab = &memblock_memory_in_slab;
  	else
  		in_slab = &memblock_reserved_in_slab;
a2974133b   Mike Rapoport   mm: memblock: upd...
429
  	/* Try to find some space for it */
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
430
431
  	if (use_slab) {
  		new_array = kmalloc(new_size, GFP_KERNEL);
1f5026a7e   Tejun Heo   memblock: Kill ME...
432
  		addr = new_array ? __pa(new_array) : 0;
4e2f07750   Gavin Shan   mm/memblock: clea...
433
  	} else {
48c3b583b   Greg Pearson   mm/memblock: fix ...
434
435
436
437
438
439
  		/* only exclude range when trying to double reserved.regions */
  		if (type != &memblock.reserved)
  			new_area_start = new_area_size = 0;
  
  		addr = memblock_find_in_range(new_area_start + new_area_size,
  						memblock.current_limit,
29f673860   Yinghai Lu   memblock: free al...
440
  						new_alloc_size, PAGE_SIZE);
48c3b583b   Greg Pearson   mm/memblock: fix ...
441
442
  		if (!addr && new_area_size)
  			addr = memblock_find_in_range(0,
fd07383b6   Andrew Morton   mm/memblock.c:mem...
443
444
  				min(new_area_start, memblock.current_limit),
  				new_alloc_size, PAGE_SIZE);
48c3b583b   Greg Pearson   mm/memblock: fix ...
445

15674868d   Sachin Kamat   mm/memblock: Use ...
446
  		new_array = addr ? __va(addr) : NULL;
4e2f07750   Gavin Shan   mm/memblock: clea...
447
  	}
1f5026a7e   Tejun Heo   memblock: Kill ME...
448
  	if (!addr) {
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
449
450
  		pr_err("memblock: Failed to double %s array from %ld to %ld entries !
  ",
0262d9c84   Heiko Carstens   memblock: embed m...
451
  		       type->name, type->max, type->max * 2);
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
452
453
  		return -1;
  	}
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
454

a36aab890   Mike Rapoport   mm/memblock.c: re...
455
456
457
  	new_end = addr + new_size - 1;
  	memblock_dbg("memblock: %s is doubled to %ld at [%pa-%pa]",
  			type->name, type->max * 2, &addr, &new_end);
ea9e4376b   Yinghai Lu   memblock: Improve...
458

fd07383b6   Andrew Morton   mm/memblock.c:mem...
459
460
461
462
  	/*
  	 * Found space, we now need to move the array over before we add the
  	 * reserved region since it may be our reserved array itself that is
  	 * full.
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
463
464
465
466
467
468
  	 */
  	memcpy(new_array, type->regions, old_size);
  	memset(new_array + type->max, 0, old_size);
  	old_array = type->regions;
  	type->regions = new_array;
  	type->max <<= 1;
fd07383b6   Andrew Morton   mm/memblock.c:mem...
469
  	/* Free old array. We needn't free it if the array is the static one */
181eb3942   Gavin Shan   mm/memblock: fix ...
470
471
472
473
  	if (*in_slab)
  		kfree(old_array);
  	else if (old_array != memblock_memory_init_regions &&
  		 old_array != memblock_reserved_init_regions)
29f673860   Yinghai Lu   memblock: free al...
474
  		memblock_free(__pa(old_array), old_alloc_size);
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
475

fd07383b6   Andrew Morton   mm/memblock.c:mem...
476
477
478
  	/*
  	 * Reserve the new array if that comes from the memblock.  Otherwise, we
  	 * needn't do it
181eb3942   Gavin Shan   mm/memblock: fix ...
479
480
  	 */
  	if (!use_slab)
29f673860   Yinghai Lu   memblock: free al...
481
  		BUG_ON(memblock_reserve(addr, new_alloc_size));
181eb3942   Gavin Shan   mm/memblock: fix ...
482
483
484
  
  	/* Update slab flag */
  	*in_slab = use_slab;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
485
486
  	return 0;
  }
784656f9c   Tejun Heo   memblock: Reimple...
487
488
489
490
491
492
493
  /**
   * memblock_merge_regions - merge neighboring compatible regions
   * @type: memblock type to scan
   *
   * Scan @type and merge neighboring compatible regions.
   */
  static void __init_memblock memblock_merge_regions(struct memblock_type *type)
95f72d1ed   Yinghai Lu   lmb: rename to me...
494
  {
784656f9c   Tejun Heo   memblock: Reimple...
495
  	int i = 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
496

784656f9c   Tejun Heo   memblock: Reimple...
497
498
499
500
  	/* cnt never goes below 1 */
  	while (i < type->cnt - 1) {
  		struct memblock_region *this = &type->regions[i];
  		struct memblock_region *next = &type->regions[i + 1];
95f72d1ed   Yinghai Lu   lmb: rename to me...
501

7c0caeb86   Tejun Heo   memblock: Add opt...
502
503
  		if (this->base + this->size != next->base ||
  		    memblock_get_region_node(this) !=
66a207572   Tang Chen   memblock, numa: i...
504
505
  		    memblock_get_region_node(next) ||
  		    this->flags != next->flags) {
784656f9c   Tejun Heo   memblock: Reimple...
506
507
508
  			BUG_ON(this->base + this->size > next->base);
  			i++;
  			continue;
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
509
  		}
784656f9c   Tejun Heo   memblock: Reimple...
510
  		this->size += next->size;
c0232ae86   Lin Feng   mm: memblock: fix...
511
512
  		/* move forward from next + 1, index of which is i + 2 */
  		memmove(next, next + 1, (type->cnt - (i + 2)) * sizeof(*next));
784656f9c   Tejun Heo   memblock: Reimple...
513
  		type->cnt--;
95f72d1ed   Yinghai Lu   lmb: rename to me...
514
  	}
784656f9c   Tejun Heo   memblock: Reimple...
515
  }
95f72d1ed   Yinghai Lu   lmb: rename to me...
516

784656f9c   Tejun Heo   memblock: Reimple...
517
518
  /**
   * memblock_insert_region - insert new memblock region
209ff86d6   Tang Chen   memblock: fix mis...
519
520
521
522
523
   * @type:	memblock type to insert into
   * @idx:	index for the insertion point
   * @base:	base address of the new region
   * @size:	size of the new region
   * @nid:	node id of the new region
66a207572   Tang Chen   memblock, numa: i...
524
   * @flags:	flags of the new region
784656f9c   Tejun Heo   memblock: Reimple...
525
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
526
   * Insert new memblock region [@base, @base + @size) into @type at @idx.
412d0008d   Alexander Kuleshov   mm/memblock: fix ...
527
   * @type must already have extra room to accommodate the new region.
784656f9c   Tejun Heo   memblock: Reimple...
528
529
530
   */
  static void __init_memblock memblock_insert_region(struct memblock_type *type,
  						   int idx, phys_addr_t base,
66a207572   Tang Chen   memblock, numa: i...
531
  						   phys_addr_t size,
e1720fee2   Mike Rapoport   mm/memblock: add ...
532
533
  						   int nid,
  						   enum memblock_flags flags)
784656f9c   Tejun Heo   memblock: Reimple...
534
535
536
537
538
539
540
  {
  	struct memblock_region *rgn = &type->regions[idx];
  
  	BUG_ON(type->cnt >= type->max);
  	memmove(rgn + 1, rgn, (type->cnt - idx) * sizeof(*rgn));
  	rgn->base = base;
  	rgn->size = size;
66a207572   Tang Chen   memblock, numa: i...
541
  	rgn->flags = flags;
7c0caeb86   Tejun Heo   memblock: Add opt...
542
  	memblock_set_region_node(rgn, nid);
784656f9c   Tejun Heo   memblock: Reimple...
543
  	type->cnt++;
1440c4e2c   Tejun Heo   memblock: Track t...
544
  	type->total_size += size;
784656f9c   Tejun Heo   memblock: Reimple...
545
546
547
  }
  
  /**
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
548
   * memblock_add_range - add new memblock region
784656f9c   Tejun Heo   memblock: Reimple...
549
550
551
   * @type: memblock type to add new region into
   * @base: base address of the new region
   * @size: size of the new region
7fb0bc3f0   Tejun Heo   memblock: Impleme...
552
   * @nid: nid of the new region
66a207572   Tang Chen   memblock, numa: i...
553
   * @flags: flags of the new region
784656f9c   Tejun Heo   memblock: Reimple...
554
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
555
   * Add new memblock region [@base, @base + @size) into @type.  The new region
784656f9c   Tejun Heo   memblock: Reimple...
556
557
558
559
   * is allowed to overlap with existing ones - overlaps don't affect already
   * existing regions.  @type is guaranteed to be minimal (all neighbouring
   * compatible regions are merged) after the addition.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
560
   * Return:
784656f9c   Tejun Heo   memblock: Reimple...
561
562
   * 0 on success, -errno on failure.
   */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
563
  int __init_memblock memblock_add_range(struct memblock_type *type,
66a207572   Tang Chen   memblock, numa: i...
564
  				phys_addr_t base, phys_addr_t size,
e1720fee2   Mike Rapoport   mm/memblock: add ...
565
  				int nid, enum memblock_flags flags)
784656f9c   Tejun Heo   memblock: Reimple...
566
567
  {
  	bool insert = false;
eb18f1b5b   Tejun Heo   memblock: Make me...
568
569
  	phys_addr_t obase = base;
  	phys_addr_t end = base + memblock_cap_size(base, &size);
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
570
571
  	int idx, nr_new;
  	struct memblock_region *rgn;
784656f9c   Tejun Heo   memblock: Reimple...
572

b3dc627ca   Tejun Heo   memblock: membloc...
573
574
  	if (!size)
  		return 0;
784656f9c   Tejun Heo   memblock: Reimple...
575
576
  	/* special case for empty array */
  	if (type->regions[0].size == 0) {
1440c4e2c   Tejun Heo   memblock: Track t...
577
  		WARN_ON(type->cnt != 1 || type->total_size);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
578
579
  		type->regions[0].base = base;
  		type->regions[0].size = size;
66a207572   Tang Chen   memblock, numa: i...
580
  		type->regions[0].flags = flags;
7fb0bc3f0   Tejun Heo   memblock: Impleme...
581
  		memblock_set_region_node(&type->regions[0], nid);
1440c4e2c   Tejun Heo   memblock: Track t...
582
  		type->total_size = size;
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
583
  		return 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
584
  	}
784656f9c   Tejun Heo   memblock: Reimple...
585
586
587
588
  repeat:
  	/*
  	 * The following is executed twice.  Once with %false @insert and
  	 * then with %true.  The first counts the number of regions needed
412d0008d   Alexander Kuleshov   mm/memblock: fix ...
589
  	 * to accommodate the new area.  The second actually inserts them.
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
590
  	 */
784656f9c   Tejun Heo   memblock: Reimple...
591
592
  	base = obase;
  	nr_new = 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
593

66e8b438b   Gioh Kim   mm/memblock.c: ma...
594
  	for_each_memblock_type(idx, type, rgn) {
784656f9c   Tejun Heo   memblock: Reimple...
595
596
597
598
  		phys_addr_t rbase = rgn->base;
  		phys_addr_t rend = rbase + rgn->size;
  
  		if (rbase >= end)
95f72d1ed   Yinghai Lu   lmb: rename to me...
599
  			break;
784656f9c   Tejun Heo   memblock: Reimple...
600
601
602
603
604
605
606
  		if (rend <= base)
  			continue;
  		/*
  		 * @rgn overlaps.  If it separates the lower part of new
  		 * area, insert that portion.
  		 */
  		if (rbase > base) {
c0a294988   Wei Yang   mm/memblock: WARN...
607
608
609
  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
  			WARN_ON(nid != memblock_get_region_node(rgn));
  #endif
4fcab5f43   Wei Yang   mm/memblock.c: WA...
610
  			WARN_ON(flags != rgn->flags);
784656f9c   Tejun Heo   memblock: Reimple...
611
612
  			nr_new++;
  			if (insert)
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
613
  				memblock_insert_region(type, idx++, base,
66a207572   Tang Chen   memblock, numa: i...
614
615
  						       rbase - base, nid,
  						       flags);
95f72d1ed   Yinghai Lu   lmb: rename to me...
616
  		}
784656f9c   Tejun Heo   memblock: Reimple...
617
618
  		/* area below @rend is dealt with, forget about it */
  		base = min(rend, end);
95f72d1ed   Yinghai Lu   lmb: rename to me...
619
  	}
784656f9c   Tejun Heo   memblock: Reimple...
620
621
622
623
624
  
  	/* insert the remaining portion */
  	if (base < end) {
  		nr_new++;
  		if (insert)
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
625
  			memblock_insert_region(type, idx, base, end - base,
66a207572   Tang Chen   memblock, numa: i...
626
  					       nid, flags);
95f72d1ed   Yinghai Lu   lmb: rename to me...
627
  	}
95f72d1ed   Yinghai Lu   lmb: rename to me...
628

ef3cc4db4   nimisolo   mm/memblock.c:mem...
629
630
  	if (!nr_new)
  		return 0;
784656f9c   Tejun Heo   memblock: Reimple...
631
632
633
  	/*
  	 * If this was the first round, resize array and repeat for actual
  	 * insertions; otherwise, merge and return.
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
634
  	 */
784656f9c   Tejun Heo   memblock: Reimple...
635
636
  	if (!insert) {
  		while (type->cnt + nr_new > type->max)
48c3b583b   Greg Pearson   mm/memblock: fix ...
637
  			if (memblock_double_array(type, obase, size) < 0)
784656f9c   Tejun Heo   memblock: Reimple...
638
639
640
641
642
643
  				return -ENOMEM;
  		insert = true;
  		goto repeat;
  	} else {
  		memblock_merge_regions(type);
  		return 0;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
644
  	}
95f72d1ed   Yinghai Lu   lmb: rename to me...
645
  }
48a833cc7   Mike Rapoport   docs/mm: memblock...
646
647
648
649
650
651
652
653
654
655
656
657
  /**
   * memblock_add_node - add new memblock region within a NUMA node
   * @base: base address of the new region
   * @size: size of the new region
   * @nid: nid of the new region
   *
   * Add new memblock region [@base, @base + @size) to the "memory"
   * type. See memblock_add_range() description for mode details
   *
   * Return:
   * 0 on success, -errno on failure.
   */
7fb0bc3f0   Tejun Heo   memblock: Impleme...
658
659
660
  int __init_memblock memblock_add_node(phys_addr_t base, phys_addr_t size,
  				       int nid)
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
661
  	return memblock_add_range(&memblock.memory, base, size, nid, 0);
7fb0bc3f0   Tejun Heo   memblock: Impleme...
662
  }
48a833cc7   Mike Rapoport   docs/mm: memblock...
663
664
665
666
667
668
669
670
671
672
673
  /**
   * memblock_add - add new memblock region
   * @base: base address of the new region
   * @size: size of the new region
   *
   * Add new memblock region [@base, @base + @size) to the "memory"
   * type. See memblock_add_range() description for mode details
   *
   * Return:
   * 0 on success, -errno on failure.
   */
f705ac4b3   Alexander Kuleshov   mm/memblock.c: mo...
674
  int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
6a4055bc7   Alexander Kuleshov   mm/memblock.c: ad...
675
  {
5d63f81c9   Miles Chen   mm/memblock.c: re...
676
  	phys_addr_t end = base + size - 1;
d75f773c8   Sakari Ailus   treewide: Switch ...
677
678
  	memblock_dbg("memblock_add: [%pa-%pa] %pS
  ",
5d63f81c9   Miles Chen   mm/memblock.c: re...
679
  		     &base, &end, (void *)_RET_IP_);
6a4055bc7   Alexander Kuleshov   mm/memblock.c: ad...
680

f705ac4b3   Alexander Kuleshov   mm/memblock.c: mo...
681
  	return memblock_add_range(&memblock.memory, base, size, MAX_NUMNODES, 0);
95f72d1ed   Yinghai Lu   lmb: rename to me...
682
  }
6a9ceb31c   Tejun Heo   memblock: Separat...
683
684
685
686
687
688
689
690
691
  /**
   * memblock_isolate_range - isolate given range into disjoint memblocks
   * @type: memblock type to isolate range for
   * @base: base of range to isolate
   * @size: size of range to isolate
   * @start_rgn: out parameter for the start of isolated region
   * @end_rgn: out parameter for the end of isolated region
   *
   * Walk @type and ensure that regions don't cross the boundaries defined by
47cec4432   Mike Rapoport   docs/mm: memblock...
692
   * [@base, @base + @size).  Crossing regions are split at the boundaries,
6a9ceb31c   Tejun Heo   memblock: Separat...
693
694
695
   * which may create at most two more regions.  The index of the first
   * region inside the range is returned in *@start_rgn and end in *@end_rgn.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
696
   * Return:
6a9ceb31c   Tejun Heo   memblock: Separat...
697
698
699
700
701
702
   * 0 on success, -errno on failure.
   */
  static int __init_memblock memblock_isolate_range(struct memblock_type *type,
  					phys_addr_t base, phys_addr_t size,
  					int *start_rgn, int *end_rgn)
  {
eb18f1b5b   Tejun Heo   memblock: Make me...
703
  	phys_addr_t end = base + memblock_cap_size(base, &size);
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
704
705
  	int idx;
  	struct memblock_region *rgn;
6a9ceb31c   Tejun Heo   memblock: Separat...
706
707
  
  	*start_rgn = *end_rgn = 0;
b3dc627ca   Tejun Heo   memblock: membloc...
708
709
  	if (!size)
  		return 0;
6a9ceb31c   Tejun Heo   memblock: Separat...
710
711
  	/* we'll create at most two more regions */
  	while (type->cnt + 2 > type->max)
48c3b583b   Greg Pearson   mm/memblock: fix ...
712
  		if (memblock_double_array(type, base, size) < 0)
6a9ceb31c   Tejun Heo   memblock: Separat...
713
  			return -ENOMEM;
66e8b438b   Gioh Kim   mm/memblock.c: ma...
714
  	for_each_memblock_type(idx, type, rgn) {
6a9ceb31c   Tejun Heo   memblock: Separat...
715
716
717
718
719
720
721
722
723
724
725
726
727
728
  		phys_addr_t rbase = rgn->base;
  		phys_addr_t rend = rbase + rgn->size;
  
  		if (rbase >= end)
  			break;
  		if (rend <= base)
  			continue;
  
  		if (rbase < base) {
  			/*
  			 * @rgn intersects from below.  Split and continue
  			 * to process the next region - the new top half.
  			 */
  			rgn->base = base;
1440c4e2c   Tejun Heo   memblock: Track t...
729
730
  			rgn->size -= base - rbase;
  			type->total_size -= base - rbase;
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
731
  			memblock_insert_region(type, idx, rbase, base - rbase,
66a207572   Tang Chen   memblock, numa: i...
732
733
  					       memblock_get_region_node(rgn),
  					       rgn->flags);
6a9ceb31c   Tejun Heo   memblock: Separat...
734
735
736
737
738
739
  		} else if (rend > end) {
  			/*
  			 * @rgn intersects from above.  Split and redo the
  			 * current region - the new bottom half.
  			 */
  			rgn->base = end;
1440c4e2c   Tejun Heo   memblock: Track t...
740
741
  			rgn->size -= end - rbase;
  			type->total_size -= end - rbase;
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
742
  			memblock_insert_region(type, idx--, rbase, end - rbase,
66a207572   Tang Chen   memblock, numa: i...
743
744
  					       memblock_get_region_node(rgn),
  					       rgn->flags);
6a9ceb31c   Tejun Heo   memblock: Separat...
745
746
747
  		} else {
  			/* @rgn is fully contained, record it */
  			if (!*end_rgn)
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
748
749
  				*start_rgn = idx;
  			*end_rgn = idx + 1;
6a9ceb31c   Tejun Heo   memblock: Separat...
750
751
752
753
754
  		}
  	}
  
  	return 0;
  }
6a9ceb31c   Tejun Heo   memblock: Separat...
755

35bd16a22   Alexander Kuleshov   mm/memblock: make...
756
  static int __init_memblock memblock_remove_range(struct memblock_type *type,
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
757
  					  phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
758
  {
719361809   Tejun Heo   memblock: Reimple...
759
760
  	int start_rgn, end_rgn;
  	int i, ret;
95f72d1ed   Yinghai Lu   lmb: rename to me...
761

719361809   Tejun Heo   memblock: Reimple...
762
763
764
  	ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);
  	if (ret)
  		return ret;
95f72d1ed   Yinghai Lu   lmb: rename to me...
765

719361809   Tejun Heo   memblock: Reimple...
766
767
  	for (i = end_rgn - 1; i >= start_rgn; i--)
  		memblock_remove_region(type, i);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
768
  	return 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
769
  }
581adcbe1   Tejun Heo   memblock: Make me...
770
  int __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
771
  {
25cf23d7a   Minchan Kim   mm/memblock: prin...
772
773
774
775
776
  	phys_addr_t end = base + size - 1;
  
  	memblock_dbg("memblock_remove: [%pa-%pa] %pS
  ",
  		     &base, &end, (void *)_RET_IP_);
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
777
  	return memblock_remove_range(&memblock.memory, base, size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
778
  }
4d72868c8   Mike Rapoport   memblock: replace...
779
780
781
782
783
784
785
786
  /**
   * memblock_free - free boot memory block
   * @base: phys starting address of the  boot memory block
   * @size: size of the boot memory block in bytes
   *
   * Free boot memory block previously allocated by memblock_alloc_xx() API.
   * The freeing memory will not be released to the buddy allocator.
   */
581adcbe1   Tejun Heo   memblock: Make me...
787
  int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
788
  {
5d63f81c9   Miles Chen   mm/memblock.c: re...
789
  	phys_addr_t end = base + size - 1;
d75f773c8   Sakari Ailus   treewide: Switch ...
790
791
  	memblock_dbg("   memblock_free: [%pa-%pa] %pS
  ",
5d63f81c9   Miles Chen   mm/memblock.c: re...
792
  		     &base, &end, (void *)_RET_IP_);
24aa07882   Tejun Heo   memblock, x86: Re...
793

9099daed9   Catalin Marinas   mm: kmemleak: avo...
794
  	kmemleak_free_part_phys(base, size);
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
795
  	return memblock_remove_range(&memblock.reserved, base, size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
796
  }
f705ac4b3   Alexander Kuleshov   mm/memblock.c: mo...
797
  int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
798
  {
5d63f81c9   Miles Chen   mm/memblock.c: re...
799
  	phys_addr_t end = base + size - 1;
d75f773c8   Sakari Ailus   treewide: Switch ...
800
801
  	memblock_dbg("memblock_reserve: [%pa-%pa] %pS
  ",
5d63f81c9   Miles Chen   mm/memblock.c: re...
802
  		     &base, &end, (void *)_RET_IP_);
95f72d1ed   Yinghai Lu   lmb: rename to me...
803

f705ac4b3   Alexander Kuleshov   mm/memblock.c: mo...
804
  	return memblock_add_range(&memblock.reserved, base, size, MAX_NUMNODES, 0);
95f72d1ed   Yinghai Lu   lmb: rename to me...
805
  }
35fd0808d   Tejun Heo   memblock: Impleme...
806
  /**
47cec4432   Mike Rapoport   docs/mm: memblock...
807
808
809
810
811
   * memblock_setclr_flag - set or clear flag for a memory region
   * @base: base address of the region
   * @size: size of the region
   * @set: set or clear the flag
   * @flag: the flag to udpate
66b16edf9   Tang Chen   memblock, mem_hot...
812
   *
4308ce17f   Tony Luck   mm/memblock.c: re...
813
   * This function isolates region [@base, @base + @size), and sets/clears flag
66b16edf9   Tang Chen   memblock, mem_hot...
814
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
815
   * Return: 0 on success, -errno on failure.
66b16edf9   Tang Chen   memblock, mem_hot...
816
   */
4308ce17f   Tony Luck   mm/memblock.c: re...
817
818
  static int __init_memblock memblock_setclr_flag(phys_addr_t base,
  				phys_addr_t size, int set, int flag)
66b16edf9   Tang Chen   memblock, mem_hot...
819
820
821
822
823
824
825
  {
  	struct memblock_type *type = &memblock.memory;
  	int i, ret, start_rgn, end_rgn;
  
  	ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);
  	if (ret)
  		return ret;
fe145124d   Mike Rapoport   memblock: remove ...
826
827
  	for (i = start_rgn; i < end_rgn; i++) {
  		struct memblock_region *r = &type->regions[i];
4308ce17f   Tony Luck   mm/memblock.c: re...
828
  		if (set)
fe145124d   Mike Rapoport   memblock: remove ...
829
  			r->flags |= flag;
4308ce17f   Tony Luck   mm/memblock.c: re...
830
  		else
fe145124d   Mike Rapoport   memblock: remove ...
831
832
  			r->flags &= ~flag;
  	}
66b16edf9   Tang Chen   memblock, mem_hot...
833
834
835
836
837
838
  
  	memblock_merge_regions(type);
  	return 0;
  }
  
  /**
4308ce17f   Tony Luck   mm/memblock.c: re...
839
   * memblock_mark_hotplug - Mark hotpluggable memory with flag MEMBLOCK_HOTPLUG.
66b16edf9   Tang Chen   memblock, mem_hot...
840
841
842
   * @base: the base phys addr of the region
   * @size: the size of the region
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
843
   * Return: 0 on success, -errno on failure.
4308ce17f   Tony Luck   mm/memblock.c: re...
844
845
846
847
848
849
850
851
852
853
   */
  int __init_memblock memblock_mark_hotplug(phys_addr_t base, phys_addr_t size)
  {
  	return memblock_setclr_flag(base, size, 1, MEMBLOCK_HOTPLUG);
  }
  
  /**
   * memblock_clear_hotplug - Clear flag MEMBLOCK_HOTPLUG for a specified region.
   * @base: the base phys addr of the region
   * @size: the size of the region
66b16edf9   Tang Chen   memblock, mem_hot...
854
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
855
   * Return: 0 on success, -errno on failure.
66b16edf9   Tang Chen   memblock, mem_hot...
856
857
858
   */
  int __init_memblock memblock_clear_hotplug(phys_addr_t base, phys_addr_t size)
  {
4308ce17f   Tony Luck   mm/memblock.c: re...
859
  	return memblock_setclr_flag(base, size, 0, MEMBLOCK_HOTPLUG);
66b16edf9   Tang Chen   memblock, mem_hot...
860
861
862
  }
  
  /**
a3f5bafcc   Tony Luck   mm/memblock: allo...
863
864
865
866
   * memblock_mark_mirror - Mark mirrored memory with flag MEMBLOCK_MIRROR.
   * @base: the base phys addr of the region
   * @size: the size of the region
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
867
   * Return: 0 on success, -errno on failure.
a3f5bafcc   Tony Luck   mm/memblock: allo...
868
869
870
871
872
873
874
   */
  int __init_memblock memblock_mark_mirror(phys_addr_t base, phys_addr_t size)
  {
  	system_has_some_mirror = true;
  
  	return memblock_setclr_flag(base, size, 1, MEMBLOCK_MIRROR);
  }
bf3d3cc58   Ard Biesheuvel   mm/memblock: add ...
875
876
877
878
879
  /**
   * memblock_mark_nomap - Mark a memory region with flag MEMBLOCK_NOMAP.
   * @base: the base phys addr of the region
   * @size: the size of the region
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
880
   * Return: 0 on success, -errno on failure.
bf3d3cc58   Ard Biesheuvel   mm/memblock: add ...
881
882
883
884
885
   */
  int __init_memblock memblock_mark_nomap(phys_addr_t base, phys_addr_t size)
  {
  	return memblock_setclr_flag(base, size, 1, MEMBLOCK_NOMAP);
  }
a3f5bafcc   Tony Luck   mm/memblock: allo...
886
887
  
  /**
4c546b8a3   AKASHI Takahiro   memblock: add mem...
888
889
890
891
   * memblock_clear_nomap - Clear flag MEMBLOCK_NOMAP for a specified region.
   * @base: the base phys addr of the region
   * @size: the size of the region
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
892
   * Return: 0 on success, -errno on failure.
4c546b8a3   AKASHI Takahiro   memblock: add mem...
893
894
895
896
897
898
899
   */
  int __init_memblock memblock_clear_nomap(phys_addr_t base, phys_addr_t size)
  {
  	return memblock_setclr_flag(base, size, 0, MEMBLOCK_NOMAP);
  }
  
  /**
8e7a7f861   Robin Holt   memblock: introdu...
900
901
902
903
904
905
906
907
908
909
910
   * __next_reserved_mem_region - next function for for_each_reserved_region()
   * @idx: pointer to u64 loop variable
   * @out_start: ptr to phys_addr_t for start address of the region, can be %NULL
   * @out_end: ptr to phys_addr_t for end address of the region, can be %NULL
   *
   * Iterate over all reserved memory regions.
   */
  void __init_memblock __next_reserved_mem_region(u64 *idx,
  					   phys_addr_t *out_start,
  					   phys_addr_t *out_end)
  {
567d117b8   Alexander Kuleshov   mm/memblock.c: re...
911
  	struct memblock_type *type = &memblock.reserved;
8e7a7f861   Robin Holt   memblock: introdu...
912

cd33a76b0   Richard Leitner   mm/memblock.c: re...
913
  	if (*idx < type->cnt) {
567d117b8   Alexander Kuleshov   mm/memblock.c: re...
914
  		struct memblock_region *r = &type->regions[*idx];
8e7a7f861   Robin Holt   memblock: introdu...
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
  		phys_addr_t base = r->base;
  		phys_addr_t size = r->size;
  
  		if (out_start)
  			*out_start = base;
  		if (out_end)
  			*out_end = base + size - 1;
  
  		*idx += 1;
  		return;
  	}
  
  	/* signal end of iteration */
  	*idx = ULLONG_MAX;
  }
c9a688a3e   Mike Rapoport   memblock: split c...
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
  static bool should_skip_region(struct memblock_region *m, int nid, int flags)
  {
  	int m_nid = memblock_get_region_node(m);
  
  	/* only memory regions are associated with nodes, check it */
  	if (nid != NUMA_NO_NODE && nid != m_nid)
  		return true;
  
  	/* skip hotpluggable memory regions if needed */
  	if (movable_node_is_enabled() && memblock_is_hotpluggable(m))
  		return true;
  
  	/* if we want mirror memory skip non-mirror memory regions */
  	if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
  		return true;
  
  	/* skip nomap memory unless we were asked for it explicitly */
  	if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
  		return true;
  
  	return false;
  }
8e7a7f861   Robin Holt   memblock: introdu...
952
  /**
a2974133b   Mike Rapoport   mm: memblock: upd...
953
   * __next_mem_range - next function for for_each_free_mem_range() etc.
35fd0808d   Tejun Heo   memblock: Impleme...
954
   * @idx: pointer to u64 loop variable
b11542335   Grygorii Strashko   mm/memblock: swit...
955
   * @nid: node selector, %NUMA_NO_NODE for all nodes
fc6daaf93   Tony Luck   mm/memblock: add ...
956
   * @flags: pick from blocks based on memory attributes
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
957
958
   * @type_a: pointer to memblock_type from where the range is taken
   * @type_b: pointer to memblock_type which excludes memory from being taken
dad7557eb   Wanpeng Li   mm: fix kernel-do...
959
960
961
   * @out_start: ptr to phys_addr_t for start address of the range, can be %NULL
   * @out_end: ptr to phys_addr_t for end address of the range, can be %NULL
   * @out_nid: ptr to int for nid of the range, can be %NULL
35fd0808d   Tejun Heo   memblock: Impleme...
962
   *
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
963
   * Find the first area from *@idx which matches @nid, fill the out
35fd0808d   Tejun Heo   memblock: Impleme...
964
   * parameters, and update *@idx for the next iteration.  The lower 32bit of
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
965
966
   * *@idx contains index into type_a and the upper 32bit indexes the
   * areas before each region in type_b.	For example, if type_b regions
35fd0808d   Tejun Heo   memblock: Impleme...
967
968
969
970
971
972
973
974
975
976
977
   * look like the following,
   *
   *	0:[0-16), 1:[32-48), 2:[128-130)
   *
   * The upper 32bit indexes the following regions.
   *
   *	0:[0-0), 1:[16-32), 2:[48-128), 3:[130-MAX)
   *
   * As both region arrays are sorted, the function advances the two indices
   * in lockstep and returns each intersection.
   */
e1720fee2   Mike Rapoport   mm/memblock: add ...
978
979
  void __init_memblock __next_mem_range(u64 *idx, int nid,
  				      enum memblock_flags flags,
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
980
981
982
983
  				      struct memblock_type *type_a,
  				      struct memblock_type *type_b,
  				      phys_addr_t *out_start,
  				      phys_addr_t *out_end, int *out_nid)
35fd0808d   Tejun Heo   memblock: Impleme...
984
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
985
986
  	int idx_a = *idx & 0xffffffff;
  	int idx_b = *idx >> 32;
b11542335   Grygorii Strashko   mm/memblock: swit...
987

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
988
989
990
  	if (WARN_ONCE(nid == MAX_NUMNODES,
  	"Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead
  "))
560dca27a   Grygorii Strashko   mm/memblock: use ...
991
  		nid = NUMA_NO_NODE;
35fd0808d   Tejun Heo   memblock: Impleme...
992

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
993
994
  	for (; idx_a < type_a->cnt; idx_a++) {
  		struct memblock_region *m = &type_a->regions[idx_a];
35fd0808d   Tejun Heo   memblock: Impleme...
995
996
  		phys_addr_t m_start = m->base;
  		phys_addr_t m_end = m->base + m->size;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
997
  		int	    m_nid = memblock_get_region_node(m);
35fd0808d   Tejun Heo   memblock: Impleme...
998

c9a688a3e   Mike Rapoport   memblock: split c...
999
  		if (should_skip_region(m, nid, flags))
bf3d3cc58   Ard Biesheuvel   mm/memblock: add ...
1000
  			continue;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
  		if (!type_b) {
  			if (out_start)
  				*out_start = m_start;
  			if (out_end)
  				*out_end = m_end;
  			if (out_nid)
  				*out_nid = m_nid;
  			idx_a++;
  			*idx = (u32)idx_a | (u64)idx_b << 32;
  			return;
  		}
  
  		/* scan areas before each reservation */
  		for (; idx_b < type_b->cnt + 1; idx_b++) {
  			struct memblock_region *r;
  			phys_addr_t r_start;
  			phys_addr_t r_end;
  
  			r = &type_b->regions[idx_b];
  			r_start = idx_b ? r[-1].base + r[-1].size : 0;
  			r_end = idx_b < type_b->cnt ?
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1022
  				r->base : PHYS_ADDR_MAX;
35fd0808d   Tejun Heo   memblock: Impleme...
1023

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1024
1025
1026
1027
  			/*
  			 * if idx_b advanced past idx_a,
  			 * break out to advance idx_a
  			 */
35fd0808d   Tejun Heo   memblock: Impleme...
1028
1029
1030
1031
1032
  			if (r_start >= m_end)
  				break;
  			/* if the two regions intersect, we're done */
  			if (m_start < r_end) {
  				if (out_start)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1033
1034
  					*out_start =
  						max(m_start, r_start);
35fd0808d   Tejun Heo   memblock: Impleme...
1035
1036
1037
  				if (out_end)
  					*out_end = min(m_end, r_end);
  				if (out_nid)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1038
  					*out_nid = m_nid;
35fd0808d   Tejun Heo   memblock: Impleme...
1039
  				/*
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1040
1041
  				 * The region which ends first is
  				 * advanced for the next iteration.
35fd0808d   Tejun Heo   memblock: Impleme...
1042
1043
  				 */
  				if (m_end <= r_end)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1044
  					idx_a++;
35fd0808d   Tejun Heo   memblock: Impleme...
1045
  				else
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1046
1047
  					idx_b++;
  				*idx = (u32)idx_a | (u64)idx_b << 32;
35fd0808d   Tejun Heo   memblock: Impleme...
1048
1049
1050
1051
1052
1053
1054
1055
  				return;
  			}
  		}
  	}
  
  	/* signal end of iteration */
  	*idx = ULLONG_MAX;
  }
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1056
  /**
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1057
1058
   * __next_mem_range_rev - generic next function for for_each_*_range_rev()
   *
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1059
   * @idx: pointer to u64 loop variable
ad5ea8cd5   Alexander Kuleshov   mm/memblock.c: fi...
1060
   * @nid: node selector, %NUMA_NO_NODE for all nodes
fc6daaf93   Tony Luck   mm/memblock: add ...
1061
   * @flags: pick from blocks based on memory attributes
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1062
1063
   * @type_a: pointer to memblock_type from where the range is taken
   * @type_b: pointer to memblock_type which excludes memory from being taken
dad7557eb   Wanpeng Li   mm: fix kernel-do...
1064
1065
1066
   * @out_start: ptr to phys_addr_t for start address of the range, can be %NULL
   * @out_end: ptr to phys_addr_t for end address of the range, can be %NULL
   * @out_nid: ptr to int for nid of the range, can be %NULL
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1067
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1068
1069
1070
   * Finds the next range from type_a which is not marked as unsuitable
   * in type_b.
   *
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1071
   * Reverse of __next_mem_range().
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1072
   */
e1720fee2   Mike Rapoport   mm/memblock: add ...
1073
1074
  void __init_memblock __next_mem_range_rev(u64 *idx, int nid,
  					  enum memblock_flags flags,
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1075
1076
1077
1078
  					  struct memblock_type *type_a,
  					  struct memblock_type *type_b,
  					  phys_addr_t *out_start,
  					  phys_addr_t *out_end, int *out_nid)
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1079
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1080
1081
  	int idx_a = *idx & 0xffffffff;
  	int idx_b = *idx >> 32;
b11542335   Grygorii Strashko   mm/memblock: swit...
1082

560dca27a   Grygorii Strashko   mm/memblock: use ...
1083
1084
1085
  	if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead
  "))
  		nid = NUMA_NO_NODE;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1086
1087
  
  	if (*idx == (u64)ULLONG_MAX) {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1088
  		idx_a = type_a->cnt - 1;
e47608ab6   zijun_hu   mm/memblock.c: fi...
1089
1090
1091
1092
  		if (type_b != NULL)
  			idx_b = type_b->cnt;
  		else
  			idx_b = 0;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1093
  	}
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1094
1095
  	for (; idx_a >= 0; idx_a--) {
  		struct memblock_region *m = &type_a->regions[idx_a];
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1096
1097
  		phys_addr_t m_start = m->base;
  		phys_addr_t m_end = m->base + m->size;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1098
  		int m_nid = memblock_get_region_node(m);
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1099

c9a688a3e   Mike Rapoport   memblock: split c...
1100
  		if (should_skip_region(m, nid, flags))
bf3d3cc58   Ard Biesheuvel   mm/memblock: add ...
1101
  			continue;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1102
1103
1104
1105
1106
1107
1108
  		if (!type_b) {
  			if (out_start)
  				*out_start = m_start;
  			if (out_end)
  				*out_end = m_end;
  			if (out_nid)
  				*out_nid = m_nid;
fb399b485   zijun_hu   mm/memblock.c: fi...
1109
  			idx_a--;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
  			*idx = (u32)idx_a | (u64)idx_b << 32;
  			return;
  		}
  
  		/* scan areas before each reservation */
  		for (; idx_b >= 0; idx_b--) {
  			struct memblock_region *r;
  			phys_addr_t r_start;
  			phys_addr_t r_end;
  
  			r = &type_b->regions[idx_b];
  			r_start = idx_b ? r[-1].base + r[-1].size : 0;
  			r_end = idx_b < type_b->cnt ?
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1123
  				r->base : PHYS_ADDR_MAX;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1124
1125
1126
1127
  			/*
  			 * if idx_b advanced past idx_a,
  			 * break out to advance idx_a
  			 */
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1128

7bd0b0f0d   Tejun Heo   memblock: Reimple...
1129
1130
1131
1132
1133
1134
1135
1136
1137
  			if (r_end <= m_start)
  				break;
  			/* if the two regions intersect, we're done */
  			if (m_end > r_start) {
  				if (out_start)
  					*out_start = max(m_start, r_start);
  				if (out_end)
  					*out_end = min(m_end, r_end);
  				if (out_nid)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1138
  					*out_nid = m_nid;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1139
  				if (m_start >= r_start)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1140
  					idx_a--;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1141
  				else
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1142
1143
  					idx_b--;
  				*idx = (u32)idx_a | (u64)idx_b << 32;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1144
1145
1146
1147
  				return;
  			}
  		}
  	}
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1148
  	/* signal end of iteration */
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1149
1150
  	*idx = ULLONG_MAX;
  }
7c0caeb86   Tejun Heo   memblock: Add opt...
1151
1152
  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
  /*
45e79815b   Chen Chang   mm/memblock.c: fi...
1153
   * Common iterator interface used to define for_each_mem_pfn_range().
7c0caeb86   Tejun Heo   memblock: Add opt...
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
   */
  void __init_memblock __next_mem_pfn_range(int *idx, int nid,
  				unsigned long *out_start_pfn,
  				unsigned long *out_end_pfn, int *out_nid)
  {
  	struct memblock_type *type = &memblock.memory;
  	struct memblock_region *r;
  
  	while (++*idx < type->cnt) {
  		r = &type->regions[*idx];
  
  		if (PFN_UP(r->base) >= PFN_DOWN(r->base + r->size))
  			continue;
  		if (nid == MAX_NUMNODES || nid == r->nid)
  			break;
  	}
  	if (*idx >= type->cnt) {
  		*idx = -1;
  		return;
  	}
  
  	if (out_start_pfn)
  		*out_start_pfn = PFN_UP(r->base);
  	if (out_end_pfn)
  		*out_end_pfn = PFN_DOWN(r->base + r->size);
  	if (out_nid)
  		*out_nid = r->nid;
  }
  
  /**
   * memblock_set_node - set node ID on memblock regions
   * @base: base of area to set node ID for
   * @size: size of area to set node ID for
e7e8de591   Tang Chen   memblock: make me...
1187
   * @type: memblock type to set node ID for
7c0caeb86   Tejun Heo   memblock: Add opt...
1188
1189
   * @nid: node ID to set
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1190
   * Set the nid of memblock @type regions in [@base, @base + @size) to @nid.
7c0caeb86   Tejun Heo   memblock: Add opt...
1191
1192
   * Regions which cross the area boundaries are split as necessary.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1193
   * Return:
7c0caeb86   Tejun Heo   memblock: Add opt...
1194
1195
1196
   * 0 on success, -errno on failure.
   */
  int __init_memblock memblock_set_node(phys_addr_t base, phys_addr_t size,
e7e8de591   Tang Chen   memblock: make me...
1197
  				      struct memblock_type *type, int nid)
7c0caeb86   Tejun Heo   memblock: Add opt...
1198
  {
6a9ceb31c   Tejun Heo   memblock: Separat...
1199
1200
  	int start_rgn, end_rgn;
  	int i, ret;
7c0caeb86   Tejun Heo   memblock: Add opt...
1201

6a9ceb31c   Tejun Heo   memblock: Separat...
1202
1203
1204
  	ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);
  	if (ret)
  		return ret;
7c0caeb86   Tejun Heo   memblock: Add opt...
1205

6a9ceb31c   Tejun Heo   memblock: Separat...
1206
  	for (i = start_rgn; i < end_rgn; i++)
e9d24ad30   Wanpeng Li   mm/memblock: use ...
1207
  		memblock_set_region_node(&type->regions[i], nid);
7c0caeb86   Tejun Heo   memblock: Add opt...
1208
1209
1210
1211
1212
  
  	memblock_merge_regions(type);
  	return 0;
  }
  #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
837566e7e   Alexander Duyck   mm: implement new...
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
  #ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
  /**
   * __next_mem_pfn_range_in_zone - iterator for for_each_*_range_in_zone()
   *
   * @idx: pointer to u64 loop variable
   * @zone: zone in which all of the memory blocks reside
   * @out_spfn: ptr to ulong for start pfn of the range, can be %NULL
   * @out_epfn: ptr to ulong for end pfn of the range, can be %NULL
   *
   * This function is meant to be a zone/pfn specific wrapper for the
   * for_each_mem_range type iterators. Specifically they are used in the
   * deferred memory init routines and as such we were duplicating much of
   * this logic throughout the code. So instead of having it in multiple
   * locations it seemed like it would make more sense to centralize this to
   * one new iterator that does everything they need.
   */
  void __init_memblock
  __next_mem_pfn_range_in_zone(u64 *idx, struct zone *zone,
  			     unsigned long *out_spfn, unsigned long *out_epfn)
  {
  	int zone_nid = zone_to_nid(zone);
  	phys_addr_t spa, epa;
  	int nid;
  
  	__next_mem_range(idx, zone_nid, MEMBLOCK_NONE,
  			 &memblock.memory, &memblock.reserved,
  			 &spa, &epa, &nid);
  
  	while (*idx != U64_MAX) {
  		unsigned long epfn = PFN_DOWN(epa);
  		unsigned long spfn = PFN_UP(spa);
  
  		/*
  		 * Verify the end is at least past the start of the zone and
  		 * that we have at least one PFN to initialize.
  		 */
  		if (zone->zone_start_pfn < epfn && spfn < epfn) {
  			/* if we went too far just stop searching */
  			if (zone_end_pfn(zone) <= spfn) {
  				*idx = U64_MAX;
  				break;
  			}
  
  			if (out_spfn)
  				*out_spfn = max(zone->zone_start_pfn, spfn);
  			if (out_epfn)
  				*out_epfn = min(zone_end_pfn(zone), epfn);
  
  			return;
  		}
  
  		__next_mem_range(idx, zone_nid, MEMBLOCK_NONE,
  				 &memblock.memory, &memblock.reserved,
  				 &spa, &epa, &nid);
  	}
  
  	/* signal end of iteration */
  	if (out_spfn)
  		*out_spfn = ULONG_MAX;
  	if (out_epfn)
  		*out_epfn = 0;
  }
  
  #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
7c0caeb86   Tejun Heo   memblock: Add opt...
1277

92d12f954   Mike Rapoport   memblock: refacto...
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
  /**
   * memblock_alloc_range_nid - allocate boot memory block
   * @size: size of memory block to be allocated in bytes
   * @align: alignment of the region and block's size
   * @start: the lower bound of the memory region to allocate (phys address)
   * @end: the upper bound of the memory region to allocate (phys address)
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
   *
   * The allocation is performed from memory region limited by
   * memblock.current_limit if @max_addr == %MEMBLOCK_ALLOC_ACCESSIBLE.
   *
   * If the specified node can not hold the requested memory the
   * allocation falls back to any node in the system
   *
   * For systems with memory mirroring, the allocation is attempted first
   * from the regions with mirroring enabled and then retried from any
   * memory region.
   *
   * In addition, function sets the min_count to 0 using kmemleak_alloc_phys for
   * allocated boot memory block, so that it is never reported as leaks.
   *
   * Return:
   * Physical address of allocated memory block on success, %0 on failure.
   */
2bfc2862c   Akinobu Mita   memblock: introdu...
1302
1303
  static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
  					phys_addr_t align, phys_addr_t start,
92d12f954   Mike Rapoport   memblock: refacto...
1304
  					phys_addr_t end, int nid)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1305
  {
92d12f954   Mike Rapoport   memblock: refacto...
1306
  	enum memblock_flags flags = choose_memblock_flags();
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1307
  	phys_addr_t found;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1308

92d12f954   Mike Rapoport   memblock: refacto...
1309
1310
1311
  	if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead
  "))
  		nid = NUMA_NO_NODE;
2f770806f   Mike Rapoport   mm/memblock.c: wa...
1312
1313
1314
1315
1316
  	if (!align) {
  		/* Can't use WARNs this early in boot on powerpc */
  		dump_stack();
  		align = SMP_CACHE_BYTES;
  	}
92d12f954   Mike Rapoport   memblock: refacto...
1317
  again:
fc6daaf93   Tony Luck   mm/memblock: add ...
1318
1319
  	found = memblock_find_in_range_node(size, align, start, end, nid,
  					    flags);
92d12f954   Mike Rapoport   memblock: refacto...
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
  	if (found && !memblock_reserve(found, size))
  		goto done;
  
  	if (nid != NUMA_NO_NODE) {
  		found = memblock_find_in_range_node(size, align, start,
  						    end, NUMA_NO_NODE,
  						    flags);
  		if (found && !memblock_reserve(found, size))
  			goto done;
  	}
  
  	if (flags & MEMBLOCK_MIRROR) {
  		flags &= ~MEMBLOCK_MIRROR;
  		pr_warn("Could not allocate %pap bytes of mirrored memory
  ",
  			&size);
  		goto again;
  	}
  
  	return 0;
  
  done:
  	/* Skip kmemleak for kasan_init() due to high volume. */
  	if (end != MEMBLOCK_ALLOC_KASAN)
aedf95ea0   Catalin Marinas   mm/memblock.c: ca...
1344
  		/*
92d12f954   Mike Rapoport   memblock: refacto...
1345
1346
1347
1348
  		 * The min_count is set to 0 so that memblock allocated
  		 * blocks are never reported as leaks. This is because many
  		 * of these blocks are only referred via the physical
  		 * address which is not looked up by kmemleak.
aedf95ea0   Catalin Marinas   mm/memblock.c: ca...
1349
  		 */
9099daed9   Catalin Marinas   mm: kmemleak: avo...
1350
  		kmemleak_alloc_phys(found, size, 0, 0);
92d12f954   Mike Rapoport   memblock: refacto...
1351
1352
  
  	return found;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1353
  }
a2974133b   Mike Rapoport   mm: memblock: upd...
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
  /**
   * memblock_phys_alloc_range - allocate a memory block inside specified range
   * @size: size of memory block to be allocated in bytes
   * @align: alignment of the region and block's size
   * @start: the lower bound of the memory region to allocate (physical address)
   * @end: the upper bound of the memory region to allocate (physical address)
   *
   * Allocate @size bytes in the between @start and @end.
   *
   * Return: physical address of the allocated memory block on success,
   * %0 on failure.
   */
8a770c2a8   Mike Rapoport   memblock: emphasi...
1366
1367
1368
1369
  phys_addr_t __init memblock_phys_alloc_range(phys_addr_t size,
  					     phys_addr_t align,
  					     phys_addr_t start,
  					     phys_addr_t end)
2bfc2862c   Akinobu Mita   memblock: introdu...
1370
  {
92d12f954   Mike Rapoport   memblock: refacto...
1371
  	return memblock_alloc_range_nid(size, align, start, end, NUMA_NO_NODE);
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1372
  }
a2974133b   Mike Rapoport   mm: memblock: upd...
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
  /**
   * memblock_phys_alloc_try_nid - allocate a memory block from specified MUMA node
   * @size: size of memory block to be allocated in bytes
   * @align: alignment of the region and block's size
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
   *
   * Allocates memory block from the specified NUMA node. If the node
   * has no available memory, attempts to allocated from any node in the
   * system.
   *
   * Return: physical address of the allocated memory block on success,
   * %0 on failure.
   */
9a8dd708d   Mike Rapoport   memblock: rename ...
1386
  phys_addr_t __init memblock_phys_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid)
9d1e24928   Benjamin Herrenschmidt   memblock: Separat...
1387
  {
337555744   Mike Rapoport   memblock: membloc...
1388
  	return memblock_alloc_range_nid(size, align, 0,
92d12f954   Mike Rapoport   memblock: refacto...
1389
  					MEMBLOCK_ALLOC_ACCESSIBLE, nid);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1390
  }
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1391
  /**
eb31d559f   Mike Rapoport   memblock: remove ...
1392
   * memblock_alloc_internal - allocate boot memory block
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1393
1394
1395
1396
1397
1398
   * @size: size of memory block to be allocated in bytes
   * @align: alignment of the region and block's size
   * @min_addr: the lower bound of the memory region to allocate (phys address)
   * @max_addr: the upper bound of the memory region to allocate (phys address)
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
   *
92d12f954   Mike Rapoport   memblock: refacto...
1399
1400
   * Allocates memory block using memblock_alloc_range_nid() and
   * converts the returned physical address to virtual.
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1401
   *
92d12f954   Mike Rapoport   memblock: refacto...
1402
1403
1404
1405
   * The @min_addr limit is dropped if it can not be satisfied and the allocation
   * will fall back to memory below @min_addr. Other constraints, such
   * as node and mirrored memory will be handled again in
   * memblock_alloc_range_nid().
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1406
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1407
   * Return:
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1408
1409
   * Virtual address of allocated memory block on success, NULL on failure.
   */
eb31d559f   Mike Rapoport   memblock: remove ...
1410
  static void * __init memblock_alloc_internal(
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1411
1412
1413
1414
1415
  				phys_addr_t size, phys_addr_t align,
  				phys_addr_t min_addr, phys_addr_t max_addr,
  				int nid)
  {
  	phys_addr_t alloc;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1416
1417
1418
1419
  
  	/*
  	 * Detect any accidental use of these APIs after slab is ready, as at
  	 * this moment memblock may be deinitialized already and its
c6ffc5ca8   Mike Rapoport   memblock: rename ...
1420
  	 * internal data may be destroyed (after execution of memblock_free_all)
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1421
1422
1423
  	 */
  	if (WARN_ON_ONCE(slab_is_available()))
  		return kzalloc_node(size, GFP_NOWAIT, nid);
f3057ad76   Mike Rapoport   mm: memblock: do ...
1424
1425
  	if (max_addr > memblock.current_limit)
  		max_addr = memblock.current_limit;
92d12f954   Mike Rapoport   memblock: refacto...
1426
  	alloc = memblock_alloc_range_nid(size, align, min_addr, max_addr, nid);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1427

92d12f954   Mike Rapoport   memblock: refacto...
1428
1429
1430
  	/* retry allocation without lower limit */
  	if (!alloc && min_addr)
  		alloc = memblock_alloc_range_nid(size, align, 0, max_addr, nid);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1431

92d12f954   Mike Rapoport   memblock: refacto...
1432
1433
  	if (!alloc)
  		return NULL;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1434

92d12f954   Mike Rapoport   memblock: refacto...
1435
  	return phys_to_virt(alloc);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1436
1437
1438
  }
  
  /**
eb31d559f   Mike Rapoport   memblock: remove ...
1439
   * memblock_alloc_try_nid_raw - allocate boot memory block without zeroing
ea1f5f371   Pavel Tatashin   mm: define memblo...
1440
1441
1442
1443
1444
1445
   * memory and without panicking
   * @size: size of memory block to be allocated in bytes
   * @align: alignment of the region and block's size
   * @min_addr: the lower bound of the memory region from where the allocation
   *	  is preferred (phys address)
   * @max_addr: the upper bound of the memory region from where the allocation
97ad1087e   Mike Rapoport   memblock: replace...
1446
   *	      is preferred (phys address), or %MEMBLOCK_ALLOC_ACCESSIBLE to
ea1f5f371   Pavel Tatashin   mm: define memblo...
1447
1448
1449
1450
1451
1452
1453
   *	      allocate only from memory limited by memblock.current_limit value
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
   *
   * Public function, provides additional debug information (including caller
   * info), if enabled. Does not zero allocated memory, does not panic if request
   * cannot be satisfied.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1454
   * Return:
ea1f5f371   Pavel Tatashin   mm: define memblo...
1455
1456
   * Virtual address of allocated memory block on success, NULL on failure.
   */
eb31d559f   Mike Rapoport   memblock: remove ...
1457
  void * __init memblock_alloc_try_nid_raw(
ea1f5f371   Pavel Tatashin   mm: define memblo...
1458
1459
1460
1461
1462
  			phys_addr_t size, phys_addr_t align,
  			phys_addr_t min_addr, phys_addr_t max_addr,
  			int nid)
  {
  	void *ptr;
d75f773c8   Sakari Ailus   treewide: Switch ...
1463
1464
  	memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pS
  ",
a36aab890   Mike Rapoport   mm/memblock.c: re...
1465
1466
  		     __func__, (u64)size, (u64)align, nid, &min_addr,
  		     &max_addr, (void *)_RET_IP_);
ea1f5f371   Pavel Tatashin   mm: define memblo...
1467

eb31d559f   Mike Rapoport   memblock: remove ...
1468
  	ptr = memblock_alloc_internal(size, align,
ea1f5f371   Pavel Tatashin   mm: define memblo...
1469
  					   min_addr, max_addr, nid);
ea1f5f371   Pavel Tatashin   mm: define memblo...
1470
  	if (ptr && size > 0)
f682a97a0   Alexander Duyck   mm: provide kerne...
1471
  		page_init_poison(ptr, size);
ea1f5f371   Pavel Tatashin   mm: define memblo...
1472
1473
1474
1475
  	return ptr;
  }
  
  /**
c0dbe825a   Mike Rapoport   memblock: membloc...
1476
   * memblock_alloc_try_nid - allocate boot memory block
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1477
1478
1479
1480
1481
   * @size: size of memory block to be allocated in bytes
   * @align: alignment of the region and block's size
   * @min_addr: the lower bound of the memory region from where the allocation
   *	  is preferred (phys address)
   * @max_addr: the upper bound of the memory region from where the allocation
97ad1087e   Mike Rapoport   memblock: replace...
1482
   *	      is preferred (phys address), or %MEMBLOCK_ALLOC_ACCESSIBLE to
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1483
1484
1485
   *	      allocate only from memory limited by memblock.current_limit value
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
   *
c0dbe825a   Mike Rapoport   memblock: membloc...
1486
1487
   * Public function, provides additional debug information (including caller
   * info), if enabled. This function zeroes the allocated memory.
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1488
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1489
   * Return:
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1490
1491
   * Virtual address of allocated memory block on success, NULL on failure.
   */
eb31d559f   Mike Rapoport   memblock: remove ...
1492
  void * __init memblock_alloc_try_nid(
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1493
1494
1495
1496
1497
  			phys_addr_t size, phys_addr_t align,
  			phys_addr_t min_addr, phys_addr_t max_addr,
  			int nid)
  {
  	void *ptr;
d75f773c8   Sakari Ailus   treewide: Switch ...
1498
1499
  	memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pS
  ",
a36aab890   Mike Rapoport   mm/memblock.c: re...
1500
1501
  		     __func__, (u64)size, (u64)align, nid, &min_addr,
  		     &max_addr, (void *)_RET_IP_);
eb31d559f   Mike Rapoport   memblock: remove ...
1502
  	ptr = memblock_alloc_internal(size, align,
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1503
  					   min_addr, max_addr, nid);
c0dbe825a   Mike Rapoport   memblock: membloc...
1504
  	if (ptr)
ea1f5f371   Pavel Tatashin   mm: define memblo...
1505
  		memset(ptr, 0, size);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1506

c0dbe825a   Mike Rapoport   memblock: membloc...
1507
  	return ptr;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1508
1509
1510
  }
  
  /**
a2974133b   Mike Rapoport   mm: memblock: upd...
1511
   * __memblock_free_late - free pages directly to buddy allocator
48a833cc7   Mike Rapoport   docs/mm: memblock...
1512
   * @base: phys starting address of the  boot memory block
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1513
1514
   * @size: size of the boot memory block in bytes
   *
a2974133b   Mike Rapoport   mm: memblock: upd...
1515
   * This is only useful when the memblock allocator has already been torn
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1516
   * down, but we are still initializing the system.  Pages are released directly
a2974133b   Mike Rapoport   mm: memblock: upd...
1517
   * to the buddy allocator.
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1518
1519
1520
   */
  void __init __memblock_free_late(phys_addr_t base, phys_addr_t size)
  {
a36aab890   Mike Rapoport   mm/memblock.c: re...
1521
  	phys_addr_t cursor, end;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1522

a36aab890   Mike Rapoport   mm/memblock.c: re...
1523
  	end = base + size - 1;
d75f773c8   Sakari Ailus   treewide: Switch ...
1524
1525
  	memblock_dbg("%s: [%pa-%pa] %pS
  ",
a36aab890   Mike Rapoport   mm/memblock.c: re...
1526
  		     __func__, &base, &end, (void *)_RET_IP_);
9099daed9   Catalin Marinas   mm: kmemleak: avo...
1527
  	kmemleak_free_part_phys(base, size);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1528
1529
1530
1531
  	cursor = PFN_UP(base);
  	end = PFN_DOWN(base + size);
  
  	for (; cursor < end; cursor++) {
7c2ee349c   Mike Rapoport   memblock: rename ...
1532
  		memblock_free_pages(pfn_to_page(cursor), cursor, 0);
ca79b0c21   Arun KS   mm: convert total...
1533
  		totalram_pages_inc();
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1534
1535
  	}
  }
9d1e24928   Benjamin Herrenschmidt   memblock: Separat...
1536
1537
1538
1539
  
  /*
   * Remaining API functions
   */
1f1ffb8a1   David Gibson   memblock: don't m...
1540
  phys_addr_t __init_memblock memblock_phys_mem_size(void)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1541
  {
1440c4e2c   Tejun Heo   memblock: Track t...
1542
  	return memblock.memory.total_size;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1543
  }
8907de5dc   Srikar Dronamraju   mm/memblock.c: ex...
1544
1545
1546
1547
  phys_addr_t __init_memblock memblock_reserved_size(void)
  {
  	return memblock.reserved.total_size;
  }
595ad9af8   Yinghai Lu   memblock: Add mem...
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
  phys_addr_t __init memblock_mem_size(unsigned long limit_pfn)
  {
  	unsigned long pages = 0;
  	struct memblock_region *r;
  	unsigned long start_pfn, end_pfn;
  
  	for_each_memblock(memory, r) {
  		start_pfn = memblock_region_memory_base_pfn(r);
  		end_pfn = memblock_region_memory_end_pfn(r);
  		start_pfn = min_t(unsigned long, start_pfn, limit_pfn);
  		end_pfn = min_t(unsigned long, end_pfn, limit_pfn);
  		pages += end_pfn - start_pfn;
  	}
167632303   Fabian Frederick   mm/memblock.c: us...
1561
  	return PFN_PHYS(pages);
595ad9af8   Yinghai Lu   memblock: Add mem...
1562
  }
0a93ebef6   Sam Ravnborg   memblock: add mem...
1563
1564
1565
1566
1567
  /* lowest address */
  phys_addr_t __init_memblock memblock_start_of_DRAM(void)
  {
  	return memblock.memory.regions[0].base;
  }
10d064398   Yinghai Lu   memblock: Option ...
1568
  phys_addr_t __init_memblock memblock_end_of_DRAM(void)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1569
1570
  {
  	int idx = memblock.memory.cnt - 1;
e3239ff92   Benjamin Herrenschmidt   memblock: Rename ...
1571
  	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1572
  }
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1573
  static phys_addr_t __init_memblock __find_max_addr(phys_addr_t limit)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1574
  {
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1575
  	phys_addr_t max_addr = PHYS_ADDR_MAX;
136199f0a   Emil Medve   memblock: use for...
1576
  	struct memblock_region *r;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1577

a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1578
1579
1580
  	/*
  	 * translate the memory @limit size into the max address within one of
  	 * the memory memblock regions, if the @limit exceeds the total size
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1581
  	 * of those regions, max_addr will keep original value PHYS_ADDR_MAX
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1582
  	 */
136199f0a   Emil Medve   memblock: use for...
1583
  	for_each_memblock(memory, r) {
c0ce8fef5   Tejun Heo   memblock: Reimple...
1584
1585
1586
  		if (limit <= r->size) {
  			max_addr = r->base + limit;
  			break;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1587
  		}
c0ce8fef5   Tejun Heo   memblock: Reimple...
1588
  		limit -= r->size;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1589
  	}
c0ce8fef5   Tejun Heo   memblock: Reimple...
1590

a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1591
1592
1593
1594
1595
  	return max_addr;
  }
  
  void __init memblock_enforce_memory_limit(phys_addr_t limit)
  {
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1596
  	phys_addr_t max_addr = PHYS_ADDR_MAX;
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1597
1598
1599
1600
1601
1602
1603
  
  	if (!limit)
  		return;
  
  	max_addr = __find_max_addr(limit);
  
  	/* @limit exceeds the total size of the memory, do nothing */
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1604
  	if (max_addr == PHYS_ADDR_MAX)
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1605
  		return;
c0ce8fef5   Tejun Heo   memblock: Reimple...
1606
  	/* truncate both memory and reserved regions */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1607
  	memblock_remove_range(&memblock.memory, max_addr,
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1608
  			      PHYS_ADDR_MAX);
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1609
  	memblock_remove_range(&memblock.reserved, max_addr,
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1610
  			      PHYS_ADDR_MAX);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1611
  }
c9ca9b4e2   AKASHI Takahiro   memblock: add mem...
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
  void __init memblock_cap_memory_range(phys_addr_t base, phys_addr_t size)
  {
  	int start_rgn, end_rgn;
  	int i, ret;
  
  	if (!size)
  		return;
  
  	ret = memblock_isolate_range(&memblock.memory, base, size,
  						&start_rgn, &end_rgn);
  	if (ret)
  		return;
  
  	/* remove all the MAP regions */
  	for (i = memblock.memory.cnt - 1; i >= end_rgn; i--)
  		if (!memblock_is_nomap(&memblock.memory.regions[i]))
  			memblock_remove_region(&memblock.memory, i);
  
  	for (i = start_rgn - 1; i >= 0; i--)
  		if (!memblock_is_nomap(&memblock.memory.regions[i]))
  			memblock_remove_region(&memblock.memory, i);
  
  	/* truncate the reserved regions */
  	memblock_remove_range(&memblock.reserved, 0, base);
  	memblock_remove_range(&memblock.reserved,
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1637
  			base + size, PHYS_ADDR_MAX);
c9ca9b4e2   AKASHI Takahiro   memblock: add mem...
1638
  }
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1639
1640
  void __init memblock_mem_limit_remove_map(phys_addr_t limit)
  {
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1641
  	phys_addr_t max_addr;
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1642
1643
1644
1645
1646
1647
1648
  
  	if (!limit)
  		return;
  
  	max_addr = __find_max_addr(limit);
  
  	/* @limit exceeds the total size of the memory, do nothing */
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1649
  	if (max_addr == PHYS_ADDR_MAX)
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1650
  		return;
c9ca9b4e2   AKASHI Takahiro   memblock: add mem...
1651
  	memblock_cap_memory_range(0, max_addr);
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1652
  }
cd79481d2   Yinghai Lu   memblock: Annotat...
1653
  static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
  {
  	unsigned int left = 0, right = type->cnt;
  
  	do {
  		unsigned int mid = (right + left) / 2;
  
  		if (addr < type->regions[mid].base)
  			right = mid;
  		else if (addr >= (type->regions[mid].base +
  				  type->regions[mid].size))
  			left = mid + 1;
  		else
  			return mid;
  	} while (left < right);
  	return -1;
  }
f5a222dc2   Yueyi Li   memblock: annotat...
1670
  bool __init_memblock memblock_is_reserved(phys_addr_t addr)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1671
  {
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1672
1673
  	return memblock_search(&memblock.reserved, addr) != -1;
  }
95f72d1ed   Yinghai Lu   lmb: rename to me...
1674

b4ad0c7e0   Yaowei Bai   mm/memblock.c: me...
1675
  bool __init_memblock memblock_is_memory(phys_addr_t addr)
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1676
1677
1678
  {
  	return memblock_search(&memblock.memory, addr) != -1;
  }
937f0c267   Yaowei Bai   mm/memblock: memb...
1679
  bool __init_memblock memblock_is_map_memory(phys_addr_t addr)
bf3d3cc58   Ard Biesheuvel   mm/memblock: add ...
1680
1681
1682
1683
1684
1685
1686
  {
  	int i = memblock_search(&memblock.memory, addr);
  
  	if (i == -1)
  		return false;
  	return !memblock_is_nomap(&memblock.memory.regions[i]);
  }
e76b63f80   Yinghai Lu   memblock, numa: b...
1687
1688
1689
1690
1691
  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
  int __init_memblock memblock_search_pfn_nid(unsigned long pfn,
  			 unsigned long *start_pfn, unsigned long *end_pfn)
  {
  	struct memblock_type *type = &memblock.memory;
167632303   Fabian Frederick   mm/memblock.c: us...
1692
  	int mid = memblock_search(type, PFN_PHYS(pfn));
e76b63f80   Yinghai Lu   memblock, numa: b...
1693
1694
1695
  
  	if (mid == -1)
  		return -1;
f7e2f7e89   Fabian Frederick   mm/memblock.c: us...
1696
1697
  	*start_pfn = PFN_DOWN(type->regions[mid].base);
  	*end_pfn = PFN_DOWN(type->regions[mid].base + type->regions[mid].size);
e76b63f80   Yinghai Lu   memblock, numa: b...
1698
1699
1700
1701
  
  	return type->regions[mid].nid;
  }
  #endif
eab309494   Stephen Boyd   memblock: Documen...
1702
1703
1704
1705
1706
  /**
   * memblock_is_region_memory - check if a region is a subset of memory
   * @base: base of region to check
   * @size: size of region to check
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1707
   * Check if the region [@base, @base + @size) is a subset of a memory block.
eab309494   Stephen Boyd   memblock: Documen...
1708
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1709
   * Return:
eab309494   Stephen Boyd   memblock: Documen...
1710
1711
   * 0 if false, non-zero if true
   */
937f0c267   Yaowei Bai   mm/memblock: memb...
1712
  bool __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size)
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1713
  {
abb65272a   Tomi Valkeinen   memblock: fix mem...
1714
  	int idx = memblock_search(&memblock.memory, base);
eb18f1b5b   Tejun Heo   memblock: Make me...
1715
  	phys_addr_t end = base + memblock_cap_size(base, &size);
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1716
1717
  
  	if (idx == -1)
937f0c267   Yaowei Bai   mm/memblock: memb...
1718
  		return false;
ef415ef41   Wei Yang   mm/memblock.c: tr...
1719
  	return (memblock.memory.regions[idx].base +
eb18f1b5b   Tejun Heo   memblock: Make me...
1720
  		 memblock.memory.regions[idx].size) >= end;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1721
  }
eab309494   Stephen Boyd   memblock: Documen...
1722
1723
1724
1725
1726
  /**
   * memblock_is_region_reserved - check if a region intersects reserved memory
   * @base: base of region to check
   * @size: size of region to check
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1727
1728
   * Check if the region [@base, @base + @size) intersects a reserved
   * memory block.
eab309494   Stephen Boyd   memblock: Documen...
1729
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1730
   * Return:
c5c5c9d10   Tang Chen   mm/memblock.c: ma...
1731
   * True if they intersect, false if not.
eab309494   Stephen Boyd   memblock: Documen...
1732
   */
c5c5c9d10   Tang Chen   mm/memblock.c: ma...
1733
  bool __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1734
  {
eb18f1b5b   Tejun Heo   memblock: Make me...
1735
  	memblock_cap_size(base, &size);
c5c5c9d10   Tang Chen   mm/memblock.c: ma...
1736
  	return memblock_overlaps_region(&memblock.reserved, base, size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1737
  }
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1738
1739
  void __init_memblock memblock_trim_memory(phys_addr_t align)
  {
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1740
  	phys_addr_t start, end, orig_start, orig_end;
136199f0a   Emil Medve   memblock: use for...
1741
  	struct memblock_region *r;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1742

136199f0a   Emil Medve   memblock: use for...
1743
1744
1745
  	for_each_memblock(memory, r) {
  		orig_start = r->base;
  		orig_end = r->base + r->size;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1746
1747
1748
1749
1750
1751
1752
  		start = round_up(orig_start, align);
  		end = round_down(orig_end, align);
  
  		if (start == orig_start && end == orig_end)
  			continue;
  
  		if (start < end) {
136199f0a   Emil Medve   memblock: use for...
1753
1754
  			r->base = start;
  			r->size = end - start;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1755
  		} else {
136199f0a   Emil Medve   memblock: use for...
1756
1757
1758
  			memblock_remove_region(&memblock.memory,
  					       r - memblock.memory.regions);
  			r--;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1759
1760
1761
  		}
  	}
  }
e63075a3c   Benjamin Herrenschmidt   memblock: Introdu...
1762

3661ca66a   Yinghai Lu   memblock: Fix sec...
1763
  void __init_memblock memblock_set_current_limit(phys_addr_t limit)
e63075a3c   Benjamin Herrenschmidt   memblock: Introdu...
1764
1765
1766
  {
  	memblock.current_limit = limit;
  }
fec510141   Laura Abbott   ARM: 7993/1: mm/m...
1767
1768
1769
1770
  phys_addr_t __init_memblock memblock_get_current_limit(void)
  {
  	return memblock.current_limit;
  }
0262d9c84   Heiko Carstens   memblock: embed m...
1771
  static void __init_memblock memblock_dump(struct memblock_type *type)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1772
  {
5d63f81c9   Miles Chen   mm/memblock.c: re...
1773
  	phys_addr_t base, end, size;
e1720fee2   Mike Rapoport   mm/memblock: add ...
1774
  	enum memblock_flags flags;
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
1775
1776
  	int idx;
  	struct memblock_region *rgn;
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1777

0262d9c84   Heiko Carstens   memblock: embed m...
1778
1779
  	pr_info(" %s.cnt  = 0x%lx
  ", type->name, type->cnt);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1780

66e8b438b   Gioh Kim   mm/memblock.c: ma...
1781
  	for_each_memblock_type(idx, type, rgn) {
7c0caeb86   Tejun Heo   memblock: Add opt...
1782
1783
1784
1785
  		char nid_buf[32] = "";
  
  		base = rgn->base;
  		size = rgn->size;
5d63f81c9   Miles Chen   mm/memblock.c: re...
1786
  		end = base + size - 1;
66a207572   Tang Chen   memblock, numa: i...
1787
  		flags = rgn->flags;
7c0caeb86   Tejun Heo   memblock: Add opt...
1788
1789
1790
1791
1792
  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
  		if (memblock_get_region_node(rgn) != MAX_NUMNODES)
  			snprintf(nid_buf, sizeof(nid_buf), " on node %d",
  				 memblock_get_region_node(rgn));
  #endif
e1720fee2   Mike Rapoport   mm/memblock: add ...
1793
1794
  		pr_info(" %s[%#x]\t[%pa-%pa], %pa bytes%s flags: %#x
  ",
0262d9c84   Heiko Carstens   memblock: embed m...
1795
  			type->name, idx, &base, &end, &size, nid_buf, flags);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1796
1797
  	}
  }
4ff7b82f1   Tejun Heo   memblock: Add __m...
1798
  void __init_memblock __memblock_dump_all(void)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1799
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1800
1801
  	pr_info("MEMBLOCK configuration:
  ");
5d63f81c9   Miles Chen   mm/memblock.c: re...
1802
1803
1804
1805
  	pr_info(" memory size = %pa reserved size = %pa
  ",
  		&memblock.memory.total_size,
  		&memblock.reserved.total_size);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1806

0262d9c84   Heiko Carstens   memblock: embed m...
1807
1808
  	memblock_dump(&memblock.memory);
  	memblock_dump(&memblock.reserved);
409efd4c9   Heiko Carstens   memblock: also du...
1809
  #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
0262d9c84   Heiko Carstens   memblock: embed m...
1810
  	memblock_dump(&memblock.physmem);
409efd4c9   Heiko Carstens   memblock: also du...
1811
  #endif
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1812
  }
1aadc0560   Tejun Heo   memblock: s/membl...
1813
  void __init memblock_allow_resize(void)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1814
  {
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
1815
  	memblock_can_resize = 1;
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1816
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1817
1818
1819
1820
1821
1822
1823
  static int __init early_memblock(char *p)
  {
  	if (p && strstr(p, "debug"))
  		memblock_debug = 1;
  	return 0;
  }
  early_param("memblock", early_memblock);
bda49a811   Mike Rapoport   mm: remove nobootmem
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
  static void __init __free_pages_memory(unsigned long start, unsigned long end)
  {
  	int order;
  
  	while (start < end) {
  		order = min(MAX_ORDER - 1UL, __ffs(start));
  
  		while (start + (1UL << order) > end)
  			order--;
  
  		memblock_free_pages(pfn_to_page(start), start, order);
  
  		start += (1UL << order);
  	}
  }
  
  static unsigned long __init __free_memory_core(phys_addr_t start,
  				 phys_addr_t end)
  {
  	unsigned long start_pfn = PFN_UP(start);
  	unsigned long end_pfn = min_t(unsigned long,
  				      PFN_DOWN(end), max_low_pfn);
  
  	if (start_pfn >= end_pfn)
  		return 0;
  
  	__free_pages_memory(start_pfn, end_pfn);
  
  	return end_pfn - start_pfn;
  }
  
  static unsigned long __init free_low_memory_core_early(void)
  {
  	unsigned long count = 0;
  	phys_addr_t start, end;
  	u64 i;
  
  	memblock_clear_hotplug(0, -1);
  
  	for_each_reserved_mem_region(i, &start, &end)
  		reserve_bootmem_region(start, end);
  
  	/*
  	 * We need to use NUMA_NO_NODE instead of NODE_DATA(0)->node_id
  	 *  because in some case like Node0 doesn't have RAM installed
  	 *  low ram will be on Node1
  	 */
  	for_each_free_mem_range(i, NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end,
  				NULL)
  		count += __free_memory_core(start, end);
  
  	return count;
  }
  
  static int reset_managed_pages_done __initdata;
  
  void reset_node_managed_pages(pg_data_t *pgdat)
  {
  	struct zone *z;
  
  	for (z = pgdat->node_zones; z < pgdat->node_zones + MAX_NR_ZONES; z++)
9705bea5f   Arun KS   mm: convert zone-...
1885
  		atomic_long_set(&z->managed_pages, 0);
bda49a811   Mike Rapoport   mm: remove nobootmem
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
  }
  
  void __init reset_all_zones_managed_pages(void)
  {
  	struct pglist_data *pgdat;
  
  	if (reset_managed_pages_done)
  		return;
  
  	for_each_online_pgdat(pgdat)
  		reset_node_managed_pages(pgdat);
  
  	reset_managed_pages_done = 1;
  }
  
  /**
   * memblock_free_all - release free pages to the buddy allocator
   *
   * Return: the number of pages actually released.
   */
  unsigned long __init memblock_free_all(void)
  {
  	unsigned long pages;
  
  	reset_all_zones_managed_pages();
  
  	pages = free_low_memory_core_early();
ca79b0c21   Arun KS   mm: convert total...
1913
  	totalram_pages_add(pages);
bda49a811   Mike Rapoport   mm: remove nobootmem
1914
1915
1916
  
  	return pages;
  }
350e88bad   Mike Rapoport   mm: memblock: mak...
1917
  #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_ARCH_KEEP_MEMBLOCK)
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1918
1919
1920
1921
1922
1923
  
  static int memblock_debug_show(struct seq_file *m, void *private)
  {
  	struct memblock_type *type = m->private;
  	struct memblock_region *reg;
  	int i;
5d63f81c9   Miles Chen   mm/memblock.c: re...
1924
  	phys_addr_t end;
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1925
1926
1927
  
  	for (i = 0; i < type->cnt; i++) {
  		reg = &type->regions[i];
5d63f81c9   Miles Chen   mm/memblock.c: re...
1928
  		end = reg->base + reg->size - 1;
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1929

5d63f81c9   Miles Chen   mm/memblock.c: re...
1930
1931
1932
  		seq_printf(m, "%4d: ", i);
  		seq_printf(m, "%pa..%pa
  ", &reg->base, &end);
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1933
1934
1935
  	}
  	return 0;
  }
5ad350936   Andy Shevchenko   mm: reuse DEFINE_...
1936
  DEFINE_SHOW_ATTRIBUTE(memblock_debug);
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1937
1938
1939
1940
  
  static int __init memblock_init_debugfs(void)
  {
  	struct dentry *root = debugfs_create_dir("memblock", NULL);
d9f7979c9   Greg Kroah-Hartman   mm: no need to ch...
1941

0825a6f98   Joe Perches   mm: use octal not...
1942
1943
1944
1945
  	debugfs_create_file("memory", 0444, root,
  			    &memblock.memory, &memblock_debug_fops);
  	debugfs_create_file("reserved", 0444, root,
  			    &memblock.reserved, &memblock_debug_fops);
70210ed95   Philipp Hachtmann   mm/memblock: add ...
1946
  #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
0825a6f98   Joe Perches   mm: use octal not...
1947
1948
  	debugfs_create_file("physmem", 0444, root,
  			    &memblock.physmem, &memblock_debug_fops);
70210ed95   Philipp Hachtmann   mm/memblock: add ...
1949
  #endif
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1950
1951
1952
1953
1954
1955
  
  	return 0;
  }
  __initcall(memblock_init_debugfs);
  
  #endif /* CONFIG_DEBUG_FS */