Lines Matching +full:memory +full:- +full:to +full:- +full:memory
1 // SPDX-License-Identifier: GPL-2.0-only
3 * powerpc code to implement the kexec_file_load syscall
12 * Based on kexec-tools' kexec-ppc64.c, fs2dt.c.
27 #include <asm/crashdump-ppc64.h>
31 * get_max_nr_ranges - Get the max no. of ranges crash_mem structure
39 return ((size - sizeof(struct crash_mem)) / in get_max_nr_ranges()
44 * get_mem_rngs_size - Get the allocated size of mem_rngs based on
46 * @mem_rngs: Memory ranges.
58 (mem_rngs->max_nr_ranges * sizeof(struct range))); in get_mem_rngs_size()
61 * Memory is allocated in size multiple of MEM_RANGE_CHUNK_SZ. in get_mem_rngs_size()
62 * So, align to get the actual length. in get_mem_rngs_size()
68 * __add_mem_range - add a memory range to memory ranges list.
69 * @mem_ranges: Range list to add the memory range to.
70 * @base: Base address of the range to add.
71 * @size: Size of the memory range to add.
73 * (Re)allocates memory, if needed.
81 if (!mem_rngs || (mem_rngs->nr_ranges == mem_rngs->max_nr_ranges)) { in __add_mem_range()
84 return -ENOMEM; in __add_mem_range()
87 mem_rngs->ranges[mem_rngs->nr_ranges].start = base; in __add_mem_range()
88 mem_rngs->ranges[mem_rngs->nr_ranges].end = base + size - 1; in __add_mem_range()
89 pr_debug("Added memory range [%#016llx - %#016llx] at index %d\n", in __add_mem_range()
90 base, base + size - 1, mem_rngs->nr_ranges); in __add_mem_range()
91 mem_rngs->nr_ranges++; in __add_mem_range()
96 * __merge_memory_ranges - Merges the given memory ranges list.
97 * @mem_rngs: Range list to merge.
112 ranges = &(mem_rngs->ranges[0]); in __merge_memory_ranges()
113 for (i = 1; i < mem_rngs->nr_ranges; i++) { in __merge_memory_ranges()
114 if (ranges[i].start <= (ranges[i-1].end + 1)) in __merge_memory_ranges()
124 mem_rngs->nr_ranges = idx + 1; in __merge_memory_ranges()
127 /* cmp_func_t callback to sort ranges with sort() */
132 if (x->start > y->start) in rngcmp()
134 if (x->start < y->start) in rngcmp()
135 return -1; in rngcmp()
140 * sort_memory_ranges - Sorts the given memory ranges list.
141 * @mem_rngs: Range list to sort.
153 /* Sort the ranges in-place */ in sort_memory_ranges()
154 sort(&(mem_rngs->ranges[0]), mem_rngs->nr_ranges, in sort_memory_ranges()
155 sizeof(mem_rngs->ranges[0]), rngcmp, NULL); in sort_memory_ranges()
161 pr_debug("Memory ranges:\n"); in sort_memory_ranges()
162 for (i = 0; i < mem_rngs->nr_ranges; i++) { in sort_memory_ranges()
163 pr_debug("\t[%03d][%#016llx - %#016llx]\n", i, in sort_memory_ranges()
164 mem_rngs->ranges[i].start, in sort_memory_ranges()
165 mem_rngs->ranges[i].end); in sort_memory_ranges()
170 * realloc_mem_ranges - reallocate mem_ranges with size incremented
171 * by MEM_RANGE_CHUNK_SZ. Frees up the old memory,
172 * if memory allocation fails.
173 * @mem_ranges: Memory ranges to reallocate.
175 * Returns pointer to reallocated memory on success, NULL otherwise.
184 nr_ranges = mem_rngs ? mem_rngs->nr_ranges : 0; in realloc_mem_ranges()
194 mem_rngs->nr_ranges = nr_ranges; in realloc_mem_ranges()
195 mem_rngs->max_nr_ranges = get_max_nr_ranges(size); in realloc_mem_ranges()
202 * add_mem_range - Updates existing memory range, if there is an overlap.
203 * Else, adds a new memory range.
204 * @mem_ranges: Range list to add the memory range to.
205 * @base: Base address of the range to add.
206 * @size: Size of the memory range to add.
208 * (Re)allocates memory, if needed.
221 end = base + size - 1; in add_mem_range()
223 if (!mem_rngs || !(mem_rngs->nr_ranges)) in add_mem_range()
226 for (i = 0; i < mem_rngs->nr_ranges; i++) { in add_mem_range()
227 mstart = mem_rngs->ranges[i].start; in add_mem_range()
228 mend = mem_rngs->ranges[i].end; in add_mem_range()
231 mem_rngs->ranges[i].start = base; in add_mem_range()
233 mem_rngs->ranges[i].end = end; in add_mem_range()
245 * add_tce_mem_ranges - Adds tce-table range to the given memory ranges list.
246 * @mem_ranges: Range list to add the memory range(s) to.
259 ret = of_property_read_u64(dn, "linux,tce-base", &base); in add_tce_mem_ranges()
260 ret |= of_property_read_u32(dn, "linux,tce-size", &size); in add_tce_mem_ranges()
263 * It is ok to have pci nodes without tce. So, ignore in add_tce_mem_ranges()
266 if (ret == -EINVAL) { in add_tce_mem_ranges()
283 * add_initrd_mem_range - Adds initrd range to the given memory ranges list,
285 * @mem_ranges: Range list to add the memory range to.
298 ret = of_property_read_u64(of_chosen, "linux,initrd-start", &base); in add_initrd_mem_range()
299 ret |= of_property_read_u64(of_chosen, "linux,initrd-end", &end); in add_initrd_mem_range()
301 ret = add_mem_range(mem_ranges, base, end - base + 1); in add_initrd_mem_range()
307 * add_htab_mem_range - Adds htab range to the given memory ranges list,
309 * @mem_ranges: Range list to add the memory range to.
327 * add_kernel_mem_range - Adds kernel text region to the given
328 * memory ranges list.
329 * @mem_ranges: Range list to add the memory range to.
341 * add_rtas_mem_range - Adds RTAS region to the given memory ranges list.
342 * @mem_ranges: Range list to add the memory range to.
356 ret = of_property_read_u32(dn, "linux,rtas-base", &base); in add_rtas_mem_range()
357 ret |= of_property_read_u32(dn, "rtas-size", &size); in add_rtas_mem_range()
366 * add_opal_mem_range - Adds OPAL region to the given memory ranges list.
367 * @mem_ranges: Range list to add the memory range to.
381 ret = of_property_read_u64(dn, "opal-base-address", &base); in add_opal_mem_range()
382 ret |= of_property_read_u64(dn, "opal-runtime-size", &size); in add_opal_mem_range()
393 * add_reserved_mem_ranges - Adds "/reserved-ranges" regions exported by f/w
394 * to the given memory ranges list.
395 * @mem_ranges: Range list to add the memory ranges to.
405 prop = of_get_property(root, "reserved-ranges", &len); in add_reserved_mem_ranges()
431 * get_reserved_memory_ranges - Get reserve memory ranges. This list includes
432 * memory regions that should be added to the
433 * memory reserve map to ensure the region is
435 * @mem_ranges: Range list to add the memory ranges to.
454 pr_err("Failed to setup reserved memory ranges\n"); in get_reserved_memory_ranges()
459 * get_exclude_memory_ranges - Get exclude memory ranges. This list includes
460 * regions like opal/rtas, tce-table, initrd,
463 * @mem_ranges: Range list to add the memory ranges to.
499 /* exclude memory ranges should be sorted for easy lookup */ in get_exclude_memory_ranges()
503 pr_err("Failed to setup exclude memory ranges\n"); in get_exclude_memory_ranges()
509 * get_usable_memory_ranges - Get usable memory ranges. This list includes
510 * regions like crashkernel, opal/rtas & tce-table,
512 * @mem_ranges: Range list to add the memory ranges to.
521 * Early boot failure observed on guests when low memory (first memory in get_usable_memory_ranges()
522 * block?) is not added to usable memory. So, add [0, crashk_res.end] in get_usable_memory_ranges()
523 * instead of [crashk_res.start, crashk_res.end] to workaround it. in get_usable_memory_ranges()
524 * Also, crashed kernel's memory must be added to reserve map to in get_usable_memory_ranges()
542 pr_err("Failed to setup usable memory ranges\n"); in get_usable_memory_ranges()
550 * get_crash_memory_ranges - Get crash memory ranges. This list includes
551 * first/crashing kernel's memory regions that
553 * @mem_ranges: Range list to add the memory ranges to.
565 u64 size = end - base; in get_crash_memory_ranges()
567 /* Skip backup memory region, which needs a separate entry */ in get_crash_memory_ranges()
571 size -= BACKUP_SRC_SIZE; in get_crash_memory_ranges()
581 if ((*mem_ranges)->nr_ranges == (*mem_ranges)->max_nr_ranges) in get_crash_memory_ranges()
585 /* Reallocate memory ranges if there is no space to split ranges */ in get_crash_memory_ranges()
587 if (tmem && (tmem->nr_ranges == tmem->max_nr_ranges)) { in get_crash_memory_ranges()
599 * FIXME: For now, stay in parity with kexec-tools but if RTAS/OPAL in get_crash_memory_ranges()
600 * regions are exported to save their context at the time of in get_crash_memory_ranges()
602 * first 64K bytes of memory. in get_crash_memory_ranges()
620 pr_err("Failed to setup crash memory ranges\n"); in get_crash_memory_ranges()
625 * remove_mem_range - Removes the given memory range from the range list.
626 * @mem_ranges: Range list to remove the memory range to.
627 * @base: Base address of the range to remove.
628 * @size: Size of the memory range to remove.
630 * (Re)allocates memory, if needed.
646 * Memory range are stored as start and end address, use in remove_mem_range()
647 * the same format to do remove operation. in remove_mem_range()
649 end = base + size - 1; in remove_mem_range()
651 for (i = 0; i < mem_rngs->nr_ranges; i++) { in remove_mem_range()
652 mstart = mem_rngs->ranges[i].start; in remove_mem_range()
653 mend = mem_rngs->ranges[i].end; in remove_mem_range()
656 * Memory range to remove is not part of this range entry in remove_mem_range()
657 * in the memory range list in remove_mem_range()
663 * Memory range to remove is equivalent to this entry in the in remove_mem_range()
664 * memory range list. Remove the range entry from the list. in remove_mem_range()
667 for (; i < mem_rngs->nr_ranges - 1; i++) { in remove_mem_range()
668 mem_rngs->ranges[i].start = mem_rngs->ranges[i+1].start; in remove_mem_range()
669 mem_rngs->ranges[i].end = mem_rngs->ranges[i+1].end; in remove_mem_range()
671 mem_rngs->nr_ranges--; in remove_mem_range()
675 * Start address of the memory range to remove and the in remove_mem_range()
676 * current memory range entry in the list is same. Just in remove_mem_range()
677 * move the start address of the current memory range in remove_mem_range()
678 * entry in the list to end + 1. in remove_mem_range()
681 mem_rngs->ranges[i].start = end + 1; in remove_mem_range()
685 * End address of the memory range to remove and the in remove_mem_range()
686 * current memory range entry in the list is same. in remove_mem_range()
687 * Just move the end address of the current memory in remove_mem_range()
688 * range entry in the list to base - 1. in remove_mem_range()
691 mem_rngs->ranges[i].end = base - 1; in remove_mem_range()
695 * Memory range to remove is not at the edge of current in remove_mem_range()
696 * memory range entry. Split the current memory entry into in remove_mem_range()
700 mem_rngs->ranges[i].end = base - 1; in remove_mem_range()
701 size = mem_rngs->ranges[i].end - end; in remove_mem_range()