Discussion:
[PATCH v6 0/9] (kexec-tools) arm64: add kdump support
AKASHI Takahiro
2017-03-15 09:38:15 UTC
Permalink
My kernel patches of kdump support on arm64 are currently under review.

This patchset is synced with them (v33 [1]) and provides necessary changes
for kexec-tools. It can be applied on top of kexec-tools master branch.

[1] T.B.D.

Changes for v6:
- use get_kernel_sym() from x86, not from arm (patch #2)
- always take root node's "#address-cells" and "#size-cells" into account
when adding "linux,usable-memory-range" and "linux,elfcorehdr"
(patch #8)

Changes for v5:
- remove "linux,crashkernel-base/size" handling aligned with a change
on the kernel side

Changes for v4:
- rebased on the master branch (including Geoff's v6)
- revive "linux,usable-memory-range" DT property (from v2), dropping
use of "reserved-memory" nodes introduced in v3 (patch #8)
- extend the semantics of kexec_iomem_for_each_line() per Pratyush
(patch #1)

Changes for v3:
- rebased on Geoff's v5
- fix a value of estimated PHYS_OFFSET
- add a kernel code/data segment because they now reside out of linear
mapping due to KASLR introduction
- remove "linux,usable-memory-range" dependency, instead using
"reserved-memory" node
- add -mem-min/-mem-max support

Changes for v2:
- trim a temoprary buffer in setup_2nd_dtb()
- add patch#6("kexec: generalize and rename get_kernel_stext_sym()")
- update patch#7 from Pratyush
(re-worked by akashi)

AKASHI Takahiro (7):
kexec: exntend the semantics of kexec_iomem_for_each_line
arm64: identify PHYS_OFFSET correctly
arm64: kdump: identify memory regions
arm64: kdump: add elf core header segment
arm64: kdump: set up kernel image segment
arm64: kdump: set up other segments
arm64: kdump: add DT properties to crash dump kernel's dtb

Pratyush Anand (2):
kexec: generalize and rename get_kernel_stext_sym()
arm64: kdump: Add support for binary image files

kexec/Makefile | 1 +
kexec/arch/arm/crashdump-arm.c | 40 +-----
kexec/arch/arm64/Makefile | 2 +
kexec/arch/arm64/crashdump-arm64.c | 219 +++++++++++++++++++++++++++++++-
kexec/arch/arm64/crashdump-arm64.h | 18 ++-
kexec/arch/arm64/iomem.h | 10 ++
kexec/arch/arm64/kexec-arm64.c | 239 +++++++++++++++++++++++++++++++++--
kexec/arch/arm64/kexec-elf-arm64.c | 25 +++-
kexec/arch/arm64/kexec-image-arm64.c | 12 ++
kexec/arch/i386/crashdump-x86.c | 29 -----
kexec/kexec-iomem.c | 15 ++-
kexec/kexec.h | 2 +
kexec/symbols.c | 34 +++++
13 files changed, 551 insertions(+), 95 deletions(-)
create mode 100644 kexec/arch/arm64/iomem.h
create mode 100644 kexec/symbols.c
--
2.11.1
AKASHI Takahiro
2017-03-15 09:38:16 UTC
Permalink
The current kexec_iomem_for_each_line() counts up all the lines for which
a callback function returns zero(0) or positive, and otherwise it stops
further scanning.
This behavior is incovenient in some cases. For instance, on arm64, we want
to count up "System RAM" entries, but need to skip "reserved" entries.

So this patch extends the semantics so that we will continue to scan
succeeding entries but not count lines for which a callback function
returns positive.

The current users of kexec_iomem_for_each_line(), arm, sh and x86, will not
be affected by this change because
* arm
The callback function only returns -1 or 0, and the return value of
kexec_iomem_for_each_line() will never be used.
* sh, x86
The callback function may return (-1 for sh,) 0 or 1, but always returns
1 once we have reached the maximum number of entries allowed.
Even so the current kexec_iomem_for_each_line() counts them up.
This change actually fixes this bug.

Signed-off-by: AKASHI Takahiro <***@linaro.org>
---
kexec/kexec-iomem.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/kexec/kexec-iomem.c b/kexec/kexec-iomem.c
index 485a2e8..0a0277a 100644
--- a/kexec/kexec-iomem.c
+++ b/kexec/kexec-iomem.c
@@ -18,6 +18,9 @@
* Iterate over each line in the file returned by proc_iomem(). If match is
* NULL or if the line matches with our match-pattern then call the
* callback if non-NULL.
+ * If match is NULL, callback should return a negative if error.
+ * Otherwise the interation goes on, incrementing nr but only if callback
+ * returns 0 (matched).
*
* Return the number of lines matched.
*/
@@ -37,7 +40,7 @@ int kexec_iomem_for_each_line(char *match,
char *str;
int consumed;
int count;
- int nr = 0;
+ int nr = 0, ret;

fp = fopen(iomem, "r");
if (!fp)
@@ -50,11 +53,13 @@ int kexec_iomem_for_each_line(char *match,
str = line + consumed;
size = end - start + 1;
if (!match || memcmp(str, match, strlen(match)) == 0) {
- if (callback
- && callback(data, nr, str, start, size) < 0) {
- break;
+ if (callback) {
+ ret = callback(data, nr, str, start, size);
+ if (ret < 0)
+ break;
+ else if (ret == 0)
+ nr++;
}
- nr++;
}
}
--
2.11.1
AKASHI Takahiro
2017-03-15 09:38:17 UTC
Permalink
From: Pratyush Anand <***@redhat.com>

get_kernel_stext_sym() has been defined for both arm and i386. Other
architecture might need some other kernel symbol address. Therefore rewrite
this function as generic function to get any kernel symbol address.

More over, kallsyms is not arch specific representation, therefore have
common function for all arches.

Signed-off-by: Pratyush Anand <***@redhat.com>
[created symbols.c]
Signed-off-by: AKASHI Takahiro <***@linaro.org>
---
kexec/Makefile | 1 +
kexec/arch/arm/crashdump-arm.c | 40 +---------------------------------------
kexec/arch/i386/crashdump-x86.c | 29 -----------------------------
kexec/kexec.h | 2 ++
kexec/symbols.c | 34 ++++++++++++++++++++++++++++++++++
5 files changed, 38 insertions(+), 68 deletions(-)
create mode 100644 kexec/symbols.c

diff --git a/kexec/Makefile b/kexec/Makefile
index 39f365f..2b4fb3d 100644
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -26,6 +26,7 @@ KEXEC_SRCS_base += kexec/kernel_version.c
KEXEC_SRCS_base += kexec/lzma.c
KEXEC_SRCS_base += kexec/zlib.c
KEXEC_SRCS_base += kexec/kexec-xen.c
+KEXEC_SRCS_base += kexec/symbols.c

KEXEC_GENERATED_SRCS += $(PURGATORY_HEX_C)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index ac76e0a..daa4788 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -73,48 +73,10 @@ static struct crash_elf_info elf_info = {

extern unsigned long long user_page_offset;

-/* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */
-static unsigned long long get_kernel_stext_sym(void)
-{
- const char *kallsyms = "/proc/kallsyms";
- const char *stext = "_stext";
- char sym[128];
- char line[128];
- FILE *fp;
- unsigned long long vaddr = 0;
- char type;
-
- fp = fopen(kallsyms, "r");
- if (!fp) {
- fprintf(stderr, "Cannot open %s\n", kallsyms);
- return 0;
- }
-
- while(fgets(line, sizeof(line), fp) != NULL) {
- unsigned long long addr;
-
- if (sscanf(line, "%Lx %c %s", &addr, &type, sym) != 3)
- continue;
-
- if (strcmp(sym, stext) == 0) {
- dbgprintf("kernel symbol %s vaddr = %#llx\n", stext, addr);
- vaddr = addr;
- break;
- }
- }
-
- fclose(fp);
-
- if (vaddr == 0)
- fprintf(stderr, "Cannot get kernel %s symbol address\n", stext);
-
- return vaddr;
-}
-
static int get_kernel_page_offset(struct kexec_info *info,
struct crash_elf_info *elf_info)
{
- unsigned long long stext_sym_addr = get_kernel_stext_sym();
+ unsigned long long stext_sym_addr = get_kernel_sym("_stext");
if (stext_sym_addr == 0) {
if (user_page_offset != (-1ULL)) {
elf_info->page_offset = user_page_offset;
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index c4cf201..a324c6c 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -102,35 +102,6 @@ static int get_kernel_paddr(struct kexec_info *UNUSED(info),
return -1;
}

-/* Retrieve kernel symbol virtual address from /proc/kallsyms */
-static unsigned long long get_kernel_sym(const char *symbol)
-{
- const char *kallsyms = "/proc/kallsyms";
- char sym[128];
- char line[128];
- FILE *fp;
- unsigned long long vaddr;
- char type;
-
- fp = fopen(kallsyms, "r");
- if (!fp) {
- fprintf(stderr, "Cannot open %s\n", kallsyms);
- return 0;
- }
-
- while(fgets(line, sizeof(line), fp) != NULL) {
- if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
- continue;
- if (strcmp(sym, symbol) == 0) {
- dbgprintf("kernel symbol %s vaddr = %16llx\n", symbol, vaddr);
- return vaddr;
- }
- }
-
- dbgprintf("Cannot get kernel %s symbol address\n", symbol);
- return 0;
-}
-
/* Retrieve info regarding virtual address kernel has been compiled for and
* size of the kernel from /proc/kcore. Current /proc/kcore parsing from
* from kexec-tools fails because of malformed elf notes. A kernel patch has
diff --git a/kexec/kexec.h b/kexec/kexec.h
index 52bef9b..26225d2 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -317,4 +317,6 @@ int xen_kexec_unload(uint64_t kexec_flags);
void xen_kexec_exec(void);
int xen_kexec_status(uint64_t kexec_flags);

+extern unsigned long long get_kernel_sym(const char *text);
+
#endif /* KEXEC_H */
diff --git a/kexec/symbols.c b/kexec/symbols.c
new file mode 100644
index 0000000..5e42de9
--- /dev/null
+++ b/kexec/symbols.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <string.h>
+#include "kexec.h"
+
+/* Retrieve kernel symbol virtual address from /proc/kallsyms */
+unsigned long long get_kernel_sym(const char *symbol)
+{
+ const char *kallsyms = "/proc/kallsyms";
+ char sym[128];
+ char line[128];
+ FILE *fp;
+ unsigned long long vaddr;
+ char type;
+
+ fp = fopen(kallsyms, "r");
+ if (!fp) {
+ fprintf(stderr, "Cannot open %s\n", kallsyms);
+ return 0;
+ }
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
+ continue;
+ if (strcmp(sym, symbol) == 0) {
+ dbgprintf("kernel symbol %s vaddr = %16llx\n",
+ symbol, vaddr);
+ return vaddr;
+ }
+ }
+
+ dbgprintf("Cannot get kernel %s symbol address\n", symbol);
+
+ return 0;
+}
--
2.11.1
AKASHI Takahiro
2017-03-15 09:38:18 UTC
Permalink
Due to the kernel patch, commit e7cd190385d1 ("arm64: mark reserved
memblock regions explicitly in iomem"), the current code will not be able
to identify the correct value of PHYS_OFFSET if some "reserved" memory
region, which is likely to be UEFI runtime services code/data, exists at
an address below the first "System RAM" regions.

This patch fixes this issue.

Signed-off-by: AKASHI Takahiro <***@linaro.org>
---
kexec/arch/arm64/iomem.h | 7 +++++++
kexec/arch/arm64/kexec-arm64.c | 12 ++++++++++--
2 files changed, 17 insertions(+), 2 deletions(-)
create mode 100644 kexec/arch/arm64/iomem.h

diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h
new file mode 100644
index 0000000..7fd66eb
--- /dev/null
+++ b/kexec/arch/arm64/iomem.h
@@ -0,0 +1,7 @@
+#ifndef IOMEM_H
+#define IOMEM_H
+
+#define SYSTEM_RAM "System RAM\n"
+#define IOMEM_RESERVED "reserved\n"
+
+#endif
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 04fd396..d02b9da 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -21,6 +21,7 @@
#include "crashdump-arm64.h"
#include "dt-ops.h"
#include "fs2dt.h"
+#include "iomem.h"
#include "kexec-syscall.h"
#include "arch/options.h"

@@ -476,7 +477,14 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
return -1;

r = (struct memory_range *)data + nr;
- r->type = RANGE_RAM;
+
+ if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)))
+ r->type = RANGE_RAM;
+ else if (!strncmp(str, IOMEM_RESERVED, strlen(IOMEM_RESERVED)))
+ r->type = RANGE_RESERVED;
+ else
+ return 1;
+
r->start = base;
r->end = base + length - 1;

@@ -495,7 +503,7 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
static int get_memory_ranges_iomem(struct memory_range *array,
unsigned int *count)
{
- *count = kexec_iomem_for_each_line("System RAM\n",
+ *count = kexec_iomem_for_each_line(NULL,
get_memory_ranges_iomem_cb, array);

if (!*count) {
--
2.11.1
AKASHI Takahiro
2017-03-15 09:38:19 UTC
Permalink
The following regions need to be identified for later use:
a) memory regions which belong to the 1st kernel
b) usable memory reserved for crash dump kernel

We go through /proc/iomem to find out a) and b) which are marked
as "System RAM" and "Crash kernel", respectively.

Signed-off-by: AKASHI Takahiro <***@linaro.org>
---
kexec/arch/arm64/Makefile | 2 +
kexec/arch/arm64/crashdump-arm64.c | 100 ++++++++++++++++++++++++++++++++++++-
kexec/arch/arm64/crashdump-arm64.h | 14 +++++-
kexec/arch/arm64/iomem.h | 1 +
4 files changed, 114 insertions(+), 3 deletions(-)

diff --git a/kexec/arch/arm64/Makefile b/kexec/arch/arm64/Makefile
index 74b677f..2d4ae0e 100644
--- a/kexec/arch/arm64/Makefile
+++ b/kexec/arch/arm64/Makefile
@@ -6,6 +6,8 @@ arm64_FS2DT_INCLUDE += \

arm64_DT_OPS += kexec/dt-ops.c

+arm64_MEM_REGIONS = kexec/mem_regions.c
+
arm64_CPPFLAGS += -I $(srcdir)/kexec/

arm64_KEXEC_SRCS += \
diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
index b0e4713..ca50677 100644
--- a/kexec/arch/arm64/crashdump-arm64.c
+++ b/kexec/arch/arm64/crashdump-arm64.c
@@ -1,5 +1,13 @@
/*
* ARM64 crashdump.
+ * partly derived from arm implementation
+ *
+ * Copyright (c) 2014-2016 Linaro Limited
+ * Author: AKASHI Takahiro <***@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*/

#define _GNU_SOURCE
@@ -10,13 +18,103 @@
#include "kexec.h"
#include "crashdump.h"
#include "crashdump-arm64.h"
+#include "iomem.h"
#include "kexec-arm64.h"
#include "kexec-elf.h"
+#include "mem_regions.h"

-struct memory_ranges usablemem_rgns = {};
+/* memory ranges on crashed kernel */
+static struct memory_range crash_memory_ranges[CRASH_MAX_MEMORY_RANGES];
+static struct memory_ranges crash_memory_rgns = {
+ .size = 0,
+ .max_size = CRASH_MAX_MEMORY_RANGES,
+ .ranges = crash_memory_ranges,
+};
+
+/* memory range reserved for crashkernel */
+struct memory_range crash_reserved_mem;
+struct memory_ranges usablemem_rgns = {
+ .size = 0,
+ .max_size = 1,
+ .ranges = &crash_reserved_mem,
+};
+
+/*
+ * iomem_range_callback() - callback called for each iomem region
+ * @data: not used
+ * @nr: not used
+ * @str: name of the memory region
+ * @base: start address of the memory region
+ * @length: size of the memory region
+ *
+ * This function is called once for each memory region found in /proc/iomem.
+ * It locates system RAM and crashkernel reserved memory and places these to
+ * variables, respectively, crash_memory_ranges and crash_reserved_mem.
+ */
+
+static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
+ char *str, unsigned long long base,
+ unsigned long long length)
+{
+ if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0)
+ return mem_regions_add(&usablemem_rgns,
+ base, length, RANGE_RAM);
+ else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0)
+ return mem_regions_add(&crash_memory_rgns,
+ base, length, RANGE_RAM);
+
+ return 0;
+}

int is_crashkernel_mem_reserved(void)
{
+ if (!crash_reserved_mem.end)
+ kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL);
+
+ return crash_reserved_mem.start != crash_reserved_mem.end;
+}
+
+/*
+ * crash_get_memory_ranges() - read system physical memory
+ *
+ * Function reads through system physical memory and stores found memory
+ * regions in crash_memory_ranges.
+ * Regions are sorted in ascending order.
+ *
+ * Returns 0 in case of success and -1 otherwise (errno is set).
+ */
+static int crash_get_memory_ranges(void)
+{
+ /*
+ * First read all memory regions that can be considered as
+ * system memory including the crash area.
+ */
+ if (!usablemem_rgns.size)
+ kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL);
+
+ /* allow only a single region for crash dump kernel */
+ if (usablemem_rgns.size != 1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ dbgprint_mem_range("Reserved memory range", &crash_reserved_mem, 1);
+
+ if (mem_regions_exclude(&crash_memory_rgns, &crash_reserved_mem)) {
+ fprintf(stderr,
+ "Error: Number of crash memory ranges excedeed the max limit\n");
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /*
+ * Make sure that the memory regions are sorted.
+ */
+ mem_regions_sort(&crash_memory_rgns);
+
+ dbgprint_mem_range("Coredump memory ranges",
+ crash_memory_rgns.ranges, crash_memory_rgns.size);
+
return 0;
}

diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
index f33c7a2..07a0ed0 100644
--- a/kexec/arch/arm64/crashdump-arm64.h
+++ b/kexec/arch/arm64/crashdump-arm64.h
@@ -1,12 +1,22 @@
/*
* ARM64 crashdump.
+ *
+ * Copyright (c) 2014-2016 Linaro Limited
+ * Author: AKASHI Takahiro <***@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*/

-#if !defined(CRASHDUMP_ARM64_H)
+#ifndef CRASHDUMP_ARM64_H
#define CRASHDUMP_ARM64_H

#include "kexec.h"

+#define CRASH_MAX_MEMORY_RANGES 32
+
extern struct memory_ranges usablemem_rgns;
+extern struct memory_range crash_reserved_mem;

-#endif
+#endif /* CRASHDUMP_ARM64_H */
diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h
index 7fd66eb..20cda87 100644
--- a/kexec/arch/arm64/iomem.h
+++ b/kexec/arch/arm64/iomem.h
@@ -2,6 +2,7 @@
#define IOMEM_H

#define SYSTEM_RAM "System RAM\n"
+#define CRASH_KERNEL "Crash kernel\n"
#define IOMEM_RESERVED "reserved\n"

#endif
--
2.11.1
AKASHI Takahiro
2017-03-15 09:38:20 UTC
Permalink
Elf core header contains the information necessary for the coredump of
the 1st kernel, including its physcal memory layout as well as cpu register
states at the panic.
The segment is allocated inside the reserved memory of crash dump kernel.

Signed-off-by: AKASHI Takahiro <***@linaro.org>
---
kexec/arch/arm64/crashdump-arm64.c | 96 ++++++++++++++++++++++++++++++++++++++
kexec/arch/arm64/crashdump-arm64.h | 3 ++
kexec/arch/arm64/iomem.h | 2 +
kexec/arch/arm64/kexec-elf-arm64.c | 10 ++++
4 files changed, 111 insertions(+)

diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
index ca50677..2497d94 100644
--- a/kexec/arch/arm64/crashdump-arm64.c
+++ b/kexec/arch/arm64/crashdump-arm64.c
@@ -39,6 +39,39 @@ struct memory_ranges usablemem_rgns = {
.ranges = &crash_reserved_mem,
};

+struct memory_range elfcorehdr_mem;
+
+static struct crash_elf_info elf_info = {
+ .class = ELFCLASS64,
+#if (__BYTE_ORDER == __LITTLE_ENDIAN)
+ .data = ELFDATA2LSB,
+#else
+ .data = ELFDATA2MSB,
+#endif
+ .machine = EM_AARCH64,
+};
+
+/*
+ * Note: The returned value is correct only if !CONFIG_RANDOMIZE_BASE.
+ */
+static uint64_t get_kernel_page_offset(void)
+{
+ int i;
+
+ if (elf_info.kern_vaddr_start == UINT64_MAX)
+ return UINT64_MAX;
+
+ /* Current max virtual memory range is 48-bits. */
+ for (i = 48; i > 0; i--)
+ if (!(elf_info.kern_vaddr_start & (1UL << i)))
+ break;
+
+ if (i <= 0)
+ return UINT64_MAX;
+ else
+ return UINT64_MAX << i;
+}
+
/*
* iomem_range_callback() - callback called for each iomem region
* @data: not used
@@ -62,6 +95,10 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0)
return mem_regions_add(&crash_memory_rgns,
base, length, RANGE_RAM);
+ else if (strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) == 0)
+ elf_info.kern_paddr_start = base;
+ else if (strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) == 0)
+ elf_info.kern_size = base + length - elf_info.kern_paddr_start;

return 0;
}
@@ -115,6 +152,65 @@ static int crash_get_memory_ranges(void)
dbgprint_mem_range("Coredump memory ranges",
crash_memory_rgns.ranges, crash_memory_rgns.size);

+ /*
+ * For additional kernel code/data segment.
+ * kern_paddr_start/kern_size are determined in iomem_range_callback
+ */
+ elf_info.kern_vaddr_start = get_kernel_sym("_text");
+ if (!elf_info.kern_vaddr_start)
+ elf_info.kern_vaddr_start = UINT64_MAX;
+
+ return 0;
+}
+
+/*
+ * load_crashdump_segments() - load the elf core header
+ * @info: kexec info structure
+ *
+ * This function creates and loads an additional segment of elf core header
+ : which is used to construct /proc/vmcore on crash dump kernel.
+ *
+ * Return 0 in case of success and -1 in case of error.
+ */
+
+int load_crashdump_segments(struct kexec_info *info)
+{
+ unsigned long elfcorehdr;
+ unsigned long bufsz;
+ void *buf;
+ int err;
+
+ /*
+ * First fetch all the memory (RAM) ranges that we are going to
+ * pass to the crash dump kernel during panic.
+ */
+
+ err = crash_get_memory_ranges();
+
+ if (err)
+ return err;
+
+ elf_info.page_offset = get_kernel_page_offset();
+ dbgprintf("%s: page_offset: %016llx\n", __func__,
+ elf_info.page_offset);
+
+ err = crash_create_elf64_headers(info, &elf_info,
+ crash_memory_rgns.ranges, crash_memory_rgns.size,
+ &buf, &bufsz, ELF_CORE_HEADER_ALIGN);
+
+ if (err)
+ return err;
+
+ elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 0,
+ crash_reserved_mem.start, crash_reserved_mem.end,
+ -1, 0);
+
+ elfcorehdr_mem.start = elfcorehdr;
+ elfcorehdr_mem.end = elfcorehdr + bufsz - 1;
+
+ dbgprintf("%s: elfcorehdr 0x%llx-0x%llx\n", __func__,
+ elfcorehdr_mem.start, elfcorehdr_mem.end);
+
return 0;
}

diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
index 07a0ed0..da75a2d 100644
--- a/kexec/arch/arm64/crashdump-arm64.h
+++ b/kexec/arch/arm64/crashdump-arm64.h
@@ -18,5 +18,8 @@

extern struct memory_ranges usablemem_rgns;
extern struct memory_range crash_reserved_mem;
+extern struct memory_range elfcorehdr_mem;
+
+extern int load_crashdump_segments(struct kexec_info *info);

#endif /* CRASHDUMP_ARM64_H */
diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h
index 20cda87..d4864bb 100644
--- a/kexec/arch/arm64/iomem.h
+++ b/kexec/arch/arm64/iomem.h
@@ -2,6 +2,8 @@
#define IOMEM_H

#define SYSTEM_RAM "System RAM\n"
+#define KERNEL_CODE "Kernel code\n"
+#define KERNEL_DATA "Kernel data\n"
#define CRASH_KERNEL "Crash kernel\n"
#define IOMEM_RESERVED "reserved\n"

diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
index daf8bf0..c70a37a 100644
--- a/kexec/arch/arm64/kexec-elf-arm64.c
+++ b/kexec/arch/arm64/kexec-elf-arm64.c
@@ -119,6 +119,16 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
dbgprintf("%s: PE format: %s\n", __func__,
(arm64_header_check_pe_sig(header) ? "yes" : "no"));

+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ /* create and initialize elf core header segment */
+ result = load_crashdump_segments(info);
+ if (result) {
+ dbgprintf("%s: Creating eflcorehdr failed.\n",
+ __func__);
+ goto exit;
+ }
+ }
+
/* load the kernel */
result = elf_exec_load(&ehdr, info);
--
2.11.1
AKASHI Takahiro
2017-03-15 09:38:21 UTC
Permalink
On arm64, we can use the same kernel image as 1st kernel, but
we have to modify the entry point as well as segments' addresses
in the kernel's elf header in order to load them into correct places.

Signed-off-by: AKASHI Takahiro <***@linaro.org>
---
kexec/arch/arm64/crashdump-arm64.c | 23 +++++++++++++++++++++++
kexec/arch/arm64/crashdump-arm64.h | 1 +
kexec/arch/arm64/kexec-arm64.c | 25 ++++++++++++++++++++-----
kexec/arch/arm64/kexec-elf-arm64.c | 10 +++++++++-
4 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
index 2497d94..64b4660 100644
--- a/kexec/arch/arm64/crashdump-arm64.c
+++ b/kexec/arch/arm64/crashdump-arm64.c
@@ -214,6 +214,29 @@ int load_crashdump_segments(struct kexec_info *info)
return 0;
}

