Blame view

mm/memblock.c 54.5 KB
95f72d1ed   Yinghai Lu   lmb: rename to me...
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * Procedures for maintaining information about logical memory blocks.
   *
   * Peter Bergner, IBM Corp.	June 2001.
   * Copyright (C) 2001 Peter Bergner.
   *
   *      This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
   *      as published by the Free Software Foundation; either version
   *      2 of the License, or (at your option) any later version.
   */
  
  #include <linux/kernel.h>
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
14
  #include <linux/slab.h>
95f72d1ed   Yinghai Lu   lmb: rename to me...
15
16
  #include <linux/init.h>
  #include <linux/bitops.h>
449e8df39   Benjamin Herrenschmidt   memblock: Add deb...
17
  #include <linux/poison.h>
c196f76fd   Benjamin Herrenschmidt   memblock: NUMA al...
18
  #include <linux/pfn.h>
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
19
  #include <linux/debugfs.h>
514c60324   Randy Dunlap   headers: untangle...
20
  #include <linux/kmemleak.h>
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
21
  #include <linux/seq_file.h>
95f72d1ed   Yinghai Lu   lmb: rename to me...
22
  #include <linux/memblock.h>
193736720   Mathieu Malaterre   mm/memblock: add ...
23
  #include <linux/bootmem.h>
95f72d1ed   Yinghai Lu   lmb: rename to me...
24

c4c5ad6b3   Christoph Hellwig   memblock: include...
25
  #include <asm/sections.h>
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
26
27
28
  #include <linux/io.h>
  
  #include "internal.h"
79442ed18   Tang Chen   mm/memblock.c: in...
29

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
73
74
75
76
77
78
79
80
81
82
83
  /**
   * 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.
   *
   * Once memblock is setup the memory can be allocated using either
   * memblock or bootmem APIs.
   *
   * As the system boot progresses, the architecture specific
   * :c:func:`mem_init` function frees all the memory to the buddy page
   * allocator.
   *
   * If an architecure enables %CONFIG_ARCH_DISCARD_MEMBLOCK, the
   * memblock data structures will be discarded after the system
   * initialization compltes.
   */
fe091c208   Tejun Heo   memblock: Kill me...
84
85
  static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
  static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
70210ed95   Philipp Hachtmann   mm/memblock: add ...
86
87
88
  #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...
89
90
91
92
93
  
  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...
94
  	.memory.name		= "memory",
fe091c208   Tejun Heo   memblock: Kill me...
95
96
97
98
  
  	.reserved.regions	= memblock_reserved_init_regions,
  	.reserved.cnt		= 1,	/* empty dummy entry */
  	.reserved.max		= INIT_MEMBLOCK_REGIONS,
0262d9c84   Heiko Carstens   memblock: embed m...
99
  	.reserved.name		= "reserved",
fe091c208   Tejun Heo   memblock: Kill me...
100

70210ed95   Philipp Hachtmann   mm/memblock: add ...
101
102
103
104
  #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...
105
  	.physmem.name		= "physmem",
70210ed95   Philipp Hachtmann   mm/memblock: add ...
106
  #endif
79442ed18   Tang Chen   mm/memblock.c: in...
107
  	.bottom_up		= false,
fe091c208   Tejun Heo   memblock: Kill me...
108
109
  	.current_limit		= MEMBLOCK_ALLOC_ANYWHERE,
  };
95f72d1ed   Yinghai Lu   lmb: rename to me...
110

10d064398   Yinghai Lu   memblock: Option ...
111
  int memblock_debug __initdata_memblock;
a3f5bafcc   Tony Luck   mm/memblock: allo...
112
  static bool system_has_some_mirror __initdata_memblock = false;
1aadc0560   Tejun Heo   memblock: s/membl...
113
  static int memblock_can_resize __initdata_memblock;
181eb3942   Gavin Shan   mm/memblock: fix ...
114
115
  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...
116

e1720fee2   Mike Rapoport   mm/memblock: add ...
117
  enum memblock_flags __init_memblock choose_memblock_flags(void)
a3f5bafcc   Tony Luck   mm/memblock: allo...
118
119
120
  {
  	return system_has_some_mirror ? MEMBLOCK_MIRROR : MEMBLOCK_NONE;
  }
eb18f1b5b   Tejun Heo   memblock: Make me...
121
122
123
  /* 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...
124
  	return *size = min(*size, PHYS_ADDR_MAX - base);
eb18f1b5b   Tejun Heo   memblock: Make me...
125
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
126
127
128
  /*
   * Address comparison utilities
   */
10d064398   Yinghai Lu   memblock: Option ...
129
  static unsigned long __init_memblock memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
2898cc4cd   Benjamin Herrenschmidt   memblock: Change ...
130
  				       phys_addr_t base2, phys_addr_t size2)
95f72d1ed   Yinghai Lu   lmb: rename to me...
131
132
133
  {
  	return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
  }
95cf82ecc   Tang Chen   mem-hotplug: hand...
134
  bool __init_memblock memblock_overlaps_region(struct memblock_type *type,
2d7d3eb2b   H Hartley Sweeten   mm/memblock.c: qu...
135
  					phys_addr_t base, phys_addr_t size)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
136
137
  {
  	unsigned long i;
f14516fbf   Alexander Kuleshov   mm/memblock: remo...
138
139
140
  	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...
141
  			break;
c5c5c9d10   Tang Chen   mm/memblock.c: ma...
142
  	return i < type->cnt;
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
143
  }
47cec4432   Mike Rapoport   docs/mm: memblock...
144
  /**
79442ed18   Tang Chen   mm/memblock.c: in...
145
146
   * __memblock_find_range_bottom_up - find free area utility in bottom-up
   * @start: start of candidate range
47cec4432   Mike Rapoport   docs/mm: memblock...
147
148
   * @end: end of candidate range, can be %MEMBLOCK_ALLOC_ANYWHERE or
   *       %MEMBLOCK_ALLOC_ACCESSIBLE
79442ed18   Tang Chen   mm/memblock.c: in...
149
150
   * @size: size of free area to find
   * @align: alignment of free area to find
b11542335   Grygorii Strashko   mm/memblock: swit...
151
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
fc6daaf93   Tony Luck   mm/memblock: add ...
152
   * @flags: pick from blocks based on memory attributes
79442ed18   Tang Chen   mm/memblock.c: in...
153
154
155
   *
   * Utility called from memblock_find_in_range_node(), find free area bottom-up.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
156
   * Return:
79442ed18   Tang Chen   mm/memblock.c: in...
157
158
159
160
   * 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 ...
161
  				phys_addr_t size, phys_addr_t align, int nid,
e1720fee2   Mike Rapoport   mm/memblock: add ...
162
  				enum memblock_flags flags)
79442ed18   Tang Chen   mm/memblock.c: in...
163
164
165
  {
  	phys_addr_t this_start, this_end, cand;
  	u64 i;
fc6daaf93   Tony Luck   mm/memblock: add ...
166
  	for_each_free_mem_range(i, nid, flags, &this_start, &this_end, NULL) {
79442ed18   Tang Chen   mm/memblock.c: in...
167
168
169
170
171
172
173
174
175
176
  		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...
177
  /**
1402899e4   Tang Chen   mm/memblock.c: fa...
178
   * __memblock_find_range_top_down - find free area utility, in top-down
7bd0b0f0d   Tejun Heo   memblock: Reimple...
179
   * @start: start of candidate range
47cec4432   Mike Rapoport   docs/mm: memblock...
180
181
   * @end: end of candidate range, can be %MEMBLOCK_ALLOC_ANYWHERE or
   *       %MEMBLOCK_ALLOC_ACCESSIBLE
7bd0b0f0d   Tejun Heo   memblock: Reimple...
182
183
   * @size: size of free area to find
   * @align: alignment of free area to find
b11542335   Grygorii Strashko   mm/memblock: swit...
184
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
fc6daaf93   Tony Luck   mm/memblock: add ...
185
   * @flags: pick from blocks based on memory attributes
7bd0b0f0d   Tejun Heo   memblock: Reimple...
186
   *
1402899e4   Tang Chen   mm/memblock.c: fa...
187
   * Utility called from memblock_find_in_range_node(), find free area top-down.
7bd0b0f0d   Tejun Heo   memblock: Reimple...
188
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
189
   * Return:
79442ed18   Tang Chen   mm/memblock.c: in...
190
   * Found address on success, 0 on failure.
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
191
   */
1402899e4   Tang Chen   mm/memblock.c: fa...
192
193
  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 ...
194
  			       phys_addr_t size, phys_addr_t align, int nid,
e1720fee2   Mike Rapoport   mm/memblock: add ...
195
  			       enum memblock_flags flags)
