diff mbox

[v21,1/8] arm64: kdump: reserve memory for crash dump kernel

Message ID 20160706075226.27609-2-takahiro.akashi@linaro.org
State New
Headers show

Commit Message

AKASHI Takahiro July 6, 2016, 7:52 a.m. UTC
On the startup of primary kernel, the memory region used by crash dump
kernel must be specified by "crashkernel=" kernel parameter.
reserve_crashkernel() will allocate and reserve the region for later use.

User space tools, like kexec-tools, will be able to find that region marked
as "Crash kernel" in /proc/iomem.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Signed-off-by: Mark Salter <msalter@redhat.com>

Signed-off-by: Pratyush Anand <panand@redhat.com>

Reviewed-by: James Morse <james.morse@arm.com>

---
 arch/arm64/kernel/setup.c |  7 +++++-
 arch/arm64/mm/init.c      | 62 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 68 insertions(+), 1 deletion(-)

-- 
2.9.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Comments

AKASHI Takahiro July 7, 2016, 12:19 a.m. UTC | #1
Geoff,

Thank you for your reviewing.

On Wed, Jul 06, 2016 at 10:00:18AM -0700, Geoff Levand wrote:
> On Wed, 2016-07-06 at 16:52 +0900, AKASHI Takahiro wrote:

> >  

> > +#ifdef CONFIG_KEXEC_CORE

> > +/*

> > + * reserve_crashkernel() - reserves memory for crash kernel

> > + *

> > + * This function reserves memory area given in "crashkernel=" kernel command

> > + * line parameter. The memory reserved is used by dump capture kernel when

> > + * primary kernel is crashing.

> > + */

> > +static void __init reserve_crashkernel(void)

> > +{

> > +> 	> unsigned long long crash_size = 0, crash_base = 0;

> > +> 	> int ret;

> > +

> > +> 	> ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),

> > +> 	> 	> 	> 	> &crash_size, &crash_base);

> > +> 	> /* no crashkernel= or invalid value specified */

> > +> 	> if (ret || !crash_size)

> > +> 	> 	> return;

> > +

> > +> 	> if (crash_base == 0) {

> > +> 	> 	> /* Current arm64 boot protocol requires 2MB alignment */

> > +> 	> 	> crash_base = memblock_find_in_range(0,

> > +> 	> 	> 	> 	> MEMBLOCK_ALLOC_ACCESSIBLE, crash_size, SZ_2M);

> > +> 	> 	> if (crash_base == 0) {

> > +> 	> 	> 	> pr_warn("Unable to allocate crashkernel (size:%llx)\n",

> > +> 	> 	> 	> 	> crash_size);

> > +> 	> 	> 	> return;

> > +> 	> 	> }

> > +> 	> 	> memblock_reserve(crash_base, crash_size);

> > +

> > +> 	> } else {

> > +> 	> 	> /* User specifies base address explicitly. */

> > +> 	> 	> if (!memblock_is_region_memory(crash_base, crash_size) ||

> > +> 	> 	> 	> memblock_is_region_reserved(crash_base, crash_size)) {

> > +> 	> 	> 	> pr_warn("crashkernel has wrong address or size\n");

> > +> 	> 	> 	> return;

> > +> 	> 	> }

> > +

> > +> 	> 	> if (!IS_ALIGNED(crash_base, SZ_2M)) {

> > +> 	> 	> 	> pr_warn("crashkernel base address is not 2MB aligned\n");

> > +> 	> 	> 	> return;

> > +> 	> 	> }

> > +

> > +> 	> 	> memblock_reserve(crash_base, crash_size);

> > +> 	> }

> > +

> > +> 	> pr_info("Reserving %lldMB of memory at %lldMB for crashkernel\n",

> > +> 	> 	> crash_size >> 20, crash_base >> 20);

> > +

> > +> 	> crashk_res.start = crash_base;

> > +> 	> crashk_res.end = crash_base + crash_size - 1;

> > +}

> > +#else

> > +static void __init reserve_crashkernel(void)

> > +{

> > +> 	> ;

> > +}

> > +#endif /* CONFIG_KEXEC_CORE */

> > +


I know that this is just a matter of preference, but
I can see more use cases of the above than the below
that you mentioned under arm64 directory.
So I want to keep the current style unchanged unless
the maintainers don't like it.

Thanks,
-Takahiro AKASHI

> I think it is a bit cleaner if you move this conditional

> into the function and have something like:

> 

> static void __init reserve_crashkernel(void)

> {

> #ifdef CONFIG_KEXEC_CORE

> #else

> #endif

> }

>

> -Geoff

> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
AKASHI Takahiro July 7, 2016, 1:17 a.m. UTC | #2
On Wed, Jul 06, 2016 at 03:11:45PM -0300, Thiago Jung Bauermann wrote:
> Am Mittwoch, 06 Juli 2016, 16:52:19 schrieb AKASHI Takahiro:

> > On the startup of primary kernel, the memory region used by crash dump

> > kernel must be specified by "crashkernel=" kernel parameter.

> > reserve_crashkernel() will allocate and reserve the region for later use.

> > 

> > User space tools, like kexec-tools, will be able to find that region

> > marked as "Crash kernel" in /proc/iomem.

> 

> On powerpc, userspace tools get everything from the device tree (exposed to 

> userspace in /proc/device-tree/), not /proc/iomem.


I started my kdump patches with arm (not arm64) implementation, and
so /proc/iomem is used for consistency. Since my kexec-tools (for arm64)
have to access /proc/iomem to identify usable memory regions on
*UEFI* systems anyway, I didn't think it was odd.

(Please note that UEFI won't expose memory regions information via
a device tree, but via ACPI table.)

> In the case of the crashkernel reserved region, that information is in 

> /chosen/linux,crashkernel-base and /chosen/linux,crashkernel-size.

> 

> Either way is fine I think. I'm just mentioning this for reference in case 

> you want the ARM implementation to be closer to another arch which is also 

> based on the device tree.


Adding those properties to a device tree is quite easy
(and it won't conflict with /proc/iomem), so I'd like 
to defer to arm64 maintainers.

Thanks,
-Takahiro AKASHI

> -- 

> []'s

> Thiago Jung Bauermann

> IBM Linux Technology Center

> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
diff mbox

Patch

diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index c1509e6..cb5eee0 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -31,7 +31,6 @@ 
 #include <linux/screen_info.h>
 #include <linux/init.h>
 #include <linux/kexec.h>
-#include <linux/crash_dump.h>
 #include <linux/root_dev.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
@@ -222,6 +221,12 @@  static void __init request_standard_resources(void)
 		    kernel_data.end <= res->end)
 			request_resource(res, &kernel_data);
 	}
+
+#ifdef CONFIG_KEXEC_CORE
+	/* User space tools will find "Crash kernel" region in /proc/iomem. */
+	if (crashk_res.end)
+		insert_resource(&iomem_resource, &crashk_res);
+#endif
 }
 
 u64 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = INVALID_HWID };
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 2ade7a6..e1134fb 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -34,6 +34,7 @@ 
 #include <linux/dma-contiguous.h>
 #include <linux/efi.h>
 #include <linux/swiotlb.h>
+#include <linux/kexec.h>
 
 #include <asm/boot.h>
 #include <asm/fixmap.h>
@@ -76,6 +77,65 @@  static int __init early_initrd(char *p)
 early_param("initrd", early_initrd);
 #endif
 
+#ifdef CONFIG_KEXEC_CORE
+/*
+ * reserve_crashkernel() - reserves memory for crash kernel
+ *
+ * This function reserves memory area given in "crashkernel=" kernel command
+ * line parameter. The memory reserved is used by dump capture kernel when
+ * primary kernel is crashing.
+ */
+static void __init reserve_crashkernel(void)
+{
+	unsigned long long crash_size = 0, crash_base = 0;
+	int ret;
+
+	ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
+				&crash_size, &crash_base);
+	/* no crashkernel= or invalid value specified */
+	if (ret || !crash_size)
+		return;
+
+	if (crash_base == 0) {
+		/* Current arm64 boot protocol requires 2MB alignment */
+		crash_base = memblock_find_in_range(0,
+				MEMBLOCK_ALLOC_ACCESSIBLE, crash_size, SZ_2M);
+		if (crash_base == 0) {
+			pr_warn("Unable to allocate crashkernel (size:%llx)\n",
+				crash_size);
+			return;
+		}
+		memblock_reserve(crash_base, crash_size);
+
+	} else {
+		/* User specifies base address explicitly. */
+		if (!memblock_is_region_memory(crash_base, crash_size) ||
+			memblock_is_region_reserved(crash_base, crash_size)) {
+			pr_warn("crashkernel has wrong address or size\n");
+			return;
+		}
+
+		if (!IS_ALIGNED(crash_base, SZ_2M)) {
+			pr_warn("crashkernel base address is not 2MB aligned\n");
+			return;
+		}
+
+		memblock_reserve(crash_base, crash_size);
+	}
+
+	pr_info("Reserving %lldMB of memory at %lldMB for crashkernel\n",
+		crash_size >> 20, crash_base >> 20);
+
+	crashk_res.start = crash_base;
+	crashk_res.end = crash_base + crash_size - 1;
+}
+#else
+static void __init reserve_crashkernel(void)
+{
+	;
+}
+#endif /* CONFIG_KEXEC_CORE */
+
 /*
  * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It
  * currently assumes that for memory starting above 4G, 32-bit devices will
@@ -289,6 +349,8 @@  void __init arm64_memblock_init(void)
 	}
 #endif
 
+	reserve_crashkernel();
+
 	early_init_fdt_scan_reserved_mem();
 
 	/* 4GB maximum for 32-bit only capable devices */