Lines Matching +full:reserved +full:- +full:memory
1 // SPDX-License-Identifier: GPL-2.0-or-later
6 * memory contents. The most of the code implementation has been adapted
32 #include <asm/fadump-internal.h>
56 #define RESERVED_RNGS_SZ 16384 /* 16K - 128 entries */
60 struct fadump_mrange_info reserved_mrange_info = { "reserved", rngs,
70 * fadump_cma_init() - Initialize CMA area from a fadump reserved memory
72 * This function initializes CMA area from fadump reserved memory.
73 * The total size of fadump reserved memory covers for boot memory size
75 * Initialize only the area equivalent to boot memory size for CMA use.
76 * The reamining portion of fadump reserved memory will be not given
77 * to CMA and pages for thoes will stay reserved. boot memory size is
79 * But for some reason even if it fails we still have the memory reservation
105 pr_err("Failed to init cma area for firmware-assisted dump,%d\n", rc); in fadump_cma_init()
107 * Though the CMA init has failed we still have memory in fadump_cma_init()
108 * reservation with us. The reserved memory will be in fadump_cma_init()
119 "bytes of memory reserved for firmware-assisted dump\n", in fadump_cma_init()
155 * If fadump is registered, check if the memory provided
156 * falls within boot memory area and reserved memory area.
189 * Returns true, if there are no holes in memory area between d_start to d_end,
202 /* Memory hole from d_start to start */ in is_fadump_mem_area_contiguous()
219 * Returns true, if there are no holes in boot memory area,
241 * Returns true, if there are no holes in reserved memory area,
258 pr_debug("Support for firmware-assisted dump (fadump): %s\n", in fadump_show_config()
271 pr_debug(" Boot memory size : %lx\n", fw_dump.boot_memory_size); in fadump_show_config()
272 pr_debug(" Boot memory top : %llx\n", fw_dump.boot_mem_top); in fadump_show_config()
273 pr_debug("Boot memory regions cnt: %llx\n", fw_dump.boot_mem_regs_cnt); in fadump_show_config()
283 * Function to find the largest memory size we need to reserve during early
284 * boot process. This will be the size of the memory that is required for a
287 * This function has been taken from phyp-assisted dump feature implementation.
291 * TODO: Come up with better approach to find out more accurate memory size
306 * memory at a predefined offset. in fadump_calculate_reserve_size()
314 pr_info("Using 'crashkernel=' parameter for memory reservation.\n"); in fadump_calculate_reserve_size()
319 * Adjust if the boot memory size specified is above in fadump_calculate_reserve_size()
325 pr_info("Adjusted boot memory size to %luMB\n", in fadump_calculate_reserve_size()
332 * 'fadump_reserve_mem=' is being used to reserve memory in fadump_calculate_reserve_size()
333 * for firmware-assisted dump. in fadump_calculate_reserve_size()
344 /* Truncate to memory_limit. We don't want to over reserve the memory.*/ in fadump_calculate_reserve_size()
348 bootmem_min = fw_dump.ops->fadump_get_bootmem_min(); in fadump_calculate_reserve_size()
353 * Calculate the total memory size required to be reserved for
354 * firmware-assisted dump registration.
366 /* Program headers for crash memory regions. */ in get_fadump_area_size()
367 size += sizeof(struct elf_phdr) * (memblock_num_regions(memory) + 2); in get_fadump_area_size()
372 size += (fw_dump.ops->fadump_get_metadata_size ? in get_fadump_area_size()
373 fw_dump.ops->fadump_get_metadata_size() : 0); in get_fadump_area_size()
387 pr_debug("Added boot memory range[%d] [%#016lx-%#016lx)\n", in add_boot_mem_region()
396 * Honour that by splitting a memory range into multiple regions.
416 msize -= rsize; in add_boot_mem_regions()
437 size = reg_end - reg_start; in fadump_get_boot_mem_regions()
438 hole_size += (reg_start - last_end); in fadump_get_boot_mem_regions()
441 size = (mem_size - cur_size); in fadump_get_boot_mem_regions()
446 mem_size -= size; in fadump_get_boot_mem_regions()
460 * Returns true, if the given range overlaps with reserved memory ranges
461 * starting at idx. Also, updates idx to index of overlapping memory range
462 * with the given memory range.
488 * Locate a suitable memory area to reserve memory for FADump. While at it,
489 * lookup reserved-ranges & avoid overlap with them, as they are used by F/W.
507 while ((mend > base) && ((mend - base) >= size)) { in fadump_locate_reserve_mem()
531 pr_info("Firmware-Assisted Dump is not supported on this hardware\n"); in fadump_reserve_mem()
536 * Initialize boot memory size in fadump_reserve_mem()
551 bootmem_min = fw_dump.ops->fadump_get_bootmem_min(); in fadump_reserve_mem()
553 pr_err("Can't enable fadump with boot memory size (0x%lx) less than 0x%llx\n", in fadump_reserve_mem()
559 pr_err("Too many holes in boot memory area to enable fadump\n"); in fadump_reserve_mem()
565 * Calculate the memory boundary. in fadump_reserve_mem()
566 * If memory_limit is less than actual memory boundary then reserve in fadump_reserve_mem()
567 * the memory for fadump beyond the memory_limit and adjust the in fadump_reserve_mem()
577 printk(KERN_INFO "Adjusted memory_limit for firmware-assisted" in fadump_reserve_mem()
589 pr_info("Firmware-assisted dump is active.\n"); in fadump_reserve_mem()
600 * If last boot has crashed then reserve all the memory in fadump_reserve_mem()
601 * above boot memory size so that we don't touch it until in fadump_reserve_mem()
602 * dump is written to disk by userspace tool. This memory in fadump_reserve_mem()
612 * Reserve memory at an offset closer to bottom of the RAM to in fadump_reserve_mem()
613 * minimize the impact of memory hot-remove operation. in fadump_reserve_mem()
618 pr_err("Failed to find memory chunk for reservation!\n"); in fadump_reserve_mem()
627 if (fw_dump.ops->fadump_setup_metadata && in fadump_reserve_mem()
628 (fw_dump.ops->fadump_setup_metadata(&fw_dump) < 0)) in fadump_reserve_mem()
632 pr_err("Failed to reserve memory!\n"); in fadump_reserve_mem()
636 pr_info("Reserved %lldMB of memory at %#016llx (System RAM: %lldMB)\n", in fadump_reserve_mem()
686 unsigned int ncpus = num_online_cpus() - 1; in crash_fadump()
692 * old_cpu == -1 means this is the first CPU which has come here, in crash_fadump()
695 * old_cpu != -1 means some other CPU has already on it's way in crash_fadump()
699 old_cpu = cmpxchg(&crashing_cpu, -1, this_cpu); in crash_fadump()
701 if (old_cpu != -1) { in crash_fadump()
706 * is in force. If we race with fadump un-registration this in crash_fadump()
717 fdh->crashing_cpu = crashing_cpu; in crash_fadump()
721 fdh->regs = *regs; in crash_fadump()
723 ppc_save_regs(&fdh->regs); in crash_fadump()
725 fdh->online_mask = *cpu_online_mask; in crash_fadump()
731 if (TRAP(&(fdh->regs)) == 0x100) { in crash_fadump()
733 while ((atomic_read(&cpus_in_fadump) < ncpus) && (--msecs > 0)) in crash_fadump()
737 fw_dump.ops->fadump_trigger(fdh, str); in crash_fadump()
764 if (phdr->p_type == PT_NOTE) { in fadump_update_elfcore_header()
765 phdr->p_paddr = __pa(fw_dump.cpu_notes_buf_vaddr); in fadump_update_elfcore_header()
766 phdr->p_offset = phdr->p_paddr; in fadump_update_elfcore_header()
767 phdr->p_filesz = fw_dump.cpu_notes_buf_size; in fadump_update_elfcore_header()
768 phdr->p_memsz = fw_dump.cpu_notes_buf_size; in fadump_update_elfcore_header()
792 free_reserved_area((void *)vaddr, (void *)(vaddr + size), -1, NULL); in fadump_free_buffer()
805 return -ENOMEM; in fadump_setup_cpu_notes_buf()
827 if (mrange_info->is_static) { in fadump_free_mem_ranges()
828 mrange_info->mem_range_cnt = 0; in fadump_free_mem_ranges()
832 kfree(mrange_info->mem_ranges); in fadump_free_mem_ranges()
834 (sizeof(struct fadump_mrange_info) - RNG_NAME_SZ)); in fadump_free_mem_ranges()
846 new_size = mrange_info->mem_ranges_sz + PAGE_SIZE; in fadump_alloc_mem_ranges()
847 pr_debug("Allocating %llu bytes of memory for %s memory ranges\n", in fadump_alloc_mem_ranges()
848 new_size, mrange_info->name); in fadump_alloc_mem_ranges()
850 new_array = krealloc(mrange_info->mem_ranges, new_size, GFP_KERNEL); in fadump_alloc_mem_ranges()
852 pr_err("Insufficient memory for setting up %s memory ranges\n", in fadump_alloc_mem_ranges()
853 mrange_info->name); in fadump_alloc_mem_ranges()
855 return -ENOMEM; in fadump_alloc_mem_ranges()
858 mrange_info->mem_ranges = new_array; in fadump_alloc_mem_ranges()
859 mrange_info->mem_ranges_sz = new_size; in fadump_alloc_mem_ranges()
860 mrange_info->max_mem_ranges = (new_size / in fadump_alloc_mem_ranges()
868 struct fadump_memory_range *mem_ranges = mrange_info->mem_ranges; in fadump_add_mem_range()
876 * Fold adjacent memory ranges to bring down the memory ranges/ in fadump_add_mem_range()
879 if (mrange_info->mem_range_cnt) { in fadump_add_mem_range()
880 start = mem_ranges[mrange_info->mem_range_cnt - 1].base; in fadump_add_mem_range()
881 size = mem_ranges[mrange_info->mem_range_cnt - 1].size; in fadump_add_mem_range()
888 if (mrange_info->mem_range_cnt == mrange_info->max_mem_ranges) { in fadump_add_mem_range()
891 if (mrange_info->is_static) { in fadump_add_mem_range()
892 pr_err("Reached array size limit for %s memory ranges\n", in fadump_add_mem_range()
893 mrange_info->name); in fadump_add_mem_range()
894 return -ENOSPC; in fadump_add_mem_range()
902 mem_ranges = mrange_info->mem_ranges; in fadump_add_mem_range()
906 mem_ranges[mrange_info->mem_range_cnt].base = start; in fadump_add_mem_range()
907 mrange_info->mem_range_cnt++; in fadump_add_mem_range()
910 mem_ranges[mrange_info->mem_range_cnt - 1].size = (end - start); in fadump_add_mem_range()
911 pr_debug("%s_memory_range[%d] [%#016llx-%#016llx], %#llx bytes\n", in fadump_add_mem_range()
912 mrange_info->name, (mrange_info->mem_range_cnt - 1), in fadump_add_mem_range()
913 start, end - 1, (end - start)); in fadump_add_mem_range()
953 memcpy(elf->e_ident, ELFMAG, SELFMAG); in fadump_init_elfcore_header()
954 elf->e_ident[EI_CLASS] = ELF_CLASS; in fadump_init_elfcore_header()
955 elf->e_ident[EI_DATA] = ELF_DATA; in fadump_init_elfcore_header()
956 elf->e_ident[EI_VERSION] = EV_CURRENT; in fadump_init_elfcore_header()
957 elf->e_ident[EI_OSABI] = ELF_OSABI; in fadump_init_elfcore_header()
958 memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); in fadump_init_elfcore_header()
959 elf->e_type = ET_CORE; in fadump_init_elfcore_header()
960 elf->e_machine = ELF_ARCH; in fadump_init_elfcore_header()
961 elf->e_version = EV_CURRENT; in fadump_init_elfcore_header()
962 elf->e_entry = 0; in fadump_init_elfcore_header()
963 elf->e_phoff = sizeof(struct elfhdr); in fadump_init_elfcore_header()
964 elf->e_shoff = 0; in fadump_init_elfcore_header()
966 elf->e_flags = _CALL_ELF; in fadump_init_elfcore_header()
968 elf->e_flags = 0; in fadump_init_elfcore_header()
970 elf->e_ehsize = sizeof(struct elfhdr); in fadump_init_elfcore_header()
971 elf->e_phentsize = sizeof(struct elf_phdr); in fadump_init_elfcore_header()
972 elf->e_phnum = 0; in fadump_init_elfcore_header()
973 elf->e_shentsize = 0; in fadump_init_elfcore_header()
974 elf->e_shnum = 0; in fadump_init_elfcore_header()
975 elf->e_shstrndx = 0; in fadump_init_elfcore_header()
981 * Traverse through memblock structure and setup crash memory ranges. These
989 pr_debug("Setup crash memory ranges.\n"); in fadump_setup_crash_memory_ranges()
993 * Boot memory region(s) registered with firmware are moved to in fadump_setup_crash_memory_ranges()
995 * header(s) for this memory chunk(s) with the correct offset. in fadump_setup_crash_memory_ranges()
1007 * skip the memory chunk that is already added in fadump_setup_crash_memory_ranges()
1017 /* add this range excluding the reserved dump area. */ in fadump_setup_crash_memory_ranges()
1027 * If the given physical address falls within the boot memory region then
1028 * return the relocated address that points to the dump region reserved
1029 * for saving initial boot memory contents.
1042 hole_size += (rstart - rlast); in fadump_relocate()
1045 raddr += fw_dump.boot_mem_dest_addr - hole_size; in fadump_relocate()
1076 phdr->p_type = PT_NOTE; in fadump_create_elfcore_headers()
1077 phdr->p_flags = 0; in fadump_create_elfcore_headers()
1078 phdr->p_vaddr = 0; in fadump_create_elfcore_headers()
1079 phdr->p_align = 0; in fadump_create_elfcore_headers()
1081 phdr->p_offset = 0; in fadump_create_elfcore_headers()
1082 phdr->p_paddr = 0; in fadump_create_elfcore_headers()
1083 phdr->p_filesz = 0; in fadump_create_elfcore_headers()
1084 phdr->p_memsz = 0; in fadump_create_elfcore_headers()
1086 (elf->e_phnum)++; in fadump_create_elfcore_headers()
1091 phdr->p_type = PT_NOTE; in fadump_create_elfcore_headers()
1092 phdr->p_flags = 0; in fadump_create_elfcore_headers()
1093 phdr->p_vaddr = 0; in fadump_create_elfcore_headers()
1094 phdr->p_align = 0; in fadump_create_elfcore_headers()
1096 phdr->p_paddr = fadump_relocate(paddr_vmcoreinfo_note()); in fadump_create_elfcore_headers()
1097 phdr->p_offset = phdr->p_paddr; in fadump_create_elfcore_headers()
1098 phdr->p_memsz = phdr->p_filesz = VMCOREINFO_NOTE_SIZE; in fadump_create_elfcore_headers()
1101 (elf->e_phnum)++; in fadump_create_elfcore_headers()
1117 phdr->p_type = PT_LOAD; in fadump_create_elfcore_headers()
1118 phdr->p_flags = PF_R|PF_W|PF_X; in fadump_create_elfcore_headers()
1119 phdr->p_offset = mbase; in fadump_create_elfcore_headers()
1123 * The entire real memory region will be moved by in fadump_create_elfcore_headers()
1127 phdr->p_offset = fw_dump.boot_mem_dest_addr + offset; in fadump_create_elfcore_headers()
1128 if (j < (fw_dump.boot_mem_regs_cnt - 1)) { in fadump_create_elfcore_headers()
1134 phdr->p_paddr = mbase; in fadump_create_elfcore_headers()
1135 phdr->p_vaddr = (unsigned long)__va(mbase); in fadump_create_elfcore_headers()
1136 phdr->p_filesz = msize; in fadump_create_elfcore_headers()
1137 phdr->p_memsz = msize; in fadump_create_elfcore_headers()
1138 phdr->p_align = 0; in fadump_create_elfcore_headers()
1141 (elf->e_phnum)++; in fadump_create_elfcore_headers()
1157 fdh->magic_number = FADUMP_CRASH_INFO_MAGIC; in init_fadump_header()
1158 fdh->elfcorehdr_addr = addr; in init_fadump_header()
1160 fdh->crashing_cpu = FADUMP_CPU_UNKNOWN; in init_fadump_header()
1172 * If no memory is reserved then we can not register for firmware- in register_fadump()
1176 return -ENODEV; in register_fadump()
1192 pr_debug("Registering for firmware-assisted kernel dump...\n"); in register_fadump()
1193 return fw_dump.ops->fadump_register(&fw_dump); in register_fadump()
1203 pr_debug("Invalidating firmware-assisted dump registration\n"); in fadump_cleanup()
1204 fw_dump.ops->fadump_invalidate(&fw_dump); in fadump_cleanup()
1206 /* Un-register Firmware-assisted dump if it was registered. */ in fadump_cleanup()
1207 fw_dump.ops->fadump_unregister(&fw_dump); in fadump_cleanup()
1211 if (fw_dump.ops->fadump_cleanup) in fadump_cleanup()
1212 fw_dump.ops->fadump_cleanup(&fw_dump); in fadump_cleanup()
1221 pr_info("freeing reserved memory (0x%llx - 0x%llx)\n", in fadump_free_reserved_memory()
1235 * Skip memory holes and free memory that was actually reserved.
1262 * Sort the mem ranges in-place and merge adjacent ranges
1263 * to minimize the memory ranges count.
1275 /* Sort the memory ranges */ in sort_and_merge_mem_ranges()
1276 mem_ranges = mrange_info->mem_ranges; in sort_and_merge_mem_ranges()
1277 for (i = 0; i < mrange_info->mem_range_cnt; i++) { in sort_and_merge_mem_ranges()
1279 for (j = (i + 1); j < mrange_info->mem_range_cnt; j++) { in sort_and_merge_mem_ranges()
1290 /* Merge adjacent reserved ranges */ in sort_and_merge_mem_ranges()
1292 for (i = 1; i < mrange_info->mem_range_cnt; i++) { in sort_and_merge_mem_ranges()
1293 base = mem_ranges[i-1].base; in sort_and_merge_mem_ranges()
1294 size = mem_ranges[i-1].size; in sort_and_merge_mem_ranges()
1305 mrange_info->mem_range_cnt = idx + 1; in sort_and_merge_mem_ranges()
1309 * Scan reserved-ranges to consider them while reserving/releasing
1310 * memory for FADump.
1315 int len, ret = -1; in early_init_dt_scan_reserved_ranges()
1318 /* reserved-ranges already scanned */ in early_init_dt_scan_reserved_ranges()
1322 prop = of_get_flat_dt_prop(node, "reserved-ranges", &len); in early_init_dt_scan_reserved_ranges()
1327 * Each reserved range is an (address,size) pair, 2 cells each, in early_init_dt_scan_reserved_ranges()
1340 pr_warn("some reserved ranges are ignored!\n"); in early_init_dt_scan_reserved_ranges()
1346 /* Compact reserved ranges */ in early_init_dt_scan_reserved_ranges()
1351 * Release the memory that was reserved during early boot to preserve the
1352 * crash'ed kernel's memory contents except reserved dump area (permanent
1353 * reservation) and reserved ranges used by F/W. The released memory will
1365 * If reserved ranges array limit is hit, overwrite the last reserved in fadump_release_memory()
1366 * memory range with reserved dump area to ensure it is excluded from in fadump_release_memory()
1367 * the memory being released (reused for next FADump registration). in fadump_release_memory()
1371 reserved_mrange_info.mem_range_cnt--; in fadump_release_memory()
1377 /* Get the reserved ranges list in order first. */ in fadump_release_memory()
1380 /* Exclude reserved ranges and release remaining memory */ in fadump_release_memory()
1414 * memory structure for FADump re-registration. in fadump_invalidate_release_mem()
1416 if (fw_dump.ops->fadump_setup_metadata && in fadump_invalidate_release_mem()
1417 (fw_dump.ops->fadump_setup_metadata(&fw_dump) < 0)) in fadump_invalidate_release_mem()
1419 fw_dump.ops->fadump_init_mem_struct(&fw_dump); in fadump_invalidate_release_mem()
1426 int input = -1; in release_mem_store()
1429 return -EPERM; in release_mem_store()
1432 return -EINVAL; in release_mem_store()
1437 * memory, hence it will not be valid anymore. in release_mem_store()
1445 return -EINVAL; in release_mem_store()
1449 /* Release the reserved memory and disable the FADump */
1485 int input = -1; in registered_store()
1488 return -EPERM; in registered_store()
1491 return -EINVAL; in registered_store()
1501 /* Un-register Firmware-assisted dump */ in registered_store()
1502 pr_debug("Un-register firmware-assisted dump\n"); in registered_store()
1503 fw_dump.ops->fadump_unregister(&fw_dump); in registered_store()
1507 /* Un-register Firmware-assisted dump */ in registered_store()
1508 fw_dump.ops->fadump_unregister(&fw_dump); in registered_store()
1510 /* Register Firmware-assisted dump */ in registered_store()
1514 ret = -EINVAL; in registered_store()
1529 fw_dump.ops->fadump_region_show(&fw_dump, m); in fadump_region_show()
1582 * - fadump_enabled -> fadump/enabled in fadump_init_files()
1583 * - fadump_registered -> fadump/registered in fadump_init_files()
1584 * - fadump_release_mem -> fadump/release_mem in fadump_init_files()
1615 * Prepare for firmware-assisted dump.
1635 * and release memory before proceeding for re-registration. in setup_fadump()
1637 if (fw_dump.ops->fadump_process(&fw_dump) < 0) in setup_fadump()
1640 /* Initialize the kernel dump memory structure for FAD registration. */ in setup_fadump()
1642 fw_dump.ops->fadump_init_mem_struct(&fw_dump); in setup_fadump()
1662 * preserve crash data. The subsequent memory preserving kernel boot
1669 * If last boot has crashed then reserve all the memory in fadump_reserve_mem()
1670 * above boot memory to preserve crash data. in fadump_reserve_mem()
1675 pr_debug("FADump-aware kernel..\n"); in fadump_reserve_mem()
1687 msize = mend - mstart; in fadump_reserve_crash_area()
1693 msize -= (base - mstart); in fadump_reserve_crash_area()
1697 pr_info("Reserving %lluMB of memory at %#016llx for preserving crash data", in fadump_reserve_crash_area()