f7210e6c4   Tang Chen   mm/memblock.c: us...
196
197
198
  {
  	phys_addr_t this_start, this_end, cand;
  	u64 i;
fc6daaf93   Tony Luck   mm/memblock: add ...
199
200
  	for_each_free_mem_range_reverse(i, nid, flags, &this_start, &this_end,
  					NULL) {
f7210e6c4   Tang Chen   mm/memblock.c: us...
201
202
203
204
205
206
207
208
209
210
  		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...
211

f7210e6c4   Tang Chen   mm/memblock.c: us...
212
213
  	return 0;
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
214

7bd0b0f0d   Tejun Heo   memblock: Reimple...
215
  /**
1402899e4   Tang Chen   mm/memblock.c: fa...
216
   * memblock_find_in_range_node - find free area in given range and node
1402899e4   Tang Chen   mm/memblock.c: fa...
217
218
   * @size: size of free area to find
   * @align: alignment of free area to find
87029ee93   Grygorii Strashko   mm/memblock: reor...
219
   * @start: start of candidate range
47cec4432   Mike Rapoport   docs/mm: memblock...
220
221
   * @end: end of candidate range, can be %MEMBLOCK_ALLOC_ANYWHERE or
   *       %MEMBLOCK_ALLOC_ACCESSIBLE
b11542335   Grygorii Strashko   mm/memblock: swit...
222
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
fc6daaf93   Tony Luck   mm/memblock: add ...
223
   * @flags: pick from blocks based on memory attributes
1402899e4   Tang Chen   mm/memblock.c: fa...
224
225
226
   *
   * Find @size free area aligned to @align in the specified range and node.
   *
79442ed18   Tang Chen   mm/memblock.c: in...
227
228
229
230
231
232
233
234
   * 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...
235
   * Return:
79442ed18   Tang Chen   mm/memblock.c: in...
236
   * Found address on success, 0 on failure.
1402899e4   Tang Chen   mm/memblock.c: fa...
237
   */
87029ee93   Grygorii Strashko   mm/memblock: reor...
238
239
  phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
  					phys_addr_t align, phys_addr_t start,
e1720fee2   Mike Rapoport   mm/memblock: add ...
240
241
  					phys_addr_t end, int nid,
  					enum memblock_flags flags)
1402899e4   Tang Chen   mm/memblock.c: fa...
242
  {
0cfb8f0c3   Tang Chen   memblock, memhotp...
243
  	phys_addr_t kernel_end, ret;
79442ed18   Tang Chen   mm/memblock.c: in...
244

1402899e4   Tang Chen   mm/memblock.c: fa...
245
246
247
248
249
250
251
  	/* pump up @end */
  	if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
  		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...
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  	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 ...
266
  						      size, align, nid, flags);
79442ed18   Tang Chen   mm/memblock.c: in...
267
268
269
270
271
272
273
274
275
276
277
278
279
  		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...
280
281
282
  		WARN_ONCE(IS_ENABLED(CONFIG_MEMORY_HOTREMOVE),
  			  "memblock: bottom-up allocation failed, memory hotremove may be affected
  ");
79442ed18   Tang Chen   mm/memblock.c: in...
283
  	}
1402899e4   Tang Chen   mm/memblock.c: fa...
284

fc6daaf93   Tony Luck   mm/memblock: add ...
285
286
  	return __memblock_find_range_top_down(start, end, size, align, nid,
  					      flags);
1402899e4   Tang Chen   mm/memblock.c: fa...
287
288
289
  }
  
  /**
7bd0b0f0d   Tejun Heo   memblock: Reimple...
290
291
   * memblock_find_in_range - find free area in given range
   * @start: start of candidate range
47cec4432   Mike Rapoport   docs/mm: memblock...
292
293
   * @end: end of candidate range, can be %MEMBLOCK_ALLOC_ANYWHERE or
   *       %MEMBLOCK_ALLOC_ACCESSIBLE
7bd0b0f0d   Tejun Heo   memblock: Reimple...
294
295
296
297
298
   * @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...
299
   * Return:
79442ed18   Tang Chen   mm/memblock.c: in...
300
   * Found address on success, 0 on failure.
fc769a8e7   Tejun Heo   memblock: Replace...
301
   */
7bd0b0f0d   Tejun Heo   memblock: Reimple...
302
303
304
  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...
305
  {
a3f5bafcc   Tony Luck   mm/memblock: allo...
306
  	phys_addr_t ret;
e1720fee2   Mike Rapoport   mm/memblock: add ...
307
  	enum memblock_flags flags = choose_memblock_flags();
a3f5bafcc   Tony Luck   mm/memblock: allo...
308
309
310
311
312
313
314
315
316
317
318
319
320
321
  
  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...
322
  }
10d064398   Yinghai Lu   memblock: Option ...
323
  static void __init_memblock memblock_remove_region(struct memblock_type *type, unsigned long r)
95f72d1ed   Yinghai Lu   lmb: rename to me...
324
  {
1440c4e2c   Tejun Heo   memblock: Track t...
325
  	type->total_size -= type->regions[r].size;
7c0caeb86   Tejun Heo   memblock: Add opt...
326
327
  	memmove(&type->regions[r], &type->regions[r + 1],
  		(type->cnt - (r + 1)) * sizeof(type->regions[r]));
e3239ff92   Benjamin Herrenschmidt   memblock: Rename ...
328
  	type->cnt--;
95f72d1ed   Yinghai Lu   lmb: rename to me...
329

8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
330
331
  	/* Special case for empty arrays */
  	if (type->cnt == 0) {
1440c4e2c   Tejun Heo   memblock: Track t...
332
  		WARN_ON(type->total_size != 0);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
333
334
335
  		type->cnt = 1;
  		type->regions[0].base = 0;
  		type->regions[0].size = 0;
66a207572   Tang Chen   memblock, numa: i...
336
  		type->regions[0].flags = 0;
7c0caeb86   Tejun Heo   memblock: Add opt...
337
  		memblock_set_region_node(&type->regions[0], MAX_NUMNODES);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
338
  	}
95f72d1ed   Yinghai Lu   lmb: rename to me...
339
  }
354f17e1e   Philipp Hachtmann   mm/nobootmem: fre...
340
  #ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
3010f8765   Pavel Tatashin   mm: discard membl...
341
  /**
47cec4432   Mike Rapoport   docs/mm: memblock...
342
   * memblock_discard - discard memory and reserved arrays if they were allocated
3010f8765   Pavel Tatashin   mm: discard membl...
343
344
   */
  void __init memblock_discard(void)
