Blame view

mm/memblock.c 45 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
20
  #include <linux/debugfs.h>
  #include <linux/seq_file.h>
95f72d1ed   Yinghai Lu   lmb: rename to me...
21
  #include <linux/memblock.h>
79442ed18   Tang Chen   mm/memblock.c: in...
22
  #include <asm-generic/sections.h>
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
23
24
25
  #include <linux/io.h>
  
  #include "internal.h"
79442ed18   Tang Chen   mm/memblock.c: in...
26

fe091c208   Tejun Heo   memblock: Kill me...
27
28
  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 ...
29
30
31
  #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...
32
33
34
35
36
37
38
39
40
  
  struct memblock memblock __initdata_memblock = {
  	.memory.regions		= memblock_memory_init_regions,
  	.memory.cnt		= 1,	/* empty dummy entry */
  	.memory.max		= INIT_MEMBLOCK_REGIONS,
  
  	.reserved.regions	= memblock_reserved_init_regions,
  	.reserved.cnt		= 1,	/* empty dummy entry */
  	.reserved.max		= INIT_MEMBLOCK_REGIONS,
70210ed95   Philipp Hachtmann   mm/memblock: add ...
41
42
43
44
45
  #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
  	.physmem.regions	= memblock_physmem_init_regions,
  	.physmem.cnt		= 1,	/* empty dummy entry */
  	.physmem.max		= INIT_PHYSMEM_REGIONS,
  #endif
79442ed18   Tang Chen   mm/memblock.c: in...
46
  	.bottom_up		= false,
fe091c208   Tejun Heo   memblock: Kill me...
47
48
  	.current_limit		= MEMBLOCK_ALLOC_ANYWHERE,
  };
95f72d1ed   Yinghai Lu   lmb: rename to me...
49

10d064398   Yinghai Lu   memblock: Option ...
50
  int memblock_debug __initdata_memblock;
55ac590c2   Tang Chen   memblock, mem_hot...
51
52
53
  #ifdef CONFIG_MOVABLE_NODE
  bool movable_node_enabled __initdata_memblock = false;
  #endif
1aadc0560   Tejun Heo   memblock: s/membl...
54
  static int memblock_can_resize __initdata_memblock;
181eb3942   Gavin Shan   mm/memblock: fix ...
55
56
  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...
57

142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
58
  /* inline so we don't get a warning when pr_debug is compiled out */
c22331166   Raghavendra D Prabhu   mm: avoid section...
59
60
  static __init_memblock const char *
  memblock_type_name(struct memblock_type *type)
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
61
62
63
64
65
66
67
68
  {
  	if (type == &memblock.memory)
  		return "memory";
  	else if (type == &memblock.reserved)
  		return "reserved";
  	else
  		return "unknown";
  }
eb18f1b5b   Tejun Heo   memblock: Make me...
69
70
71
72
73
  /* 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)
  {
  	return *size = min(*size, (phys_addr_t)ULLONG_MAX - base);
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
74
75
76
  /*
   * Address comparison utilities
   */
10d064398   Yinghai Lu   memblock: Option ...
77
  static unsigned long __init_memblock memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
2898cc4cd   Benjamin Herrenschmidt   memblock: Change ...
78
  				       phys_addr_t base2, phys_addr_t size2)
95f72d1ed   Yinghai Lu   lmb: rename to me...
79
80
81
  {
  	return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
  }
2d7d3eb2b   H Hartley Sweeten   mm/memblock.c: qu...
82
83
  static long __init_memblock memblock_overlaps_region(struct memblock_type *type,
  					phys_addr_t base, phys_addr_t size)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
84
85
86
87
88
89
90
91
92
93
94
95
  {
  	unsigned long i;
  
  	for (i = 0; i < type->cnt; i++) {
  		phys_addr_t rgnbase = type->regions[i].base;
  		phys_addr_t rgnsize = type->regions[i].size;
  		if (memblock_addrs_overlap(base, size, rgnbase, rgnsize))
  			break;
  	}
  
  	return (i < type->cnt) ? i : -1;
  }
79442ed18   Tang Chen   mm/memblock.c: in...
96
97
98
99
100
101
  /*
   * __memblock_find_range_bottom_up - find free area utility in bottom-up
   * @start: start of candidate range
   * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
   * @size: size of free area to find
   * @align: alignment of free area to find
b11542335   Grygorii Strashko   mm/memblock: swit...
102
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
79442ed18   Tang Chen   mm/memblock.c: in...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
   *
   * Utility called from memblock_find_in_range_node(), find free area bottom-up.
   *
   * RETURNS:
   * 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,
  				phys_addr_t size, phys_addr_t align, int nid)
  {
  	phys_addr_t this_start, this_end, cand;
  	u64 i;
  
  	for_each_free_mem_range(i, nid, &this_start, &this_end, NULL) {
  		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...
127
  /**
1402899e4   Tang Chen   mm/memblock.c: fa...
128
   * __memblock_find_range_top_down - find free area utility, in top-down
7bd0b0f0d   Tejun Heo   memblock: Reimple...
129
130
131
132
   * @start: start of candidate range
   * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
   * @size: size of free area to find
   * @align: alignment of free area to find
b11542335   Grygorii Strashko   mm/memblock: swit...
133
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
7bd0b0f0d   Tejun Heo   memblock: Reimple...
134
   *
1402899e4   Tang Chen   mm/memblock.c: fa...
135
   * Utility called from memblock_find_in_range_node(), find free area top-down.
7bd0b0f0d   Tejun Heo   memblock: Reimple...
136
137
   *
   * RETURNS:
79442ed18   Tang Chen   mm/memblock.c: in...
138
   * Found address on success, 0 on failure.
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
139
   */
1402899e4   Tang Chen   mm/memblock.c: fa...
140
141
142
  static phys_addr_t __init_memblock
  __memblock_find_range_top_down(phys_addr_t start, phys_addr_t end,
  			       phys_addr_t size, phys_addr_t align, int nid)
