Blame view

mm/memblock.c 49.8 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>
c4c5ad6b3   Christoph Hellwig   memblock: include...
22
  #include <asm/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
  
  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...
37
  	.memory.name		= "memory",
fe091c208   Tejun Heo   memblock: Kill me...
38
39
40
41
  
  	.reserved.regions	= memblock_reserved_init_regions,
  	.reserved.cnt		= 1,	/* empty dummy entry */
  	.reserved.max		= INIT_MEMBLOCK_REGIONS,
0262d9c84   Heiko Carstens   memblock: embed m...
42
  	.reserved.name		= "reserved",
fe091c208   Tejun Heo   memblock: Kill me...
43

70210ed95   Philipp Hachtmann   mm/memblock: add ...
44
45
46
47
  #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...
48
  	.physmem.name		= "physmem",
70210ed95   Philipp Hachtmann   mm/memblock: add ...
49
  #endif
79442ed18   Tang Chen   mm/memblock.c: in...
50
  	.bottom_up		= false,
fe091c208   Tejun Heo   memblock: Kill me...
51
52
  	.current_limit		= MEMBLOCK_ALLOC_ANYWHERE,
  };
95f72d1ed   Yinghai Lu   lmb: rename to me...
53

10d064398   Yinghai Lu   memblock: Option ...
54
  int memblock_debug __initdata_memblock;
a3f5bafcc   Tony Luck   mm/memblock: allo...
55
  static bool system_has_some_mirror __initdata_memblock = false;
1aadc0560   Tejun Heo   memblock: s/membl...
56
  static int memblock_can_resize __initdata_memblock;
181eb3942   Gavin Shan   mm/memblock: fix ...
57
58
  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...
59

a3f5bafcc   Tony Luck   mm/memblock: allo...
60
61
62
63
  ulong __init_memblock choose_memblock_flags(void)
  {
  	return system_has_some_mirror ? MEMBLOCK_MIRROR : MEMBLOCK_NONE;
  }
eb18f1b5b   Tejun Heo   memblock: Make me...
64
65
66
67
68
  /* 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...
69
70
71
  /*
   * Address comparison utilities
   */
10d064398   Yinghai Lu   memblock: Option ...
72
  static unsigned long __init_memblock memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
2898cc4cd   Benjamin Herrenschmidt   memblock: Change ...
73
  				       phys_addr_t base2, phys_addr_t size2)
95f72d1ed   Yinghai Lu   lmb: rename to me...
74
75
76
  {
  	return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
  }
95cf82ecc   Tang Chen   mem-hotplug: hand...
77
  bool __init_memblock memblock_overlaps_region(struct memblock_type *type,
2d7d3eb2b   H Hartley Sweeten   mm/memblock.c: qu...
78
  					phys_addr_t base, phys_addr_t size)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
79
80
  {
  	unsigned long i;
f14516fbf   Alexander Kuleshov   mm/memblock: remo...
81
82
83
  	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...
84
  			break;
c5c5c9d10   Tang Chen   mm/memblock.c: ma...
85
  	return i < type->cnt;
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
86
  }
79442ed18   Tang Chen   mm/memblock.c: in...
87
88
89
90
91
92
  /*
   * __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...
93
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
fc6daaf93   Tony Luck   mm/memblock: add ...
94
   * @flags: pick from blocks based on memory attributes
79442ed18   Tang Chen   mm/memblock.c: in...
95
96
97
98
99
100
101
102
   *
   * 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,
fc6daaf93   Tony Luck   mm/memblock: add ...
103
104
  				phys_addr_t size, phys_addr_t align, int nid,
  				ulong flags)
79442ed18   Tang Chen   mm/memblock.c: in...
105
106
107
  {
  	phys_addr_t this_start, this_end, cand;
  	u64 i;
fc6daaf93   Tony Luck   mm/memblock: add ...
108
  	for_each_free_mem_range(i, nid, flags, &this_start, &this_end, NULL) {
79442ed18   Tang Chen   mm/memblock.c: in...
109
110
111
112
113
114
115
116
117
118
  		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...
119
  /**
1402899e4   Tang Chen   mm/memblock.c: fa...
120
   * __memblock_find_range_top_down - find free area utility, in top-down
7bd0b0f0d   Tejun Heo   memblock: Reimple...
121
122
123
124
   * @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...
125
   * @nid: nid of the free area to find, %NUMA_NO_NODE for any node
fc6daaf93   Tony Luck   mm/memblock: add ...
126
   * @flags: pick from blocks based on memory attributes
7bd0b0f0d   Tejun Heo   memblock: Reimple...
127
   *
1402899e4   Tang Chen   mm/memblock.c: fa...
128
   * Utility called from memblock_find_in_range_node(), find free area top-down.
7bd0b0f0d   Tejun Heo   memblock: Reimple...
129
130
   *
   * RETURNS:
79442ed18   Tang Chen   mm/memblock.c: in...
131
   * Found address on success, 0 on failure.
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
132
   */
1402899e4   Tang Chen   mm/memblock.c: fa...
133
134
  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 ...
135
136
  			       phys_addr_t size, phys_addr_t align, int nid,
  			       ulong flags)