5e270e254   Philipp Hachtmann   mm: free memblock...
345
  {
3010f8765   Pavel Tatashin   mm: discard membl...
346
  	phys_addr_t addr, size;
5e270e254   Philipp Hachtmann   mm: free memblock...
347

3010f8765   Pavel Tatashin   mm: discard membl...
348
349
350
351
352
353
  	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...
354

91b540f98   Pavel Tatashin   mm/memblock.c: re...
355
  	if (memblock.memory.regions != memblock_memory_init_regions) {
3010f8765   Pavel Tatashin   mm: discard membl...
356
357
358
359
360
  		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...
361
  }
5e270e254   Philipp Hachtmann   mm: free memblock...
362
  #endif
48c3b583b   Greg Pearson   mm/memblock: fix ...
363
364
365
366
367
368
369
370
  /**
   * 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...
371
   * allocated memory range [@new_area_start, @new_area_start + @new_area_size]
48c3b583b   Greg Pearson   mm/memblock: fix ...
372
373
374
   * waiting to be reserved, ensure the memory used by the new array does
   * not overlap.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
375
   * Return:
48c3b583b   Greg Pearson   mm/memblock: fix ...
376
377
378
379
380
   * 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...
381
382
  {
  	struct memblock_region *new_array, *old_array;
29f673860   Yinghai Lu   memblock: free al...
383
  	phys_addr_t old_alloc_size, new_alloc_size;
a36aab890   Mike Rapoport   mm/memblock.c: re...
384
  	phys_addr_t old_size, new_size, addr, new_end;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
385
  	int use_slab = slab_is_available();
181eb3942   Gavin Shan   mm/memblock: fix ...
386
  	int *in_slab;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
387
388
389
390
391
392
  
  	/* 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...
393
394
395
  	/* Calculate new doubled size */
  	old_size = type->max * sizeof(struct memblock_region);
  	new_size = old_size << 1;
29f673860   Yinghai Lu   memblock: free al...
396
397
398
399
400
401
  	/*
  	 * 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...
402

181eb3942   Gavin Shan   mm/memblock: fix ...
403
404
405
406
407
  	/* Retrieve the slab flag */
  	if (type == &memblock.memory)
  		in_slab = &memblock_memory_in_slab;
  	else
  		in_slab = &memblock_reserved_in_slab;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
408
409
410
  	/* Try to find some space for it.
  	 *
  	 * WARNING: We assume that either slab_is_available() and we use it or
fd07383b6   Andrew Morton   mm/memblock.c:mem...
411
412
413
  	 * we use MEMBLOCK for allocations. That means that this is unsafe to
  	 * use when bootmem is currently active (unless bootmem itself is
  	 * implemented on top of MEMBLOCK which isn't the case yet)
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
414
415
  	 *
  	 * This should however not be an issue for now, as we currently only
fd07383b6   Andrew Morton   mm/memblock.c:mem...
416
417
  	 * call into MEMBLOCK while it's still active, or much later when slab
  	 * is active for memory hotplug operations
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
418
419
420
  	 */
  	if (use_slab) {
  		new_array = kmalloc(new_size, GFP_KERNEL);
1f5026a7e   Tejun Heo   memblock: Kill ME...
421
  		addr = new_array ? __pa(new_array) : 0;
4e2f07750   Gavin Shan   mm/memblock: clea...
422
  	} else {
48c3b583b   Greg Pearson   mm/memblock: fix ...
423
424
425
426
427
428
  		/* 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...
429
  						new_alloc_size, PAGE_SIZE);
48c3b583b   Greg Pearson   mm/memblock: fix ...
430
431
  		if (!addr && new_area_size)
  			addr = memblock_find_in_range(0,
fd07383b6   Andrew Morton   mm/memblock.c:mem...
432
433
  				min(new_area_start, memblock.current_limit),
  				new_alloc_size, PAGE_SIZE);
48c3b583b   Greg Pearson   mm/memblock: fix ...
434

15674868d   Sachin Kamat   mm/memblock: Use ...
435
  		new_array = addr ? __va(addr) : NULL;
4e2f07750   Gavin Shan   mm/memblock: clea...
436
  	}
1f5026a7e   Tejun Heo   memblock: Kill ME...
437
  	if (!addr) {
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
438
439
  		pr_err("memblock: Failed to double %s array from %ld to %ld entries !
  ",
0262d9c84   Heiko Carstens   memblock: embed m...
440
  		       type->name, type->max, type->max * 2);
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
441
442
  		return -1;
  	}
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
443

a36aab890   Mike Rapoport   mm/memblock.c: re...
444
445
446
  	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...
447

fd07383b6   Andrew Morton   mm/memblock.c:mem...
448
449
450
451
  	/*
  	 * 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...
452
453
454
455
456
457
  	 */
  	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...
458
  	/* Free old array. We needn't free it if the array is the static one */
181eb3942   Gavin Shan   mm/memblock: fix ...
459
460
461
462
  	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...
463
  		memblock_free(__pa(old_array), old_alloc_size);
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
464

fd07383b6   Andrew Morton   mm/memblock.c:mem...
465
466
467
  	/*
  	 * Reserve the new array if that comes from the memblock.  Otherwise, we
  	 * needn't do it
181eb3942   Gavin Shan   mm/memblock: fix ...
468
469
  	 */
  	if (!use_slab)
29f673860   Yinghai Lu   memblock: free al...
470
  		BUG_ON(memblock_reserve(addr, new_alloc_size));
181eb3942   Gavin Shan   mm/memblock: fix ...
471
472
473
  
  	/* Update slab flag */
  	*in_slab = use_slab;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
474
475
  	return 0;
  }
784656f9c   Tejun Heo   memblock: Reimple...
476
477
478
479
480
481
482
  /**
   * 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...
483
  {
784656f9c   Tejun Heo   memblock: Reimple...
484
  	int i = 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
485

784656f9c   Tejun Heo   memblock: Reimple...
486
487
488
489
  	/* 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...
490

7c0caeb86   Tejun Heo   memblock: Add opt...
491
492
  		if (this->base + this->size != next->base ||
  		    memblock_get_region_node(this) !=
66a207572   Tang Chen   memblock, numa: i...
493
494
  		    memblock_get_region_node(next) ||
  		    this->flags != next->flags) {
784656f9c   Tejun Heo   memblock: Reimple...
495
496
497
  			BUG_ON(this->base + this->size > next->base);
  			i++;
  			continue;
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
498
  		}
784656f9c   Tejun Heo   memblock: Reimple...
499
  		this->size += next->size;
c0232ae86   Lin Feng   mm: memblock: fix...
500
501
  		/* 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...
502
  		type->cnt--;
95f72d1ed   Yinghai Lu   lmb: rename to me...
503
  	}
784656f9c   Tejun Heo   memblock: Reimple...
504
  }
95f72d1ed   Yinghai Lu   lmb: rename to me...
505

784656f9c   Tejun Heo   memblock: Reimple...
506
507
  /**
   * memblock_insert_region - insert new memblock region
209ff86d6   Tang Chen   memblock: fix mis...
508
509
510
511
512
   * @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...
513
   * @flags:	flags of the new region
784656f9c   Tejun Heo   memblock: Reimple...
514
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
515
   * Insert new memblock region [@base, @base + @size) into @type at @idx.
412d0008d   Alexander Kuleshov   mm/memblock: fix ...
516
   * @type must already have extra room to accommodate the new region.
784656f9c   Tejun Heo   memblock: Reimple...
517
518
519
   */
  static void __init_memblock memblock_insert_region(struct memblock_type *type,
  						   int idx, phys_addr_t base,
66a207572   Tang Chen   memblock, numa: i...
520
  						   phys_addr_t size,
e1720fee2   Mike Rapoport   mm/memblock: add ...
521
522
  						   int nid,
  						   enum memblock_flags flags)
784656f9c   Tejun Heo   memblock: Reimple...
523
524
525
526
527
528
529
  {
  	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...
530
  	rgn->flags = flags;
7c0caeb86   Tejun Heo   memblock: Add opt...
531
  	memblock_set_region_node(rgn, nid);
784656f9c   Tejun Heo   memblock: Reimple...
532
  	type->cnt++;
1440c4e2c   Tejun Heo   memblock: Track t...
533
  	type->total_size += size;
784656f9c   Tejun Heo   memblock: Reimple...
534
535
536
  }
  
  /**
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
537
   * memblock_add_range - add new memblock region
784656f9c   Tejun Heo   memblock: Reimple...
538
539
540
   * @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...
541
   * @nid: nid of the new region
66a207572   Tang Chen   memblock, numa: i...
542
   * @flags: flags of the new region
784656f9c   Tejun Heo   memblock: Reimple...
543
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
544
   * Add new memblock region [@base, @base + @size) into @type.  The new region
784656f9c   Tejun Heo   memblock: Reimple...
545
546
547
548
   * 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...
549
   * Return:
784656f9c   Tejun Heo   memblock: Reimple...
550
551
   * 0 on success, -errno on failure.
   */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
552
  int __init_memblock memblock_add_range(struct memblock_type *type,
66a207572   Tang Chen   memblock, numa: i...
553
  				phys_addr_t base, phys_addr_t size,
e1720fee2   Mike Rapoport   mm/memblock: add ...
554
  				int nid, enum memblock_flags flags)
784656f9c   Tejun Heo   memblock: Reimple...
555
556
  {
  	bool insert = false;
eb18f1b5b   Tejun Heo   memblock: Make me...
557
558
  	phys_addr_t obase = base;
  	phys_addr_t end = base + memblock_cap_size(base, &size);
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
559
560
  	int idx, nr_new;
  	struct memblock_region *rgn;
784656f9c   Tejun Heo   memblock: Reimple...
561

b3dc627ca   Tejun Heo   memblock: membloc...
562
563
  	if (!size)
  		return 0;
784656f9c   Tejun Heo   memblock: Reimple...
564
565
  	/* special case for empty array */
  	if (type->regions[0].size == 0) {
1440c4e2c   Tejun Heo   memblock: Track t...
566
  		WARN_ON(type->cnt != 1 || type->total_size);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
567
568
  		type->regions[0].base = base;
  		type->regions[0].size = size;
66a207572   Tang Chen   memblock, numa: i...
569
  		type->regions[0].flags = flags;
7fb0bc3f0   Tejun Heo   memblock: Impleme...
570
  		memblock_set_region_node(&type->regions[0], nid);
1440c4e2c   Tejun Heo   memblock: Track t...
571
  		type->total_size = size;
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
572
  		return 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
573
  	}
784656f9c   Tejun Heo   memblock: Reimple...
574
575
576
577
  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 ...
578
  	 * to accommodate the new area.  The second actually inserts them.
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
579
  	 */
784656f9c   Tejun Heo   memblock: Reimple...
580
581
  	base = obase;
  	nr_new = 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
582

66e8b438b   Gioh Kim   mm/memblock.c: ma...
583
  	for_each_memblock_type(idx, type, rgn) {
784656f9c   Tejun Heo   memblock: Reimple...
584
585
586
587
  		phys_addr_t rbase = rgn->base;
  		phys_addr_t rend = rbase + rgn->size;
  
  		if (rbase >= end)
95f72d1ed   Yinghai Lu   lmb: rename to me...
588
  			break;
784656f9c   Tejun Heo   memblock: Reimple...
589
590
591
592
593
594
595
  		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...
596
597
598
  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
  			WARN_ON(nid != memblock_get_region_node(rgn));
  #endif
4fcab5f43   Wei Yang   mm/memblock.c: WA...
599
  			WARN_ON(flags != rgn->flags);
784656f9c   Tejun Heo   memblock: Reimple...
600
601
  			nr_new++;
  			if (insert)
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
602
  				memblock_insert_region(type, idx++, base,
66a207572   Tang Chen   memblock, numa: i...
603
604
  						       rbase - base, nid,
  						       flags);
95f72d1ed   Yinghai Lu   lmb: rename to me...
605
  		}
784656f9c   Tejun Heo   memblock: Reimple...
606
607
  		/* area below @rend is dealt with, forget about it */
  		base = min(rend, end);
95f72d1ed   Yinghai Lu   lmb: rename to me...
608
  	}
784656f9c   Tejun Heo   memblock: Reimple...
609
610
611
612
613
  
  	/* insert the remaining portion */
  	if (base < end) {
  		nr_new++;
  		if (insert)
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
614
  			memblock_insert_region(type, idx, base, end - base,
66a207572   Tang Chen   memblock, numa: i...
615
  					       nid, flags);
95f72d1ed   Yinghai Lu   lmb: rename to me...
616
  	}
95f72d1ed   Yinghai Lu   lmb: rename to me...
617

ef3cc4db4   nimisolo   mm/memblock.c:mem...
618
619
  	if (!nr_new)
  		return 0;
784656f9c   Tejun Heo   memblock: Reimple...
620
621
622
  	/*
  	 * If this was the first round, resize array and repeat for actual
  	 * insertions; otherwise, merge and return.
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
623
  	 */
784656f9c   Tejun Heo   memblock: Reimple...
624
625
  	if (!insert) {
  		while (type->cnt + nr_new > type->max)
48c3b583b   Greg Pearson   mm/memblock: fix ...
626
  			if (memblock_double_array(type, obase, size) < 0)
784656f9c   Tejun Heo   memblock: Reimple...
627
628
629
630
631
632
  				return -ENOMEM;
  		insert = true;
  		goto repeat;
  	} else {
  		memblock_merge_regions(type);
  		return 0;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
633
  	}
95f72d1ed   Yinghai Lu   lmb: rename to me...
634
  }