f7210e6c4   Tang Chen   mm/memblock.c: us...
143
144
145
  {
  	phys_addr_t this_start, this_end, cand;
  	u64 i;
f7210e6c4   Tang Chen   mm/memblock.c: us...
146
147
148
149
150
151
152
153
154
155
156
  	for_each_free_mem_range_reverse(i, nid, &this_start, &this_end, NULL) {
  		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...
157

f7210e6c4   Tang Chen   mm/memblock.c: us...
158
159
  	return 0;
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
160

7bd0b0f0d   Tejun Heo   memblock: Reimple...
161
  /**
1402899e4   Tang Chen   mm/memblock.c: fa...
162
   * memblock_find_in_range_node - find free area in given range and node
1402899e4   Tang Chen   mm/memblock.c: fa...
163
164
   * @size: size of free area to find
   * @align: alignment of free area to find
87029ee93   Grygorii Strashko   mm/memblock: reor...
165
166
   * @start: start of candidate range
   * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
b11542335   Grygorii Strashko   mm/memblock: swit...
167
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
1402899e4   Tang Chen   mm/memblock.c: fa...
168
169
170
   *
   * Find @size free area aligned to @align in the specified range and node.
   *
79442ed18   Tang Chen   mm/memblock.c: in...
171
172
173
174
175
176
177
178
   * 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.
   *
1402899e4   Tang Chen   mm/memblock.c: fa...
179
   * RETURNS:
79442ed18   Tang Chen   mm/memblock.c: in...
180
   * Found address on success, 0 on failure.
1402899e4   Tang Chen   mm/memblock.c: fa...
181
   */
87029ee93   Grygorii Strashko   mm/memblock: reor...
182
183
184
  phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
  					phys_addr_t align, phys_addr_t start,
  					phys_addr_t end, int nid)
1402899e4   Tang Chen   mm/memblock.c: fa...
185
  {
0cfb8f0c3   Tang Chen   memblock, memhotp...
186
  	phys_addr_t kernel_end, ret;
79442ed18   Tang Chen   mm/memblock.c: in...
187

1402899e4   Tang Chen   mm/memblock.c: fa...
188
189
190
191
192
193
194
  	/* 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...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
  	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,
  						      size, align, nid);
  		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.
  		 */
  		WARN_ONCE(1, "memblock: bottom-up allocation failed, "
  			     "memory hotunplug may be affected
  ");
  	}
1402899e4   Tang Chen   mm/memblock.c: fa...
227
228
229
230
231
  
  	return __memblock_find_range_top_down(start, end, size, align, nid);
  }
  
  /**
7bd0b0f0d   Tejun Heo   memblock: Reimple...
232
233
234
235
236
237
238
239
240
   * memblock_find_in_range - find free area in given range
   * @start: start of candidate range
   * @end: end of candidate range, can be %MEMBLOCK_ALLOC_{ANYWHERE|ACCESSIBLE}
   * @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.
   *
   * RETURNS:
79442ed18   Tang Chen   mm/memblock.c: in...
241
   * Found address on success, 0 on failure.
fc769a8e7   Tejun Heo   memblock: Replace...
242
   */
7bd0b0f0d   Tejun Heo   memblock: Reimple...
243
244
245
  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...
246
  {
87029ee93   Grygorii Strashko   mm/memblock: reor...
247
  	return memblock_find_in_range_node(size, align, start, end,
b11542335   Grygorii Strashko   mm/memblock: swit...
248
  					    NUMA_NO_NODE);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
249
  }
10d064398   Yinghai Lu   memblock: Option ...
250
  static void __init_memblock memblock_remove_region(struct memblock_type *type, unsigned long r)
95f72d1ed   Yinghai Lu   lmb: rename to me...
251
  {
1440c4e2c   Tejun Heo   memblock: Track t...
252
  	type->total_size -= type->regions[r].size;
7c0caeb86   Tejun Heo   memblock: Add opt...
253
254
  	memmove(&type->regions[r], &type->regions[r + 1],
  		(type->cnt - (r + 1)) * sizeof(type->regions[r]));
e3239ff92   Benjamin Herrenschmidt   memblock: Rename ...
255
  	type->cnt--;
95f72d1ed   Yinghai Lu   lmb: rename to me...
256

8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
257
258
  	/* Special case for empty arrays */
  	if (type->cnt == 0) {
1440c4e2c   Tejun Heo   memblock: Track t...
259
  		WARN_ON(type->total_size != 0);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
260
261
262
  		type->cnt = 1;
  		type->regions[0].base = 0;
  		type->regions[0].size = 0;
66a207572   Tang Chen   memblock, numa: i...
263
  		type->regions[0].flags = 0;
7c0caeb86   Tejun Heo   memblock: Add opt...
264
  		memblock_set_region_node(&type->regions[0], MAX_NUMNODES);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
265
  	}
95f72d1ed   Yinghai Lu   lmb: rename to me...
266
  }
354f17e1e   Philipp Hachtmann   mm/nobootmem: fre...
267
  #ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
29f673860   Yinghai Lu   memblock: free al...
268
269
270
271
272
273
274
275
276
277
278
  phys_addr_t __init_memblock get_allocated_memblock_reserved_regions_info(
  					phys_addr_t *addr)
  {
  	if (memblock.reserved.regions == memblock_reserved_init_regions)
  		return 0;
  
  	*addr = __pa(memblock.reserved.regions);
  
  	return PAGE_ALIGN(sizeof(struct memblock_region) *
  			  memblock.reserved.max);
  }
5e270e254   Philipp Hachtmann   mm: free memblock...
279
280
281
282
283
284
285
286
287
288
289
290
291
  phys_addr_t __init_memblock get_allocated_memblock_memory_regions_info(
  					phys_addr_t *addr)
  {
  	if (memblock.memory.regions == memblock_memory_init_regions)
  		return 0;
  
  	*addr = __pa(memblock.memory.regions);
  
  	return PAGE_ALIGN(sizeof(struct memblock_region) *
  			  memblock.memory.max);
  }
  
  #endif
48c3b583b   Greg Pearson   mm/memblock: fix ...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
  /**
   * 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
   * allocated memory range [@new_area_start,@new_area_start+@new_area_size]
   * waiting to be reserved, ensure the memory used by the new array does
   * not overlap.
   *
   * RETURNS:
   * 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...
310
311
  {
  	struct memblock_region *new_array, *old_array;
29f673860   Yinghai Lu   memblock: free al...
312
  	phys_addr_t old_alloc_size, new_alloc_size;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
313
314
  	phys_addr_t old_size, new_size, addr;
  	int use_slab = slab_is_available();
181eb3942   Gavin Shan   mm/memblock: fix ...
315
  	int *in_slab;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
316
317
318
319
320
321
  
  	/* 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...
322
323
324
  	/* Calculate new doubled size */
  	old_size = type->max * sizeof(struct memblock_region);
  	new_size = old_size << 1;
29f673860   Yinghai Lu   memblock: free al...
325
326
327
328
329
330
  	/*
  	 * 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...
331

181eb3942   Gavin Shan   mm/memblock: fix ...
332
333
334
335
336
  	/* 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...
337
338
339
  	/* 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...
340
341
342
  	 * 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...
343
344
  	 *
  	 * This should however not be an issue for now, as we currently only
fd07383b6   Andrew Morton   mm/memblock.c:mem...
345
346
  	 * 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...
347
348
349
  	 */
  	if (use_slab) {
  		new_array = kmalloc(new_size, GFP_KERNEL);
1f5026a7e   Tejun Heo   memblock: Kill ME...
350
  		addr = new_array ? __pa(new_array) : 0;
4e2f07750   Gavin Shan   mm/memblock: clea...
351
  	} else {
48c3b583b   Greg Pearson   mm/memblock: fix ...
352
353
354
355
356
357
  		/* 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...
358
  						new_alloc_size, PAGE_SIZE);
48c3b583b   Greg Pearson   mm/memblock: fix ...
359
360
  		if (!addr && new_area_size)
  			addr = memblock_find_in_range(0,
fd07383b6   Andrew Morton   mm/memblock.c:mem...
361
362
  				min(new_area_start, memblock.current_limit),
  				new_alloc_size, PAGE_SIZE);
48c3b583b   Greg Pearson   mm/memblock: fix ...
363

15674868d   Sachin Kamat   mm/memblock: Use ...
364
  		new_array = addr ? __va(addr) : NULL;
4e2f07750   Gavin Shan   mm/memblock: clea...
365
  	}
1f5026a7e   Tejun Heo   memblock: Kill ME...
366
  	if (!addr) {
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
367
368
369
370
371
  		pr_err("memblock: Failed to double %s array from %ld to %ld entries !
  ",
  		       memblock_type_name(type), type->max, type->max * 2);
  		return -1;
  	}
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
372

fd07383b6   Andrew Morton   mm/memblock.c:mem...
373
374
375
  	memblock_dbg("memblock: %s is doubled to %ld at [%#010llx-%#010llx]",
  			memblock_type_name(type), type->max * 2, (u64)addr,
  			(u64)addr + new_size - 1);
ea9e4376b   Yinghai Lu   memblock: Improve...
376

fd07383b6   Andrew Morton   mm/memblock.c:mem...
377
378
379
380
  	/*
  	 * 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...
381
382
383
384
385
386
  	 */
  	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...
387
  	/* Free old array. We needn't free it if the array is the static one */
181eb3942   Gavin Shan   mm/memblock: fix ...
388
389
390
391
  	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...
392
  		memblock_free(__pa(old_array), old_alloc_size);
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
393

fd07383b6   Andrew Morton   mm/memblock.c:mem...
394
395
396
  	/*
  	 * Reserve the new array if that comes from the memblock.  Otherwise, we
  	 * needn't do it
181eb3942   Gavin Shan   mm/memblock: fix ...
397
398
  	 */
  	if (!use_slab)
29f673860   Yinghai Lu   memblock: free al...
399
  		BUG_ON(memblock_reserve(addr, new_alloc_size));
181eb3942   Gavin Shan   mm/memblock: fix ...
400
401
402
  
  	/* Update slab flag */
  	*in_slab = use_slab;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
403
404
  	return 0;
  }
784656f9c   Tejun Heo   memblock: Reimple...
405
406
407
408
409
410
411
  /**
   * 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...
412
  {
784656f9c   Tejun Heo   memblock: Reimple...
413
  	int i = 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
414

784656f9c   Tejun Heo   memblock: Reimple...
415
416
417
418
  	/* 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...
419

7c0caeb86   Tejun Heo   memblock: Add opt...
420
421
  		if (this->base + this->size != next->base ||
  		    memblock_get_region_node(this) !=
66a207572   Tang Chen   memblock, numa: i...
422
423
  		    memblock_get_region_node(next) ||
  		    this->flags != next->flags) {
784656f9c   Tejun Heo   memblock: Reimple...
424
425
426
  			BUG_ON(this->base + this->size > next->base);
  			i++;
  			continue;
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
427
  		}
784656f9c   Tejun Heo   memblock: Reimple...
428
  		this->size += next->size;
c0232ae86   Lin Feng   mm: memblock: fix...
429
430
  		/* 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...
431
  		type->cnt--;
95f72d1ed   Yinghai Lu   lmb: rename to me...
432
  	}
784656f9c   Tejun Heo   memblock: Reimple...
433
  }
95f72d1ed   Yinghai Lu   lmb: rename to me...
434

784656f9c   Tejun Heo   memblock: Reimple...
435
436
  /**
   * memblock_insert_region - insert new memblock region
209ff86d6   Tang Chen   memblock: fix mis...
437
438
439
440
441
   * @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...
442
   * @flags:	flags of the new region
784656f9c   Tejun Heo   memblock: Reimple...
443
444
445
446
447
448
   *
   * Insert new memblock region [@base,@base+@size) into @type at @idx.
   * @type must already have extra room to accomodate the new region.
   */
  static void __init_memblock memblock_insert_region(struct memblock_type *type,
  						   int idx, phys_addr_t base,
66a207572   Tang Chen   memblock, numa: i...
449
450
  						   phys_addr_t size,
  						   int nid, unsigned long flags)
784656f9c   Tejun Heo   memblock: Reimple...
451
452
453
454
455
456
457
  {
  	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...
458
  	rgn->flags = flags;
7c0caeb86   Tejun Heo   memblock: Add opt...
459
  	memblock_set_region_node(rgn, nid);
784656f9c   Tejun Heo   memblock: Reimple...
460
  	type->cnt++;
1440c4e2c   Tejun Heo   memblock: Track t...
461
  	type->total_size += size;
784656f9c   Tejun Heo   memblock: Reimple...
462
463
464
  }
  
  /**
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
465
   * memblock_add_range - add new memblock region
784656f9c   Tejun Heo   memblock: Reimple...
466
467
468
   * @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...
469
   * @nid: nid of the new region
66a207572   Tang Chen   memblock, numa: i...
470
   * @flags: flags of the new region
784656f9c   Tejun Heo   memblock: Reimple...
471
472
473
474
475
476
477
478
479
   *
   * Add new memblock region [@base,@base+@size) into @type.  The new region
   * 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.
   *
   * RETURNS:
   * 0 on success, -errno on failure.
   */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
480
  int __init_memblock memblock_add_range(struct memblock_type *type,
66a207572   Tang Chen   memblock, numa: i...
481
482
  				phys_addr_t base, phys_addr_t size,
  				int nid, unsigned long flags)
784656f9c   Tejun Heo   memblock: Reimple...
483
484
  {
  	bool insert = false;
eb18f1b5b   Tejun Heo   memblock: Make me...
485
486
  	phys_addr_t obase = base;
  	phys_addr_t end = base + memblock_cap_size(base, &size);
784656f9c   Tejun Heo   memblock: Reimple...
487
  	int i, nr_new;
b3dc627ca   Tejun Heo   memblock: membloc...
488
489
  	if (!size)
  		return 0;
784656f9c   Tejun Heo   memblock: Reimple...
490
491
  	/* special case for empty array */
  	if (type->regions[0].size == 0) {
1440c4e2c   Tejun Heo   memblock: Track t...
492
  		WARN_ON(type->cnt != 1 || type->total_size);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
493
494
  		type->regions[0].base = base;
  		type->regions[0].size = size;
66a207572   Tang Chen   memblock, numa: i...
495
  		type->regions[0].flags = flags;
7fb0bc3f0   Tejun Heo   memblock: Impleme...
496
  		memblock_set_region_node(&type->regions[0], nid);
1440c4e2c   Tejun Heo   memblock: Track t...
497
  		type->total_size = size;
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
498
  		return 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
499
  	}
784656f9c   Tejun Heo   memblock: Reimple...
500
501
502
503
504
  repeat:
  	/*
  	 * The following is executed twice.  Once with %false @insert and
  	 * then with %true.  The first counts the number of regions needed
  	 * to accomodate the new area.  The second actually inserts them.
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
505
  	 */
784656f9c   Tejun Heo   memblock: Reimple...
506
507
  	base = obase;
  	nr_new = 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
508

784656f9c   Tejun Heo   memblock: Reimple...
509
510
511
512
513
514
  	for (i = 0; i < type->cnt; i++) {
  		struct memblock_region *rgn = &type->regions[i];
  		phys_addr_t rbase = rgn->base;
  		phys_addr_t rend = rbase + rgn->size;
  
  		if (rbase >= end)
95f72d1ed   Yinghai Lu   lmb: rename to me...
515
  			break;
784656f9c   Tejun Heo   memblock: Reimple...
516
517
518
519
520
521
522
523
524
525
  		if (rend <= base)
  			continue;
  		/*
  		 * @rgn overlaps.  If it separates the lower part of new
  		 * area, insert that portion.
  		 */
  		if (rbase > base) {
  			nr_new++;
  			if (insert)
  				memblock_insert_region(type, i++, base,
66a207572   Tang Chen   memblock, numa: i...
526
527
  						       rbase - base, nid,
  						       flags);
95f72d1ed   Yinghai Lu   lmb: rename to me...
528
  		}
784656f9c   Tejun Heo   memblock: Reimple...
529
530
  		/* area below @rend is dealt with, forget about it */
  		base = min(rend, end);
95f72d1ed   Yinghai Lu   lmb: rename to me...
531
  	}
784656f9c   Tejun Heo   memblock: Reimple...
532
533
534
535
536
  
  	/* insert the remaining portion */
  	if (base < end) {
  		nr_new++;
  		if (insert)
66a207572   Tang Chen   memblock, numa: i...
537
538
  			memblock_insert_region(type, i, base, end - base,
  					       nid, flags);
95f72d1ed   Yinghai Lu   lmb: rename to me...
539
  	}
95f72d1ed   Yinghai Lu   lmb: rename to me...
540

784656f9c   Tejun Heo   memblock: Reimple...
541
542
543
  	/*
  	 * If this was the first round, resize array and repeat for actual
  	 * insertions; otherwise, merge and return.
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
544
  	 */
784656f9c   Tejun Heo   memblock: Reimple...
545
546
  	if (!insert) {
  		while (type->cnt + nr_new > type->max)
48c3b583b   Greg Pearson   mm/memblock: fix ...
547
  			if (memblock_double_array(type, obase, size) < 0)
784656f9c   Tejun Heo   memblock: Reimple...
548
549
550
551
552
553
  				return -ENOMEM;
  		insert = true;
  		goto repeat;
  	} else {
  		memblock_merge_regions(type);
  		return 0;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
554
  	}
95f72d1ed   Yinghai Lu   lmb: rename to me...
555
  }
7fb0bc3f0   Tejun Heo   memblock: Impleme...
556
557
558
  int __init_memblock memblock_add_node(phys_addr_t base, phys_addr_t size,
  				       int nid)
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
559
  	return memblock_add_range(&memblock.memory, base, size, nid, 0);
7fb0bc3f0   Tejun Heo   memblock: Impleme...
560
  }