f7210e6c4   Tang Chen   mm/memblock.c: us...
137
138
139
  {
  	phys_addr_t this_start, this_end, cand;
  	u64 i;
fc6daaf93   Tony Luck   mm/memblock: add ...
140
141
  	for_each_free_mem_range_reverse(i, nid, flags, &this_start, &this_end,
  					NULL) {
f7210e6c4   Tang Chen   mm/memblock.c: us...
142
143
144
145
146
147
148
149
150
151
  		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...
152

f7210e6c4   Tang Chen   mm/memblock.c: us...
153
154
  	return 0;
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
155

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

1402899e4   Tang Chen   mm/memblock.c: fa...
184
185
186
187
188
189
190
  	/* 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...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  	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 ...
205
  						      size, align, nid, flags);
79442ed18   Tang Chen   mm/memblock.c: in...
206
207
208
209
210
211
212
213
214
215
216
217
218
  		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.
  		 */
756a025f0   Joe Perches   mm: coalesce spli...
219
220
  		WARN_ONCE(1, "memblock: bottom-up allocation failed, memory hotunplug may be affected
  ");
79442ed18   Tang Chen   mm/memblock.c: in...
221
  	}
1402899e4   Tang Chen   mm/memblock.c: fa...
222

fc6daaf93   Tony Luck   mm/memblock: add ...
223
224
  	return __memblock_find_range_top_down(start, end, size, align, nid,
  					      flags);
1402899e4   Tang Chen   mm/memblock.c: fa...
225
226
227
  }
  
  /**
7bd0b0f0d   Tejun Heo   memblock: Reimple...
228
229
230
231
232
233
234
235
236
   * 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...
237
   * Found address on success, 0 on failure.
fc769a8e7   Tejun Heo   memblock: Replace...
238
   */
7bd0b0f0d   Tejun Heo   memblock: Reimple...
239
240
241
  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...
242
  {
a3f5bafcc   Tony Luck   mm/memblock: allo...
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
  	phys_addr_t ret;
  	ulong flags = choose_memblock_flags();
  
  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...
259
  }
10d064398   Yinghai Lu   memblock: Option ...
260
  static void __init_memblock memblock_remove_region(struct memblock_type *type, unsigned long r)
95f72d1ed   Yinghai Lu   lmb: rename to me...
261
  {
1440c4e2c   Tejun Heo   memblock: Track t...
262
  	type->total_size -= type->regions[r].size;
7c0caeb86   Tejun Heo   memblock: Add opt...
263
264
  	memmove(&type->regions[r], &type->regions[r + 1],
  		(type->cnt - (r + 1)) * sizeof(type->regions[r]));
e3239ff92   Benjamin Herrenschmidt   memblock: Rename ...
265
  	type->cnt--;
95f72d1ed   Yinghai Lu   lmb: rename to me...
266

8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
267
268
  	/* Special case for empty arrays */
  	if (type->cnt == 0) {
1440c4e2c   Tejun Heo   memblock: Track t...
269
  		WARN_ON(type->total_size != 0);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
270
271
272
  		type->cnt = 1;
  		type->regions[0].base = 0;
  		type->regions[0].size = 0;
66a207572   Tang Chen   memblock, numa: i...
273
  		type->regions[0].flags = 0;
7c0caeb86   Tejun Heo   memblock: Add opt...
274
  		memblock_set_region_node(&type->regions[0], MAX_NUMNODES);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
275
  	}
95f72d1ed   Yinghai Lu   lmb: rename to me...
276
  }
354f17e1e   Philipp Hachtmann   mm/nobootmem: fre...
277
  #ifdef CONFIG_ARCH_DISCARD_MEMBLOCK
3010f8765   Pavel Tatashin   mm: discard membl...
278
279
280
281
  /**
   * Discard memory and reserved arrays if they were allocated
   */
  void __init memblock_discard(void)
5e270e254   Philipp Hachtmann   mm: free memblock...
282
  {
3010f8765   Pavel Tatashin   mm: discard membl...
283
  	phys_addr_t addr, size;
5e270e254   Philipp Hachtmann   mm: free memblock...
284

3010f8765   Pavel Tatashin   mm: discard membl...
285
286
287
288
289
290
  	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...
291

91b540f98   Pavel Tatashin   mm/memblock.c: re...
292
  	if (memblock.memory.regions != memblock_memory_init_regions) {
3010f8765   Pavel Tatashin   mm: discard membl...
293
294
295
296
297
  		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...
298
  }
5e270e254   Philipp Hachtmann   mm: free memblock...
299
  #endif
48c3b583b   Greg Pearson   mm/memblock: fix ...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
  /**
   * 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...
318
319
  {
  	struct memblock_region *new_array, *old_array;
29f673860   Yinghai Lu   memblock: free al...
320
  	phys_addr_t old_alloc_size, new_alloc_size;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
321
322
  	phys_addr_t old_size, new_size, addr;
  	int use_slab = slab_is_available();
181eb3942   Gavin Shan   mm/memblock: fix ...
323
  	int *in_slab;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
324
325
326
327
328
329
  
  	/* 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...
330
331
332
  	/* Calculate new doubled size */
  	old_size = type->max * sizeof(struct memblock_region);
  	new_size = old_size << 1;
29f673860   Yinghai Lu   memblock: free al...
333
334
335
336
337
338
  	/*
  	 * 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...
339

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

15674868d   Sachin Kamat   mm/memblock: Use ...
372
  		new_array = addr ? __va(addr) : NULL;
4e2f07750   Gavin Shan   mm/memblock: clea...
373
  	}
1f5026a7e   Tejun Heo   memblock: Kill ME...
374
  	if (!addr) {
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
375
376
  		pr_err("memblock: Failed to double %s array from %ld to %ld entries !
  ",
0262d9c84   Heiko Carstens   memblock: embed m...
377
  		       type->name, type->max, type->max * 2);
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
378
379
  		return -1;
  	}
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
380

fd07383b6   Andrew Morton   mm/memblock.c:mem...
381
  	memblock_dbg("memblock: %s is doubled to %ld at [%#010llx-%#010llx]",
0262d9c84   Heiko Carstens   memblock: embed m...
382
  			type->name, type->max * 2, (u64)addr,
fd07383b6   Andrew Morton   mm/memblock.c:mem...
383
  			(u64)addr + new_size - 1);
ea9e4376b   Yinghai Lu   memblock: Improve...
384

fd07383b6   Andrew Morton   mm/memblock.c:mem...
385
386
387
388
  	/*
  	 * 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...
389
390
391
392
393
394
  	 */
  	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...
395
  	/* Free old array. We needn't free it if the array is the static one */
181eb3942   Gavin Shan   mm/memblock: fix ...
396
397
398
399
  	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...
400
  		memblock_free(__pa(old_array), old_alloc_size);
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
401

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

784656f9c   Tejun Heo   memblock: Reimple...
423
424
425
426
  	/* 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...
427

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

784656f9c   Tejun Heo   memblock: Reimple...
443
444
  /**
   * memblock_insert_region - insert new memblock region
209ff86d6   Tang Chen   memblock: fix mis...
445
446
447
448
449
   * @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...
450
   * @flags:	flags of the new region
784656f9c   Tejun Heo   memblock: Reimple...
451
452
   *
   * Insert new memblock region [@base,@base+@size) into @type at @idx.
412d0008d   Alexander Kuleshov   mm/memblock: fix ...
453
   * @type must already have extra room to accommodate the new region.
784656f9c   Tejun Heo   memblock: Reimple...
454
455
456
   */
  static void __init_memblock memblock_insert_region(struct memblock_type *type,
  						   int idx, phys_addr_t base,
66a207572   Tang Chen   memblock, numa: i...
457
458
  						   phys_addr_t size,
  						   int nid, unsigned long flags)
784656f9c   Tejun Heo   memblock: Reimple...
459
460
461
462
463
464
465
  {
  	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...
466
  	rgn->flags = flags;
7c0caeb86   Tejun Heo   memblock: Add opt...
467
  	memblock_set_region_node(rgn, nid);
784656f9c   Tejun Heo   memblock: Reimple...
468
  	type->cnt++;
1440c4e2c   Tejun Heo   memblock: Track t...
469
  	type->total_size += size;
784656f9c   Tejun Heo   memblock: Reimple...
470
471
472
  }
  
  /**
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
473
   * memblock_add_range - add new memblock region
784656f9c   Tejun Heo   memblock: Reimple...
474
475
476
   * @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...
477
   * @nid: nid of the new region
66a207572   Tang Chen   memblock, numa: i...
478
   * @flags: flags of the new region
784656f9c   Tejun Heo   memblock: Reimple...
479
480
481
482
483
484
485
486
487
   *
   * 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...
488
  int __init_memblock memblock_add_range(struct memblock_type *type,
66a207572   Tang Chen   memblock, numa: i...
489
490
  				phys_addr_t base, phys_addr_t size,
  				int nid, unsigned long flags)
784656f9c   Tejun Heo   memblock: Reimple...
491
492
  {
  	bool insert = false;
eb18f1b5b   Tejun Heo   memblock: Make me...
493
494
  	phys_addr_t obase = base;
  	phys_addr_t end = base + memblock_cap_size(base, &size);
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
495
496
  	int idx, nr_new;
  	struct memblock_region *rgn;
784656f9c   Tejun Heo   memblock: Reimple...
497

b3dc627ca   Tejun Heo   memblock: membloc...
498
499
  	if (!size)
  		return 0;
784656f9c   Tejun Heo   memblock: Reimple...
500
501
  	/* special case for empty array */
  	if (type->regions[0].size == 0) {
1440c4e2c   Tejun Heo   memblock: Track t...
502
  		WARN_ON(type->cnt != 1 || type->total_size);
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
503
504
  		type->regions[0].base = base;
  		type->regions[0].size = size;
66a207572   Tang Chen   memblock, numa: i...
505
  		type->regions[0].flags = flags;
7fb0bc3f0   Tejun Heo   memblock: Impleme...
506
  		memblock_set_region_node(&type->regions[0], nid);
1440c4e2c   Tejun Heo   memblock: Track t...
507
  		type->total_size = size;
8f7a66051   Benjamin Herrenschmidt   mm/memblock: prop...
508
  		return 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
509
  	}
784656f9c   Tejun Heo   memblock: Reimple...
510
511
512
513
  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 ...
514
  	 * to accommodate the new area.  The second actually inserts them.
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
515
  	 */
784656f9c   Tejun Heo   memblock: Reimple...
516
517
  	base = obase;
  	nr_new = 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
518

8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
519
  	for_each_memblock_type(type, rgn) {
784656f9c   Tejun Heo   memblock: Reimple...
520
521
522
523
  		phys_addr_t rbase = rgn->base;
  		phys_addr_t rend = rbase + rgn->size;
  
  		if (rbase >= end)
95f72d1ed   Yinghai Lu   lmb: rename to me...
524
  			break;
784656f9c   Tejun Heo   memblock: Reimple...
525
526
527
528
529
530
531
  		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...
532
533
534
  #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
  			WARN_ON(nid != memblock_get_region_node(rgn));
  #endif
4fcab5f43   Wei Yang   mm/memblock.c: WA...
535
  			WARN_ON(flags != rgn->flags);
784656f9c   Tejun Heo   memblock: Reimple...
536
537
  			nr_new++;
  			if (insert)
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
538
  				memblock_insert_region(type, idx++, base,
66a207572   Tang Chen   memblock, numa: i...
539
540
  						       rbase - base, nid,
  						       flags);
95f72d1ed   Yinghai Lu   lmb: rename to me...
541
  		}
784656f9c   Tejun Heo   memblock: Reimple...
542
543
  		/* area below @rend is dealt with, forget about it */
  		base = min(rend, end);
95f72d1ed   Yinghai Lu   lmb: rename to me...
544
  	}
784656f9c   Tejun Heo   memblock: Reimple...
545
546
547
548
549
  
  	/* insert the remaining portion */
  	if (base < end) {
  		nr_new++;
  		if (insert)
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
550
  			memblock_insert_region(type, idx, base, end - base,
66a207572   Tang Chen   memblock, numa: i...
551
  					       nid, flags);
95f72d1ed   Yinghai Lu   lmb: rename to me...
552
  	}
95f72d1ed   Yinghai Lu   lmb: rename to me...
553

ef3cc4db4   nimisolo   mm/memblock.c:mem...
554
555
  	if (!nr_new)
  		return 0;
784656f9c   Tejun Heo   memblock: Reimple...
556
557
558
  	/*
  	 * If this was the first round, resize array and repeat for actual
  	 * insertions; otherwise, merge and return.
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
559
  	 */
784656f9c   Tejun Heo   memblock: Reimple...
560
561
  	if (!insert) {
  		while (type->cnt + nr_new > type->max)
48c3b583b   Greg Pearson   mm/memblock: fix ...
562
  			if (memblock_double_array(type, obase, size) < 0)
784656f9c   Tejun Heo   memblock: Reimple...
563
564
565
566
567
568
  				return -ENOMEM;
  		insert = true;
  		goto repeat;
  	} else {
  		memblock_merge_regions(type);
  		return 0;
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
569
  	}
95f72d1ed   Yinghai Lu   lmb: rename to me...
570
  }