48a833cc7   Mike Rapoport   docs/mm: memblock...
635
636
637
638
639
640
641
642
643
644
645
646
  /**
   * 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...
647
648
649
  int __init_memblock memblock_add_node(phys_addr_t base, phys_addr_t size,
  				       int nid)
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
650
  	return memblock_add_range(&memblock.memory, base, size, nid, 0);
7fb0bc3f0   Tejun Heo   memblock: Impleme...
651
  }
48a833cc7   Mike Rapoport   docs/mm: memblock...
652
653
654
655
656
657
658
659
660
661
662
  /**
   * 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...
663
  int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
6a4055bc7   Alexander Kuleshov   mm/memblock.c: ad...
664
  {
5d63f81c9   Miles Chen   mm/memblock.c: re...
665
666
667
668
669
  	phys_addr_t end = base + size - 1;
  
  	memblock_dbg("memblock_add: [%pa-%pa] %pF
  ",
  		     &base, &end, (void *)_RET_IP_);
6a4055bc7   Alexander Kuleshov   mm/memblock.c: ad...
670

f705ac4b3   Alexander Kuleshov   mm/memblock.c: mo...
671
  	return memblock_add_range(&memblock.memory, base, size, MAX_NUMNODES, 0);
95f72d1ed   Yinghai Lu   lmb: rename to me...
672
  }
6a9ceb31c   Tejun Heo   memblock: Separat...
673
674
675
676
677
678
679
680
681
  /**
   * 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...
682
   * [@base, @base + @size).  Crossing regions are split at the boundaries,
6a9ceb31c   Tejun Heo   memblock: Separat...
683
684
685
   * 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...
686
   * Return:
6a9ceb31c   Tejun Heo   memblock: Separat...
687
688
689
690
691
692
   * 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...
693
  	phys_addr_t end = base + memblock_cap_size(base, &size);
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
694
695
  	int idx;
  	struct memblock_region *rgn;
6a9ceb31c   Tejun Heo   memblock: Separat...
696
697
  
  	*start_rgn = *end_rgn = 0;
b3dc627ca   Tejun Heo   memblock: membloc...
698
699
  	if (!size)
  		return 0;
6a9ceb31c   Tejun Heo   memblock: Separat...
700
701
  	/* we'll create at most two more regions */
  	while (type->cnt + 2 > type->max)
48c3b583b   Greg Pearson   mm/memblock: fix ...
702
  		if (memblock_double_array(type, base, size) < 0)
6a9ceb31c   Tejun Heo   memblock: Separat...
703
  			return -ENOMEM;
66e8b438b   Gioh Kim   mm/memblock.c: ma...
704
  	for_each_memblock_type(idx, type, rgn) {
6a9ceb31c   Tejun Heo   memblock: Separat...
705
706
707
708
709
710
711
712
713
714
715
716
717
718
  		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...
719
720
  			rgn->size -= base - rbase;
  			type->total_size -= base - rbase;
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
721
  			memblock_insert_region(type, idx, rbase, base - rbase,
66a207572   Tang Chen   memblock, numa: i...
722
723
  					       memblock_get_region_node(rgn),
  					       rgn->flags);
6a9ceb31c   Tejun Heo   memblock: Separat...
724
725
726
727
728
729
  		} 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...
730
731
  			rgn->size -= end - rbase;
  			type->total_size -= end - rbase;
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
732
  			memblock_insert_region(type, idx--, rbase, end - rbase,
66a207572   Tang Chen   memblock, numa: i...
733
734
  					       memblock_get_region_node(rgn),
  					       rgn->flags);
6a9ceb31c   Tejun Heo   memblock: Separat...
735
736
737
  		} else {
  			/* @rgn is fully contained, record it */
  			if (!*end_rgn)
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
738
739
  				*start_rgn = idx;
  			*end_rgn = idx + 1;
6a9ceb31c   Tejun Heo   memblock: Separat...
740
741
742
743
744
  		}
  	}
  
  	return 0;
  }
6a9ceb31c   Tejun Heo   memblock: Separat...
745

35bd16a22   Alexander Kuleshov   mm/memblock: make...
746
  static int __init_memblock memblock_remove_range(struct memblock_type *type,
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
747
  					  phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
748
  {
719361809   Tejun Heo   memblock: Reimple...
749
750
  	int start_rgn, end_rgn;
  	int i, ret;
95f72d1ed   Yinghai Lu   lmb: rename to me...
751

719361809   Tejun Heo   memblock: Reimple...
752
753
754
  	ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);
  	if (ret)
  		return ret;
95f72d1ed   Yinghai Lu   lmb: rename to me...
755

719361809   Tejun Heo   memblock: Reimple...
756
757
  	for (i = end_rgn - 1; i >= start_rgn; i--)
  		memblock_remove_region(type, i);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
758
  	return 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
759
  }
581adcbe1   Tejun Heo   memblock: Make me...
760
  int __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