6a4055bc7   Alexander Kuleshov   mm/memblock.c: ad...
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
  static int __init_memblock memblock_add_region(phys_addr_t base,
  						phys_addr_t size,
  						int nid,
  						unsigned long flags)
  {
  	struct memblock_type *_rgn = &memblock.memory;
  
  	memblock_dbg("memblock_add: [%#016llx-%#016llx] flags %#02lx %pF
  ",
  		     (unsigned long long)base,
  		     (unsigned long long)base + size - 1,
  		     flags, (void *)_RET_IP_);
  
  	return memblock_add_range(_rgn, base, size, nid, flags);
  }
581adcbe1   Tejun Heo   memblock: Make me...
576
  int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
577
  {
6a4055bc7   Alexander Kuleshov   mm/memblock.c: ad...
578
  	return memblock_add_region(base, size, MAX_NUMNODES, 0);
95f72d1ed   Yinghai Lu   lmb: rename to me...
579
  }
6a9ceb31c   Tejun Heo   memblock: Separat...
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
  /**
   * 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
   * [@base,@base+@size).  Crossing regions are split at the boundaries,
   * 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.
   *
   * RETURNS:
   * 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...
600
  	phys_addr_t end = base + memblock_cap_size(base, &size);
6a9ceb31c   Tejun Heo   memblock: Separat...
601
602
603
  	int i;
  
  	*start_rgn = *end_rgn = 0;
b3dc627ca   Tejun Heo   memblock: membloc...
604
605
  	if (!size)
  		return 0;
6a9ceb31c   Tejun Heo   memblock: Separat...
606
607
  	/* we'll create at most two more regions */
  	while (type->cnt + 2 > type->max)