7fb0bc3f0   Tejun Heo   memblock: Impleme...
571
572
573
  int __init_memblock memblock_add_node(phys_addr_t base, phys_addr_t size,
  				       int nid)
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
574
  	return memblock_add_range(&memblock.memory, base, size, nid, 0);
7fb0bc3f0   Tejun Heo   memblock: Impleme...
575
  }
f705ac4b3   Alexander Kuleshov   mm/memblock.c: mo...
576
  int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
6a4055bc7   Alexander Kuleshov   mm/memblock.c: ad...
577
  {
5d63f81c9   Miles Chen   mm/memblock.c: re...
578
579
580
581
582
  	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...
583

f705ac4b3   Alexander Kuleshov   mm/memblock.c: mo...
584
  	return memblock_add_range(&memblock.memory, base, size, MAX_NUMNODES, 0);
95f72d1ed   Yinghai Lu   lmb: rename to me...
585
  }
6a9ceb31c   Tejun Heo   memblock: Separat...
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
  /**
   * 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...
606
  	phys_addr_t end = base + memblock_cap_size(base, &size);
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
607
608
  	int idx;
  	struct memblock_region *rgn;
6a9ceb31c   Tejun Heo   memblock: Separat...
609
610
  
  	*start_rgn = *end_rgn = 0;
b3dc627ca   Tejun Heo   memblock: membloc...
611
612
  	if (!size)
  		return 0;
6a9ceb31c   Tejun Heo   memblock: Separat...
613
614
  	/* we'll create at most two more regions */
  	while (type->cnt + 2 > type->max)
48c3b583b   Greg Pearson   mm/memblock: fix ...
615
  		if (memblock_double_array(type, base, size) < 0)
