|
|
766e0d |
From af338a51df9012f1b1dca87ddd27a5c66db5b80b Mon Sep 17 00:00:00 2001
|
|
|
766e0d |
Message-Id: <af338a51df9012f1b1dca87ddd27a5c66db5b80b.1489676829.git.panand@redhat.com>
|
|
|
766e0d |
In-Reply-To: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
|
|
|
766e0d |
References: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
|
|
|
766e0d |
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
|
|
|
766e0d |
Date: Wed, 15 Mar 2017 18:38:21 +0900
|
|
|
766e0d |
Subject: [PATCH 07/10] arm64: kdump: set up kernel image segment
|
|
|
766e0d |
|
|
|
766e0d |
On arm64, we can use the same kernel image as 1st kernel, but
|
|
|
766e0d |
we have to modify the entry point as well as segments' addresses
|
|
|
766e0d |
in the kernel's elf header in order to load them into correct places.
|
|
|
766e0d |
|
|
|
766e0d |
Minor conflicts was resolved in kexec/arch/arm64/crashdump-arm64.c because
|
|
|
766e0d |
get_crash_kernel_load_range() is not yet backported.
|
|
|
766e0d |
|
|
|
766e0d |
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
|
|
|
766e0d |
---
|
|
|
766e0d |
kexec/arch/arm64/crashdump-arm64.c | 23 +++++++++++++++++++++++
|
|
|
766e0d |
kexec/arch/arm64/crashdump-arm64.h | 1 +
|
|
|
766e0d |
kexec/arch/arm64/kexec-arm64.c | 25 ++++++++++++++++++++-----
|
|
|
766e0d |
kexec/arch/arm64/kexec-elf-arm64.c | 10 +++++++++-
|
|
|
766e0d |
4 files changed, 53 insertions(+), 6 deletions(-)
|
|
|
766e0d |
|
|
|
766e0d |
diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
|
|
|
766e0d |
index 83461312d412..9517329e1086 100644
|
|
|
766e0d |
--- a/kexec/arch/arm64/crashdump-arm64.c
|
|
|
766e0d |
+++ b/kexec/arch/arm64/crashdump-arm64.c
|
|
|
766e0d |
@@ -213,3 +213,26 @@ int load_crashdump_segments(struct kexec_info *info)
|
|
|
766e0d |
|
|
|
766e0d |
return 0;
|
|
|
766e0d |
}
|
|
|
766e0d |
+
|
|
|
766e0d |
+/*
|
|
|
766e0d |
+ * e_entry and p_paddr are actually in virtual address space.
|
|
|
766e0d |
+ * Those values will be translated to physcal addresses by
|
|
|
766e0d |
+ * using virt_to_phys().
|
|
|
766e0d |
+ * So let's get ready for later use so the memory base (phys_offset)
|
|
|
766e0d |
+ * will be correctly replaced with crash_reserved_mem.start.
|
|
|
766e0d |
+ */
|
|
|
766e0d |
+void modify_ehdr_for_crashdump(struct mem_ehdr *ehdr)
|
|
|
766e0d |
+{
|
|
|
766e0d |
+ struct mem_phdr *phdr;
|
|
|
766e0d |
+ int i;
|
|
|
766e0d |
+
|
|
|
766e0d |
+ ehdr->e_entry += - arm64_mem.phys_offset + crash_reserved_mem.start;
|
|
|
766e0d |
+
|
|
|
766e0d |
+ for (i = 0; i < ehdr->e_phnum; i++) {
|
|
|
766e0d |
+ phdr = &ehdr->e_phdr[i];
|
|
|
766e0d |
+ if (phdr->p_type != PT_LOAD)
|
|
|
766e0d |
+ continue;
|
|
|
766e0d |
+ phdr->p_paddr +=
|
|
|
766e0d |
+ (-arm64_mem.phys_offset + crash_reserved_mem.start);
|
|
|
766e0d |
+ }
|
|
|
766e0d |
+}
|
|
|
766e0d |
diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
|
|
|
766e0d |
index da75a2d0c5f1..382f57154f2a 100644
|
|
|
766e0d |
--- a/kexec/arch/arm64/crashdump-arm64.h
|
|
|
766e0d |
+++ b/kexec/arch/arm64/crashdump-arm64.h
|
|
|
766e0d |
@@ -21,5 +21,6 @@ extern struct memory_range crash_reserved_mem;
|
|
|
766e0d |
extern struct memory_range elfcorehdr_mem;
|
|
|
766e0d |
|
|
|
766e0d |
extern int load_crashdump_segments(struct kexec_info *info);
|
|
|
766e0d |
+extern void modify_ehdr_for_crashdump(struct mem_ehdr *ehdr);
|
|
|
766e0d |
|
|
|
766e0d |
#endif /* CRASHDUMP_ARM64_H */
|
|
|
766e0d |
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
|
|
|
766e0d |
index d02b9dac3d33..5a1da2ec1a34 100644
|
|
|
766e0d |
--- a/kexec/arch/arm64/kexec-arm64.c
|
|
|
766e0d |
+++ b/kexec/arch/arm64/kexec-arm64.c
|
|
|
766e0d |
@@ -307,12 +307,27 @@ unsigned long arm64_locate_kernel_segment(struct kexec_info *info)
|
|
|
766e0d |
{
|
|
|
766e0d |
unsigned long hole;
|
|
|
766e0d |
|
|
|
766e0d |
- hole = locate_hole(info,
|
|
|
766e0d |
- arm64_mem.text_offset + arm64_mem.image_size,
|
|
|
766e0d |
- MiB(2), 0, ULONG_MAX, 1);
|
|
|
766e0d |
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
|
|
|
766e0d |
+ unsigned long hole_end;
|
|
|
766e0d |
+
|
|
|
766e0d |
+ hole = (crash_reserved_mem.start < mem_min ?
|
|
|
766e0d |
+ mem_min : crash_reserved_mem.start);
|
|
|
766e0d |
+ hole = _ALIGN_UP(hole, MiB(2));
|
|
|
766e0d |
+ hole_end = hole + arm64_mem.text_offset + arm64_mem.image_size;
|
|
|
766e0d |
+
|
|
|
766e0d |
+ if ((hole_end > mem_max) ||
|
|
|
766e0d |
+ (hole_end > crash_reserved_mem.end)) {
|
|
|
766e0d |
+ dbgprintf("%s: Crash kernel out of range\n", __func__);
|
|
|
766e0d |
+ hole = ULONG_MAX;
|
|
|
766e0d |
+ }
|
|
|
766e0d |
+ } else {
|
|
|
766e0d |
+ hole = locate_hole(info,
|
|
|
766e0d |
+ arm64_mem.text_offset + arm64_mem.image_size,
|
|
|
766e0d |
+ MiB(2), 0, ULONG_MAX, 1);
|
|
|
766e0d |
|
|
|
766e0d |
- if (hole == ULONG_MAX)
|
|
|
766e0d |
- dbgprintf("%s: locate_hole failed\n", __func__);
|
|
|
766e0d |
+ if (hole == ULONG_MAX)
|
|
|
766e0d |
+ dbgprintf("%s: locate_hole failed\n", __func__);
|
|
|
766e0d |
+ }
|
|
|
766e0d |
|
|
|
766e0d |
return hole;
|
|
|
766e0d |
}
|
|
|
766e0d |
diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
|
|
|
766e0d |
index c70a37ae7732..842ce21e2387 100644
|
|
|
766e0d |
--- a/kexec/arch/arm64/kexec-elf-arm64.c
|
|
|
766e0d |
+++ b/kexec/arch/arm64/kexec-elf-arm64.c
|
|
|
766e0d |
@@ -9,6 +9,7 @@
|
|
|
766e0d |
#include <stdlib.h>
|
|
|
766e0d |
#include <linux/elf.h>
|
|
|
766e0d |
|
|
|
766e0d |
+#include "crashdump-arm64.h"
|
|
|
766e0d |
#include "kexec-arm64.h"
|
|
|
766e0d |
#include "kexec-elf.h"
|
|
|
766e0d |
#include "kexec-syscall.h"
|
|
|
766e0d |
@@ -105,7 +106,8 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
|
|
|
766e0d |
}
|
|
|
766e0d |
|
|
|
766e0d |
arm64_mem.vp_offset = _ALIGN_DOWN(ehdr.e_entry, MiB(2));
|
|
|
766e0d |
- arm64_mem.vp_offset -= kernel_segment - get_phys_offset();
|
|
|
766e0d |
+ if (!(info->kexec_flags & KEXEC_ON_CRASH))
|
|
|
766e0d |
+ arm64_mem.vp_offset -= kernel_segment - get_phys_offset();
|
|
|
766e0d |
|
|
|
766e0d |
dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment);
|
|
|
766e0d |
dbgprintf("%s: text_offset: %016lx\n", __func__,
|
|
|
766e0d |
@@ -127,6 +129,12 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
|
|
|
766e0d |
__func__);
|
|
|
766e0d |
goto exit;
|
|
|
766e0d |
}
|
|
|
766e0d |
+
|
|
|
766e0d |
+ /*
|
|
|
766e0d |
+ * offset addresses in order to fit vmlinux
|
|
|
766e0d |
+ * (elf_exec) into crash kernel's memory
|
|
|
766e0d |
+ */
|
|
|
766e0d |
+ modify_ehdr_for_crashdump(&ehdr);
|
|
|
766e0d |
}
|
|
|
766e0d |
|
|
|
766e0d |
/* load the kernel */
|
|
|
766e0d |
--
|
|
|
766e0d |
2.9.3
|
|
|
766e0d |
|