Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 32105f7f authored by Bernhard Walle's avatar Bernhard Walle Committed by Ingo Molnar
Browse files

x86: find offset for crashkernel reservation automatically



This patch removes the need of the crashkernel=...@offset parameter to define
a fixed offset for crashkernel reservation. That feature can be used together
with a relocatable kernel where the kexec-tools relocate the kernel and
get the actual offset from /proc/iomem.

The use case is a kernel where the .text+.data+.bss is after 16M physical
memory (debug kernel with lockdep on x86_64 can cause that) which caused a
major pain in autoconfiguration in our distribution.

Also, that patch unifies crashdump architectures a bit since IA64 has
that semantics from the very beginning of the kdump port.

Signed-off-by: default avatarBernhard Walle <bwalle@suse.de>
Cc: vgoyal@redhat.com
Cc: Bernhard Walle <bwalle@suse.de>
Cc: kexec@lists.infradead.org
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent fd6493e1
Loading
Loading
Loading
Loading
+52 −18
Original line number Original line Diff line number Diff line
@@ -422,6 +422,34 @@ static void __init reserve_setup_data(void)
 */
 */


#ifdef CONFIG_KEXEC
#ifdef CONFIG_KEXEC

/**
 * Reserve @size bytes of crashkernel memory at any suitable offset.
 *
 * @size: Size of the crashkernel memory to reserve.
 * Returns the base address on success, and -1ULL on failure.
 */
unsigned long long find_and_reserve_crashkernel(unsigned long long size)
{
	const unsigned long long alignment = 16<<20; 	/* 16M */
	unsigned long long start = 0LL;

	while (1) {
		int ret;

		start = find_e820_area(start, ULONG_MAX, size, alignment);
		if (start == -1ULL)
			return start;

		/* try to reserve it */
		ret = reserve_bootmem_generic(start, size, BOOTMEM_EXCLUSIVE);
		if (ret >= 0)
			return start;

		start += alignment;
	}
}

static inline unsigned long long get_total_mem(void)
static inline unsigned long long get_total_mem(void)
{
{
	unsigned long long total;
	unsigned long long total;
@@ -444,19 +472,26 @@ static void __init reserve_crashkernel(void)


	ret = parse_crashkernel(boot_command_line, total_mem,
	ret = parse_crashkernel(boot_command_line, total_mem,
			&crash_size, &crash_base);
			&crash_size, &crash_base);
	if (ret == 0 && crash_size > 0) {
	if (ret != 0 || crash_size <= 0)
		return;

	/* 0 means: find the address automatically */
	if (crash_base <= 0) {
	if (crash_base <= 0) {
			printk(KERN_INFO "crashkernel reservation failed - "
		crash_base = find_and_reserve_crashkernel(crash_size);
					"you have to specify a base address\n");
		if (crash_base == -1ULL) {
			pr_info("crashkernel reservation failed. "
				"No suitable area found.\n");
			return;
			return;
		}
		}

	} else {
		if (reserve_bootmem_generic(crash_base, crash_size,
		ret = reserve_bootmem_generic(crash_base, crash_size,
					BOOTMEM_EXCLUSIVE) < 0) {
					BOOTMEM_EXCLUSIVE);
			printk(KERN_INFO "crashkernel reservation failed - "
		if (ret < 0) {
			pr_info("crashkernel reservation failed - "
				"memory is in use\n");
				"memory is in use\n");
			return;
			return;
		}
		}
	}


	printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
	printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
			"for crashkernel (System RAM: %ldMB)\n",
			"for crashkernel (System RAM: %ldMB)\n",
@@ -468,7 +503,6 @@ static void __init reserve_crashkernel(void)
	crashk_res.end   = crash_base + crash_size - 1;
	crashk_res.end   = crash_base + crash_size - 1;
	insert_resource(&iomem_resource, &crashk_res);
	insert_resource(&iomem_resource, &crashk_res);
}
}
}
#else
#else
static void __init reserve_crashkernel(void)
static void __init reserve_crashkernel(void)
{
{