761
  {
25cf23d7a   Minchan Kim   mm/memblock: prin...
762
763
764
765
766
  	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...
767
  	return memblock_remove_range(&memblock.memory, base, size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
768
  }
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
769

581adcbe1   Tejun Heo   memblock: Make me...
770
  int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
771
  {
5d63f81c9   Miles Chen   mm/memblock.c: re...
772
773
774
775
776
  	phys_addr_t end = base + size - 1;
  
  	memblock_dbg("   memblock_free: [%pa-%pa] %pF
  ",
  		     &base, &end, (void *)_RET_IP_);
24aa07882   Tejun Heo   memblock, x86: Re...
777

9099daed9   Catalin Marinas   mm: kmemleak: avo...
778
  	kmemleak_free_part_phys(base, size);
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
779
  	return memblock_remove_range(&memblock.reserved, base, size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
780
  }
f705ac4b3   Alexander Kuleshov   mm/memblock.c: mo...
781
  int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
782
  {
5d63f81c9   Miles Chen   mm/memblock.c: re...
783
784
785
786
787
  	phys_addr_t end = base + size - 1;
  
  	memblock_dbg("memblock_reserve: [%pa-%pa] %pF
  ",
  		     &base, &end, (void *)_RET_IP_);
95f72d1ed   Yinghai Lu   lmb: rename to me...
788

f705ac4b3   Alexander Kuleshov   mm/memblock.c: mo...
789
  	return memblock_add_range(&memblock.reserved, base, size, MAX_NUMNODES, 0);
95f72d1ed   Yinghai Lu   lmb: rename to me...
790
  }
35fd0808d   Tejun Heo   memblock: Impleme...
791
  /**
47cec4432   Mike Rapoport   docs/mm: memblock...
792
793
794
795
796
   * 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...
797
   *
4308ce17f   Tony Luck   mm/memblock.c: re...
798
   * This function isolates region [@base, @base + @size), and sets/clears flag
66b16edf9   Tang Chen   memblock, mem_hot...
799
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
800
   * Return: 0 on success, -errno on failure.
66b16edf9   Tang Chen   memblock, mem_hot...
801
   */
4308ce17f   Tony Luck   mm/memblock.c: re...
802
803
  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...
804
805
806
807
808
809
810
811
812
  {
  	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;
  
  	for (i = start_rgn; i < end_rgn; i++)
4308ce17f   Tony Luck   mm/memblock.c: re...
813
814
815
816
  		if (set)
  			memblock_set_region_flags(&type->regions[i], flag);
  		else
  			memblock_clear_region_flags(&type->regions[i], flag);
66b16edf9   Tang Chen   memblock, mem_hot...
817
818
819
820
821
822
  
  	memblock_merge_regions(type);
  	return 0;
  }
  
  /**
4308ce17f   Tony Luck   mm/memblock.c: re...
823
   * memblock_mark_hotplug - Mark hotpluggable memory with flag MEMBLOCK_HOTPLUG.
66b16edf9   Tang Chen   memblock, mem_hot...
824
825
826
   * @base: the base phys addr of the region
   * @size: the size of the region
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
827
   * Return: 0 on success, -errno on failure.
4308ce17f   Tony Luck   mm/memblock.c: re...
828
829
830
831
832
833
834
835
836
837
   */
  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...
838
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
839
   * Return: 0 on success, -errno on failure.
66b16edf9   Tang Chen   memblock, mem_hot...
840
841
842
   */
  int __init_memblock memblock_clear_hotplug(phys_addr_t base, phys_addr_t size)
  {
4308ce17f   Tony Luck   mm/memblock.c: re...
843
  	return memblock_setclr_flag(base, size, 0, MEMBLOCK_HOTPLUG);
66b16edf9   Tang Chen   memblock, mem_hot...
844
845
846
  }
  
  /**
a3f5bafcc   Tony Luck   mm/memblock: allo...
847
848
849
850
   * 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...
851
   * Return: 0 on success, -errno on failure.
a3f5bafcc   Tony Luck   mm/memblock: allo...
852
853
854
855
856
857
858
   */
  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 ...
859
860
861
862
863
  /**
   * 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...
864
   * Return: 0 on success, -errno on failure.
bf3d3cc58   Ard Biesheuvel   mm/memblock: add ...
865
866
867
868
869
   */
  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...
870
871
  
  /**
4c546b8a3   AKASHI Takahiro   memblock: add mem...
872
873
874
875
   * 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...
876
   * Return: 0 on success, -errno on failure.
4c546b8a3   AKASHI Takahiro   memblock: add mem...
877
878
879
880
881
882
883
   */
  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...
884
885
886
887
888
889
890
891
892
893
894
   * __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...
895
  	struct memblock_type *type = &memblock.reserved;
8e7a7f861   Robin Holt   memblock: introdu...
896

cd33a76b0   Richard Leitner   mm/memblock.c: re...
897
  	if (*idx < type->cnt) {
567d117b8   Alexander Kuleshov   mm/memblock.c: re...
898
  		struct memblock_region *r = &type->regions[*idx];
8e7a7f861   Robin Holt   memblock: introdu...
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
  		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;
  }
  
  /**
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
916
   * __next__mem_range - next function for for_each_free_mem_range() etc.
35fd0808d   Tejun Heo   memblock: Impleme...
917
   * @idx: pointer to u64 loop variable
b11542335   Grygorii Strashko   mm/memblock: swit...
918
   * @nid: node selector, %NUMA_NO_NODE for all nodes
fc6daaf93   Tony Luck   mm/memblock: add ...
919
   * @flags: pick from blocks based on memory attributes
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
920
921
   * @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...
922
923
924
   * @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...
925
   *
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
926
   * Find the first area from *@idx which matches @nid, fill the out
35fd0808d   Tejun Heo   memblock: Impleme...
927
   * parameters, and update *@idx for the next iteration.  The lower 32bit of
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
928
929
   * *@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...
930
931
932
933
934
935
936
937
938
939
940
   * 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 ...
941
942
  void __init_memblock __next_mem_range(u64 *idx, int nid,
  				      enum memblock_flags flags,
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
943
944
945
946
  				      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...
947
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
948
949
  	int idx_a = *idx & 0xffffffff;
  	int idx_b = *idx >> 32;
b11542335   Grygorii Strashko   mm/memblock: swit...
950

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
951
952
953
  	if (WARN_ONCE(nid == MAX_NUMNODES,
  	"Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead
  "))
560dca27a   Grygorii Strashko   mm/memblock: use ...
954
  		nid = NUMA_NO_NODE;
35fd0808d   Tejun Heo   memblock: Impleme...
955

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
956
957
  	for (; idx_a < type_a->cnt; idx_a++) {
  		struct memblock_region *m = &type_a->regions[idx_a];
35fd0808d   Tejun Heo   memblock: Impleme...
958
959
  		phys_addr_t m_start = m->base;
  		phys_addr_t m_end = m->base + m->size;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
960
  		int	    m_nid = memblock_get_region_node(m);
35fd0808d   Tejun Heo   memblock: Impleme...
961
962
  
  		/* only memory regions are associated with nodes, check it */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
963
  		if (nid != NUMA_NO_NODE && nid != m_nid)
35fd0808d   Tejun Heo   memblock: Impleme...
964
  			continue;
0a313a998   Xishi Qiu   mem-hotplug: let ...
965
966
967
  		/* skip hotpluggable memory regions if needed */
  		if (movable_node_is_enabled() && memblock_is_hotpluggable(m))
  			continue;
a3f5bafcc   Tony Luck   mm/memblock: allo...
968
969
970
  		/* if we want mirror memory skip non-mirror memory regions */
  		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
  			continue;
bf3d3cc58   Ard Biesheuvel   mm/memblock: add ...
971
972
973
  		/* skip nomap memory unless we were asked for it explicitly */
  		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
  			continue;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
  		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...
995
  				r->base : PHYS_ADDR_MAX;
35fd0808d   Tejun Heo   memblock: Impleme...
996

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
997
998
999
1000
  			/*
  			 * if idx_b advanced past idx_a,
  			 * break out to advance idx_a
  			 */
35fd0808d   Tejun Heo   memblock: Impleme...
1001
1002
1003
1004
1005
  			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...
1006
1007
  					*out_start =
  						max(m_start, r_start);
35fd0808d   Tejun Heo   memblock: Impleme...
1008
1009
1010
  				if (out_end)
  					*out_end = min(m_end, r_end);
  				if (out_nid)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1011
  					*out_nid = m_nid;
35fd0808d   Tejun Heo   memblock: Impleme...
1012
  				/*
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1013
1014
  				 * The region which ends first is
  				 * advanced for the next iteration.
35fd0808d   Tejun Heo   memblock: Impleme...
1015
1016
  				 */
  				if (m_end <= r_end)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1017
  					idx_a++;
35fd0808d   Tejun Heo   memblock: Impleme...
1018
  				else
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1019
1020
  					idx_b++;
  				*idx = (u32)idx_a | (u64)idx_b << 32;
35fd0808d   Tejun Heo   memblock: Impleme...
1021
1022
1023
1024
1025
1026
1027
1028
  				return;
  			}
  		}
  	}
  
  	/* signal end of iteration */
  	*idx = ULLONG_MAX;
  }
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1029
  /**
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1030
1031
   * __next_mem_range_rev - generic next function for for_each_*_range_rev()
   *
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1032
   * @idx: pointer to u64 loop variable
ad5ea8cd5   Alexander Kuleshov   mm/memblock.c: fi...
1033
   * @nid: node selector, %NUMA_NO_NODE for all nodes
fc6daaf93   Tony Luck   mm/memblock: add ...
1034
   * @flags: pick from blocks based on memory attributes
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1035
1036
   * @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...
1037
1038
1039
   * @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...
1040
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1041
1042
1043
   * Finds the next range from type_a which is not marked as unsuitable
   * in type_b.
   *
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1044
   * Reverse of __next_mem_range().
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1045
   */
e1720fee2   Mike Rapoport   mm/memblock: add ...
1046
1047
  void __init_memblock __next_mem_range_rev(u64 *idx, int nid,
  					  enum memblock_flags flags,
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1048
1049
1050
1051
  					  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...
1052
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1053
1054
  	int idx_a = *idx & 0xffffffff;
  	int idx_b = *idx >> 32;
b11542335   Grygorii Strashko   mm/memblock: swit...
1055

560dca27a   Grygorii Strashko   mm/memblock: use ...
1056
1057
1058
  	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...
1059
1060
  
  	if (*idx == (u64)ULLONG_MAX) {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1061
  		idx_a = type_a->cnt - 1;
e47608ab6   zijun_hu   mm/memblock.c: fi...
1062
1063
1064
1065
  		if (type_b != NULL)
  			idx_b = type_b->cnt;
  		else
  			idx_b = 0;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1066
  	}
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1067
1068
  	for (; idx_a >= 0; idx_a--) {
  		struct memblock_region *m = &type_a->regions[idx_a];
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1069
1070
  		phys_addr_t m_start = m->base;
  		phys_addr_t m_end = m->base + m->size;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1071
  		int m_nid = memblock_get_region_node(m);
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1072
1073
  
  		/* only memory regions are associated with nodes, check it */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1074
  		if (nid != NUMA_NO_NODE && nid != m_nid)
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1075
  			continue;
55ac590c2   Tang Chen   memblock, mem_hot...
1076
1077
1078
  		/* skip hotpluggable memory regions if needed */
  		if (movable_node_is_enabled() && memblock_is_hotpluggable(m))
  			continue;
a3f5bafcc   Tony Luck   mm/memblock: allo...
1079
1080
1081
  		/* if we want mirror memory skip non-mirror memory regions */
  		if ((flags & MEMBLOCK_MIRROR) && !memblock_is_mirror(m))
  			continue;
bf3d3cc58   Ard Biesheuvel   mm/memblock: add ...
1082
1083
1084
  		/* skip nomap memory unless we were asked for it explicitly */
  		if (!(flags & MEMBLOCK_NOMAP) && memblock_is_nomap(m))
  			continue;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1085
1086
1087
1088
1089
1090
1091
  		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...
1092
  			idx_a--;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
  			*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...
1106
  				r->base : PHYS_ADDR_MAX;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1107
1108
1109
1110
  			/*
  			 * if idx_b advanced past idx_a,
  			 * break out to advance idx_a
  			 */
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1111

7bd0b0f0d   Tejun Heo   memblock: Reimple...
1112
1113
1114
1115
1116
1117
1118
1119
1120
  			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...
1121
  					*out_nid = m_nid;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1122
  				if (m_start >= r_start)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1123
  					idx_a--;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1124
  				else
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1125
1126
  					idx_b--;
  				*idx = (u32)idx_a | (u64)idx_b << 32;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1127
1128
1129
1130
  				return;
  			}
  		}
  	}
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1131
  	/* signal end of iteration */
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1132
1133
  	*idx = ULLONG_MAX;
  }