+/*
+ * e_entry and p_paddr are actually in virtual address space.
+ * Those values will be translated to physcal addresses by
+ * using virt_to_phys().
+ * So let's get ready for later use so the memory base (phys_offset)
+ * will be correctly replaced with crash_reserved_mem.start.
+ */
+void modify_ehdr_for_crashdump(struct mem_ehdr *ehdr)
+{
+ struct mem_phdr *phdr;
+ int i;
+
+ ehdr->e_entry += - arm64_mem.phys_offset + crash_reserved_mem.start;
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ phdr = &ehdr->e_phdr[i];
+ if (phdr->p_type != PT_LOAD)
+ continue;
+ phdr->p_paddr +=
+ (-arm64_mem.phys_offset + crash_reserved_mem.start);
+ }
+}
+
int get_crash_kernel_load_range(uint64_t *start, uint64_t *end)
{
/* Crash kernel region size is not exposed by the system */
diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
index da75a2d..382f571 100644
--- a/kexec/arch/arm64/crashdump-arm64.h
+++ b/kexec/arch/arm64/crashdump-arm64.h
@@ -21,5 +21,6 @@ extern struct memory_range crash_reserved_mem;
extern struct memory_range elfcorehdr_mem;

extern int load_crashdump_segments(struct kexec_info *info);
+extern void modify_ehdr_for_crashdump(struct mem_ehdr *ehdr);

#endif /* CRASHDUMP_ARM64_H */
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index d02b9da..5a1da2e 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -307,12 +307,27 @@ unsigned long arm64_locate_kernel_segment(struct kexec_info *info)
{
unsigned long hole;

- hole = locate_hole(info,
- arm64_mem.text_offset + arm64_mem.image_size,
- MiB(2), 0, ULONG_MAX, 1);
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ unsigned long hole_end;
+
+ hole = (crash_reserved_mem.start < mem_min ?
+ mem_min : crash_reserved_mem.start);
+ hole = _ALIGN_UP(hole, MiB(2));
+ hole_end = hole + arm64_mem.text_offset + arm64_mem.image_size;
+
+ if ((hole_end > mem_max) ||
+ (hole_end > crash_reserved_mem.end)) {
+ dbgprintf("%s: Crash kernel out of range\n", __func__);
+ hole = ULONG_MAX;
+ }
+ } else {
+ hole = locate_hole(info,
+ arm64_mem.text_offset + arm64_mem.image_size,
+ MiB(2), 0, ULONG_MAX, 1);

- if (hole == ULONG_MAX)
- dbgprintf("%s: locate_hole failed\n", __func__);
+ if (hole == ULONG_MAX)
+ dbgprintf("%s: locate_hole failed\n", __func__);
+ }

return hole;
}
diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
index c70a37a..842ce21 100644
--- a/kexec/arch/arm64/kexec-elf-arm64.c
+++ b/kexec/arch/arm64/kexec-elf-arm64.c
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <linux/elf.h>

