Blame SOURCES/kexec-tools-2.0.14-arm64-kdump-add-elf-core-header-segment.patch

766e0d
From dd3886b82ed56c18d9d6d0e7228a2b31eed0ec5a Mon Sep 17 00:00:00 2001
766e0d
Message-Id: <dd3886b82ed56c18d9d6d0e7228a2b31eed0ec5a.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:20 +0900
766e0d
Subject: [PATCH 06/10] arm64: kdump: add elf core header segment
766e0d
766e0d
Elf core header contains the information necessary for the coredump of
766e0d
the 1st kernel, including its physcal memory layout as well as cpu register
766e0d
states at the panic.
766e0d
The segment is allocated inside the reserved memory of crash dump kernel.
766e0d
766e0d
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
766e0d
---
766e0d
 kexec/arch/arm64/crashdump-arm64.c | 96 ++++++++++++++++++++++++++++++++++++++
766e0d
 kexec/arch/arm64/crashdump-arm64.h |  3 ++
766e0d
 kexec/arch/arm64/iomem.h           |  2 +
766e0d
 kexec/arch/arm64/kexec-elf-arm64.c | 10 ++++
766e0d
 4 files changed, 111 insertions(+)
766e0d
766e0d
diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
766e0d
index dcaca434af62..83461312d412 100644
766e0d
--- a/kexec/arch/arm64/crashdump-arm64.c
766e0d
+++ b/kexec/arch/arm64/crashdump-arm64.c
766e0d
@@ -39,6 +39,39 @@ struct memory_ranges usablemem_rgns = {
766e0d
 	.ranges = &crash_reserved_mem,
766e0d
 };
766e0d
 
766e0d
+struct memory_range elfcorehdr_mem;
766e0d
+
766e0d
+static struct crash_elf_info elf_info = {
766e0d
+	.class		= ELFCLASS64,
766e0d
+#if (__BYTE_ORDER == __LITTLE_ENDIAN)
766e0d
+	.data		= ELFDATA2LSB,
766e0d
+#else
766e0d
+	.data		= ELFDATA2MSB,
766e0d
+#endif
766e0d
+	.machine	= EM_AARCH64,
766e0d
+};
766e0d
+
766e0d
+/*
766e0d
+ * Note: The returned value is correct only if !CONFIG_RANDOMIZE_BASE.
766e0d
+ */
766e0d
+static uint64_t get_kernel_page_offset(void)
766e0d
+{
766e0d
+	int i;
766e0d
+
766e0d
+	if (elf_info.kern_vaddr_start == UINT64_MAX)
766e0d
+		return UINT64_MAX;
766e0d
+
766e0d
+	/* Current max virtual memory range is 48-bits. */
766e0d
+	for (i = 48; i > 0; i--)
766e0d
+		if (!(elf_info.kern_vaddr_start & (1UL << i)))
766e0d
+			break;
766e0d
+
766e0d
+	if (i <= 0)
766e0d
+		return UINT64_MAX;
766e0d
+	else
766e0d
+		return UINT64_MAX << i;
766e0d
+}
766e0d
+
766e0d
 /*
766e0d
  * iomem_range_callback() - callback called for each iomem region
766e0d
  * @data: not used
766e0d
@@ -62,6 +95,10 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
766e0d
 	else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0)
766e0d
 		return mem_regions_add(&crash_memory_rgns,
766e0d
 				       base, length, RANGE_RAM);
766e0d
+	else if (strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) == 0)
766e0d
+		elf_info.kern_paddr_start = base;
766e0d
+	else if (strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) == 0)
766e0d
+		elf_info.kern_size = base + length - elf_info.kern_paddr_start;
766e0d
 
766e0d
 	return 0;
766e0d
 }
766e0d
@@ -115,5 +152,64 @@ static int crash_get_memory_ranges(void)
766e0d
 	dbgprint_mem_range("Coredump memory ranges",
766e0d
 			   crash_memory_rgns.ranges, crash_memory_rgns.size);
766e0d
 
766e0d
+	/*
766e0d
+	 * For additional kernel code/data segment.
766e0d
+	 * kern_paddr_start/kern_size are determined in iomem_range_callback
766e0d
+	 */
766e0d
+	elf_info.kern_vaddr_start = get_kernel_sym("_text");
766e0d
+	if (!elf_info.kern_vaddr_start)
766e0d
+		elf_info.kern_vaddr_start = UINT64_MAX;
766e0d
+
766e0d
+	return 0;
766e0d
+}
766e0d
+
766e0d
+/*
766e0d
+ * load_crashdump_segments() - load the elf core header
766e0d
+ * @info: kexec info structure
766e0d
+ *
766e0d
+ * This function creates and loads an additional segment of elf core header
766e0d
+ : which is used to construct /proc/vmcore on crash dump kernel.
766e0d
+ *
766e0d
+ * Return 0 in case of success and -1 in case of error.
766e0d
+ */
766e0d
+
766e0d
+int load_crashdump_segments(struct kexec_info *info)
766e0d
+{
766e0d
+	unsigned long elfcorehdr;
766e0d
+	unsigned long bufsz;
766e0d
+	void *buf;
766e0d
+	int err;
766e0d
+
766e0d
+	/*
766e0d
+	 * First fetch all the memory (RAM) ranges that we are going to
766e0d
+	 * pass to the crash dump kernel during panic.
766e0d
+	 */
766e0d
+
766e0d
+	err = crash_get_memory_ranges();
766e0d
+
766e0d
+	if (err)
766e0d
+		return err;
766e0d
+
766e0d
+	elf_info.page_offset = get_kernel_page_offset();
766e0d
+	dbgprintf("%s: page_offset:   %016llx\n", __func__,
766e0d
+			elf_info.page_offset);
766e0d
+
766e0d
+	err = crash_create_elf64_headers(info, &elf_info,
766e0d
+			crash_memory_rgns.ranges, crash_memory_rgns.size,
766e0d
+			&buf, &bufsz, ELF_CORE_HEADER_ALIGN);
766e0d
+
766e0d
+	if (err)
766e0d
+		return err;
766e0d
+
766e0d
+	elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 0,
766e0d
+		crash_reserved_mem.start, crash_reserved_mem.end,
766e0d
+		-1, 0);
766e0d
+
766e0d
+	elfcorehdr_mem.start = elfcorehdr;
766e0d
+	elfcorehdr_mem.end = elfcorehdr + bufsz - 1;
766e0d
+
766e0d
+	dbgprintf("%s: elfcorehdr 0x%llx-0x%llx\n", __func__,
766e0d
+			elfcorehdr_mem.start, elfcorehdr_mem.end);
766e0d
+
766e0d
 	return 0;