48c3b583b   Greg Pearson   mm/memblock: fix ...
608
  		if (memblock_double_array(type, base, size) < 0)
6a9ceb31c   Tejun Heo   memblock: Separat...
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
  			return -ENOMEM;
  
  	for (i = 0; i < type->cnt; i++) {
  		struct memblock_region *rgn = &type->regions[i];
  		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...
627
628
  			rgn->size -= base - rbase;
  			type->total_size -= base - rbase;
6a9ceb31c   Tejun Heo   memblock: Separat...
629
  			memblock_insert_region(type, i, rbase, base - rbase,
66a207572   Tang Chen   memblock, numa: i...
630
631
  					       memblock_get_region_node(rgn),
  					       rgn->flags);
6a9ceb31c   Tejun Heo   memblock: Separat...
632
633
634
635
636
637
  		} 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...
638
639
  			rgn->size -= end - rbase;
  			type->total_size -= end - rbase;
6a9ceb31c   Tejun Heo   memblock: Separat...
640
  			memblock_insert_region(type, i--, rbase, end - rbase,
66a207572   Tang Chen   memblock, numa: i...
641
642
  					       memblock_get_region_node(rgn),
  					       rgn->flags);
6a9ceb31c   Tejun Heo   memblock: Separat...
643
644
645
646
647
648
649
650
651
652
  		} else {
  			/* @rgn is fully contained, record it */
  			if (!*end_rgn)
  				*start_rgn = i;
  			*end_rgn = i + 1;
  		}
  	}
  
  	return 0;
  }
6a9ceb31c   Tejun Heo   memblock: Separat...
653

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
654
655
  int __init_memblock memblock_remove_range(struct memblock_type *type,
  					  phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
656
  {
719361809   Tejun Heo   memblock: Reimple...
657
658
  	int start_rgn, end_rgn;
  	int i, ret;
95f72d1ed   Yinghai Lu   lmb: rename to me...
659

719361809   Tejun Heo   memblock: Reimple...
660
661
662
  	ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);
  	if (ret)
  		return ret;
95f72d1ed   Yinghai Lu   lmb: rename to me...
663

719361809   Tejun Heo   memblock: Reimple...
664
665
  	for (i = end_rgn - 1; i >= start_rgn; i--)
  		memblock_remove_region(type, i);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
666
  	return 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
667
  }
