1 // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 /*
3  * Simple memory allocator
4  *
5  * Copyright 2013-2018 IBM Corp.
6  */
7 
8 #include <inttypes.h>
9 #include <skiboot.h>
10 #include <mem-map.h>
11 #include <libfdt_env.h>
12 #include <lock.h>
13 #include <device.h>
14 #include <cpu.h>
15 #include <chip.h>
16 #include <affinity.h>
17 #include <types.h>
18 #include <mem_region.h>
19 #include <mem_region-malloc.h>
20 
21 /* Memory poisoning on free (if POISON_MEM_REGION set to 1) */
22 #ifdef DEBUG
23 #define POISON_MEM_REGION	1
24 #else
25 #define POISON_MEM_REGION	0
26 #endif
27 #define POISON_MEM_REGION_WITH	0x99
28 #define POISON_MEM_REGION_LIMIT 1*1024*1024*1024
29 
30 /* Locking: The mem_region_lock protects the regions list from concurrent
31  * updates. Additions to, or removals from, the region list must be done
32  * with this lock held. This is typically done when we're establishing
33  * the memory & reserved regions.
34  *
35  * Each region has a lock (region->free_list_lock) to protect the free list
36  * from concurrent modification. This lock is used when we're allocating
37  * memory out of a specific region.
38  *
39  * If both locks are needed (eg, __local_alloc, where we need to find a region,
40  * then allocate from it), the mem_region_lock must be acquired before (and
41  * released after) the per-region lock.
42  */
43 struct lock mem_region_lock = LOCK_UNLOCKED;
44 
45 static struct list_head regions = LIST_HEAD_INIT(regions);
46 static struct list_head early_reserves = LIST_HEAD_INIT(early_reserves);
47 
48 static bool mem_region_init_done = false;
49 static bool mem_regions_finalised = false;
50 
51 unsigned long top_of_ram = SKIBOOT_BASE + SKIBOOT_SIZE;
52 
53 static struct mem_region skiboot_os_reserve = {
54 	.name		= "ibm,os-reserve",
55 	.start		= 0,
56 	.len		= SKIBOOT_BASE,
57 	.type		= REGION_OS,
58 };
59 
60 struct mem_region skiboot_heap = {
61 	.name		= "ibm,firmware-heap",
62 	.start		= HEAP_BASE,
63 	.len		= HEAP_SIZE,
64 	.type		= REGION_SKIBOOT_HEAP,
65 };
66 
67 static struct mem_region skiboot_code_and_text = {
68 	.name		= "ibm,firmware-code",
69 	.start		= SKIBOOT_BASE,
70 	.len		= HEAP_BASE - SKIBOOT_BASE,
71 	.type		= REGION_SKIBOOT_FIRMWARE,
72 };
73 
74 static struct mem_region skiboot_after_heap = {
75 	.name		= "ibm,firmware-data",
76 	.start		= HEAP_BASE + HEAP_SIZE,
77 	.len		= SKIBOOT_BASE + SKIBOOT_SIZE - (HEAP_BASE + HEAP_SIZE),
78 	.type		= REGION_SKIBOOT_FIRMWARE,
79 };
80 
81 static struct mem_region skiboot_cpu_stacks = {
82 	.name		= "ibm,firmware-stacks",
83 	.start		= CPU_STACKS_BASE,
84 	.len		= 0, /* TBA */
85 	.type		= REGION_SKIBOOT_FIRMWARE,
86 };
87 
88 static struct mem_region skiboot_mambo_kernel = {
89 	.name		= "ibm,firmware-mambo-kernel",
90 	.start		= (unsigned long)KERNEL_LOAD_BASE,
91 	.len		= KERNEL_LOAD_SIZE,
92 	.type		= REGION_SKIBOOT_FIRMWARE,
93 };
94 
95 static struct mem_region skiboot_mambo_initramfs = {
96 	.name		= "ibm,firmware-mambo-initramfs",
97 	.start		= (unsigned long)INITRAMFS_LOAD_BASE,
98 	.len		= INITRAMFS_LOAD_SIZE,
99 	.type		= REGION_SKIBOOT_FIRMWARE,
100 };
101 
102 
103 struct alloc_hdr {
104 	bool free : 1;
105 	bool prev_free : 1;
106 	bool printed : 1;
107 	unsigned long num_longs : BITS_PER_LONG-3; /* Including header. */
108 	const char *location;
109 };
110 
111 struct free_hdr {
112 	struct alloc_hdr hdr;
113 	struct list_node list;
114 	/* ... unsigned long tailer; */
115 };
116 
117 #define ALLOC_HDR_LONGS (sizeof(struct alloc_hdr) / sizeof(long))
118 #define ALLOC_MIN_LONGS (sizeof(struct free_hdr) / sizeof(long) + 1)
119 
120 /* Avoid ugly casts. */
region_start(const struct mem_region * region)121 static void *region_start(const struct mem_region *region)
122 {
123 	return (void *)(unsigned long)region->start;
124 }
125 
126 /* Each free block has a tailer, so we can walk backwards. */
tailer(struct free_hdr * f)127 static unsigned long *tailer(struct free_hdr *f)
128 {
129 	return (unsigned long *)f + f->hdr.num_longs - 1;
130 }
131 
132 /* This walks forward to the next hdr (or NULL if at the end). */
next_hdr(const struct mem_region * region,const struct alloc_hdr * hdr)133 static struct alloc_hdr *next_hdr(const struct mem_region *region,
134 				  const struct alloc_hdr *hdr)
135 {
136 	void *next;
137 
138 	next = ((unsigned long *)hdr + hdr->num_longs);
139 	if (next >= region_start(region) + region->len)
140 		next = NULL;
141 	return next;
142 }
143 
144 #if POISON_MEM_REGION == 1
mem_poison(struct free_hdr * f)145 static void mem_poison(struct free_hdr *f)
146 {
147 	size_t poison_size = (void*)tailer(f) - (void*)(f+1);
148 
149 	/* We only poison up to a limit, as otherwise boot is
150 	 * kinda slow */
151 	if (poison_size > POISON_MEM_REGION_LIMIT)
152 		poison_size = POISON_MEM_REGION_LIMIT;
153 
154 	memset(f+1, POISON_MEM_REGION_WITH, poison_size);
155 }
156 #endif
157 
158 /* Creates free block covering entire region. */
init_allocatable_region(struct mem_region * region)159 static void init_allocatable_region(struct mem_region *region)
160 {
161 	struct free_hdr *f = region_start(region);
162 	assert(region->type == REGION_SKIBOOT_HEAP ||
163 	       region->type == REGION_MEMORY);
164 	f->hdr.num_longs = region->len / sizeof(long);
165 	f->hdr.free = true;
166 	f->hdr.prev_free = false;
167 	*tailer(f) = f->hdr.num_longs;
168 	list_head_init(&region->free_list);
169 	list_add(&region->free_list, &f->list);
170 #if POISON_MEM_REGION == 1
171 	mem_poison(f);
172 #endif
173 }
174 
make_free(struct mem_region * region,struct free_hdr * f,const char * location,bool skip_poison)175 static void make_free(struct mem_region *region, struct free_hdr *f,
176 		      const char *location, bool skip_poison)
177 {
178 	struct alloc_hdr *next;
179 
180 #if POISON_MEM_REGION == 1
181 	if (!skip_poison)
182 		mem_poison(f);
183 #else
184 	(void)skip_poison;
185 #endif
186 
187 	if (f->hdr.prev_free) {
188 		struct free_hdr *prev;
189 		unsigned long *prev_tailer = (unsigned long *)f - 1;
190 
191 		assert(*prev_tailer);
192 		prev = (void *)((unsigned long *)f - *prev_tailer);
193 		assert(prev->hdr.free);
194 		assert(!prev->hdr.prev_free);
195 
196 		/* Expand to cover the one we just freed. */
197 		prev->hdr.num_longs += f->hdr.num_longs;
198 		f = prev;
199 	} else {
200 		f->hdr.free = true;
201 		f->hdr.location = location;
202 		list_add(&region->free_list, &f->list);
203 	}
204 
205 	/* Fix up tailer. */
206 	*tailer(f) = f->hdr.num_longs;
207 
208 	/* If next is free, coalesce it */
209 	next = next_hdr(region, &f->hdr);
210 	if (next) {
211 		next->prev_free = true;
212 		if (next->free) {
213 			struct free_hdr *next_free = (void *)next;
214 			list_del_from(&region->free_list, &next_free->list);
215 			/* Maximum of one level of recursion */
216 			make_free(region, next_free, location, true);
217 		}
218 	}
219 }
220 
221 /* Can we fit this many longs with this alignment in this free block? */
fits(struct free_hdr * f,size_t longs,size_t align,size_t * offset)222 static bool fits(struct free_hdr *f, size_t longs, size_t align, size_t *offset)
223 {
224 	*offset = 0;
225 
226 	while (f->hdr.num_longs >= *offset + longs) {
227 		size_t addr;
228 
229 		addr = (unsigned long)f
230 			+ (*offset + ALLOC_HDR_LONGS) * sizeof(long);
231 		if ((addr & (align - 1)) == 0)
232 			return true;
233 
234 		/* Don't make tiny chunks! */
235 		if (*offset == 0)
236 			*offset = ALLOC_MIN_LONGS;
237 		else
238 			(*offset)++;
239 	}
240 	return false;
241 }
242 
discard_excess(struct mem_region * region,struct alloc_hdr * hdr,size_t alloc_longs,const char * location,bool skip_poison)243 static void discard_excess(struct mem_region *region,
244 			   struct alloc_hdr *hdr, size_t alloc_longs,
245 			   const char *location, bool skip_poison)
246 {
247 	/* Do we have excess? */
248 	if (hdr->num_longs > alloc_longs + ALLOC_MIN_LONGS) {
249 		struct free_hdr *post;
250 
251 		/* Set up post block. */
252 		post = (void *)hdr + alloc_longs * sizeof(long);
253 		post->hdr.num_longs = hdr->num_longs - alloc_longs;
254 		post->hdr.prev_free = false;
255 
256 		/* Trim our block. */
257 		hdr->num_longs = alloc_longs;
258 
259 		/* This coalesces as required. */
260 		make_free(region, post, location, skip_poison);
261 	}
262 }
263 
hdr_location(const struct alloc_hdr * hdr)264 static const char *hdr_location(const struct alloc_hdr *hdr)
265 {
266 	/* Corrupt: step carefully! */
267 	if (is_rodata(hdr->location))
268 		return hdr->location;
269 	return "*CORRUPT*";
270 }
271 
bad_header(const struct mem_region * region,const struct alloc_hdr * hdr,const char * during,const char * location)272 static void bad_header(const struct mem_region *region,
273 		       const struct alloc_hdr *hdr,
274 		       const char *during,
275 		       const char *location)
276 {
277 	/* Corrupt: step carefully! */
278 	if (is_rodata(hdr->location))
279 		prerror("%p (in %s) %s at %s, previously %s\n",
280 			hdr-1, region->name, during, location, hdr->location);
281 	else
282 		prerror("%p (in %s) %s at %s, previously %p\n",
283 			hdr-1, region->name, during, location, hdr->location);
284 	abort();
285 }
286 
region_is_reservable(struct mem_region * region)287 static bool region_is_reservable(struct mem_region *region)
288 {
289 	return region->type != REGION_OS;
290 }
291 
region_is_reserved(struct mem_region * region)292 static bool region_is_reserved(struct mem_region *region)
293 {
294 	return region->type != REGION_OS && region->type != REGION_MEMORY;
295 }
296 
mem_dump_allocs(void)297 void mem_dump_allocs(void)
298 {
299 	struct mem_region *region;
300 	struct alloc_hdr *h, *i;
301 
302 	/* Second pass: populate property data */
303 	prlog(PR_INFO, "Memory regions:\n");
304 	list_for_each(&regions, region, list) {
305 		if (!(region->type == REGION_SKIBOOT_HEAP ||
306 		      region->type == REGION_MEMORY))
307 			continue;
308 		prlog(PR_INFO, "  0x%012llx..%012llx : %s\n",
309 		       (long long)region->start,
310 		       (long long)(region->start + region->len - 1),
311 		       region->name);
312 		if (region->free_list.n.next == NULL) {
313 			prlog(PR_INFO, "    no allocs\n");
314 			continue;
315 		}
316 
317 		/*
318 		 * XXX: When dumping the allocation list we coalase allocations
319 		 * with the same location and size into a single line. This is
320 		 * quadratic, but it makes the dump human-readable and the raw
321 		 * dump sometimes causes the log buffer to wrap.
322 		 */
323 		for (h = region_start(region); h; h = next_hdr(region, h))
324 			h->printed = false;
325 
326 		for (h = region_start(region); h; h = next_hdr(region, h)) {
327 			unsigned long bytes;
328 			int count = 0;
329 
330 			if (h->free)
331 				continue;
332 			if (h->printed)
333 				continue;
334 
335 			for (i = h; i; i = next_hdr(region, i)) {
336 				if (i->free)
337 					continue;
338 				if (i->num_longs != h->num_longs)
339 					continue;
340 				if (strcmp(i->location, h->location))
341 					continue;
342 
343 				i->printed = true;
344 				count++;
345 			}
346 
347 			bytes = h->num_longs * sizeof(long);
348 			prlog(PR_NOTICE, " % 8d allocs of 0x%.8lx bytes at %s (total 0x%lx)\n",
349 				count, bytes, hdr_location(h), bytes * count);
350 		}
351 	}
352 }
353 
mem_dump_free(void)354 int64_t mem_dump_free(void)
355 {
356 	struct mem_region *region;
357 	struct alloc_hdr *hdr;
358 	int64_t total_free;
359 	int64_t region_free;
360 
361 	total_free = 0;
362 
363 	prlog(PR_INFO, "Free space in HEAP memory regions:\n");
364 	list_for_each(&regions, region, list) {
365 		if (!(region->type == REGION_SKIBOOT_HEAP ||
366 		      region->type == REGION_MEMORY))
367 			continue;
368 		region_free = 0;
369 
370 		if (region->free_list.n.next == NULL) {
371 			continue;
372 		}
373 		for (hdr = region_start(region); hdr; hdr = next_hdr(region, hdr)) {
374 			if (!hdr->free)
375 				continue;
376 
377 			region_free+= hdr->num_longs * sizeof(long);
378 		}
379 		prlog(PR_INFO, "Region %s free: %"PRIx64"\n",
380 		       region->name, region_free);
381 		total_free += region_free;
382 	}
383 
384 	prlog(PR_INFO, "Total free: %"PRIu64"\n", total_free);
385 
386 	return total_free;
387 }
388 
__mem_alloc(struct mem_region * region,size_t size,size_t align,const char * location)389 static void *__mem_alloc(struct mem_region *region, size_t size, size_t align,
390 			 const char *location)
391 {
392 	size_t alloc_longs, offset;
393 	struct free_hdr *f;
394 	struct alloc_hdr *next;
395 
396 	/* Align must be power of 2. */
397 	assert(!((align - 1) & align));
398 
399 	/* This should be a constant. */
400 	assert(is_rodata(location));
401 
402 	/* Unallocatable region? */
403 	if (!(region->type == REGION_SKIBOOT_HEAP ||
404 	      region->type == REGION_MEMORY))
405 		return NULL;
406 
407 	/* First allocation? */
408 	if (region->free_list.n.next == NULL)
409 		init_allocatable_region(region);
410 
411 	/* Don't do screwy sizes. */
412 	if (size > region->len)
413 		return NULL;
414 
415 	/* Don't do tiny alignments, we deal in long increments. */
416 	if (align < sizeof(long))
417 		align = sizeof(long);
418 
419 	/* Convert size to number of longs, too. */
420 	alloc_longs = (size + sizeof(long)-1) / sizeof(long) + ALLOC_HDR_LONGS;
421 
422 	/* Can't be too small for when we free it, either. */
423 	if (alloc_longs < ALLOC_MIN_LONGS)
424 		alloc_longs = ALLOC_MIN_LONGS;
425 
426 	/* Walk free list. */
427 	list_for_each(&region->free_list, f, list) {
428 		/* We may have to skip some to meet alignment. */
429 		if (fits(f, alloc_longs, align, &offset))
430 			goto found;
431 	}
432 
433 	return NULL;
434 
435 found:
436 	assert(f->hdr.free);
437 	assert(!f->hdr.prev_free);
438 
439 	/* This block is no longer free. */
440 	list_del_from(&region->free_list, &f->list);
441 	f->hdr.free = false;
442 	f->hdr.location = location;
443 
444 	next = next_hdr(region, &f->hdr);
445 	if (next) {
446 		assert(next->prev_free);
447 		next->prev_free = false;
448 	}
449 
450 	if (offset != 0) {
451 		struct free_hdr *pre = f;
452 
453 		f = (void *)f + offset * sizeof(long);
454 		assert(f >= pre + 1);
455 
456 		/* Set up new header. */
457 		f->hdr.num_longs = pre->hdr.num_longs - offset;
458 		/* f->hdr.prev_free will be set by make_free below. */
459 		f->hdr.free = false;
460 		f->hdr.location = location;
461 
462 		/* Fix up old header. */
463 		pre->hdr.num_longs = offset;
464 		pre->hdr.prev_free = false;
465 
466 		/* This coalesces as required. */
467 		make_free(region, pre, location, true);
468 	}
469 
470 	/* We might be too long; put the rest back. */
471 	discard_excess(region, &f->hdr, alloc_longs, location, true);
472 
473 	/* Clear tailer for debugging */
474 	*tailer(f) = 0;
475 
476 	/* Their pointer is immediately after header. */
477 	return &f->hdr + 1;
478 }
479 
mem_alloc(struct mem_region * region,size_t size,size_t align,const char * location)480 void *mem_alloc(struct mem_region *region, size_t size, size_t align,
481 		const char *location)
482 {
483 	static bool dumped = false;
484 	void *r;
485 
486 	assert(lock_held_by_me(&region->free_list_lock));
487 
488 	r = __mem_alloc(region, size, align, location);
489 	if (r)
490 		return r;
491 
492 	prerror("mem_alloc(0x%lx, 0x%lx, \"%s\", %s) failed !\n",
493 		size, align, location, region->name);
494 	if (!dumped) {
495 		mem_dump_allocs();
496 		dumped = true;
497 	}
498 
499 	return NULL;
500 }
501 
mem_free(struct mem_region * region,void * mem,const char * location)502 void mem_free(struct mem_region *region, void *mem, const char *location)
503 {
504 	struct alloc_hdr *hdr;
505 
506 	/* This should be a constant. */
507 	assert(is_rodata(location));
508 
509 	assert(lock_held_by_me(&region->free_list_lock));
510 
511 	/* Freeing NULL is always a noop. */
512 	if (!mem)
513 		return;
514 
515 	/* Your memory is in the region, right? */
516 	assert(mem >= region_start(region) + sizeof(*hdr));
517 	assert(mem < region_start(region) + region->len);
518 
519 	/* Grab header. */
520 	hdr = mem - sizeof(*hdr);
521 
522 	if (hdr->free)
523 		bad_header(region, hdr, "re-freed", location);
524 
525 	make_free(region, (struct free_hdr *)hdr, location, false);
526 }
527 
mem_allocated_size(const void * ptr)528 size_t mem_allocated_size(const void *ptr)
529 {
530 	const struct alloc_hdr *hdr = ptr - sizeof(*hdr);
531 	return hdr->num_longs * sizeof(long) - sizeof(struct alloc_hdr);
532 }
533 
mem_resize(struct mem_region * region,void * mem,size_t len,const char * location)534 bool mem_resize(struct mem_region *region, void *mem, size_t len,
535 		const char *location)
536 {
537 	struct alloc_hdr *hdr, *next;
538 	struct free_hdr *f;
539 
540 	/* This should be a constant. */
541 	assert(is_rodata(location));
542 
543 	assert(lock_held_by_me(&region->free_list_lock));
544 
545 	/* Get header. */
546 	hdr = mem - sizeof(*hdr);
547 	if (hdr->free)
548 		bad_header(region, hdr, "resize", location);
549 
550 	/* Round up size to multiple of longs. */
551 	len = (sizeof(*hdr) + len + sizeof(long) - 1) / sizeof(long);
552 
553 	/* Can't be too small for when we free it, either. */
554 	if (len < ALLOC_MIN_LONGS)
555 		len = ALLOC_MIN_LONGS;
556 
557 	/* Shrinking is simple. */
558 	if (len <= hdr->num_longs) {
559 		hdr->location = location;
560 		discard_excess(region, hdr, len, location, false);
561 		return true;
562 	}
563 
564 	/* Check if we can expand. */
565 	next = next_hdr(region, hdr);
566 	if (!next || !next->free || hdr->num_longs + next->num_longs < len)
567 		return false;
568 
569 	/* OK, it's free and big enough, absorb it. */
570 	f = (struct free_hdr *)next;
571 	list_del_from(&region->free_list, &f->list);
572 	hdr->num_longs += next->num_longs;
573 	hdr->location = location;
574 
575 	/* Update next prev_free */
576 	next = next_hdr(region, &f->hdr);
577 	if (next) {
578 		assert(next->prev_free);
579 		next->prev_free = false;
580 	}
581 
582 	/* Clear tailer for debugging */
583 	*tailer(f) = 0;
584 
585 	/* Now we might have *too* much. */
586 	discard_excess(region, hdr, len, location, true);
587 	return true;
588 }
589 
mem_check(const struct mem_region * region)590 bool mem_check(const struct mem_region *region)
591 {
592 	size_t frees = 0;
593 	struct alloc_hdr *hdr, *prev_free = NULL;
594 	struct free_hdr *f;
595 
596 	/* Check it's sanely aligned. */
597 	if (region->start % sizeof(long)) {
598 		prerror("Region '%s' not sanely aligned (%llx)\n",
599 			region->name, (unsigned long long)region->start);
600 		return false;
601 	}
602 	if ((long)region->len % sizeof(long)) {
603 		prerror("Region '%s' not sane length (%llu)\n",
604 			region->name, (unsigned long long)region->len);
605 		return false;
606 	}
607 
608 	/* Not ours to play with, or empty?  Don't do anything. */
609 	if (!(region->type == REGION_MEMORY ||
610 	      region->type == REGION_SKIBOOT_HEAP) ||
611 	    region->free_list.n.next == NULL)
612 		return true;
613 
614 	/* Walk linearly. */
615 	for (hdr = region_start(region); hdr; hdr = next_hdr(region, hdr)) {
616 		if (hdr->num_longs < ALLOC_MIN_LONGS) {
617 			prerror("Region '%s' %s %p (%s) size %zu\n",
618 				region->name, hdr->free ? "free" : "alloc",
619 				hdr, hdr_location(hdr),
620 				hdr->num_longs * sizeof(long));
621 			return false;
622 		}
623 		if ((unsigned long)hdr + hdr->num_longs * sizeof(long) >
624 		    region->start + region->len) {
625 			prerror("Region '%s' %s %p (%s) oversize %zu\n",
626 				region->name, hdr->free ? "free" : "alloc",
627 				hdr, hdr_location(hdr),
628 				hdr->num_longs * sizeof(long));
629 			return false;
630 		}
631 		if (hdr->free) {
632 			if (hdr->prev_free || prev_free) {
633 				prerror("Region '%s' free %p (%s) has prev_free"
634 					" %p (%s) %sset?\n",
635 					region->name, hdr, hdr_location(hdr),
636 					prev_free,
637 					prev_free ? hdr_location(prev_free)
638 					: "NULL",
639 					hdr->prev_free ? "" : "un");
640 				return false;
641 			}
642 			prev_free = hdr;
643 			frees ^= (unsigned long)hdr - region->start;
644 		} else {
645 			if (hdr->prev_free != (bool)prev_free) {
646 				prerror("Region '%s' alloc %p (%s) has"
647 					" prev_free %p %sset?\n",
648 					region->name, hdr, hdr_location(hdr),
649 					prev_free, hdr->prev_free ? "" : "un");
650 				return false;
651 			}
652 			prev_free = NULL;
653 		}
654 	}
655 
656 	/* Now walk free list. */
657 	list_for_each(&region->free_list, f, list)
658 		frees ^= (unsigned long)f - region->start;
659 
660 	if (frees) {
661 		prerror("Region '%s' free list and walk do not match!\n",
662 			region->name);
663 		return false;
664 	}
665 	return true;
666 }
667 
mem_check_all(void)668 bool mem_check_all(void)
669 {
670 	struct mem_region *r;
671 
672 	list_for_each(&regions, r, list) {
673 		if (!mem_check(r))
674 			return false;
675 	}
676 
677 	return true;
678 }
679 
new_region(const char * name,uint64_t start,uint64_t len,struct dt_node * node,enum mem_region_type type)680 static struct mem_region *new_region(const char *name,
681 				     uint64_t start, uint64_t len,
682 				     struct dt_node *node,
683 				     enum mem_region_type type)
684 {
685 	struct mem_region *region;
686 
687 	region = malloc(sizeof(*region));
688 	if (!region)
689 		return NULL;
690 
691 	region->name = name;
692 	region->start = start;
693 	region->len = len;
694 	region->node = node;
695 	region->type = type;
696 	region->free_list.n.next = NULL;
697 	init_lock(&region->free_list_lock);
698 
699 	return region;
700 }
701 
702 /* We always split regions, so we only have to replace one. */
split_region(struct mem_region * head,uint64_t split_at,enum mem_region_type type)703 static struct mem_region *split_region(struct mem_region *head,
704 				       uint64_t split_at,
705 				       enum mem_region_type type)
706 {
707 	struct mem_region *tail;
708 	uint64_t end = head->start + head->len;
709 
710 	tail = new_region(head->name, split_at, end - split_at,
711 			  head->node, type);
712 	/* Original region becomes head. */
713 	if (tail)
714 		head->len -= tail->len;
715 
716 	return tail;
717 }
718 
intersects(const struct mem_region * region,uint64_t addr)719 static bool intersects(const struct mem_region *region, uint64_t addr)
720 {
721 	return addr > region->start &&
722 		addr < region->start + region->len;
723 }
724 
maybe_split(struct mem_region * r,uint64_t split_at)725 static bool maybe_split(struct mem_region *r, uint64_t split_at)
726 {
727 	struct mem_region *tail;
728 
729 	if (!intersects(r, split_at))
730 		return true;
731 
732 	tail = split_region(r, split_at, r->type);
733 	if (!tail)
734 		return false;
735 
736 	/* Tail add is important: we may need to split again! */
737 	list_add_after(&regions, &tail->list, &r->list);
738 	return true;
739 }
740 
overlaps(const struct mem_region * r1,const struct mem_region * r2)741 static bool overlaps(const struct mem_region *r1, const struct mem_region *r2)
742 {
743 	return (r1->start + r1->len > r2->start
744 		&& r1->start < r2->start + r2->len);
745 }
746 
contains(const struct mem_region * r1,const struct mem_region * r2)747 static bool contains(const struct mem_region *r1, const struct mem_region *r2)
748 {
749 	u64 r1_end = r1->start + r1->len;
750 	u64 r2_end = r2->start + r2->len;
751 
752 	return (r1->start <= r2->start && r2_end <= r1_end);
753 }
754 
get_overlap(const struct mem_region * region)755 static struct mem_region *get_overlap(const struct mem_region *region)
756 {
757 	struct mem_region *i;
758 
759 	list_for_each(&regions, i, list) {
760 		if (overlaps(region, i))
761 			return i;
762 	}
763 	return NULL;
764 }
765 
add_region_to_regions(struct mem_region * region)766 static void add_region_to_regions(struct mem_region *region)
767 {
768 	struct mem_region *r;
769 
770 	list_for_each(&regions, r, list) {
771 		if (r->start < region->start)
772 			continue;
773 
774 		list_add_before(&regions, &region->list, &r->list);
775 		return;
776 	}
777 	list_add_tail(&regions, &region->list);
778 }
779 
add_region(struct mem_region * region)780 static bool add_region(struct mem_region *region)
781 {
782 	struct mem_region *r;
783 
784 	if (mem_regions_finalised) {
785 		prerror("MEM: add_region(%s@0x%"PRIx64") called after finalise!\n",
786 				region->name, region->start);
787 		return false;
788 	}
789 
790 	/* First split any regions which intersect. */
791 	list_for_each(&regions, r, list) {
792 		/*
793 		 * The new region should be fully contained by an existing one.
794 		 * If it's not then we have a problem where reservations
795 		 * partially overlap which is probably broken.
796 		 *
797 		 * NB: There *might* be situations where this is legitimate,
798 		 * but the region handling does not currently support this.
799 		 */
800 		if (overlaps(r, region) && !contains(r, region)) {
801 			prerror("MEM: Partial overlap detected between regions:\n");
802 			prerror("MEM: %s [0x%"PRIx64"-0x%"PRIx64"] (new)\n",
803 				region->name, region->start,
804 				region->start + region->len);
805 			prerror("MEM: %s [0x%"PRIx64"-0x%"PRIx64"]\n",
806 				r->name, r->start, r->start + r->len);
807 			return false;
808 		}
809 
810 		if (!maybe_split(r, region->start) ||
811 		    !maybe_split(r, region->start + region->len))
812 			return false;
813 	}
814 
815 	/* Now we have only whole overlaps, if any. */
816 	while ((r = get_overlap(region)) != NULL) {
817 		assert(r->start == region->start);
818 		assert(r->len == region->len);
819 		list_del_from(&regions, &r->list);
820 		free(r);
821 	}
822 
823 	/* Finally, add in our own region. */
824 	add_region_to_regions(region);
825 	return true;
826 }
827 
mem_reserve(enum mem_region_type type,const char * name,uint64_t start,uint64_t len)828 static void mem_reserve(enum mem_region_type type, const char *name,
829 		uint64_t start, uint64_t len)
830 {
831 	struct mem_region *region;
832 	bool added = true;
833 
834 	lock(&mem_region_lock);
835 	region = new_region(name, start, len, NULL, type);
836 	assert(region);
837 
838 	if (!mem_region_init_done)
839 		list_add(&early_reserves, &region->list);
840 	else
841 		added = add_region(region);
842 
843 	assert(added);
844 	unlock(&mem_region_lock);
845 }
846 
mem_reserve_fw(const char * name,uint64_t start,uint64_t len)847 void mem_reserve_fw(const char *name, uint64_t start, uint64_t len)
848 {
849 	mem_reserve(REGION_FW_RESERVED, name, start, len);
850 }
851 
mem_reserve_hwbuf(const char * name,uint64_t start,uint64_t len)852 void mem_reserve_hwbuf(const char *name, uint64_t start, uint64_t len)
853 {
854 	mem_reserve(REGION_RESERVED, name, start, len);
855 }
856 
matches_chip_id(const __be32 ids[],size_t num,u32 chip_id)857 static bool matches_chip_id(const __be32 ids[], size_t num, u32 chip_id)
858 {
859 	size_t i;
860 
861 	for (i = 0; i < num; i++)
862 		if (be32_to_cpu(ids[i]) == chip_id)
863 			return true;
864 
865 	return false;
866 }
867 
__local_alloc(unsigned int chip_id,size_t size,size_t align,const char * location)868 void *__local_alloc(unsigned int chip_id, size_t size, size_t align,
869 		    const char *location)
870 {
871 	struct mem_region *region;
872 	void *p = NULL;
873 	bool use_local = true;
874 
875 	lock(&mem_region_lock);
876 
877 restart:
878 	list_for_each(&regions, region, list) {
879 		const struct dt_property *prop;
880 		const __be32 *ids;
881 
882 		if (!(region->type == REGION_SKIBOOT_HEAP ||
883 		      region->type == REGION_MEMORY))
884 			continue;
885 
886 		/* Don't allocate from normal heap. */
887 		if (region == &skiboot_heap)
888 			continue;
889 
890 		/* First pass, only match node local regions */
891 		if (use_local) {
892 			if (!region->node)
893 				continue;
894 			prop = dt_find_property(region->node, "ibm,chip-id");
895 			ids = (const __be32 *)prop->prop;
896 			if (!matches_chip_id(ids, prop->len/sizeof(u32),
897 					     chip_id))
898 				continue;
899 		}
900 
901 		/* Second pass, match anything */
902 		lock(&region->free_list_lock);
903 		p = mem_alloc(region, size, align, location);
904 		unlock(&region->free_list_lock);
905 		if (p)
906 			break;
907 	}
908 
909 	/*
910 	 * If we can't allocate the memory block from the expected
911 	 * node, we bail to any one that can accommodate our request.
912 	 */
913 	if (!p && use_local) {
914 		use_local = false;
915 		goto restart;
916 	}
917 
918 	unlock(&mem_region_lock);
919 
920 	return p;
921 }
922 
find_mem_region(const char * name)923 struct mem_region *find_mem_region(const char *name)
924 {
925 	struct mem_region *region;
926 
927 	list_for_each(&regions, region, list) {
928 		if (streq(region->name, name))
929 			return region;
930 	}
931 	return NULL;
932 }
933 
mem_range_is_reserved(uint64_t start,uint64_t size)934 bool mem_range_is_reserved(uint64_t start, uint64_t size)
935 {
936 	uint64_t end = start + size;
937 	struct mem_region *region;
938 	struct list_head *search;
939 
940 	/* We may have the range covered by a number of regions, which could
941 	 * appear in any order. So, we look for a region that covers the
942 	 * start address, and bump start up to the end of that region.
943 	 *
944 	 * We repeat until we've either bumped past the end of the range,
945 	 * or we didn't find a matching region.
946 	 *
947 	 * This has a worst-case of O(n^2), but n is well bounded by the
948 	 * small number of reservations.
949 	 */
950 
951 	if (!mem_region_init_done)
952 		search = &early_reserves;
953 	else
954 		search = &regions;
955 
956 	for (;;) {
957 		bool found = false;
958 
959 		list_for_each(search, region, list) {
960 			if (!region_is_reserved(region))
961 				continue;
962 
963 			/* does this region overlap the start address, and
964 			 * have a non-zero size? */
965 			if (region->start <= start &&
966 					region->start + region->len > start &&
967 					region->len) {
968 				start = region->start + region->len;
969 				found = true;
970 			}
971 		}
972 
973 		/* 'end' is the first byte outside of the range */
974 		if (start >= end)
975 			return true;
976 
977 		if (!found)
978 			break;
979 	}
980 
981 	return false;
982 }
983 
mem_region_parse_reserved_properties(void)984 static void mem_region_parse_reserved_properties(void)
985 {
986 	const struct dt_property *names, *ranges;
987 	struct mem_region *region;
988 
989 	prlog(PR_DEBUG, "MEM: parsing reserved memory from "
990 			"reserved-names/-ranges properties\n");
991 
992 	names = dt_find_property(dt_root, "reserved-names");
993 	ranges = dt_find_property(dt_root, "reserved-ranges");
994 	if (names && ranges) {
995 		const uint64_t *range;
996 		int n, len;
997 
998 		range = (const void *)ranges->prop;
999 
1000 		for (n = 0; n < names->len; n += len, range += 2) {
1001 			char *name;
1002 
1003 			len = strlen(names->prop + n) + 1;
1004 			name = strdup(names->prop + n);
1005 
1006 			region = new_region(name,
1007 					dt_get_number(range, 2),
1008 					dt_get_number(range + 1, 2),
1009 					NULL, REGION_FW_RESERVED);
1010 			if (!add_region(region)) {
1011 				prerror("Couldn't add mem_region %s\n", name);
1012 				abort();
1013 			}
1014 		}
1015 	} else if (names || ranges) {
1016 		prerror("Invalid properties: reserved-names=%p "
1017 				"with reserved-ranges=%p\n",
1018 				names, ranges);
1019 		abort();
1020 	} else {
1021 		return;
1022 	}
1023 }
1024 
mem_region_parse_reserved_nodes(const char * path)1025 static bool mem_region_parse_reserved_nodes(const char *path)
1026 {
1027 	struct dt_node *parent, *node;
1028 
1029 	parent = dt_find_by_path(dt_root, path);
1030 	if (!parent)
1031 		return false;
1032 
1033 	prlog(PR_INFO, "MEM: parsing reserved memory from node %s\n", path);
1034 
1035 	dt_for_each_child(parent, node) {
1036 		const struct dt_property *reg;
1037 		struct mem_region *region;
1038 		int type;
1039 
1040 		reg = dt_find_property(node, "reg");
1041 		if (!reg) {
1042 			char *nodepath = dt_get_path(node);
1043 			prerror("node %s has no reg property, ignoring\n",
1044 					nodepath);
1045 			free(nodepath);
1046 			continue;
1047 		}
1048 
1049 		if (dt_has_node_property(node, "no-map", NULL))
1050 			type = REGION_RESERVED;
1051 		else
1052 			type = REGION_FW_RESERVED;
1053 
1054 		region = new_region(strdup(node->name),
1055 				dt_get_number(reg->prop, 2),
1056 				dt_get_number(reg->prop + sizeof(u64), 2),
1057 				node, type);
1058 		if (!add_region(region)) {
1059 			char *nodepath = dt_get_path(node);
1060 			prerror("node %s failed to add_region()\n", nodepath);
1061 			free(nodepath);
1062 		}
1063 	}
1064 
1065 	return true;
1066 }
1067 
1068 /* Trawl through device tree, create memory regions from nodes. */
mem_region_init(void)1069 void mem_region_init(void)
1070 {
1071 	struct mem_region *region, *next;
1072 	struct dt_node *i;
1073 	bool rc;
1074 
1075 	/*
1076 	 * Add associativity properties outside of the lock
1077 	 * to avoid recursive locking caused by allocations
1078 	 * done by add_chip_dev_associativity()
1079 	 */
1080 	dt_for_each_node(dt_root, i) {
1081 		if (!dt_has_node_property(i, "device_type", "memory") &&
1082 		    !dt_has_node_property(i, "compatible", "pmem-region"))
1083 			continue;
1084 
1085 		/* Add associativity properties */
1086 		add_chip_dev_associativity(i);
1087 	}
1088 
1089 	/* Add each memory node. */
1090 	dt_for_each_node(dt_root, i) {
1091 		uint64_t start, len;
1092 		char *rname;
1093 #define NODE_REGION_PREFIX 	"ibm,firmware-allocs-"
1094 
1095 		if (!dt_has_node_property(i, "device_type", "memory"))
1096 			continue;
1097 		rname = zalloc(strlen(i->name) + strlen(NODE_REGION_PREFIX) + 1);
1098 		assert(rname);
1099 		strcat(rname, NODE_REGION_PREFIX);
1100 		strcat(rname, i->name);
1101 		start = dt_get_address(i, 0, &len);
1102 		lock(&mem_region_lock);
1103 		region = new_region(rname, start, len, i, REGION_MEMORY);
1104 		if (!region) {
1105 			prerror("MEM: Could not add mem region %s!\n", i->name);
1106 			abort();
1107 		}
1108 		add_region_to_regions(region);
1109 		if ((start + len) > top_of_ram)
1110 			top_of_ram = start + len;
1111 		unlock(&mem_region_lock);
1112 	}
1113 
1114 	/*
1115 	 * This is called after we know the maximum PIR of all CPUs,
1116 	 * so we can dynamically set the stack length.
1117 	 */
1118 	skiboot_cpu_stacks.len = (cpu_max_pir + 1) * STACK_SIZE;
1119 
1120 	lock(&mem_region_lock);
1121 
1122 	/* Now carve out our own reserved areas. */
1123 	if (!add_region(&skiboot_os_reserve) ||
1124 	    !add_region(&skiboot_code_and_text) ||
1125 	    !add_region(&skiboot_heap) ||
1126 	    !add_region(&skiboot_after_heap) ||
1127 	    !add_region(&skiboot_cpu_stacks)) {
1128 		prerror("Out of memory adding skiboot reserved areas\n");
1129 		abort();
1130 	}
1131 
1132 	if (chip_quirk(QUIRK_MAMBO_CALLOUTS)) {
1133 		if (!add_region(&skiboot_mambo_kernel) ||
1134 		    !add_region(&skiboot_mambo_initramfs)) {
1135 			prerror("Out of memory adding mambo payload\n");
1136 			abort();
1137 		}
1138 	}
1139 
1140 	/* Add reserved reanges from HDAT */
1141 	list_for_each_safe(&early_reserves, region, next, list) {
1142 		bool added;
1143 
1144 		list_del(&region->list);
1145 		added = add_region(region);
1146 		assert(added);
1147 	}
1148 
1149 	/* Add reserved ranges from the DT */
1150 	rc = mem_region_parse_reserved_nodes("/reserved-memory");
1151 	if (!rc)
1152 		rc = mem_region_parse_reserved_nodes(
1153 				"/ibm,hostboot/reserved-memory");
1154 	if (!rc)
1155 		mem_region_parse_reserved_properties();
1156 
1157 	mem_region_init_done = true;
1158 	unlock(&mem_region_lock);
1159 }
1160 
allocated_length(const struct mem_region * r)1161 static uint64_t allocated_length(const struct mem_region *r)
1162 {
1163 	struct free_hdr *f, *last = NULL;
1164 
1165 	/* No allocations at all? */
1166 	if (r->free_list.n.next == NULL)
1167 		return 0;
1168 
1169 	/* Find last free block. */
1170 	list_for_each(&r->free_list, f, list)
1171 		if (f > last)
1172 			last = f;
1173 
1174 	/* No free blocks? */
1175 	if (!last)
1176 		return r->len;
1177 
1178 	/* Last free block isn't at end? */
1179 	if (next_hdr(r, &last->hdr))
1180 		return r->len;
1181 	return (unsigned long)last - r->start;
1182 }
1183 
1184 /* Separate out allocated sections into their own region. */
mem_region_release_unused(void)1185 void mem_region_release_unused(void)
1186 {
1187 	struct mem_region *r;
1188 
1189 	lock(&mem_region_lock);
1190 	assert(!mem_regions_finalised);
1191 
1192 	prlog(PR_INFO, "Releasing unused memory:\n");
1193 	list_for_each(&regions, r, list) {
1194 		uint64_t used_len;
1195 
1196 		/* If it's not allocatable, ignore it. */
1197 		if (!(r->type == REGION_SKIBOOT_HEAP ||
1198 		      r->type == REGION_MEMORY))
1199 			continue;
1200 
1201 		used_len = allocated_length(r);
1202 
1203 		prlog(PR_INFO, "    %s: %llu/%llu used\n",
1204 		       r->name, (long long)used_len, (long long)r->len);
1205 
1206 		/* We keep the skiboot heap. */
1207 		if (r == &skiboot_heap)
1208 			continue;
1209 
1210 		/* Nothing used?  Whole thing is for Linux. */
1211 		if (used_len == 0)
1212 			r->type = REGION_OS;
1213 		/* Partially used?  Split region. */
1214 		else if (used_len != r->len) {
1215 			struct mem_region *for_linux;
1216 			struct free_hdr *last = region_start(r) + used_len;
1217 
1218 			/* Remove the final free block. */
1219 			list_del_from(&r->free_list, &last->list);
1220 
1221 			for_linux = split_region(r, r->start + used_len,
1222 						 REGION_OS);
1223 			if (!for_linux) {
1224 				prerror("OOM splitting mem node %s for linux\n",
1225 					r->name);
1226 				abort();
1227 			}
1228 			list_add(&regions, &for_linux->list);
1229 		}
1230 	}
1231 	unlock(&mem_region_lock);
1232 }
1233 
mem_clear_range(uint64_t s,uint64_t e)1234 static void mem_clear_range(uint64_t s, uint64_t e)
1235 {
1236 	uint64_t res_start, res_end;
1237 
1238 	/* Skip exception vectors */
1239 	if (s < EXCEPTION_VECTORS_END)
1240 		s = EXCEPTION_VECTORS_END;
1241 
1242 	/* Skip kernel preload area */
1243 	res_start = (uint64_t)KERNEL_LOAD_BASE;
1244 	res_end = res_start + KERNEL_LOAD_SIZE;
1245 
1246 	if (s >= res_start && s < res_end)
1247 	       s = res_end;
1248 	if (e > res_start && e <= res_end)
1249 	       e = res_start;
1250 	if (e <= s)
1251 		return;
1252 	if (s < res_start && e > res_end) {
1253 		mem_clear_range(s, res_start);
1254 		mem_clear_range(res_end, e);
1255 		return;
1256 	}
1257 
1258 	/* Skip initramfs preload area */
1259 	res_start = (uint64_t)INITRAMFS_LOAD_BASE;
1260 	res_end = res_start + INITRAMFS_LOAD_SIZE;
1261 
1262 	if (s >= res_start && s < res_end)
1263 	       s = res_end;
1264 	if (e > res_start && e <= res_end)
1265 	       e = res_start;
1266 	if (e <= s)
1267 		return;
1268 	if (s < res_start && e > res_end) {
1269 		mem_clear_range(s, res_start);
1270 		mem_clear_range(res_end, e);
1271 		return;
1272 	}
1273 
1274 	prlog(PR_DEBUG, "Clearing region %llx-%llx\n",
1275 	      (long long)s, (long long)e);
1276 	memset((void *)s, 0, e - s);
1277 }
1278 
1279 struct mem_region_clear_job_args {
1280 	char *job_name;
1281 	uint64_t s,e;
1282 };
1283 
mem_region_clear_job(void * data)1284 static void mem_region_clear_job(void *data)
1285 {
1286 	struct mem_region_clear_job_args *arg = (struct mem_region_clear_job_args*)data;
1287 	mem_clear_range(arg->s, arg->e);
1288 }
1289 
1290 #define MEM_REGION_CLEAR_JOB_SIZE (16ULL*(1<<30))
1291 
1292 static struct cpu_job **mem_clear_jobs;
1293 static struct mem_region_clear_job_args *mem_clear_job_args;
1294 static int mem_clear_njobs = 0;
1295 
start_mem_region_clear_unused(void)1296 void start_mem_region_clear_unused(void)
1297 {
1298 	struct mem_region *r;
1299 	uint64_t s,l;
1300 	uint64_t total = 0;
1301 	uint32_t chip_id;
1302 	char *path;
1303 	int i;
1304 	struct cpu_job **jobs;
1305 	struct mem_region_clear_job_args *job_args;
1306 
1307 	lock(&mem_region_lock);
1308 	assert(mem_regions_finalised);
1309 
1310 	mem_clear_njobs = 0;
1311 
1312 	list_for_each(&regions, r, list) {
1313 		if (!(r->type == REGION_OS))
1314 			continue;
1315 		mem_clear_njobs++;
1316 		/* One job per 16GB */
1317 		mem_clear_njobs += r->len / MEM_REGION_CLEAR_JOB_SIZE;
1318 	}
1319 
1320 	jobs = malloc(mem_clear_njobs * sizeof(struct cpu_job*));
1321 	job_args = malloc(mem_clear_njobs * sizeof(struct mem_region_clear_job_args));
1322 	mem_clear_jobs = jobs;
1323 	mem_clear_job_args = job_args;
1324 
1325 	prlog(PR_NOTICE, "Clearing unused memory:\n");
1326 	i = 0;
1327 	list_for_each(&regions, r, list) {
1328 		/* If it's not unused, ignore it. */
1329 		if (!(r->type == REGION_OS))
1330 			continue;
1331 
1332 		assert(r != &skiboot_heap);
1333 
1334 		s = r->start;
1335 		l = r->len;
1336 		while(l > MEM_REGION_CLEAR_JOB_SIZE) {
1337 			job_args[i].s = s+l - MEM_REGION_CLEAR_JOB_SIZE;
1338 			job_args[i].e = s+l;
1339 			l-=MEM_REGION_CLEAR_JOB_SIZE;
1340 			job_args[i].job_name = malloc(sizeof(char)*100);
1341 			total+=MEM_REGION_CLEAR_JOB_SIZE;
1342 			chip_id = __dt_get_chip_id(r->node);
1343 			if (chip_id == -1)
1344 				chip_id = 0;
1345 			path = dt_get_path(r->node);
1346 			snprintf(job_args[i].job_name, 100,
1347 				 "clear %s, %s 0x%"PRIx64" len: %"PRIx64" on %d",
1348 				 r->name, path,
1349 				 job_args[i].s,
1350 				 (job_args[i].e - job_args[i].s),
1351 				 chip_id);
1352 			free(path);
1353 			jobs[i] = cpu_queue_job_on_node(chip_id,
1354 							job_args[i].job_name,
1355 							mem_region_clear_job,
1356 							&job_args[i]);
1357 			if (!jobs[i])
1358 				jobs[i] = cpu_queue_job(NULL,
1359 							job_args[i].job_name,
1360 							mem_region_clear_job,
1361 							&job_args[i]);
1362 			assert(jobs[i]);
1363 			i++;
1364 		}
1365 		job_args[i].s = s;
1366 		job_args[i].e = s+l;
1367 		job_args[i].job_name = malloc(sizeof(char)*100);
1368 		total+=l;
1369 		chip_id = __dt_get_chip_id(r->node);
1370 		if (chip_id == -1)
1371 			chip_id = 0;
1372 		path = dt_get_path(r->node);
1373 		snprintf(job_args[i].job_name,100,
1374 			 "clear %s, %s 0x%"PRIx64" len: 0x%"PRIx64" on %d",
1375 			 r->name, path,
1376 			 job_args[i].s,
1377 			 (job_args[i].e - job_args[i].s),
1378 			 chip_id);
1379 		free(path);
1380 		jobs[i] = cpu_queue_job_on_node(chip_id,
1381 						job_args[i].job_name,
1382 						mem_region_clear_job,
1383 						&job_args[i]);
1384 		if (!jobs[i])
1385 			jobs[i] = cpu_queue_job(NULL,
1386 						job_args[i].job_name,
1387 						mem_region_clear_job,
1388 						&job_args[i]);
1389 		assert(jobs[i]);
1390 		i++;
1391 	}
1392 	unlock(&mem_region_lock);
1393 	cpu_process_local_jobs();
1394 }
1395 
wait_mem_region_clear_unused(void)1396 void wait_mem_region_clear_unused(void)
1397 {
1398 	uint64_t l;
1399 	uint64_t total = 0;
1400 	int i;
1401 
1402 	for(i=0; i < mem_clear_njobs; i++) {
1403 		total += (mem_clear_job_args[i].e - mem_clear_job_args[i].s);
1404 	}
1405 
1406 	l = 0;
1407 	for(i=0; i < mem_clear_njobs; i++) {
1408 		cpu_wait_job(mem_clear_jobs[i], true);
1409 		l += (mem_clear_job_args[i].e - mem_clear_job_args[i].s);
1410 		printf("Clearing memory... %"PRIu64"/%"PRIu64"GB done\n",
1411 		       l>>30, total>>30);
1412 		free(mem_clear_job_args[i].job_name);
1413 	}
1414 	free(mem_clear_jobs);
1415 	free(mem_clear_job_args);
1416 }
1417 
mem_region_add_dt_reserved_node(struct dt_node * parent,struct mem_region * region)1418 static void mem_region_add_dt_reserved_node(struct dt_node *parent,
1419 		struct mem_region *region)
1420 {
1421 	char *name, *p;
1422 
1423 	/* If a reserved region was established before skiboot, it may be
1424 	 * referenced by a device-tree node with extra data. In that case,
1425 	 * copy the node to /reserved-memory/, unless it's already there.
1426 	 *
1427 	 * We update region->node to the new copy here, as the prd code may
1428 	 * update regions' device-tree nodes, and we want those updates to
1429 	 * apply to the nodes in /reserved-memory/.
1430 	 */
1431 	if (region->type == REGION_FW_RESERVED && region->node) {
1432 		if (region->node->parent != parent)
1433 			region->node = dt_copy(region->node, parent);
1434 		return;
1435 	}
1436 
1437 	name = strdup(region->name);
1438 	assert(name);
1439 
1440 	/* remove any cell addresses in the region name; we have our own cell
1441 	 * addresses here */
1442 	p = strchr(name, '@');
1443 	if (p)
1444 		*p = '\0';
1445 
1446 	region->node = dt_new_addr(parent, name, region->start);
1447 	assert(region->node);
1448 	dt_add_property_u64s(region->node, "reg", region->start, region->len);
1449 
1450 	/*
1451 	 * This memory is used by hardware and may need special handling. Ask
1452 	 * the host kernel not to map it by default.
1453 	 */
1454 	if (region->type == REGION_RESERVED)
1455 		dt_add_property(region->node, "no-map", NULL, 0);
1456 
1457 	free(name);
1458 }
1459 
mem_region_add_dt_reserved(void)1460 void mem_region_add_dt_reserved(void)
1461 {
1462 	int names_len, ranges_len, len;
1463 	const struct dt_property *prop;
1464 	struct mem_region *region;
1465 	void *names, *ranges;
1466 	struct dt_node *node;
1467 	fdt64_t *range;
1468 	char *name;
1469 
1470 	names_len = 0;
1471 	ranges_len = 0;
1472 
1473 	/* Finalise the region list, so we know that the regions list won't be
1474 	 * altered after this point. The regions' free lists may change after
1475 	 * we drop the lock, but we don't access those. */
1476 	lock(&mem_region_lock);
1477 	mem_regions_finalised = true;
1478 
1479 	/* establish top-level reservation node */
1480 	node = dt_find_by_path(dt_root, "reserved-memory");
1481 	if (!node) {
1482 		node = dt_new(dt_root, "reserved-memory");
1483 		dt_add_property_cells(node, "#address-cells", 2);
1484 		dt_add_property_cells(node, "#size-cells", 2);
1485 		dt_add_property(node, "ranges", NULL, 0);
1486 	}
1487 
1488 	prlog(PR_INFO, "Reserved regions:\n");
1489 
1490 	/* First pass, create /reserved-memory/ nodes for each reservation,
1491 	 * and calculate the length for the /reserved-names and
1492 	 * /reserved-ranges properties */
1493 	list_for_each(&regions, region, list) {
1494 		if (!region_is_reservable(region))
1495 			continue;
1496 
1497 		prlog(PR_INFO, "  0x%012llx..%012llx : %s\n",
1498 		       (long long)region->start,
1499 		       (long long)(region->start + region->len - 1),
1500 		       region->name);
1501 
1502 		mem_region_add_dt_reserved_node(node, region);
1503 
1504 		/* calculate the size of the properties populated later */
1505 		names_len += strlen(region->node->name) + 1;
1506 		ranges_len += 2 * sizeof(uint64_t);
1507 	}
1508 
1509 	name = names = malloc(names_len);
1510 	range = ranges = malloc(ranges_len);
1511 
1512 	/* Second pass: populate the old-style reserved-names and
1513 	 * reserved-regions arrays based on the node data */
1514 	list_for_each(&regions, region, list) {
1515 		if (!region_is_reservable(region))
1516 			continue;
1517 
1518 		len = strlen(region->node->name) + 1;
1519 		memcpy(name, region->node->name, len);
1520 		name += len;
1521 
1522 		range[0] = cpu_to_fdt64(region->start);
1523 		range[1] = cpu_to_fdt64(region->len);
1524 		range += 2;
1525 	}
1526 	unlock(&mem_region_lock);
1527 
1528 	prop = dt_find_property(dt_root, "reserved-names");
1529 	if (prop)
1530 		dt_del_property(dt_root, (struct dt_property *)prop);
1531 
1532 	prop = dt_find_property(dt_root, "reserved-ranges");
1533 	if (prop)
1534 		dt_del_property(dt_root, (struct dt_property *)prop);
1535 
1536 	dt_add_property(dt_root, "reserved-names", names, names_len);
1537 	dt_add_property(dt_root, "reserved-ranges", ranges, ranges_len);
1538 
1539 	free(names);
1540 	free(ranges);
1541 }
1542 
mem_region_next(struct mem_region * region)1543 struct mem_region *mem_region_next(struct mem_region *region)
1544 {
1545 	struct list_node *node;
1546 
1547 	assert(lock_held_by_me(&mem_region_lock));
1548 
1549 	node = region ? &region->list : &regions.n;
1550 
1551 	if (node->next == &regions.n)
1552 		return NULL;
1553 
1554 	return list_entry(node->next, struct mem_region, list);
1555 }
1556