7c0caeb86   Tejun Heo   memblock: Add opt...
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
  /*
   * Common iterator interface used to define for_each_mem_range().
   */
  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...
1170
   * @type: memblock type to set node ID for
7c0caeb86   Tejun Heo   memblock: Add opt...
1171
1172
   * @nid: node ID to set
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1173
   * Set the nid of memblock @type regions in [@base, @base + @size) to @nid.
7c0caeb86   Tejun Heo   memblock: Add opt...
1174
1175
   * Regions which cross the area boundaries are split as necessary.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1176
   * Return:
7c0caeb86   Tejun Heo   memblock: Add opt...
1177
1178
1179
   * 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...
1180
  				      struct memblock_type *type, int nid)
7c0caeb86   Tejun Heo   memblock: Add opt...
1181
  {
6a9ceb31c   Tejun Heo   memblock: Separat...
1182
1183
  	int start_rgn, end_rgn;
  	int i, ret;
7c0caeb86   Tejun Heo   memblock: Add opt...
1184

6a9ceb31c   Tejun Heo   memblock: Separat...
1185
1186
1187
  	ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);
  	if (ret)
  		return ret;
7c0caeb86   Tejun Heo   memblock: Add opt...
1188

6a9ceb31c   Tejun Heo   memblock: Separat...
1189
  	for (i = start_rgn; i < end_rgn; i++)
e9d24ad30   Wanpeng Li   mm/memblock: use ...
1190
  		memblock_set_region_node(&type->regions[i], nid);
7c0caeb86   Tejun Heo   memblock: Add opt...
1191
1192
1193
1194
1195
  
  	memblock_merge_regions(type);
  	return 0;
  }
  #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
2bfc2862c   Akinobu Mita   memblock: introdu...
1196
1197
  static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
  					phys_addr_t align, phys_addr_t start,
e1720fee2   Mike Rapoport   mm/memblock: add ...
1198
1199
  					phys_addr_t end, int nid,
  					enum memblock_flags flags)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1200
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1201
  	phys_addr_t found;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1202

79f40fab0   Grygorii Strashko   mm/memblock: drop...
1203
1204
  	if (!align)
  		align = SMP_CACHE_BYTES;
94f3d3afb   Vineet Gupta   memblock: add ass...
1205

fc6daaf93   Tony Luck   mm/memblock: add ...
1206
1207
  	found = memblock_find_in_range_node(size, align, start, end, nid,
  					    flags);
aedf95ea0   Catalin Marinas   mm/memblock.c: ca...
1208
1209
1210
1211
1212
  	if (found && !memblock_reserve(found, size)) {
  		/*
  		 * The min_count is set to 0 so that memblock allocations are
  		 * never reported as leaks.
  		 */
9099daed9   Catalin Marinas   mm: kmemleak: avo...
1213
  		kmemleak_alloc_phys(found, size, 0, 0);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1214
  		return found;
aedf95ea0   Catalin Marinas   mm/memblock.c: ca...
1215
  	}
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1216
  	return 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1217
  }
2bfc2862c   Akinobu Mita   memblock: introdu...
1218
  phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
fc6daaf93   Tony Luck   mm/memblock: add ...
1219
  					phys_addr_t start, phys_addr_t end,
e1720fee2   Mike Rapoport   mm/memblock: add ...
1220
  					enum memblock_flags flags)
2bfc2862c   Akinobu Mita   memblock: introdu...
1221
  {
fc6daaf93   Tony Luck   mm/memblock: add ...
1222
1223
  	return memblock_alloc_range_nid(size, align, start, end, NUMA_NO_NODE,
  					flags);
2bfc2862c   Akinobu Mita   memblock: introdu...
1224
  }
b575454fa   Nicholas Piggin   mm: make memblock...
1225
  phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
2bfc2862c   Akinobu Mita   memblock: introdu...
1226
  					phys_addr_t align, phys_addr_t max_addr,
e1720fee2   Mike Rapoport   mm/memblock: add ...
1227
  					int nid, enum memblock_flags flags)
2bfc2862c   Akinobu Mita   memblock: introdu...
1228
  {
fc6daaf93   Tony Luck   mm/memblock: add ...
1229
  	return memblock_alloc_range_nid(size, align, 0, max_addr, nid, flags);
2bfc2862c   Akinobu Mita   memblock: introdu...
1230
  }
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1231
1232
  phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int nid)
  {
e1720fee2   Mike Rapoport   mm/memblock: add ...
1233
  	enum memblock_flags flags = choose_memblock_flags();
a3f5bafcc   Tony Luck   mm/memblock: allo...
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
  	phys_addr_t ret;
  
  again:
  	ret = memblock_alloc_base_nid(size, align, MEMBLOCK_ALLOC_ACCESSIBLE,
  				      nid, flags);
  
  	if (!ret && (flags & MEMBLOCK_MIRROR)) {
  		flags &= ~MEMBLOCK_MIRROR;
  		goto again;
  	}
  	return ret;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1245
1246
1247
1248
  }
  
  phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
  {
fc6daaf93   Tony Luck   mm/memblock: add ...
1249
1250
  	return memblock_alloc_base_nid(size, align, max_addr, NUMA_NO_NODE,
  				       MEMBLOCK_NONE);
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1251
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1252
  phys_addr_t __init memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1253
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1254
1255
1256
1257
1258
  	phys_addr_t alloc;
  
  	alloc = __memblock_alloc_base(size, align, max_addr);
  
  	if (alloc == 0)
5d63f81c9   Miles Chen   mm/memblock.c: re...
1259
1260
1261
  		panic("ERROR: Failed to allocate %pa bytes below %pa.
  ",
  		      &size, &max_addr);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1262
1263
  
  	return alloc;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1264
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1265
  phys_addr_t __init memblock_alloc(phys_addr_t size, phys_addr_t align)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1266
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1267
1268
  	return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
  }
95f72d1ed   Yinghai Lu   lmb: rename to me...
1269

9d1e24928   Benjamin Herrenschmidt   memblock: Separat...
1270
1271
1272
1273
1274
1275
  phys_addr_t __init memblock_alloc_try_nid(phys_addr_t size, phys_addr_t align, int nid)
  {
  	phys_addr_t res = memblock_alloc_nid(size, align, nid);
  
  	if (res)
  		return res;
15fb09722   Tejun Heo   memblock: Use MEM...
1276
  	return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1277
  }