581adcbe1   Tejun Heo   memblock: Make me...
668
  int __init_memblock memblock_remove(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
669
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
670
  	return memblock_remove_range(&memblock.memory, base, size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
671
  }
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
672

581adcbe1   Tejun Heo   memblock: Make me...
673
  int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
674
  {
24aa07882   Tejun Heo   memblock, x86: Re...
675
676
  	memblock_dbg("   memblock_free: [%#016llx-%#016llx] %pF
  ",
a150439c4   H. Peter Anvin   memblock: Cast ph...
677
  		     (unsigned long long)base,
931d13f53   Grygorii Strashko   mm/memblock: debu...
678
  		     (unsigned long long)base + size - 1,
a150439c4   H. Peter Anvin   memblock: Cast ph...
679
  		     (void *)_RET_IP_);
24aa07882   Tejun Heo   memblock, x86: Re...
680

aedf95ea0   Catalin Marinas   mm/memblock.c: ca...
681
  	kmemleak_free_part(__va(base), size);
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
682
  	return memblock_remove_range(&memblock.reserved, base, size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
683
  }
66a207572   Tang Chen   memblock, numa: i...
684
685
686
687
  static int __init_memblock memblock_reserve_region(phys_addr_t base,
  						   phys_addr_t size,
  						   int nid,
  						   unsigned long flags)
95f72d1ed   Yinghai Lu   lmb: rename to me...
688
  {
7fc825b45   Baoquan He   mm/memblock.c: re...
689
  	struct memblock_type *type = &memblock.reserved;
95f72d1ed   Yinghai Lu   lmb: rename to me...
690

66a207572   Tang Chen   memblock, numa: i...
691
692
  	memblock_dbg("memblock_reserve: [%#016llx-%#016llx] flags %#02lx %pF
  ",
a150439c4   H. Peter Anvin   memblock: Cast ph...
693
  		     (unsigned long long)base,
931d13f53   Grygorii Strashko   mm/memblock: debu...
694
  		     (unsigned long long)base + size - 1,
66a207572   Tang Chen   memblock, numa: i...
695
  		     flags, (void *)_RET_IP_);
7fc825b45   Baoquan He   mm/memblock.c: re...
696
  	return memblock_add_range(type, base, size, nid, flags);
66a207572   Tang Chen   memblock, numa: i...
697
  }
95f72d1ed   Yinghai Lu   lmb: rename to me...
698

66a207572   Tang Chen   memblock, numa: i...
699
700
701
  int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
  {
  	return memblock_reserve_region(base, size, MAX_NUMNODES, 0);
95f72d1ed   Yinghai Lu   lmb: rename to me...
702
  }
35fd0808d   Tejun Heo   memblock: Impleme...
703
  /**
66b16edf9   Tang Chen   memblock, mem_hot...
704
   *
4308ce17f   Tony Luck   mm/memblock.c: re...
705
   * This function isolates region [@base, @base + @size), and sets/clears flag
66b16edf9   Tang Chen   memblock, mem_hot...
706
707
708
   *
   * Return 0 on succees, -errno on failure.
   */
4308ce17f   Tony Luck   mm/memblock.c: re...
709
710
  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...
711
712
713
714
715
716
717
718
719
  {
  	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...
720
721
722
723
  		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...
724
725
726
727
728
729
  
  	memblock_merge_regions(type);
  	return 0;
  }
  
  /**
4308ce17f   Tony Luck   mm/memblock.c: re...
730
   * memblock_mark_hotplug - Mark hotpluggable memory with flag MEMBLOCK_HOTPLUG.
66b16edf9   Tang Chen   memblock, mem_hot...
731
732
733
   * @base: the base phys addr of the region
   * @size: the size of the region
   *
4308ce17f   Tony Luck   mm/memblock.c: re...
734
735
736
737
738
739
740
741
742
743
744
   * Return 0 on succees, -errno on failure.
   */
  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...
745
746
747
748
749
   *
   * Return 0 on succees, -errno on failure.
   */
  int __init_memblock memblock_clear_hotplug(phys_addr_t base, phys_addr_t size)
  {
4308ce17f   Tony Luck   mm/memblock.c: re...
750
  	return memblock_setclr_flag(base, size, 0, MEMBLOCK_HOTPLUG);
66b16edf9   Tang Chen   memblock, mem_hot...
751
752
753
  }
  
  /**
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
754
   * __next__mem_range - next function for for_each_free_mem_range() etc.
35fd0808d   Tejun Heo   memblock: Impleme...
755
   * @idx: pointer to u64 loop variable
b11542335   Grygorii Strashko   mm/memblock: swit...
756
   * @nid: node selector, %NUMA_NO_NODE for all nodes
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
757
758
   * @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...
759
760
761
   * @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...
762
   *
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
763
   * Find the first area from *@idx which matches @nid, fill the out
35fd0808d   Tejun Heo   memblock: Impleme...
764
   * parameters, and update *@idx for the next iteration.  The lower 32bit of
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
765
766
   * *@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...
767
768
769
770
771
772
773
774
775
776
777
   * 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.
   */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
778
779
780
781
782
  void __init_memblock __next_mem_range(u64 *idx, int nid,
  				      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...
783
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
784
785
  	int idx_a = *idx & 0xffffffff;
  	int idx_b = *idx >> 32;
b11542335   Grygorii Strashko   mm/memblock: swit...
786

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
787
788
789
  	if (WARN_ONCE(nid == MAX_NUMNODES,
  	"Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead
  "))
560dca27a   Grygorii Strashko   mm/memblock: use ...
790
  		nid = NUMA_NO_NODE;
35fd0808d   Tejun Heo   memblock: Impleme...
791

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
792
793
  	for (; idx_a < type_a->cnt; idx_a++) {
  		struct memblock_region *m = &type_a->regions[idx_a];
35fd0808d   Tejun Heo   memblock: Impleme...
794
795
  		phys_addr_t m_start = m->base;
  		phys_addr_t m_end = m->base + m->size;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
796
  		int	    m_nid = memblock_get_region_node(m);
35fd0808d   Tejun Heo   memblock: Impleme...
797
798
  
  		/* only memory regions are associated with nodes, check it */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
799
  		if (nid != NUMA_NO_NODE && nid != m_nid)
35fd0808d   Tejun Heo   memblock: Impleme...
800
  			continue;
0a313a998   Xishi Qiu   mem-hotplug: let ...
801
802
803
  		/* skip hotpluggable memory regions if needed */
  		if (movable_node_is_enabled() && memblock_is_hotpluggable(m))
  			continue;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
  		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 ?
  				r->base : ULLONG_MAX;
35fd0808d   Tejun Heo   memblock: Impleme...
826

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
827
828
829
830
  			/*
  			 * if idx_b advanced past idx_a,
  			 * break out to advance idx_a
  			 */
35fd0808d   Tejun Heo   memblock: Impleme...
831
832
833
834
835
  			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...
836
837
  					*out_start =
  						max(m_start, r_start);
35fd0808d   Tejun Heo   memblock: Impleme...
838
839
840
  				if (out_end)
  					*out_end = min(m_end, r_end);
  				if (out_nid)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
841
  					*out_nid = m_nid;
35fd0808d   Tejun Heo   memblock: Impleme...
842
  				/*
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
843
844
  				 * The region which ends first is
  				 * advanced for the next iteration.
35fd0808d   Tejun Heo   memblock: Impleme...
845
846
  				 */
  				if (m_end <= r_end)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
847
  					idx_a++;
35fd0808d   Tejun Heo   memblock: Impleme...
848
  				else
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
849
850
  					idx_b++;
  				*idx = (u32)idx_a | (u64)idx_b << 32;
35fd0808d   Tejun Heo   memblock: Impleme...
851
852
853
854
855
856
857
858
  				return;
  			}
  		}
  	}
  
  	/* signal end of iteration */
  	*idx = ULLONG_MAX;
  }
7bd0b0f0d   Tejun Heo   memblock: Reimple...
859
  /**
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
860
861
862
863
864
   * __next_mem_range_rev - generic next function for for_each_*_range_rev()
   *
   * Finds the next range from type_a which is not marked as unsuitable
   * in type_b.
   *
7bd0b0f0d   Tejun Heo   memblock: Reimple...
865
   * @idx: pointer to u64 loop variable
b11542335   Grygorii Strashko   mm/memblock: swit...
866
   * @nid: nid: node selector, %NUMA_NO_NODE for all nodes
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
867
868
   * @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...
869
870
871
   * @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...
872
   *
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
873
   * Reverse of __next_mem_range().
7bd0b0f0d   Tejun Heo   memblock: Reimple...
874
   */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
875
876
877
878
879
  void __init_memblock __next_mem_range_rev(u64 *idx, int nid,
  					  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...
880
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
881
882
  	int idx_a = *idx & 0xffffffff;
  	int idx_b = *idx >> 32;
b11542335   Grygorii Strashko   mm/memblock: swit...
883

560dca27a   Grygorii Strashko   mm/memblock: use ...
884
885
886
  	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...
887
888
  
  	if (*idx == (u64)ULLONG_MAX) {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
889
890
  		idx_a = type_a->cnt - 1;
  		idx_b = type_b->cnt;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
891
  	}
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
892
893
  	for (; idx_a >= 0; idx_a--) {
  		struct memblock_region *m = &type_a->regions[idx_a];
7bd0b0f0d   Tejun Heo   memblock: Reimple...
894
895
  		phys_addr_t m_start = m->base;
  		phys_addr_t m_end = m->base + m->size;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
896
  		int m_nid = memblock_get_region_node(m);
7bd0b0f0d   Tejun Heo   memblock: Reimple...
897
898
  
  		/* only memory regions are associated with nodes, check it */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
899
  		if (nid != NUMA_NO_NODE && nid != m_nid)
7bd0b0f0d   Tejun Heo   memblock: Reimple...
900
  			continue;
55ac590c2   Tang Chen   memblock, mem_hot...
901
902
903
  		/* skip hotpluggable memory regions if needed */
  		if (movable_node_is_enabled() && memblock_is_hotpluggable(m))
  			continue;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
  		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 >= 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 ?
  				r->base : ULLONG_MAX;
  			/*
  			 * if idx_b advanced past idx_a,
  			 * break out to advance idx_a
  			 */
7bd0b0f0d   Tejun Heo   memblock: Reimple...
930

7bd0b0f0d   Tejun Heo   memblock: Reimple...
931
932
933
934
935
936
937
938
939
  			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...
940
  					*out_nid = m_nid;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
941
  				if (m_start >= r_start)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
942
  					idx_a--;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
943
  				else
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
944
945
  					idx_b--;
  				*idx = (u32)idx_a | (u64)idx_b << 32;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
946
947
948
949
  				return;
  			}
  		}
  	}
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
950
  	/* signal end of iteration */
7bd0b0f0d   Tejun Heo   memblock: Reimple...
951
952
  	*idx = ULLONG_MAX;
  }