+#include "crashdump-arm64.h"
#include "kexec-arm64.h"
#include "kexec-elf.h"
#include "kexec-syscall.h"
@@ -105,7 +106,8 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
}

arm64_mem.vp_offset = _ALIGN_DOWN(ehdr.e_entry, MiB(2));
- arm64_mem.vp_offset -= kernel_segment - get_phys_offset();
+ if (!(info->kexec_flags & KEXEC_ON_CRASH))
+ arm64_mem.vp_offset -= kernel_segment - get_phys_offset();

dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment);
dbgprintf("%s: text_offset: %016lx\n", __func__,
@@ -127,6 +129,12 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
__func__);
goto exit;
}
+
+ /*
+ * offset addresses in order to fit vmlinux
+ * (elf_exec) into crash kernel's memory
+ */
+ modify_ehdr_for_crashdump(&ehdr);
}

/* load the kernel */
--
2.11.1
AKASHI Takahiro
2017-03-15 09:38:23 UTC
Permalink
We pass the following properties to crash dump kernel:
linux,elfcorehdr: elf core header segment,
same as "elfcorehdr=" kernel parameter on other archs
linux,usable-memory-range: usable memory reserved for crash dump kernel

Signed-off-by: AKASHI Takahiro <***@linaro.org>
---
kexec/arch/arm64/kexec-arm64.c | 197 ++++++++++++++++++++++++++++++++++++-
kexec/arch/arm64/kexec-elf-arm64.c | 5 -
2 files changed, 192 insertions(+), 10 deletions(-)

diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 5e30107..f3f101d 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -25,6 +25,14 @@
#include "kexec-syscall.h"
#include "arch/options.h"

+#define ROOT_NODE_ADDR_CELLS_DEFAULT 1
+#define ROOT_NODE_SIZE_CELLS_DEFAULT 1
+
+#define PROP_ADDR_CELLS "#address-cells"
+#define PROP_SIZE_CELLS "#size-cells"
+#define PROP_ELFCOREHDR "linux,elfcorehdr"
+#define PROP_USABLE_MEM_RANGE "linux,usable-memory-range"
+
/* Global varables the core kexec routines expect. */

unsigned char reuse_initrd;
@@ -128,9 +136,6 @@ int arch_process_options(int argc, char **argv)
case OPT_INITRD:
arm64_opts.initrd = optarg;
break;
- case OPT_PANIC:
- die("load-panic (-p) not supported");
- break;
default:
break; /* Ignore core and unknown options. */
}
@@ -281,12 +286,115 @@ on_success:
return 0;
}

+static int get_cells_size(void *fdt, uint32_t *address_cells,
+ uint32_t *size_cells)
+{
+ int nodeoffset;
+ const uint32_t *prop = NULL;
+ int prop_len;
+
+ /* default values */
+ *address_cells = ROOT_NODE_ADDR_CELLS_DEFAULT;
+ *size_cells = ROOT_NODE_SIZE_CELLS_DEFAULT;
+
+ /* under root node */
+ nodeoffset = fdt_path_offset(fdt, "/");
+ if (nodeoffset < 0)
+ goto on_error;
+
+ prop = fdt_getprop(fdt, nodeoffset, PROP_ADDR_CELLS, &prop_len);
+ if (prop) {
+ if (prop_len == sizeof(*prop))
+ *address_cells = fdt32_to_cpu(*prop);
+ else
+ goto on_error;
+ }
+
+ prop = fdt_getprop(fdt, nodeoffset, PROP_SIZE_CELLS, &prop_len);
+ if (prop) {
+ if (prop_len == sizeof(*prop))
+ *size_cells = fdt32_to_cpu(*prop);
+ else
+ goto on_error;
+ }
+
+ dbgprintf("%s: #address-cells:%d #size-cells:%d\n", __func__,
+ *address_cells, *size_cells);
+ return 0;
+
+on_error:
+ return -EFAILED;
+}
+
+bool cells_size_fitted(uint32_t address_cells, uint32_t size_cells,
+ struct memory_range *range)
+{
+ dbgprintf("%s: %llx-%llx\n", __func__, range->start, range->end);
+
+ /* if *_cells >= 2, cells can hold 64-bit values anyway */
+ if ((address_cells == 1) && (range->start >= (1ULL << 32)))
+ return false;
+
+ if ((size_cells == 1) &&
+ ((range->end - range->start + 1) >= (1ULL << 32)))
+ return false;
+
+ return true;
+}
+
+static void fill_property(void *buf, uint64_t val, uint32_t cells)
+{
+ uint32_t val32;
+ int i;
+
+ if (cells == 1) {
+ val32 = cpu_to_fdt32((uint32_t)val);
+ memcpy(buf, &val32, sizeof(uint32_t));
+ } else {
+ for (i = 0;
+ i < (cells * sizeof(uint32_t) - sizeof(uint64_t)); i++)
+ *(char *)buf++ = 0;
+
+ val = cpu_to_fdt64(val);
+ memcpy(buf, &val, sizeof(uint64_t));
+ }
+}
+
+static int setprop_range(void *fdt, int nodeoffset,
+ const char *name, struct memory_range *range,
+ uint32_t address_cells, uint32_t size_cells)
+{
+ void *buf, *prop;
+ size_t buf_size;
+ int result;
+
+ buf_size = (address_cells + size_cells) * sizeof(uint32_t);
+ prop = buf = xmalloc(buf_size);
+
+ fill_property(prop, range->start, address_cells);
+ prop += address_cells * sizeof(uint32_t);
+
+ fill_property(prop, range->end - range->start + 1, size_cells);
+ prop += size_cells * sizeof(uint32_t);
+
+ result = fdt_setprop(fdt, nodeoffset, name, buf, buf_size);
+
+ free(buf);
+
+ return result;
+}
+
/**
* setup_2nd_dtb - Setup the 2nd stage kernel's dtb.
*/