6a9ceb31c   Tejun Heo   memblock: Separat...
616
  			return -ENOMEM;
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
617
  	for_each_memblock_type(type, rgn) {
6a9ceb31c   Tejun Heo   memblock: Separat...
618
619
620
621
622
623
624
625
626
627
628
629
630
631
  		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...
632
633
  			rgn->size -= base - rbase;
  			type->total_size -= base - rbase;
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
634
  			memblock_insert_region(type, idx, rbase, base - rbase,
66a207572   Tang Chen   memblock, numa: i...
635
636
  					       memblock_get_region_node(rgn),
  					       rgn->flags);
6a9ceb31c   Tejun Heo   memblock: Separat...
637
638
639
640
641
642
  		} 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...
643
644
  			rgn->size -= end - rbase;
  			type->total_size -= end - rbase;
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
645
  			memblock_insert_region(type, idx--, rbase, end - rbase,
66a207572   Tang Chen   memblock, numa: i...
646
647
  					       memblock_get_region_node(rgn),
  					       rgn->flags);
6a9ceb31c   Tejun Heo   memblock: Separat...
648
649
650
  		} else {
  			/* @rgn is fully contained, record it */
  			if (!*end_rgn)
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
651
652
  				*start_rgn = idx;
  			*end_rgn = idx + 1;
6a9ceb31c   Tejun Heo   memblock: Separat...
653
654
655
656
657
  		}
  	}
  
  	return 0;
  }
6a9ceb31c   Tejun Heo   memblock: Separat...
658

