/** * Return a sorted list of memory ranges. * * If we have the /sys/firmware/memmap interface, then use that. If not, * or if parsing of that fails, use /proc/iomem as fallback. * * @param[out] range pointer that will be set to an array that holds the * memory ranges * @param[out] ranges number of ranges valid in @p range * @param[in] kexec_flags the kexec_flags to determine if we load a normal * or a crashdump kernel * * @return 0 on success, any other value on failure. */ int get_memory_ranges(struct memory_range **range, int *ranges, unsigned long kexec_flags) { int ret, i; if (!efi_map_added() && !xen_present() && have_sys_firmware_memmap()) { ret = get_memory_ranges_sysfs(range, ranges); if (!ret) ret = fixup_memory_ranges(range, ranges); } else if (xen_present()) { ret = get_memory_ranges_xen(range, ranges); if (!ret) ret = fixup_memory_ranges(range, ranges); } else ret = get_memory_ranges_proc_iomem(range, ranges); /* * get_memory_ranges_sysfs(), get_memory_ranges_proc_iomem() and * get_memory_ranges_xen() have already printed an error message, * so fail silently here. */ if (ret != 0) return ret; /* Don't report the interrupt table as ram */ for (i = 0; i < *ranges; i++) { if ((*range)[i].type == RANGE_RAM && ((*range)[i].start < 0x100)) { (*range)[i].start = 0x100; break; } } /* * Redefine the memory region boundaries if kernel * exports the limits and if it is panic kernel. * Override user values only if kernel exported values are * subset of user defined values. */ if ((kexec_flags & KEXEC_ON_CRASH) && !(kexec_flags & KEXEC_PRESERVE_CONTEXT)) { uint64_t start, end; ret = get_max_crash_kernel_limit(&start, &end); if (ret != 0) { fprintf(stderr, "get_max_crash_kernel_limit failed.\n"); return -1; } if (start > mem_min) mem_min = start; if (end < mem_max) mem_max = end; } dbgprint_mem_range("MEMORY RANGES", *range, *ranges); return ret; }
/** * Return a sorted list of memory ranges. * * If we have the /sys/firmware/memmap interface, then use that. If not, * or if parsing of that fails, use /proc/iomem as fallback. * * @param[out] range pointer that will be set to an array that holds the * memory ranges * @param[out] ranges number of ranges valid in @p range * @param[in] kexec_flags the kexec_flags to determine if we load a normal * or a crashdump kernel * * @return 0 on success, any other value on failure. */ int get_memory_ranges(struct memory_range **range, int *ranges, unsigned long kexec_flags) { int ret, i; /* * When using Xen, /sys/firmware/memmap (i.e., the E820 map) is * wrong, it just provides one large memory are and that cannot * be used for Kdump. Use always the /proc/iomem interface there * even if we have /sys/firmware/memmap. Without that, /proc/vmcore * is empty in the kdump kernel. */ if (!xen_present() && have_sys_firmware_memmap()) { ret = get_memory_ranges_sysfs(range, ranges); if (!ret) ret = fixup_memory_ranges_sysfs(range, ranges); } else ret = get_memory_ranges_proc_iomem(range, ranges); /* * both get_memory_ranges_sysfs() and get_memory_ranges_proc_iomem() * have already printed an error message, so fail silently here */ if (ret != 0) return ret; /* Don't report the interrupt table as ram */ for (i = 0; i < *ranges; i++) { if ((*range)[i].type == RANGE_RAM && ((*range)[i].start < 0x100)) { (*range)[i].start = 0x100; break; } } /* * Redefine the memory region boundaries if kernel * exports the limits and if it is panic kernel. * Override user values only if kernel exported values are * subset of user defined values. */ if ((kexec_flags & KEXEC_ON_CRASH) && !(kexec_flags & KEXEC_PRESERVE_CONTEXT)) { uint64_t start, end; ret = parse_iomem_single("Crash kernel\n", &start, &end); if (ret != 0) { fprintf(stderr, "parse_iomem_single failed.\n"); return -1; } if (start > mem_min) mem_min = start; if (end < mem_max) mem_max = end; } /* just set 0 to 1 to enable printing for debugging */ #if 0 { int i; printf("MEMORY RANGES\n"); for (i = 0; i < *ranges; i++) { printf("%016Lx-%016Lx (%d)\n", (*range)[i].start, (*range)[i].end, (*range)[i].type); } } #endif return ret; }