-static int setup_2nd_dtb(struct dtb *dtb, char *command_line)
+static int setup_2nd_dtb(struct dtb *dtb, char *command_line, int on_crash)
{
+ uint32_t address_cells, size_cells;
+ int range_len;
+ int nodeoffset;
+ char *new_buf = NULL;
+ int new_size;
int result;

result = fdt_check_header(dtb->buf);
@@ -298,8 +406,86 @@ static int setup_2nd_dtb(struct dtb *dtb, char *command_line)

result = set_bootargs(dtb, command_line);

+ if (on_crash) {
+ /* determine #address-cells and #size-cells */
+ result = get_cells_size(dtb->buf, &address_cells, &size_cells);
+ if (result) {
+ fprintf(stderr,
+ "kexec: cannot determine cells-size.\n");
+ result = -EINVAL;
+ goto on_error;
+ }
+
+ if (!cells_size_fitted(address_cells, size_cells,
+ &elfcorehdr_mem)) {
+ fprintf(stderr,
+ "kexec: elfcorehdr doesn't fit cells-size.\n");
+ result = -EINVAL;
+ goto on_error;
+ }
+
+ if (!cells_size_fitted(address_cells, size_cells,
+ &crash_reserved_mem)) {
+ fprintf(stderr,
+ "kexec: usable memory range doesn't fit cells-size.\n");
+ result = -EINVAL;
+ goto on_error;
+ }
+
+ /* duplicate dt blob */
+ range_len = sizeof(uint32_t) * (address_cells + size_cells);
+ new_size = fdt_totalsize(dtb->buf)
+ + fdt_prop_len(PROP_ELFCOREHDR, range_len)
+ + fdt_prop_len(PROP_USABLE_MEM_RANGE, range_len);
+
+ new_buf = xmalloc(new_size);
+ result = fdt_open_into(dtb->buf, new_buf, new_size);
+ if (result) {
+ dbgprintf("%s: fdt_open_into failed: %s\n", __func__,
+ fdt_strerror(result));
+ result = -ENOSPC;
+ goto on_error;
+ }
+
+ /* add linux,elfcorehdr */
+ nodeoffset = fdt_path_offset(new_buf, "/chosen");
+ result = setprop_range(new_buf, nodeoffset,
+ PROP_ELFCOREHDR, &elfcorehdr_mem,
+ address_cells, size_cells);
+ if (result) {
+ dbgprintf("%s: fdt_setprop failed: %s\n", __func__,
+ fdt_strerror(result));
+ result = -EINVAL;
+ goto on_error;
+ }
+
+ /* add linux,usable-memory-range */
+ nodeoffset = fdt_path_offset(new_buf, "/chosen");
+ result = setprop_range(new_buf, nodeoffset,
+ PROP_USABLE_MEM_RANGE, &crash_reserved_mem,
+ address_cells, size_cells);
+ if (result) {
+ dbgprintf("%s: fdt_setprop failed: %s\n", __func__,
+ fdt_strerror(result));
+ result = -EINVAL;
+ goto on_error;
+ }
+
+ fdt_pack(new_buf);
+ dtb->buf = new_buf;
+ dtb->size = fdt_totalsize(new_buf);
+ }
+
dump_reservemap(dtb);

+
+ return result;
+
+on_error:
+ fprintf(stderr, "kexec: %s failed.\n", __func__);
+ if (new_buf)
+ free(new_buf);
+
return result;
}