35bd16a22   Alexander Kuleshov   mm/memblock: make...
659
  static int __init_memblock memblock_remove_range(struct memblock_type *type,
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
660
  					  phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
661
  {
719361809   Tejun Heo   memblock: Reimple...
662
663
  	int start_rgn, end_rgn;
  	int i, ret;
95f72d1ed   Yinghai Lu   lmb: rename to me...
664

719361809   Tejun Heo   memblock: Reimple...
665
666
667
  	ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);
  	if (ret)
  		return ret;
95f72d1ed   Yinghai Lu   lmb: rename to me...
668

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

581adcbe1   Tejun Heo   memblock: Make me...
678
  int __init_memblock memblock_free(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
679
  {
5d63f81c9   Miles Chen   mm/memblock.c: re...
680
681
682
683
684
  	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...
685

9099daed9   Catalin Marinas   mm: kmemleak: avo...
686
  	kmemleak_free_part_phys(base, size);
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
687
  	return memblock_remove_range(&memblock.reserved, base, size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
688
  }
f705ac4b3   Alexander Kuleshov   mm/memblock.c: mo...
689
  int __init_memblock memblock_reserve(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
690
  {
5d63f81c9   Miles Chen   mm/memblock.c: re...
691
692
693
694
695
  	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...
696

f705ac4b3   Alexander Kuleshov   mm/memblock.c: mo...
697
  	return memblock_add_range(&memblock.reserved, base, size, MAX_NUMNODES, 0);
95f72d1ed   Yinghai Lu   lmb: rename to me...
698
  }
35fd0808d   Tejun Heo   memblock: Impleme...
699
  /**
66b16edf9   Tang Chen   memblock, mem_hot...
700
   *
4308ce17f   Tony Luck   mm/memblock.c: re...
701
   * This function isolates region [@base, @base + @size), and sets/clears flag
66b16edf9   Tang Chen   memblock, mem_hot...
702
   *
c11539315   Alexander Kuleshov   mm/memblock.c: fi...
703
   * Return 0 on success, -errno on failure.
66b16edf9   Tang Chen   memblock, mem_hot...
704
   */
4308ce17f   Tony Luck   mm/memblock.c: re...
705
706
  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...
707
708
709
710
711
712
713
714
715
  {
  	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...
716
717
718
719
  		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...
720
721
722
723
724
725
  
  	memblock_merge_regions(type);
  	return 0;
  }
  
  /**
4308ce17f   Tony Luck   mm/memblock.c: re...
726
   * memblock_mark_hotplug - Mark hotpluggable memory with flag MEMBLOCK_HOTPLUG.
66b16edf9   Tang Chen   memblock, mem_hot...
727
728
729
   * @base: the base phys addr of the region
   * @size: the size of the region
   *
c11539315   Alexander Kuleshov   mm/memblock.c: fi...
730
   * Return 0 on success, -errno on failure.
4308ce17f   Tony Luck   mm/memblock.c: re...
731
732
733
734
735
736
737
738
739
740
   */
  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...
741
   *
c11539315   Alexander Kuleshov   mm/memblock.c: fi...
742
   * Return 0 on success, -errno on failure.
66b16edf9   Tang Chen   memblock, mem_hot...
743
744
745
   */
  int __init_memblock memblock_clear_hotplug(phys_addr_t base, phys_addr_t size)
  {
4308ce17f   Tony Luck   mm/memblock.c: re...
746
  	return memblock_setclr_flag(base, size, 0, MEMBLOCK_HOTPLUG);
66b16edf9   Tang Chen   memblock, mem_hot...
747
748
749
  }
  
  /**
a3f5bafcc   Tony Luck   mm/memblock: allo...
750
751
752
753
   * memblock_mark_mirror - Mark mirrored memory with flag MEMBLOCK_MIRROR.
   * @base: the base phys addr of the region
   * @size: the size of the region
   *
c11539315   Alexander Kuleshov   mm/memblock.c: fi...
754
   * Return 0 on success, -errno on failure.
a3f5bafcc   Tony Luck   mm/memblock: allo...
755
756
757
758
759
760
761
   */
  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 ...
762
763
764
765
766
767
768
769
770
771
772
  /**
   * 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
   *
   * Return 0 on success, -errno on failure.
   */
  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...
773
774
  
  /**
4c546b8a3   AKASHI Takahiro   memblock: add mem...
775
776
777
778
779
780
781
782
783
784
785
786
   * 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
   *
   * Return 0 on success, -errno on failure.
   */
  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...
787
788
789
790
791
792
793
794
795
796
797
   * __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...
798
  	struct memblock_type *type = &memblock.reserved;
8e7a7f861   Robin Holt   memblock: introdu...
799

cd33a76b0   Richard Leitner   mm/memblock.c: re...
800
  	if (*idx < type->cnt) {
567d117b8   Alexander Kuleshov   mm/memblock.c: re...
801
  		struct memblock_region *r = &type->regions[*idx];
8e7a7f861   Robin Holt   memblock: introdu...
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
  		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...
819
   * __next__mem_range - next function for for_each_free_mem_range() etc.
35fd0808d   Tejun Heo   memblock: Impleme...
820
   * @idx: pointer to u64 loop variable
b11542335   Grygorii Strashko   mm/memblock: swit...
821
   * @nid: node selector, %NUMA_NO_NODE for all nodes
fc6daaf93   Tony Luck   mm/memblock: add ...
822
   * @flags: pick from blocks based on memory attributes
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
823
824
   * @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...
825
826
827
   * @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...
828
   *
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
829
   * Find the first area from *@idx which matches @nid, fill the out
35fd0808d   Tejun Heo   memblock: Impleme...
830
   * parameters, and update *@idx for the next iteration.  The lower 32bit of
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
831
832
   * *@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...
833
834
835
836
837
838
839
840
841
842
843
   * 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.
   */
fc6daaf93   Tony Luck   mm/memblock: add ...
844
  void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags,
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
845
846
847
848
  				      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...
849
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
850
851
  	int idx_a = *idx & 0xffffffff;
  	int idx_b = *idx >> 32;
b11542335   Grygorii Strashko   mm/memblock: swit...
852

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
853
854
855
  	if (WARN_ONCE(nid == MAX_NUMNODES,
  	"Usage of MAX_NUMNODES is deprecated. Use NUMA_NO_NODE instead
  "))
560dca27a   Grygorii Strashko   mm/memblock: use ...
856
  		nid = NUMA_NO_NODE;
35fd0808d   Tejun Heo   memblock: Impleme...
857

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
858
859
  	for (; idx_a < type_a->cnt; idx_a++) {
  		struct memblock_region *m = &type_a->regions[idx_a];
35fd0808d   Tejun Heo   memblock: Impleme...
860
861
  		phys_addr_t m_start = m->base;
  		phys_addr_t m_end = m->base + m->size;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
862
  		int	    m_nid = memblock_get_region_node(m);
35fd0808d   Tejun Heo   memblock: Impleme...
863
864
  
  		/* only memory regions are associated with nodes, check it */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
865
  		if (nid != NUMA_NO_NODE && nid != m_nid)
35fd0808d   Tejun Heo   memblock: Impleme...
866
  			continue;
0a313a998   Xishi Qiu   mem-hotplug: let ...
867
868
869
  		/* skip hotpluggable memory regions if needed */
  		if (movable_node_is_enabled() && memblock_is_hotpluggable(m))
  			continue;
a3f5bafcc   Tony Luck   mm/memblock: allo...
870
871
872
  		/* 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 ...
873
874
875
  		/* 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...
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
  		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...
898

f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
899
900
901
902
  			/*
  			 * if idx_b advanced past idx_a,
  			 * break out to advance idx_a
  			 */
35fd0808d   Tejun Heo   memblock: Impleme...
903
904
905
906
907
  			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...
908
909
  					*out_start =
  						max(m_start, r_start);
35fd0808d   Tejun Heo   memblock: Impleme...
910
911
912
  				if (out_end)
  					*out_end = min(m_end, r_end);
  				if (out_nid)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
913
  					*out_nid = m_nid;
35fd0808d   Tejun Heo   memblock: Impleme...
914
  				/*
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
915
916
  				 * The region which ends first is
  				 * advanced for the next iteration.
35fd0808d   Tejun Heo   memblock: Impleme...
917
918
  				 */
  				if (m_end <= r_end)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
919
  					idx_a++;
35fd0808d   Tejun Heo   memblock: Impleme...
920
  				else
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
921
922
  					idx_b++;
  				*idx = (u32)idx_a | (u64)idx_b << 32;
35fd0808d   Tejun Heo   memblock: Impleme...
923
924
925
926
927
928
929
930
  				return;
  			}
  		}
  	}
  
  	/* signal end of iteration */
  	*idx = ULLONG_MAX;
  }
7bd0b0f0d   Tejun Heo   memblock: Reimple...
931
  /**
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
932
933
934
935
936
   * __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...
937
   * @idx: pointer to u64 loop variable
ad5ea8cd5   Alexander Kuleshov   mm/memblock.c: fi...
938
   * @nid: node selector, %NUMA_NO_NODE for all nodes
fc6daaf93   Tony Luck   mm/memblock: add ...
939
   * @flags: pick from blocks based on memory attributes
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
940
941
   * @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...
942
943
944
   * @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...
945
   *
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
946
   * Reverse of __next_mem_range().
7bd0b0f0d   Tejun Heo   memblock: Reimple...
947
   */
fc6daaf93   Tony Luck   mm/memblock: add ...
948
  void __init_memblock __next_mem_range_rev(u64 *idx, int nid, ulong flags,
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
949
950
951
952
  					  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...
953
  {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
954
955
  	int idx_a = *idx & 0xffffffff;
  	int idx_b = *idx >> 32;
b11542335   Grygorii Strashko   mm/memblock: swit...
956

560dca27a   Grygorii Strashko   mm/memblock: use ...
957
958
959
  	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...
960
961
  
  	if (*idx == (u64)ULLONG_MAX) {
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
962
  		idx_a = type_a->cnt - 1;
e47608ab6   zijun_hu   mm/memblock.c: fi...
963
964
965
966
  		if (type_b != NULL)
  			idx_b = type_b->cnt;
  		else
  			idx_b = 0;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
967
  	}
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
968
969
  	for (; idx_a >= 0; idx_a--) {
  		struct memblock_region *m = &type_a->regions[idx_a];
7bd0b0f0d   Tejun Heo   memblock: Reimple...
970
971
  		phys_addr_t m_start = m->base;
  		phys_addr_t m_end = m->base + m->size;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
972
  		int m_nid = memblock_get_region_node(m);
7bd0b0f0d   Tejun Heo   memblock: Reimple...
973
974
  
  		/* only memory regions are associated with nodes, check it */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
975
  		if (nid != NUMA_NO_NODE && nid != m_nid)
7bd0b0f0d   Tejun Heo   memblock: Reimple...
976
  			continue;
55ac590c2   Tang Chen   memblock, mem_hot...
977
978
979
  		/* skip hotpluggable memory regions if needed */
  		if (movable_node_is_enabled() && memblock_is_hotpluggable(m))
  			continue;
a3f5bafcc   Tony Luck   mm/memblock: allo...
980
981
982
  		/* 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 ...
983
984
985
  		/* 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...
986
987
988
989
990
991
992
  		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...
993
  			idx_a--;
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
  			*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...
1012

7bd0b0f0d   Tejun Heo   memblock: Reimple...
1013
1014
1015
1016
1017
1018
1019
1020
1021
  			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...
1022
  					*out_nid = m_nid;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1023
  				if (m_start >= r_start)
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1024
  					idx_a--;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1025
  				else
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1026
1027
  					idx_b--;
  				*idx = (u32)idx_a | (u64)idx_b << 32;
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1028
1029
1030
1031
  				return;
  			}
  		}
  	}
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1032
  	/* signal end of iteration */
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1033
1034
  	*idx = ULLONG_MAX;
  }
7c0caeb86   Tejun Heo   memblock: Add opt...
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
  #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...
1071
   * @type: memblock type to set node ID for
7c0caeb86   Tejun Heo   memblock: Add opt...
1072
1073
   * @nid: node ID to set
   *
e7e8de591   Tang Chen   memblock: make me...
1074
   * Set the nid of memblock @type regions in [@base,@base+@size) to @nid.
7c0caeb86   Tejun Heo   memblock: Add opt...
1075
1076
1077
1078
1079
1080
   * 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...
1081
  				      struct memblock_type *type, int nid)
7c0caeb86   Tejun Heo   memblock: Add opt...
1082
  {
6a9ceb31c   Tejun Heo   memblock: Separat...
1083
1084
  	int start_rgn, end_rgn;
  	int i, ret;
7c0caeb86   Tejun Heo   memblock: Add opt...
1085

6a9ceb31c   Tejun Heo   memblock: Separat...
1086
1087
1088
  	ret = memblock_isolate_range(type, base, size, &start_rgn, &end_rgn);
  	if (ret)
  		return ret;
7c0caeb86   Tejun Heo   memblock: Add opt...
1089

6a9ceb31c   Tejun Heo   memblock: Separat...
1090
  	for (i = start_rgn; i < end_rgn; i++)
e9d24ad30   Wanpeng Li   mm/memblock: use ...
1091
  		memblock_set_region_node(&type->regions[i], nid);
7c0caeb86   Tejun Heo   memblock: Add opt...
1092
1093
1094
1095
1096
  
  	memblock_merge_regions(type);
  	return 0;
  }
  #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */
2bfc2862c   Akinobu Mita   memblock: introdu...
1097
1098
  static phys_addr_t __init memblock_alloc_range_nid(phys_addr_t size,
  					phys_addr_t align, phys_addr_t start,
fc6daaf93   Tony Luck   mm/memblock: add ...
1099
  					phys_addr_t end, int nid, ulong flags)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1100
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1101
  	phys_addr_t found;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1102

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

fc6daaf93   Tony Luck   mm/memblock: add ...
1106
1107
  	found = memblock_find_in_range_node(size, align, start, end, nid,
  					    flags);
aedf95ea0   Catalin Marinas   mm/memblock.c: ca...
1108
1109
1110
1111
1112
  	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...
1113
  		kmemleak_alloc_phys(found, size, 0, 0);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1114
  		return found;
aedf95ea0   Catalin Marinas   mm/memblock.c: ca...
1115
  	}
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1116
  	return 0;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1117
  }
2bfc2862c   Akinobu Mita   memblock: introdu...
1118
  phys_addr_t __init memblock_alloc_range(phys_addr_t size, phys_addr_t align,
fc6daaf93   Tony Luck   mm/memblock: add ...
1119
1120
  					phys_addr_t start, phys_addr_t end,
  					ulong flags)
2bfc2862c   Akinobu Mita   memblock: introdu...
1121
  {
fc6daaf93   Tony Luck   mm/memblock: add ...
1122
1123
  	return memblock_alloc_range_nid(size, align, start, end, NUMA_NO_NODE,
  					flags);
2bfc2862c   Akinobu Mita   memblock: introdu...
1124
1125
1126
1127
  }
  
  static phys_addr_t __init memblock_alloc_base_nid(phys_addr_t size,
  					phys_addr_t align, phys_addr_t max_addr,
fc6daaf93   Tony Luck   mm/memblock: add ...
1128
  					int nid, ulong flags)
2bfc2862c   Akinobu Mita   memblock: introdu...
1129
  {
fc6daaf93   Tony Luck   mm/memblock: add ...
1130
  	return memblock_alloc_range_nid(size, align, 0, max_addr, nid, flags);
2bfc2862c   Akinobu Mita   memblock: introdu...
1131
  }
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1132
1133
  phys_addr_t __init memblock_alloc_nid(phys_addr_t size, phys_addr_t align, int nid)
  {
a3f5bafcc   Tony Luck   mm/memblock: allo...
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
  	ulong flags = choose_memblock_flags();
  	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...
1146
1147
1148
1149
  }
  
  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 ...
1150
1151
  	return memblock_alloc_base_nid(size, align, max_addr, NUMA_NO_NODE,
  				       MEMBLOCK_NONE);
7bd0b0f0d   Tejun Heo   memblock: Reimple...
1152
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1153
  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...
1154
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1155
1156
1157
1158
1159
  	phys_addr_t alloc;
  
  	alloc = __memblock_alloc_base(size, align, max_addr);
  
  	if (alloc == 0)
5d63f81c9   Miles Chen   mm/memblock.c: re...
1160
1161
1162
  		panic("ERROR: Failed to allocate %pa bytes below %pa.
  ",
  		      &size, &max_addr);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1163
1164
  
  	return alloc;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1165
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1166
  phys_addr_t __init memblock_alloc(phys_addr_t size, phys_addr_t align)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1167
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1168
1169
  	return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
  }
95f72d1ed   Yinghai Lu   lmb: rename to me...
1170

9d1e24928   Benjamin Herrenschmidt   memblock: Separat...
1171
1172
1173
1174
1175
1176
  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...
1177
  	return memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ACCESSIBLE);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1178
  }
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
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
  /**
   * 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;
a3f5bafcc   Tony Luck   mm/memblock: allo...
1213
  	ulong flags = choose_memblock_flags();
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1214

560dca27a   Grygorii Strashko   mm/memblock: use ...
1215
1216
1217
  	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 ...
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
  
  	/*
  	 * 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...
1229
1230
  	if (max_addr > memblock.current_limit)
  		max_addr = memblock.current_limit;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1231
1232
  again:
  	alloc = memblock_find_in_range_node(size, align, min_addr, max_addr,
a3f5bafcc   Tony Luck   mm/memblock: allo...
1233
  					    nid, flags);
7d41c03e2   Wei Yang   mm/memblock.c: ch...
1234
  	if (alloc && !memblock_reserve(alloc, size))
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1235
1236
1237
1238
  		goto done;
  
  	if (nid != NUMA_NO_NODE) {
  		alloc = memblock_find_in_range_node(size, align, min_addr,
fc6daaf93   Tony Luck   mm/memblock: add ...
1239
  						    max_addr, NUMA_NO_NODE,
a3f5bafcc   Tony Luck   mm/memblock: allo...
1240
  						    flags);
7d41c03e2   Wei Yang   mm/memblock.c: ch...
1241
  		if (alloc && !memblock_reserve(alloc, size))
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1242
1243
1244
1245
1246
1247
  			goto done;
  	}
  
  	if (min_addr) {
  		min_addr = 0;
  		goto again;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1248
  	}
a3f5bafcc   Tony Luck   mm/memblock: allo...
1249
1250
1251
1252
1253
1254
1255
1256
1257
  	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 ...
1258
  done:
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
  	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;
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
  }
  
  /**
   * 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_);
9099daed9   Catalin Marinas   mm: kmemleak: avo...
1358
  	kmemleak_free_part_phys(base, size);
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1359
  	memblock_remove_range(&memblock.reserved, base, size);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
  }
  
  /*
   * __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_);
9099daed9   Catalin Marinas   mm: kmemleak: avo...
1379
  	kmemleak_free_part_phys(base, size);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1380
1381
1382
1383
  	cursor = PFN_UP(base);
  	end = PFN_DOWN(base + size);
  
  	for (; cursor < end; cursor++) {
d70ddd7a5   Mel Gorman   mm: page_alloc: p...
1384
  		__free_pages_bootmem(pfn_to_page(cursor), cursor, 0);
26f09e9b3   Santosh Shilimkar   mm/memblock: add ...
1385
1386
1387
  		totalram_pages++;
  	}
  }
9d1e24928   Benjamin Herrenschmidt   memblock: Separat...
1388
1389
1390
1391
  
  /*
   * Remaining API functions
   */
