[PATCH v2 7/7] arm64: kdump: Add support for binary image files

AKASHI Takahiro takahiro.akashi at linaro.org
Mon Aug 8 19:00:32 PDT 2016


From: Pratyush Anand <panand at redhat.com>

This patch adds support to use binary image ie arch/arm64/boot/Image with
kdump.

Binary image does not have sufficient knowledge to extract page offset
information, which is needed by kexec tool (specially vmcore-dmesg). Use a
new command parameter --page-offset, so that user can provide page offset
information for linear mapping.

Signed-off-by: Pratyush Anand <panand at redhat.com>
[takahiro.akashi at linaro.org: a bit reworked]
Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
---
 kexec/arch/arm64/include/arch/options.h |  8 +++--
 kexec/arch/arm64/kexec-arm64.c          |  5 +++
 kexec/arch/arm64/kexec-image-arm64.c    | 60 +++++++++++++++++++++++++++++----
 3 files changed, 65 insertions(+), 8 deletions(-)

diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h
index a17d933..3283985 100644
--- a/kexec/arch/arm64/include/arch/options.h
+++ b/kexec/arch/arm64/include/arch/options.h
@@ -5,7 +5,8 @@
 #define OPT_DTB			((OPT_MAX)+1)
 #define OPT_INITRD		((OPT_MAX)+2)
 #define OPT_REUSE_CMDLINE	((OPT_MAX)+3)
-#define OPT_ARCH_MAX		((OPT_MAX)+4)
+#define OPT_PAGE_OFFSET		((OPT_MAX)+4)
+#define OPT_ARCH_MAX		((OPT_MAX)+5)
 
 #define KEXEC_ARCH_OPTIONS \
 	KEXEC_OPTIONS \
@@ -15,6 +16,7 @@
 	{ "initrd",        1, NULL, OPT_INITRD }, \
 	{ "ramdisk",       1, NULL, OPT_INITRD }, \
 	{ "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \
+	{ "page-offset",   1, NULL, OPT_PAGE_OFFSET }, \
 
 #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */
 #define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS
@@ -26,12 +28,14 @@ static const char arm64_opts_usage[] __attribute__ ((unused)) =
 "     --dtb=FILE            Use FILE as the device tree blob.\n"
 "     --initrd=FILE         Use FILE as the kernel initial ramdisk.\n"
 "     --ramdisk=FILE        Use FILE as the kernel initial ramdisk.\n"
-"     --reuse-cmdline       Use kernel command line from running system.\n";
+"     --reuse-cmdline       Use kernel command line from running system.\n"
+"     --page-offset=OFFSET  Use OFFSET as current kernel's page_offset value.\n";
 
 struct arm64_opts {
 	const char *command_line;
 	const char *dtb;
 	const char *initrd;
+	uint64_t page_offset;
 };
 
 extern struct arm64_opts arm64_opts;
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 83ad966..959f4bb 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -126,6 +126,9 @@ int arch_process_options(int argc, char **argv)
 		case OPT_INITRD:
 			arm64_opts.initrd = optarg;
 			break;
+		case OPT_PAGE_OFFSET:
+			arm64_opts.page_offset = strtoull(optarg, NULL, 0);
+			break;
 		default:
 			break; /* Ignore core and unknown options. */
 		}
@@ -138,6 +141,8 @@ int arch_process_options(int argc, char **argv)
 	dbgprintf("%s:%d: initrd: %s\n", __func__, __LINE__,
 		arm64_opts.initrd);
 	dbgprintf("%s:%d: dtb: %s\n", __func__, __LINE__, arm64_opts.dtb);
+	dbgprintf("%s:%d: page_offset: %016lx\n", __func__, __LINE__,
+						arm64_opts.page_offset);
 
 	return 0;
 }
diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
index cad7c73..90e8a87 100644
--- a/kexec/arch/arm64/kexec-image-arm64.c
+++ b/kexec/arch/arm64/kexec-image-arm64.c
@@ -4,9 +4,15 @@
 
 #define _GNU_SOURCE
 
-#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <arch/options.h>
 
+#include "../../kexec.h"
+#include "../../crashdump.h"
+#include "crashdump-arm64.h"
 #include "kexec-arm64.h"
+#include "kexec-syscall.h"
 
 int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
 {
@@ -27,16 +33,44 @@ int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
 	return 0;
 }
 
+static uint64_t get_kernel_page_offset(void)
+{
+	uint64_t text_page_offset;
+
+	/* 2MB-aligned */
+	text_page_offset = get_kernel_sym("_text") & (UINT64_MAX << 21);
+
+	if (arm64_opts.page_offset) {
+		if (text_page_offset != arm64_opts.page_offset)
+			dbgprintf("%s: User page offset %lx did not match with text page offset %lx\n", __func__,
+				arm64_opts.page_offset, text_page_offset);
+		return arm64_opts.page_offset;
+	} else if (text_page_offset) {
+		dbgprintf("%s: text page offset is %lx\n", __func__,
+						text_page_offset);
+		return text_page_offset;
+	} else {
+		return UINT64_MAX;
+	}
+}
+
 int image_arm64_load(int argc, char **argv, const char *kernel_buf,
 	off_t kernel_size, struct kexec_info *info)
 {
 	const struct arm64_image_header *h;
-	unsigned long image_base;
+	uint64_t image_base;
+	int result;
 
 	h = (const struct arm64_image_header *)(kernel_buf);
 
 	if (arm64_process_image_header(h))
-		return -EINVAL;
+		return -1;
+
+	arm64_mem.page_offset = get_kernel_page_offset();
+	if (arm64_mem.page_offset == UINT64_MAX) {
+		fprintf(stderr, "kexec: page_offset is not specified\n");
+		return -1;
+	}
 
 	dbgprintf("%s: text_offset:   %016lx\n", __func__,
 		arm64_mem.text_offset);
@@ -44,11 +78,24 @@ int image_arm64_load(int argc, char **argv, const char *kernel_buf,
 		arm64_mem.image_size);
 	dbgprintf("%s: phys_offset:   %016lx\n", __func__,
 		arm64_mem.phys_offset);
+	dbgprintf("%s: page_offset:   %016lx\n", __func__,
+		arm64_mem.page_offset);
 	dbgprintf("%s: PE format:     %s\n", __func__,
 		(arm64_header_check_pe_sig(h) ? "yes" : "no"));
 
-	image_base = get_phys_offset() + arm64_mem.text_offset;
-	
+	if (info->kexec_flags & KEXEC_ON_CRASH) {
+		result = load_crashdump_segments(info);
+
+		if (result) {
+			fprintf(stderr,
+				"kexec: load crashdump segments failed.\n");
+			return -1;
+		}
+		image_base = crash_reserved_mem.start + arm64_mem.text_offset;
+	} else {
+		image_base = get_phys_offset() + arm64_mem.text_offset;
+	}
+
 	add_segment_phys_virt(info, kernel_buf, kernel_size, image_base,
 		arm64_mem.image_size, 0);
 
@@ -59,5 +106,6 @@ void image_arm64_usage(void)
 {
 	printf(
 "     An ARM64 binary image, compressed or not, big or little endian.\n"
-"     Typically an Image, Image.gz or Image.lzma file.\n\n");
+"     Typically an Image, Image.gz or Image.lzma file.\n"
+"     --page-offset         Kernel page-offset for binary image load.\n\n");
 }
-- 
2.9.0




More information about the kexec mailing list