7c0caeb86   Tejun Heo   memblock: Add opt...
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
  #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...
989
   * @type: memblock type to set node ID for
7c0caeb86   Tejun Heo   memblock: Add opt...
990
991
   * @nid: node ID to set
   *
e7e8de591   Tang Chen   memblock: make me...
992
   * Set the nid of memblock @type regions in [@base,@base+@size) to @nid.
7c0caeb86   Tejun Heo   memblock: Add opt...
993
994
995
996
997
998
   * Regions which cross the area boundaries are split as necessary.
   *
   * RETURNS:
   * 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...
999
  				      struct memblock_type *type, int nid)
7c0caeb86   Tejun Heo   memblock: Add opt...
1000
  {
6a9ceb31c   Tejun Heo   memblock: Separat...
1001
1002
  	int start_rgn, end_rgn;
  	int i, ret;
7c0caeb86   Tejun Heo   memblock: Add opt...
1003

6a9ceb31c   Tejun Heo   memblock: Separat...
1004
1005
1006
  	ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);
  	if (ret)
  		return ret;
7c0caeb86   Tejun Heo   memblock: Add opt...
1007

6a9ceb31c   Tejun Heo   memblock: Separat...
1008
  	for (i = start_rgn; i < end_rgn; i++)
e9d24ad30   Wanpeng Li   mm/memblock: use ...
1009
  		memblock_set_region_node(&type->regions[i], nid);
7c0caeb86   Tejun Heo   memblock: Add opt...
1010
1011
1012
1013
1014
  
  	memblock_merge_regions(type);
  	return 0;
  }
  #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
2bfc2862c   Akinobu Mita   memblock: introdu...
1015
1016
1017
  static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
  					phys_addr_t align, phys_addr_t start,
  					phys_addr_t end, int nid)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1018
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1019
  	phys_addr_t found;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1020

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

2bfc2862c   Akinobu Mita   memblock: introdu...
1024
  	found = memblock_find_in_range_node(size, align, start, end, nid);
aedf95ea0   Catalin Marinas   mm/memblock.c: ca...
1025
1026
1027
1028
1029
1030
  	if (found && !memblock_reserve(found, size)) {
  		/*
  		 * The min_count is set to 0 so that memblock allocations are
  		 * never reported as leaks.
  		 */
  		kmemleak_alloc(__va(found), size, 0, 0);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1031
  		return found;
aedf95ea0   Catalin Marinas   mm/memblock.c: ca...
1032
  	}
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1033
  	return 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1034
  }
2bfc2862c   Akinobu Mita   memblock: introdu...
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
  phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
  					phys_addr_t start, phys_addr_t end)
  {
  	return memblock_alloc_range_nid(size, align, start, end, NUMA_NO_NODE);
  }
  
  static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
  					phys_addr_t align, phys_addr_t max_addr,
  					int nid)
  {
  	return memblock_alloc_range_nid(size, align, 0, max_addr, nid);
  }
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1047
1048
1049
1050
1051
1052
1053
  phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int nid)
  {
  	return memblock_alloc_base_nid(size, align, MEMBLOCK_ALLOC_ACCESSIBLE, nid);
  }
  
  phys_addr_t __init __memblock_alloc_base(phys_addr_t size, phys_addr_t align, phys_addr_t max_addr)
  {
b11542335   Grygorii Strashko   mm/memblock: swit...
1054
  	return memblock_alloc_base_nid(size, align, max_addr, NUMA_NO_NODE);
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1055
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1056
  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...
1057
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
  	phys_addr_t alloc;
  
  	alloc = __memblock_alloc_base(size, align, max_addr);
  
  	if (alloc == 0)
  		panic("ERROR: Failed to allocate 0x%llx bytes below 0x%llx.
  ",
  		      (unsigned long long) size, (unsigned long long) max_addr);
  
  	return alloc;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1068
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1069
  phys_addr_t __init memblock_alloc(phys_addr_t size, phys_addr_t align)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1070
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1071
1072
  	return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
  }
95f72d1ed   Yinghai Lu   lmb: rename to me...
1073

9d1e24928   Benjamin Herrenschmidt   memblock: Separat...
1074
1075
1076
1077
1078
1079
  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...