1f1ffb8a1   David Gibson   memblock: don't m...
1392
  phys_addr_t __init_memblock memblock_phys_mem_size(void)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1393
  {
1440c4e2c   Tejun Heo   memblock: Track t...
1394
  	return memblock.memory.total_size;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1395
  }
8907de5dc   Srikar Dronamraju   mm/memblock.c: ex...
1396
1397
1398
1399
  phys_addr_t __init_memblock memblock_reserved_size(void)
  {
  	return memblock.reserved.total_size;
  }
595ad9af8   Yinghai Lu   memblock: Add mem...
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
  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...
1413
  	return PFN_PHYS(pages);
595ad9af8   Yinghai Lu   memblock: Add mem...
1414
  }
0a93ebef6   Sam Ravnborg   memblock: add mem...
1415
1416
1417
1418
1419
  /* lowest address */
  phys_addr_t __init_memblock memblock_start_of_DRAM(void)
  {
  	return memblock.memory.regions[0].base;
  }
10d064398   Yinghai Lu   memblock: Option ...
1420
  phys_addr_t __init_memblock memblock_end_of_DRAM(void)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1421
1422
  {
  	int idx = memblock.memory.cnt - 1;
e3239ff92   Benjamin Herrenschmidt   memblock: Rename ...
1423
  	return (memblock.memory.regions[idx].base + memblock.memory.regions[idx].size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1424
  }
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1425
  static phys_addr_t __init_memblock __find_max_addr(phys_addr_t limit)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1426
  {
c0ce8fef5   Tejun Heo   memblock: Reimple...
1427
  	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
136199f0a   Emil Medve   memblock: use for...
1428
  	struct memblock_region *r;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1429

a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1430
1431
1432
1433
1434
  	/*
  	 * translate the memory @limit size into the max address within one of
  	 * the memory memblock regions, if the @limit exceeds the total size
  	 * of those regions, max_addr will keep original value ULLONG_MAX
  	 */
136199f0a   Emil Medve   memblock: use for...
1435
  	for_each_memblock(memory, r) {
c0ce8fef5   Tejun Heo   memblock: Reimple...
1436
1437
1438
  		if (limit <= r->size) {
  			max_addr = r->base + limit;
  			break;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1439
  		}
c0ce8fef5   Tejun Heo   memblock: Reimple...
1440
  		limit -= r->size;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1441
  	}
c0ce8fef5   Tejun Heo   memblock: Reimple...
1442

a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
  	return max_addr;
  }
  
  void __init memblock_enforce_memory_limit(phys_addr_t limit)
  {
  	phys_addr_t max_addr = (phys_addr_t)ULLONG_MAX;
  
  	if (!limit)
  		return;
  
  	max_addr = __find_max_addr(limit);
  
  	/* @limit exceeds the total size of the memory, do nothing */
  	if (max_addr == (phys_addr_t)ULLONG_MAX)
  		return;
c0ce8fef5   Tejun Heo   memblock: Reimple...
1458
  	/* truncate both memory and reserved regions */
f1af9d3af   Philipp Hachtmann   mm/memblock: Do s...
1459
1460
1461
1462
  	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...
1463
  }
c9ca9b4e2   AKASHI Takahiro   memblock: add mem...
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
  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,
  			base + size, (phys_addr_t)ULLONG_MAX);
  }
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1491
1492
  void __init memblock_mem_limit_remove_map(phys_addr_t limit)
  {
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1493
  	phys_addr_t max_addr;
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1494
1495
1496
1497
1498
1499
1500
1501
1502
  
  	if (!limit)
  		return;
  
  	max_addr = __find_max_addr(limit);
  
  	/* @limit exceeds the total size of the memory, do nothing */
  	if (max_addr == (phys_addr_t)ULLONG_MAX)
  		return;
c9ca9b4e2   AKASHI Takahiro   memblock: add mem...
1503
  	memblock_cap_memory_range(0, max_addr);
a571d4eb5   Dennis Chen   mm/memblock.c: ad...
1504
  }