@@ -367,7 +553,8 @@ int arm64_load_other_segments(struct kexec_info *info,
}
}

- result = setup_2nd_dtb(&dtb, command_line);
+ result = setup_2nd_dtb(&dtb, command_line,
+ info->kexec_flags & KEXEC_ON_CRASH);

if (result)
return -EFAILED;
diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
index 842ce21..b17a31a 100644
--- a/kexec/arch/arm64/kexec-elf-arm64.c
+++ b/kexec/arch/arm64/kexec-elf-arm64.c
@@ -47,11 +47,6 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
int result;
int i;

- if (info->kexec_flags & KEXEC_ON_CRASH) {
- fprintf(stderr, "kexec: kdump not yet supported on arm64\n");
- return -EFAILED;
- }
-
result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0);

if (result < 0) {
--
2.11.1
AKASHI Takahiro
2017-03-15 09:38:24 UTC
Permalink
From: Pratyush Anand <***@redhat.com>

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

Signed-off-by: Pratyush Anand <***@redhat.com>
[***@linaro.org: a bit reworked]
Signed-off-by: AKASHI Takahiro <***@linaro.org>
---
kexec/arch/arm64/kexec-image-arm64.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
index 960ed96..982e431 100644
--- a/kexec/arch/arm64/kexec-image-arm64.c
+++ b/kexec/arch/arm64/kexec-image-arm64.c
@@ -4,7 +4,9 @@

#define _GNU_SOURCE

+#include "crashdump-arm64.h"
#include "kexec-arm64.h"
+#include "kexec-syscall.h"
#include <limits.h>

int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
@@ -58,6 +60,16 @@ int image_arm64_load(int argc, char **argv, const char *kernel_buf,
dbgprintf("%s: PE format: %s\n", __func__,
(arm64_header_check_pe_sig(header) ? "yes" : "no"));

+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ /* create and initialize elf core header segment */
+ result = load_crashdump_segments(info);
+ if (result) {
+ dbgprintf("%s: Creating eflcorehdr failed.\n",
+ __func__);
+ goto exit;
+ }
+ }
+
/* load the kernel */
add_segment_phys_virt(info, kernel_buf, kernel_size,
kernel_segment + arm64_mem.text_offset,
--
2.11.1
AKASHI Takahiro
2017-03-15 09:38:22 UTC
Permalink
We make sure that all the other segments, initrd and device-tree blob,
also be loaded into the reserved memory of crash dump kernel.

Signed-off-by: AKASHI Takahiro <***@linaro.org>
---
kexec/arch/arm64/kexec-arm64.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 5a1da2e..5e30107 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -375,7 +375,10 @@ int arm64_load_other_segments(struct kexec_info *info,
/* Put the other segments after the image. */

hole_min = image_base + arm64_mem.image_size;
- hole_max = ULONG_MAX;
+ if (info->kexec_flags & KEXEC_ON_CRASH)
+ hole_max = crash_reserved_mem.end;
+ else
+ hole_max = ULONG_MAX;

if (arm64_opts.initrd) {
initrd_buf = slurp_file(arm64_opts.initrd, &initrd_size);
--
2.11.1
Pratyush Anand
2017-05-12 02:51:07 UTC
Permalink
Post by AKASHI Takahiro
My kernel patches of kdump support on arm64 are currently under review.
This patchset is synced with them (v33 [1]) and provides necessary changes
for kexec-tools. It can be applied on top of kexec-tools master branch.
[1] T.B.D.
- use get_kernel_sym() from x86, not from arm (patch #2)
- always take root node's "#address-cells" and "#size-cells" into account
when adding "linux,usable-memory-range" and "linux,elfcorehdr"
(patch #8)
I think these patches can be merged now, as kernel patches are there in upstream.
Post by AKASHI Takahiro
- remove "linux,crashkernel-base/size" handling aligned with a change
on the kernel side
- rebased on the master branch (including Geoff's v6)
- revive "linux,usable-memory-range" DT property (from v2), dropping
use of "reserved-memory" nodes introduced in v3 (patch #8)
- extend the semantics of kexec_iomem_for_each_line() per Pratyush
(patch #1)
- rebased on Geoff's v5
- fix a value of estimated PHYS_OFFSET
- add a kernel code/data segment because they now reside out of linear
mapping due to KASLR introduction
- remove "linux,usable-memory-range" dependency, instead using
"reserved-memory" node
- add -mem-min/-mem-max support
- trim a temoprary buffer in setup_2nd_dtb()
- add patch#6("kexec: generalize and rename get_kernel_stext_sym()")
- update patch#7 from Pratyush
(re-worked by akashi)
kexec: exntend the semantics of kexec_iomem_for_each_line
arm64: identify PHYS_OFFSET correctly
arm64: kdump: identify memory regions
arm64: kdump: add elf core header segment
arm64: kdump: set up kernel image segment
arm64: kdump: set up other segments
arm64: kdump: add DT properties to crash dump kernel's dtb
kexec: generalize and rename get_kernel_stext_sym()
arm64: kdump: Add support for binary image files
kexec/Makefile | 1 +
kexec/arch/arm/crashdump-arm.c | 40 +-----
kexec/arch/arm64/Makefile | 2 +
kexec/arch/arm64/crashdump-arm64.c | 219 +++++++++++++++++++++++++++++++-
kexec/arch/arm64/crashdump-arm64.h | 18 ++-
kexec/arch/arm64/iomem.h | 10 ++
kexec/arch/arm64/kexec-arm64.c | 239 +++++++++++++++++++++++++++++++++--
kexec/arch/arm64/kexec-elf-arm64.c | 25 +++-
kexec/arch/arm64/kexec-image-arm64.c | 12 ++
kexec/arch/i386/crashdump-x86.c | 29 -----
kexec/kexec-iomem.c | 15 ++-
kexec/kexec.h | 2 +
kexec/symbols.c | 34 +++++
13 files changed, 551 insertions(+), 95 deletions(-)
create mode 100644 kexec/arch/arm64/iomem.h
create mode 100644 kexec/symbols.c
AKASHI Takahiro
2017-05-12 06:25:09 UTC
Permalink
Post by Pratyush Anand
Post by AKASHI Takahiro
My kernel patches of kdump support on arm64 are currently under review.
This patchset is synced with them (v33 [1]) and provides necessary changes
for kexec-tools. It can be applied on top of kexec-tools master branch.
[1] T.B.D.
- use get_kernel_sym() from x86, not from arm (patch #2)
- always take root node's "#address-cells" and "#size-cells" into account
when adding "linux,usable-memory-range" and "linux,elfcorehdr"
(patch #8)
I think these patches can be merged now, as kernel patches are there in upstream.
Yeah, but I might want to make _cosmetic_ changes/clean-up stuff
as I'm now working on kexec_file_load() support and want to minimize
the gap between the kernel code and kexec-tools.

I'll let all of you know once I've done. Hopefully early next week.
So if anybody have comments, those will be very much appreciated.

Thanks,
-Takahiro AKASHI
Post by Pratyush Anand
Post by AKASHI Takahiro
- remove "linux,crashkernel-base/size" handling aligned with a change
on the kernel side
- rebased on the master branch (including Geoff's v6)
- revive "linux,usable-memory-range" DT property (from v2), dropping
use of "reserved-memory" nodes introduced in v3 (patch #8)
- extend the semantics of kexec_iomem_for_each_line() per Pratyush
(patch #1)
- rebased on Geoff's v5
- fix a value of estimated PHYS_OFFSET
- add a kernel code/data segment because they now reside out of linear
mapping due to KASLR introduction
- remove "linux,usable-memory-range" dependency, instead using
"reserved-memory" node
- add -mem-min/-mem-max support
- trim a temoprary buffer in setup_2nd_dtb()
- add patch#6("kexec: generalize and rename get_kernel_stext_sym()")
- update patch#7 from Pratyush
(re-worked by akashi)
kexec: exntend the semantics of kexec_iomem_for_each_line
arm64: identify PHYS_OFFSET correctly
arm64: kdump: identify memory regions
arm64: kdump: add elf core header segment
arm64: kdump: set up kernel image segment
arm64: kdump: set up other segments
arm64: kdump: add DT properties to crash dump kernel's dtb
kexec: generalize and rename get_kernel_stext_sym()
arm64: kdump: Add support for binary image files
kexec/Makefile | 1 +
kexec/arch/arm/crashdump-arm.c | 40 +-----
kexec/arch/arm64/Makefile | 2 +
kexec/arch/arm64/crashdump-arm64.c | 219 +++++++++++++++++++++++++++++++-
kexec/arch/arm64/crashdump-arm64.h | 18 ++-
kexec/arch/arm64/iomem.h | 10 ++
kexec/arch/arm64/kexec-arm64.c | 239 +++++++++++++++++++++++++++++++++--
kexec/arch/arm64/kexec-elf-arm64.c | 25 +++-
kexec/arch/arm64/kexec-image-arm64.c | 12 ++
kexec/arch/i386/crashdump-x86.c | 29 -----
kexec/kexec-iomem.c | 15 ++-
kexec/kexec.h | 2 +
kexec/symbols.c | 34 +++++
13 files changed, 551 insertions(+), 95 deletions(-)
create mode 100644 kexec/arch/arm64/iomem.h
create mode 100644 kexec/symbols.c
Loading...