193736720   Mathieu Malaterre   mm/memblock: add ...
1278
  #if defined(CONFIG_NO_BOOTMEM)
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
  /**
   * memblock_virt_alloc_internal - allocate boot memory block
   * @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
   *
   * The @min_addr limit is dropped if it can not be satisfied and the allocation
   * will fall back to memory below @min_addr. Also, allocation may fall back
   * to any node in the system if the specified node can not
   * hold the requested memory.
   *
   * The allocation is performed from memory region limited by
   * memblock.current_limit if @max_addr == %BOOTMEM_ALLOC_ACCESSIBLE.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1295
   * The memory block is aligned on %SMP_CACHE_BYTES if @align == 0.
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1296
1297
1298
1299
1300
1301
1302
   *
   * The phys address of allocated boot memory block is converted to virtual and
   * allocated memory is reset to 0.
   *
   * In addition, function sets the min_count to 0 using kmemleak_alloc for
   * allocated boot memory block, so that it is never reported as leaks.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1303
   * Return:
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1304
1305
1306
1307
1308
1309
1310
1311
1312
   * Virtual address of allocated memory block on success, NULL on failure.
   */
  static void * __init memblock_virt_alloc_internal(
  				phys_addr_t size, phys_addr_t align,
  				phys_addr_t min_addr, phys_addr_t max_addr,
  				int nid)
  {
  	phys_addr_t alloc;
  	void *ptr;
e1720fee2   Mike Rapoport   mm/memblock: add ...
1313
  	enum memblock_flags flags = choose_memblock_flags();
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1314

560dca27a   Grygorii Strashko   mm/memblock: use ...
1315
1316
1317
  	if (WARN_ONCE(nid == MAX_NUMNODES, "Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead
  "))
  		nid = NUMA_NO_NODE;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
  
  	/*
  	 * Detect any accidental use of these APIs after slab is ready, as at
  	 * this moment memblock may be deinitialized already and its
  	 * internal data may be destroyed (after execution of free_all_bootmem)
  	 */
  	if (WARN_ON_ONCE(slab_is_available()))
  		return kzalloc_node(size, GFP_NOWAIT, nid);
  
  	if (!align)
  		align = SMP_CACHE_BYTES;
f544e14f3   Yinghai Lu   memblock: add lim...
1329
1330
  	if (max_addr > memblock.current_limit)
  		max_addr = memblock.current_limit;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1331
1332
  again:
  	alloc = memblock_find_in_range_node(size, align, min_addr, max_addr,
a3f5bafcc   Tony Luck   mm/memblock: allo...
1333
  					    nid, flags);
7d41c03e2   Wei Yang   mm/memblock.c: ch...
1334
  	if (alloc && !memblock_reserve(alloc, size))
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1335
1336
1337
1338
  		goto done;
  
  	if (nid != NUMA_NO_NODE) {
  		alloc = memblock_find_in_range_node(size, align, min_addr,
fc6daaf93   Tony Luck   mm/memblock: add ...
1339
  						    max_addr, NUMA_NO_NODE,
a3f5bafcc   Tony Luck   mm/memblock: allo...
1340
  						    flags);
7d41c03e2   Wei Yang   mm/memblock.c: ch...
1341
  		if (alloc && !memblock_reserve(alloc, size))
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1342
1343
1344
1345
1346
1347
  			goto done;
  	}
  
  	if (min_addr) {
  		min_addr = 0;
  		goto again;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1348
  	}
a3f5bafcc   Tony Luck   mm/memblock: allo...
1349
1350
1351
1352
1353
1354
1355
1356
1357
  	if (flags & MEMBLOCK_MIRROR) {
  		flags &= ~MEMBLOCK_MIRROR;
  		pr_warn("Could not allocate %pap bytes of mirrored memory
  ",
  			&size);
  		goto again;
  	}
  
  	return NULL;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1358
  done:
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1359
  	ptr = phys_to_virt(alloc);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
  
  	/*
  	 * The min_count is set to 0 so that bootmem 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.
  	 */
  	kmemleak_alloc(ptr, size, 0, 0);
  
  	return ptr;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1370
1371
1372
  }
  
  /**
ea1f5f371   Pavel Tatashin   mm: define memblo...
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
   * memblock_virt_alloc_try_nid_raw - allocate boot memory block without zeroing
   * 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
   *	      is preferred (phys address), or %BOOTMEM_ALLOC_ACCESSIBLE to
   *	      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...
1388
   * Return:
ea1f5f371   Pavel Tatashin   mm: define memblo...
1389
1390
1391
1392
1393
1394
1395
1396
   * Virtual address of allocated memory block on success, NULL on failure.
   */
  void * __init memblock_virt_alloc_try_nid_raw(
  			phys_addr_t size, phys_addr_t align,
  			phys_addr_t min_addr, phys_addr_t max_addr,
  			int nid)
  {
  	void *ptr;
a36aab890   Mike Rapoport   mm/memblock.c: re...
1397
1398
1399
1400
  	memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pF
  ",
  		     __func__, (u64)size, (u64)align, nid, &min_addr,
  		     &max_addr, (void *)_RET_IP_);
ea1f5f371   Pavel Tatashin   mm: define memblo...
1401
1402
1403
1404
1405
  
  	ptr = memblock_virt_alloc_internal(size, align,
  					   min_addr, max_addr, nid);
  #ifdef CONFIG_DEBUG_VM
  	if (ptr && size > 0)
f165b378b   Pavel Tatashin   mm: uninitialized...
1406
  		memset(ptr, PAGE_POISON_PATTERN, size);
ea1f5f371   Pavel Tatashin   mm: define memblo...
1407
1408
1409
1410
1411
  #endif
  	return ptr;
  }
  
  /**
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
   * memblock_virt_alloc_try_nid_nopanic - allocate boot memory block
   * @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
   *	      is preferred (phys address), or %BOOTMEM_ALLOC_ACCESSIBLE to
   *	      allocate only from memory limited by memblock.current_limit value
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
   *
ea1f5f371   Pavel Tatashin   mm: define memblo...
1422
1423
   * Public function, provides additional debug information (including caller
   * info), if enabled. This function zeroes the allocated memory.
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1424
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1425
   * Return:
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1426
1427
1428
1429
1430
1431
1432
   * Virtual address of allocated memory block on success, NULL on failure.
   */
  void * __init memblock_virt_alloc_try_nid_nopanic(
  				phys_addr_t size, phys_addr_t align,
  				phys_addr_t min_addr, phys_addr_t max_addr,
  				int nid)
  {
ea1f5f371   Pavel Tatashin   mm: define memblo...
1433
  	void *ptr;
a36aab890   Mike Rapoport   mm/memblock.c: re...
1434
1435
1436
1437
  	memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pF
  ",
  		     __func__, (u64)size, (u64)align, nid, &min_addr,
  		     &max_addr, (void *)_RET_IP_);
ea1f5f371   Pavel Tatashin   mm: define memblo...
1438
1439
1440
1441
1442
1443
  
  	ptr = memblock_virt_alloc_internal(size, align,
  					   min_addr, max_addr, nid);
  	if (ptr)
  		memset(ptr, 0, size);
  	return ptr;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
  }
  
  /**
   * memblock_virt_alloc_try_nid - allocate boot memory block with 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
   *	      is preferred (phys address), or %BOOTMEM_ALLOC_ACCESSIBLE to
   *	      allocate only from memory limited by memblock.current_limit value
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
   *
ea1f5f371   Pavel Tatashin   mm: define memblo...
1457
   * Public panicking version of memblock_virt_alloc_try_nid_nopanic()
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1458
1459
1460
   * which provides debug information (including caller info), if enabled,
   * and panics if the request can not be satisfied.
   *
47cec4432   Mike Rapoport   docs/mm: memblock...
1461
   * Return:
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1462
1463
1464
1465
1466
1467
1468
1469
   * Virtual address of allocated memory block on success, NULL on failure.
   */
  void * __init memblock_virt_alloc_try_nid(
  			phys_addr_t size, phys_addr_t align,
  			phys_addr_t min_addr, phys_addr_t max_addr,
  			int nid)
  {
  	void *ptr;
a36aab890   Mike Rapoport   mm/memblock.c: re...
1470
1471
1472
1473
  	memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pF
  ",
  		     __func__, (u64)size, (u64)align, nid, &min_addr,
  		     &max_addr, (void *)_RET_IP_);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1474
1475
  	ptr = memblock_virt_alloc_internal(size, align,
  					   min_addr, max_addr, nid);
ea1f5f371   Pavel Tatashin   mm: define memblo...
1476
1477
  	if (ptr) {
  		memset(ptr, 0, size);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1478
  		return ptr;
ea1f5f371   Pavel Tatashin   mm: define memblo...
1479
  	}
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1480

a36aab890   Mike Rapoport   mm/memblock.c: re...
1481
1482
1483
  	panic("%s: Failed to allocate %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa
  ",
  	      __func__, (u64)size, (u64)align, nid, &min_addr, &max_addr);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1484
1485
  	return NULL;
  }
193736720   Mathieu Malaterre   mm/memblock: add ...
1486
  #endif
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
  
  /**
   * __memblock_free_early - 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_virt_alloc_xx() API.
   * The freeing memory will not be released to the buddy allocator.
   */
  void __init __memblock_free_early(phys_addr_t base, phys_addr_t size)
  {
a36aab890   Mike Rapoport   mm/memblock.c: re...
1498
1499
1500
1501
1502
  	phys_addr_t end = base + size - 1;
  
  	memblock_dbg("%s: [%pa-%pa] %pF
  ",
  		     __func__, &base, &end, (void *)_RET_IP_);
9099daed9   Catalin Marinas   mm: kmemleak: avo...
1503
  	kmemleak_free_part_phys(base, size);
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1504
  	memblock_remove_range(&memblock.reserved, base, size);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1505
  }
48a833cc7   Mike Rapoport   docs/mm: memblock...
1506
  /**
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1507
   * __memblock_free_late - free bootmem block pages directly to buddy allocator
48a833cc7   Mike Rapoport   docs/mm: memblock...
1508
   * @base: phys starting address of the  boot memory block
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1509
1510
1511
1512
1513
1514
1515
1516
   * @size: size of the boot memory block in bytes
   *
   * This is only useful when the bootmem allocator has already been torn
   * down, but we are still initializing the system.  Pages are released directly
   * to the buddy allocator, no bootmem metadata is updated because it is gone.
   */
  void __init __memblock_free_late(phys_addr_t base, phys_addr_t size)
  {
a36aab890   Mike Rapoport   mm/memblock.c: re...
1517
  	phys_addr_t cursor, end;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1518

a36aab890   Mike Rapoport   mm/memblock.c: re...
1519
1520
1521
1522
  	end = base + size - 1;
  	memblock_dbg("%s: [%pa-%pa] %pF
  ",
  		     __func__, &base, &end, (void *)_RET_IP_);
9099daed9   Catalin Marinas   mm: kmemleak: avo...
1523
  	kmemleak_free_part_phys(base, size);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1524
1525
1526
1527
  	cursor = PFN_UP(base);
  	end = PFN_DOWN(base + size);
  
  	for (; cursor < end; cursor++) {
d70ddd7a5   Mel Gorman   mm: page_alloc: p...
1528
  		__free_pages_bootmem(pfn_to_page(cursor), cursor, 0);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1529
1530
1531
  		totalram_pages++;
  	}
  }