cd79481d2   Yinghai Lu   memblock: Annotat...
1505
  static int __init_memblock memblock_search(struct memblock_type *type, phys_addr_t addr)
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
  {
  	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...
1522
  bool __init memblock_is_reserved(phys_addr_t addr)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1523
  {
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1524
1525
  	return memblock_search(&memblock.reserved, addr) != -1;
  }
95f72d1ed   Yinghai Lu   lmb: rename to me...
1526

b4ad0c7e0   Yaowei Bai   mm/memblock.c: me...
1527
  bool __init_memblock memblock_is_memory(phys_addr_t addr)
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1528
1529
1530
  {
  	return memblock_search(&memblock.memory, addr) != -1;
  }
bf3d3cc58   Ard Biesheuvel   mm/memblock: add ...
1531
1532
1533
1534
1535
1536
1537
1538
  int __init_memblock memblock_is_map_memory(phys_addr_t addr)
  {
  	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...
1539
1540
1541
1542
1543
  #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...
1544
  	int mid = memblock_search(type, PFN_PHYS(pfn));
e76b63f80   Yinghai Lu   memblock, numa: b...
1545
1546
1547
  
  	if (mid == -1)
  		return -1;
f7e2f7e89   Fabian Frederick   mm/memblock.c: us...
1548
1549
  	*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...
1550
1551
1552
1553
  
  	return type->regions[mid].nid;
  }
  #endif
eab309494   Stephen Boyd   memblock: Documen...
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
  /**
   * 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...
1564
  int __init_memblock memblock_is_region_memory(phys_addr_t base, phys_addr_t size)
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1565
  {
abb65272a   Tomi Valkeinen   memblock: fix mem...
1566
  	int idx = memblock_search(&memblock.memory, base);
eb18f1b5b   Tejun Heo   memblock: Make me...
1567
  	phys_addr_t end = base + memblock_cap_size(base, &size);
72d4b0b4e   Benjamin Herrenschmidt   memblock: Impleme...
1568
1569
1570
  
  	if (idx == -1)
  		return 0;
ef415ef41   Wei Yang   mm/memblock.c: tr...
1571
  	return (memblock.memory.regions[idx].base +
eb18f1b5b   Tejun Heo   memblock: Make me...
1572
  		 memblock.memory.regions[idx].size) >= end;
95f72d1ed   Yinghai Lu   lmb: rename to me...
1573
  }
eab309494   Stephen Boyd   memblock: Documen...
1574
1575
1576
1577
1578
1579
1580
1581
  /**
   * 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:
c5c5c9d10   Tang Chen   mm/memblock.c: ma...
1582
   * True if they intersect, false if not.
eab309494   Stephen Boyd   memblock: Documen...
1583
   */
c5c5c9d10   Tang Chen   mm/memblock.c: ma...
1584
  bool __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t size)