1080
  	return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1081
  }
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
  /**
   * 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.
   *
   * The memory block is aligned on SMP_CACHE_BYTES if @align == 0.
   *
   * 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.
   *
   * RETURNS:
   * 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;
560dca27a   Grygorii Strashko   mm/memblock: use ...
1116
1117
1118
  	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 ...
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
  
  	/*
  	 * 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...
1130
1131
  	if (max_addr > memblock.current_limit)
  		max_addr = memblock.current_limit;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1132
1133
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
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
  again:
  	alloc = memblock_find_in_range_node(size, align, min_addr, max_addr,
  					    nid);
  	if (alloc)
  		goto done;
  
  	if (nid != NUMA_NO_NODE) {
  		alloc = memblock_find_in_range_node(size, align, min_addr,
  						    max_addr,  NUMA_NO_NODE);
  		if (alloc)
  			goto done;
  	}
  
  	if (min_addr) {
  		min_addr = 0;
  		goto again;
  	} else {
  		goto error;
  	}
  
  done:
  	memblock_reserve(alloc, size);
  	ptr = phys_to_virt(alloc);
  	memset(ptr, 0, size);
  
  	/*
  	 * 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;
  
  error:
  	return NULL;
  }
  
  /**
   * 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
   *
   * Public version of _memblock_virt_alloc_try_nid_nopanic() which provides
   * additional debug information (including caller info), if enabled.
   *
   * RETURNS:
   * 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)
  {
  	memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx %pF
  ",
  		     __func__, (u64)size, (u64)align, nid, (u64)min_addr,
  		     (u64)max_addr, (void *)_RET_IP_);
  	return memblock_virt_alloc_internal(size, align, min_addr,
  					     max_addr, nid);
  }
  
  /**
   * 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
   *
   * Public panicking version of _memblock_virt_alloc_try_nid_nopanic()
   * which provides debug information (including caller info), if enabled,
   * and panics if the request can not be satisfied.
   *
   * RETURNS:
   * 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;
  
  	memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx %pF
  ",
  		     __func__, (u64)size, (u64)align, nid, (u64)min_addr,
  		     (u64)max_addr, (void *)_RET_IP_);
  	ptr = memblock_virt_alloc_internal(size, align,
  					   min_addr, max_addr, nid);
  	if (ptr)
  		return ptr;
  
  	panic("%s: Failed to allocate %llu bytes align=0x%llx nid=%d from=0x%llx max_addr=0x%llx
  ",
  	      __func__, (u64)size, (u64)align, nid, (u64)min_addr,
  	      (u64)max_addr);
  	return NULL;
  }
  
  /**
   * __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)
  {
  	memblock_dbg("%s: [%#016llx-%#016llx] %pF
  ",
  		     __func__, (u64)base, (u64)base + size - 1,
  		     (void *)_RET_IP_);
  	kmemleak_free_part(__va(base), size);
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1257
  	memblock_remove_range(&memblock.reserved, base, size);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
  }
  
  /*
   * __memblock_free_late - free bootmem block pages directly to buddy allocator
   * @addr: phys starting address of the  boot memory block
   * @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)
  {
  	u64 cursor, end;
  
  	memblock_dbg("%s: [%#016llx-%#016llx] %pF
  ",
  		     __func__, (u64)base, (u64)base + size - 1,
  		     (void *)_RET_IP_);
  	kmemleak_free_part(__va(base), size);
  	cursor = PFN_UP(base);
  	end = PFN_DOWN(base + size);
  
  	for (; cursor < end; cursor++) {
  		__free_pages_bootmem(pfn_to_page(cursor), 0);
  		totalram_pages++;
  	}
  }
9d1e24928   Benjamin Herrenschmidt   memblock: Separat...
1286
1287
1288
1289
  
  /*
   * Remaining API functions
   */
2898cc4cd   Benjamin Herrenschmidt   memblock: Change ...
1290
  phys_addr_t __init memblock_phys_mem_size(void)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1291
  {
1440c4e2c   Tejun Heo   memblock: Track t...
1292
  	return memblock.memory.total_size;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1293
  }
595ad9af8   Yinghai Lu   memblock: Add mem...
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
  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...
1307
  	return PFN_PHYS(pages);
595ad9af8   Yinghai Lu   memblock: Add mem...
1308
  }
0a93ebef6   Sam Ravnborg   memblock: add mem...
1309
1310
1311
1312
1313
  /* lowest address */
  phys_addr_t __init_memblock memblock_start_of_DRAM(void)
  {
  	return memblock.memory.regions[0].base;
  }
10d064398   Yinghai Lu   memblock: Option ...
1314
  phys_addr_t __init_memblock memblock_end_of_DRAM(void)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1315
1316
  {
  	int idx = memblock.memory.cnt - 1;
e3239ff92   Benjamin Herrenschmidt   memblock: Rename ...
1317
  	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1318
  }
c0ce8fef5   Tejun Heo   memblock: Reimple...
1319
  void __init memblock_enforce_memory_limit(phys_addr_t limit)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1320
  {
c0ce8fef5   Tejun Heo   memblock: Reimple...
1321
  	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
136199f0a   Emil Medve   memblock: use for...
1322
  	struct memblock_region *r;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1323

c0ce8fef5   Tejun Heo   memblock: Reimple...
1324
  	if (!limit)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1325
  		return;
c0ce8fef5   Tejun Heo   memblock: Reimple...
1326
  	/* find out max address */
136199f0a   Emil Medve   memblock: use for...
1327
  	for_each_memblock(memory, r) {
c0ce8fef5   Tejun Heo   memblock: Reimple...
1328
1329
1330
  		if (limit <= r->size) {
  			max_addr = r->base + limit;
  			break;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1331
  		}
c0ce8fef5   Tejun Heo   memblock: Reimple...
1332
  		limit -= r->size;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1333
  	}
c0ce8fef5   Tejun Heo   memblock: Reimple...
1334
1335
  
  	/* truncate both memory and reserved regions */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1336
1337
1338
1339
  	memblock_remove_range(&memblock.memory, max_addr,
  			      (phys_addr_t)ULLONG_MAX);
  	memblock_remove_range(&memblock.reserved, max_addr,
  			      (phys_addr_t)ULLONG_MAX);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1340
  }
cd79481d2   Yinghai Lu   memblock: Annotat...
1341
  static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
  {
  	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;
  }
2898cc4cd   Benjamin Herrenschmidt   memblock: Change ...
1358
  int __init memblock_is_reserved(phys_addr_t addr)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1359
  {
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1360
1361
  	return memblock_search(&memblock.reserved, addr) != -1;
  }
95f72d1ed   Yinghai Lu   lmb: rename to me...
1362

3661ca66a   Yinghai Lu   memblock: Fix sec...
1363
  int __init_memblock memblock_is_memory(phys_addr_t addr)
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1364
1365
1366
  {
  	return memblock_search(&memblock.memory, addr) != -1;
  }
e76b63f80   Yinghai Lu   memblock, numa: b...
1367
1368
1369
1370
1371
  #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...
1372
  	int mid = memblock_search(type, PFN_PHYS(pfn));
e76b63f80   Yinghai Lu   memblock, numa: b...
1373
1374
1375
  
  	if (mid == -1)
  		return -1;
f7e2f7e89   Fabian Frederick   mm/memblock.c: us...
1376
1377
  	*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...
1378
1379
1380
1381
  
  	return type->regions[mid].nid;
  }
  #endif
