[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