95f72d1ed   Yinghai Lu   lmb: rename to me...
1585
  {
eb18f1b5b   Tejun Heo   memblock: Make me...
1586
  	memblock_cap_size(base, &size);
c5c5c9d10   Tang Chen   mm/memblock.c: ma...
1587
  	return memblock_overlaps_region(&memblock.reserved, base, size);
95f72d1ed   Yinghai Lu   lmb: rename to me...
1588
  }
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1589
1590
  void __init_memblock memblock_trim_memory(phys_addr_t align)
  {
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1591
  	phys_addr_t start, end, orig_start, orig_end;
136199f0a   Emil Medve   memblock: use for...
1592
  	struct memblock_region *r;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1593

136199f0a   Emil Medve   memblock: use for...
1594
1595
1596
  	for_each_memblock(memory, r) {
  		orig_start = r->base;
  		orig_end = r->base + r->size;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1597
1598
1599
1600
1601
1602
1603
  		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...
1604
1605
  			r->base = start;
  			r->size = end - start;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1606
  		} else {
136199f0a   Emil Medve   memblock: use for...
1607
1608
1609
  			memblock_remove_region(&memblock.memory,
  					       r - memblock.memory.regions);
  			r--;
6ede1fd3c   Yinghai Lu   x86, mm: Trim mem...
1610
1611
1612
  		}
  	}
  }
e63075a3c   Benjamin Herrenschmidt   memblock: Introdu...
1613

3661ca66a   Yinghai Lu   memblock: Fix sec...
1614
  void __init_memblock memblock_set_current_limit(phys_addr_t limit)
e63075a3c   Benjamin Herrenschmidt   memblock: Introdu...
1615
1616
1617
  {
  	memblock.current_limit = limit;
  }
fec510141   Laura Abbott   ARM: 7993/1: mm/m...
1618
1619
1620
1621
  phys_addr_t __init_memblock memblock_get_current_limit(void)
  {
  	return memblock.current_limit;
  }
0262d9c84   Heiko Carstens   memblock: embed m...
1622
  static void __init_memblock memblock_dump(struct memblock_type *type)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1623
  {
5d63f81c9   Miles Chen   mm/memblock.c: re...
1624
  	phys_addr_t base, end, size;
66a207572   Tang Chen   memblock, numa: i...
1625
  	unsigned long flags;
8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
1626
1627
  	int idx;
  	struct memblock_region *rgn;
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1628

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

8c9c1701c   Alexander Kuleshov   mm/memblock: intr...
1632
  	for_each_memblock_type(type, rgn) {
7c0caeb86   Tejun Heo   memblock: Add opt...
1633
1634
1635
1636
  		char nid_buf[32] = "";
  
  		base = rgn->base;
  		size = rgn->size;
5d63f81c9   Miles Chen   mm/memblock.c: re...
1637
  		end = base + size - 1;
66a207572   Tang Chen   memblock, numa: i...
1638
  		flags = rgn->flags;
7c0caeb86   Tejun Heo   memblock: Add opt...
1639
1640
1641
1642
1643
  #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
5d63f81c9   Miles Chen   mm/memblock.c: re...
1644
1645
  		pr_info(" %s[%#x]\t[%pa-%pa], %pa bytes%s flags: %#lx
  ",
0262d9c84   Heiko Carstens   memblock: embed m...
1646
  			type->name, idx, &base, &end, &size, nid_buf, flags);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1647
1648
  	}
  }
864b9a393   Michal Hocko   mm: consider memb...
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
  extern unsigned long __init_memblock
  memblock_reserved_memory_within(phys_addr_t start_addr, phys_addr_t end_addr)
  {
  	struct memblock_region *rgn;
  	unsigned long size = 0;
  	int idx;
  
  	for_each_memblock_type((&memblock.reserved), rgn) {
  		phys_addr_t start, end;
  
  		if (rgn->base + rgn->size < start_addr)
  			continue;
  		if (rgn->base > end_addr)
  			continue;
  
  		start = rgn->base;
  		end = start + rgn->size;
  		size += end - start;
  	}
  
  	return size;
  }
4ff7b82f1   Tejun Heo   memblock: Add __m...
1671
  void __init_memblock __memblock_dump_all(void)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1672
  {
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1673
1674
  	pr_info("MEMBLOCK configuration:
  ");
5d63f81c9   Miles Chen   mm/memblock.c: re...
1675
1676
1677
1678
  	pr_info(" memory size = %pa reserved size = %pa
  ",
  		&memblock.memory.total_size,
  		&memblock.reserved.total_size);
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1679

0262d9c84   Heiko Carstens   memblock: embed m...
1680
1681
  	memblock_dump(&memblock.memory);
  	memblock_dump(&memblock.reserved);
409efd4c9   Heiko Carstens   memblock: also du...
1682
  #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
0262d9c84   Heiko Carstens   memblock: embed m...
1683
  	memblock_dump(&memblock.physmem);
409efd4c9   Heiko Carstens   memblock: also du...
1684
  #endif
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1685
  }
1aadc0560   Tejun Heo   memblock: s/membl...
1686
  void __init memblock_allow_resize(void)
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1687
  {
142b45a72   Benjamin Herrenschmidt   memblock: Add arr...
1688
  	memblock_can_resize = 1;
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1689
  }
6ed311b28   Benjamin Herrenschmidt   memblock: Move fu...
1690
1691
1692
1693
1694
1695
1696
  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...
1697
  #if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_ARCH_DISCARD_MEMBLOCK)
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1698
1699
1700
1701
1702
1703
  
  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...
1704
  	phys_addr_t end;
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1705
1706
1707
  
  	for (i = 0; i < type->cnt; i++) {
  		reg = &type->regions[i];
5d63f81c9   Miles Chen   mm/memblock.c: re...
1708
  		end = reg->base + reg->size - 1;
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1709

5d63f81c9   Miles Chen   mm/memblock.c: re...
1710
1711
1712
  		seq_printf(m, "%4d: ", i);
  		seq_printf(m, "%pa..%pa
  ", &reg->base, &end);
6d03b885f   Benjamin Herrenschmidt   memblock: Add deb...
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
  	}
  	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 ...
1736
1737
1738
  #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...
1739
1740
1741
1742
1743
1744
  
  	return 0;
  }
  __initcall(memblock_init_debugfs);
  
  #endif /* CONFIG_DEBUG_FS */