eab309494   Stephen Boyd   memblock: Documen...
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
  /**
   * 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
   *
   * Check if the region [@base, @base+@size) is a subset of a memory block.
   *
   * RETURNS:
   * 0 if false, non-zero if true
   */
3661ca66a   Yinghai Lu   memblock: Fix sec...
1392
  int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size)
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1393
  {
abb65272a   Tomi Valkeinen   memblock: fix mem...
1394
  	int idx = memblock_search(&memblock.memory, base);
eb18f1b5b   Tejun Heo   memblock: Make me...
1395
  	phys_addr_t end = base + memblock_cap_size(base, &size);
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1396
1397
1398
  
  	if (idx == -1)
  		return 0;
abb65272a   Tomi Valkeinen   memblock: fix mem...
1399
1400
  	return memblock.memory.regions[idx].base <= base &&
  		(memblock.memory.regions[idx].base +
eb18f1b5b   Tejun Heo   memblock: Make me...
1401
  		 memblock.memory.regions[idx].size) >= end;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1402
  }
eab309494   Stephen Boyd   memblock: Documen...
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
  /**
   * memblock_is_region_reserved - check if a region intersects reserved memory
   * @base: base of region to check
   * @size: size of region to check
   *
   * Check if the region [@base, @base+@size) intersects a reserved memory block.
   *
   * RETURNS:
   * 0 if false, non-zero if true
   */
10d064398   Yinghai Lu   memblock: Option ...
1413
  int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1414
  {
eb18f1b5b   Tejun Heo   memblock: Make me...
1415
  	memblock_cap_size(base, &size);
f1c2c19c4   Benjamin Herrenschmidt   memblock: Fix mem...
1416
  	return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1417
  }
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1418
1419
  void __init_memblock memblock_trim_memory(phys_addr_t align)
  {
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1420
  	phys_addr_t start, end, orig_start, orig_end;
136199f0a   Emil Medve   memblock: use for...
1421
  	struct memblock_region *r;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1422

136199f0a   Emil Medve   memblock: use for...
1423
1424
1425
  	for_each_memblock(memory, r) {
  		orig_start = r->base;
  		orig_end = r->base + r->size;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1426
1427
1428
1429
1430
1431
1432
  		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...
1433
1434
  			r->base = start;
  			r->size = end - start;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1435
  		} else {
136199f0a   Emil Medve   memblock: use for...
1436
1437
1438
  			memblock_remove_region(&memblock.memory,
  					       r - memblock.memory.regions);
  			r--;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1439
1440
1441
  		}
  	}
  }
e63075a3c   Benjamin Herrenschmidt   memblock: Introdu...
1442

3661ca66a   Yinghai Lu   memblock: Fix sec...
1443
  void __init_memblock memblock_set_current_limit(phys_addr_t limit)
e63075a3c   Benjamin Herrenschmidt   memblock: Introdu...
1444
1445
1446
  {
  	memblock.current_limit = limit;
  }
fec510141   Laura Abbott   ARM: 7993/1: mm/m...
1447
1448
1449
1450
  phys_addr_t __init_memblock memblock_get_current_limit(void)
  {
  	return memblock.current_limit;
  }
7c0caeb86   Tejun Heo   memblock: Add opt...
1451
  static void __init_memblock memblock_dump(struct memblock_type *type, char *name)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1452
1453
  {
  	unsigned long long base, size;
66a207572   Tang Chen   memblock, numa: i...
1454
  	unsigned long flags;
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1455
  	int i;
7c0caeb86   Tejun Heo   memblock: Add opt...
1456
1457
  	pr_info(" %s.cnt  = 0x%lx
  ", name, type->cnt);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1458

7c0caeb86   Tejun Heo   memblock: Add opt...
1459
1460
1461
1462
1463
1464
  	for (i = 0; i < type->cnt; i++) {
  		struct memblock_region *rgn = &type->regions[i];
  		char nid_buf[32] = "";
  
  		base = rgn->base;
  		size = rgn->size;
66a207572   Tang Chen   memblock, numa: i...
1465
  		flags = rgn->flags;
7c0caeb86   Tejun Heo   memblock: Add opt...
1466
1467
1468
1469
1470
  #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
66a207572   Tang Chen   memblock, numa: i...
1471
1472
1473
  		pr_info(" %s[%#x]\t[%#016llx-%#016llx], %#llx bytes%s flags: %#lx
  ",
  			name, i, base, base + size - 1, size, nid_buf, flags);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1474
1475
  	}
  }
4ff7b82f1   Tejun Heo   memblock: Add __m...
1476
  void __init_memblock __memblock_dump_all(void)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1477
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1478
1479
  	pr_info("MEMBLOCK configuration:
  ");
1440c4e2c   Tejun Heo   memblock: Track t...
1480
1481
1482
1483
  	pr_info(" memory size = %#llx reserved size = %#llx
  ",
  		(unsigned long long)memblock.memory.total_size,
  		(unsigned long long)memblock.reserved.total_size);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1484
1485
1486
1487
  
  	memblock_dump(&memblock.memory, "memory");
  	memblock_dump(&memblock.reserved, "reserved");
  }
1aadc0560   Tejun Heo   memblock: s/membl...
1488
  void __init memblock_allow_resize(void)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1489
  {
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
1490
  	memblock_can_resize = 1;
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1491
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1492
1493
1494
1495
1496
1497
1498
  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...
1499
  #if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_ARCH_DISCARD_MEMBLOCK)
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
  
  static int memblock_debug_show(struct seq_file *m, void *private)
  {
  	struct memblock_type *type = m->private;
  	struct memblock_region *reg;
  	int i;
  
  	for (i = 0; i < type->cnt; i++) {
  		reg = &type->regions[i];
  		seq_printf(m, "%4d: ", i);
  		if (sizeof(phys_addr_t) == 4)
  			seq_printf(m, "0x%08lx..0x%08lx
  ",
  				   (unsigned long)reg->base,
  				   (unsigned long)(reg->base + reg->size - 1));
  		else
  			seq_printf(m, "0x%016llx..0x%016llx
  ",
  				   (unsigned long long)reg->base,
  				   (unsigned long long)(reg->base + reg->size - 1));
  
  	}
  	return 0;
  }
  
  static int memblock_debug_open(struct inode *inode, struct file *file)
  {
  	return single_open(file, memblock_debug_show, inode->i_private);
  }
  
  static const struct file_operations memblock_debug_fops = {
  	.open = memblock_debug_open,
  	.read = seq_read,
  	.llseek = seq_lseek,
  	.release = single_release,
  };
  
  static int __init memblock_init_debugfs(void)
  {
  	struct dentry *root = debugfs_create_dir("memblock", NULL);
  	if (!root)
  		return -ENXIO;
  	debugfs_create_file("memory", S_IRUGO, root, &memblock.memory, &memblock_debug_fops);
  	debugfs_create_file("reserved", S_IRUGO, root, &memblock.reserved, &memblock_debug_fops);
70210ed95   Philipp Hachtmann   mm/memblock: add ...
1544
1545
1546
  #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
  	debugfs_create_file("physmem", S_IRUGO, root, &memblock.physmem, &memblock_debug_fops);
  #endif
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1547
1548
1549
1550
1551
1552
  
  	return 0;
  }
  __initcall(memblock_init_debugfs);
  
  #endif /* CONFIG_DEBUG_FS */