766e0d
 }
766e0d
diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
766e0d
index 07a0ed0bc344..da75a2d0c5f1 100644
766e0d
--- a/kexec/arch/arm64/crashdump-arm64.h
766e0d
+++ b/kexec/arch/arm64/crashdump-arm64.h
766e0d
@@ -18,5 +18,8 @@
766e0d
 
766e0d
 extern struct memory_ranges usablemem_rgns;
766e0d
 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
 
766e0d
 #endif /* CRASHDUMP_ARM64_H */
766e0d
diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h
766e0d
index 20cda87dbd02..d4864bb44922 100644
766e0d
--- a/kexec/arch/arm64/iomem.h
766e0d
+++ b/kexec/arch/arm64/iomem.h
766e0d
@@ -2,6 +2,8 @@
766e0d
 #define IOMEM_H
766e0d
 
766e0d
 #define SYSTEM_RAM		"System RAM\n"
766e0d
+#define KERNEL_CODE		"Kernel code\n"
766e0d
+#define KERNEL_DATA		"Kernel data\n"
766e0d
 #define CRASH_KERNEL		"Crash kernel\n"
766e0d
 #define IOMEM_RESERVED		"reserved\n"
766e0d
 
766e0d
diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
766e0d
index daf8bf0df9c4..c70a37ae7732 100644
766e0d
--- a/kexec/arch/arm64/kexec-elf-arm64.c
766e0d
+++ b/kexec/arch/arm64/kexec-elf-arm64.c
766e0d
@@ -119,6 +119,16 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
766e0d
 	dbgprintf("%s: PE format:      %s\n", __func__,
766e0d
 		(arm64_header_check_pe_sig(header) ? "yes" : "no"));
766e0d
 
766e0d
+	if (info->kexec_flags & KEXEC_ON_CRASH) {
766e0d
+		/* create and initialize elf core header segment */
766e0d
+		result = load_crashdump_segments(info);
766e0d
+		if (result) {
766e0d
+			dbgprintf("%s: Creating eflcorehdr failed.\n",
766e0d
+								__func__);
766e0d
+			goto exit;
766e0d
+		}
766e0d
+	}
766e0d
+
766e0d
 	/* load the kernel */
766e0d
 	result = elf_exec_load(&ehdr, info);
766e0d
 
766e0d
-- 
766e0d
2.9.3
766e0d