9d1e24928   Benjamin Herrenschmidt   memblock: Separat...
1532
1533
1534
1535
  
  /*
   * Remaining API functions
   */
1f1ffb8a1   David Gibson   memblock: don't m...
1536
  phys_addr_t __init_memblock memblock_phys_mem_size(void)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1537
  {
1440c4e2c   Tejun Heo   memblock: Track t...
1538
  	return memblock.memory.total_size;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1539
  }
8907de5dc   Srikar Dronamraju   mm/memblock.c: ex...
1540
1541
1542
1543
  phys_addr_t __init_memblock memblock_reserved_size(void)
  {
  	return memblock.reserved.total_size;
  }
595ad9af8   Yinghai Lu   memblock: Add mem...
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
  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...
1557
  	return PFN_PHYS(pages);
595ad9af8   Yinghai Lu   memblock: Add mem...
1558
  }
0a93ebef6   Sam Ravnborg   memblock: add mem...
1559
1560
1561
1562
1563
  /* lowest address */
  phys_addr_t __init_memblock memblock_start_of_DRAM(void)
  {
  	return memblock.memory.regions[0].base;
  }
10d064398   Yinghai Lu   memblock: Option ...
1564
  phys_addr_t __init_memblock memblock_end_of_DRAM(void)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1565
1566
  {
  	int idx = memblock.memory.cnt - 1;
e3239ff92   Benjamin Herrenschmidt   memblock: Rename ...
1567
  	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1568
  }
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1569
  static phys_addr_t __init_memblock __find_max_addr(phys_addr_t limit)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1570
  {
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1571
  	phys_addr_t max_addr = PHYS_ADDR_MAX;
136199f0a   Emil Medve   memblock: use for...
1572
  	struct memblock_region *r;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1573

a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1574
1575
1576
  	/*
  	 * 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...
1577
  	 * of those regions, max_addr will keep original value PHYS_ADDR_MAX
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1578
  	 */
136199f0a   Emil Medve   memblock: use for...
1579
  	for_each_memblock(memory, r) {
c0ce8fef5   Tejun Heo   memblock: Reimple...
1580
1581
1582
  		if (limit <= r->size) {
  			max_addr = r->base + limit;
  			break;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1583
  		}
c0ce8fef5   Tejun Heo   memblock: Reimple...
1584
  		limit -= r->size;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1585
  	}
c0ce8fef5   Tejun Heo   memblock: Reimple...
1586

a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1587
1588
1589
1590
1591
  	return max_addr;
  }
  
  void __init memblock_enforce_memory_limit(phys_addr_t limit)
  {
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1592
  	phys_addr_t max_addr = PHYS_ADDR_MAX;
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1593
1594
1595
1596
1597
1598
1599
  
  	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...
1600
  	if (max_addr == PHYS_ADDR_MAX)
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1601
  		return;
c0ce8fef5   Tejun Heo   memblock: Reimple...
1602
  	/* truncate both memory and reserved regions */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1603
  	memblock_remove_range(&memblock.memory, max_addr,
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1604
  			      PHYS_ADDR_MAX);
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1605
  	memblock_remove_range(&memblock.reserved, max_addr,
1c4bc43dd   Stefan Agner   mm/memblock: intr...
1606
  			      PHYS_ADDR_MAX);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1607
  }
c9ca9b4e2   AKASHI Takahiro   memblock: add mem...
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
  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...
1633
  			base + size, PHYS_ADDR_MAX);
c9ca9b4e2   AKASHI Takahiro   memblock: add mem...
1634
  }
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1635
1636
  void __init memblock_mem_limit_remove_map(phys_addr_t limit)
  {
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1637
  	phys_addr_t max_addr;
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1638
1639
1640
1641
1642
1643
1644
  
  	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...
1645
  	if (max_addr == PHYS_ADDR_MAX)
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1646
  		return;
c9ca9b4e2   AKASHI Takahiro   memblock: add mem...
1647
  	memblock_cap_memory_range(0, max_addr);
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1648
  }
cd79481d2   Yinghai Lu   memblock: Annotat...
1649
  static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
  {
  	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;
  }
b4ad0c7e0   Yaowei Bai   mm/memblock.c: me...
1666
  bool __init memblock_is_reserved(phys_addr_t addr)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1667
  {
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1668
1669
  	return memblock_search(&memblock.reserved, addr) != -1;
  }
95f72d1ed   Yinghai Lu   lmb: rename to me...
1670

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

136199f0a   Emil Medve   memblock: use for...
1739
1740
1741
  	for_each_memblock(memory, r) {
  		orig_start = r->base;
  		orig_end = r->base + r->size;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1742
1743
1744
1745
1746
1747
1748
  		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...
1749
1750
  			r->base = start;
  			r->size = end - start;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1751
  		} else {
136199f0a   Emil Medve   memblock: use for...
1752
1753
1754
  			memblock_remove_region(&memblock.memory,
  					       r - memblock.memory.regions);
  			r--;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1755
1756
1757
  		}
  	}
  }
e63075a3c   Benjamin Herrenschmidt   memblock: Introdu...
1758

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

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

66e8b438b   Gioh Kim   mm/memblock.c: ma...
1777
  	for_each_memblock_type(idx, type, rgn) {
7c0caeb86   Tejun Heo   memblock: Add opt...
1778
1779
1780
1781
  		char nid_buf[32] = "";
  
  		base = rgn->base;
  		size = rgn->size;
5d63f81c9   Miles Chen   mm/memblock.c: re...
1782
  		end = base + size - 1;
66a207572   Tang Chen   memblock, numa: i...
1783
  		flags = rgn->flags;
7c0caeb86   Tejun Heo   memblock: Add opt...
1784
1785
1786
1787
1788
  #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 ...
1789
1790
  		pr_info(" %s[%#x]\t[%pa-%pa], %pa bytes%s flags: %#x
  ",
0262d9c84   Heiko Carstens   memblock: embed m...
1791
  			type->name, idx, &base, &end, &size, nid_buf, flags);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1792
1793
  	}
  }
4ff7b82f1   Tejun Heo   memblock: Add __m...
1794
  void __init_memblock __memblock_dump_all(void)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1795
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1796
1797
  	pr_info("MEMBLOCK configuration:
  ");
5d63f81c9   Miles Chen   mm/memblock.c: re...
1798
1799
1800
1801
  	pr_info(" memory size = %pa reserved size = %pa
  ",
  		&memblock.memory.total_size,
  		&memblock.reserved.total_size);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1802

0262d9c84   Heiko Carstens   memblock: embed m...
1803
1804
  	memblock_dump(&memblock.memory);
  	memblock_dump(&memblock.reserved);
409efd4c9   Heiko Carstens   memblock: also du...
1805
  #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
0262d9c84   Heiko Carstens   memblock: embed m...
1806
  	memblock_dump(&memblock.physmem);
409efd4c9   Heiko Carstens   memblock: also du...
1807
  #endif
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1808
  }
1aadc0560   Tejun Heo   memblock: s/membl...
1809
  void __init memblock_allow_resize(void)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1810
  {
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
1811
  	memblock_can_resize = 1;
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1812
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1813
1814
1815
1816
1817
1818
1819
  static int __init early_memblock(char *p)
  {
  	if (p && strstr(p, "debug"))
  		memblock_debug = 1;
  	return 0;
  }
  early_param("memblock", early_memblock);
c378ddd53   Tejun Heo   memblock, x86: Ma...
1820
  #if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_ARCH_DISCARD_MEMBLOCK)
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1821
1822
1823
1824
1825
1826
  
  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...
1827
  	phys_addr_t end;
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1828
1829
1830
  
  	for (i = 0; i < type->cnt; i++) {
  		reg = &type->regions[i];
5d63f81c9   Miles Chen   mm/memblock.c: re...
1831
  		end = reg->base + reg->size - 1;
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1832

5d63f81c9   Miles Chen   mm/memblock.c: re...
1833
1834
1835
  		seq_printf(m, "%4d: ", i);
  		seq_printf(m, "%pa..%pa
  ", &reg->base, &end);
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1836
1837
1838
  	}
  	return 0;
  }
5ad350936   Andy Shevchenko   mm: reuse DEFINE_...
1839
  DEFINE_SHOW_ATTRIBUTE(memblock_debug);
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1840
1841
1842
1843
1844
1845
  
  static int __init memblock_init_debugfs(void)
  {
  	struct dentry *root = debugfs_create_dir("memblock", NULL);
  	if (!root)
  		return -ENXIO;
0825a6f98   Joe Perches   mm: use octal not...
1846
1847
1848
1849
  	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 ...
1850
  #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
0825a6f98   Joe Perches   mm: use octal not...
1851
1852
  	debugfs_create_file("physmem", 0444, root,
  			    &memblock.physmem, &memblock_debug_fops);
70210ed95   Philipp Hachtmann   mm/memblock: add ...
1853
  #endif
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1854
1855
1856
1857
1858
1859
  
  	return 0;
  }
  __initcall(memblock_init_debugfs);
  
  #endif /* CONFIG_DEBUG_FS */