All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/4] arm64 kexec-tools patches
@ 2016-07-26 20:18 ` Geoff Levand
  0 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-26 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

This series adds the core support for kexec re-boot on ARM64.

Linux kernel support for kexec reboot [1] has been merged to the ARM64
for-next/core branch with the expectation that it will be included in the v4.8
stable kernel release.

For ARM64 kdump support see Takahiro's patches [2].

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438780.html
[2] http://lists.infradead.org/pipermail/kexec/2016-July/016642.html

Changes for v2 (July 26, 2016, 0m):

  o Inline some small routines.
  o Reformat some dbgprintf messages.
  o Remove debug_brk from entry.S
  o Change arm64_image_header.flags to uint64_t.
  o Look in iomem then dt for mem info.
  o Remove check_cpu_nodes.
  o Remove purgatory printing.

First submission v1 (July 20, 2016).

-Geoff

The following changes since commit 8d614008609f6ad5d09263767ebc771e06a173f0:

  arm: use zImage size from header (2016-07-15 13:12:28 +0900)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/geoff/kexec-tools.git for-merge-arm64-v2

for you to fetch changes up to f352dcfc827a4cbb3878dd1043877a4154b1bd08:

  arm64: Add support for binary image files (2016-07-26 11:48:01 -0700)

----------------------------------------------------------------
AKASHI Takahiro (1):
      kexec: (bugfix) calc correct end address of memory ranges in device tree

Geoff Levand (2):
      kexec: Add common device tree routines
      arm64: Add arm64 kexec support

Pratyush Anand (1):
      arm64: Add support for binary image files

 configure.ac                            |   3 +
 kexec/Makefile                          |   5 +
 kexec/arch/arm64/Makefile               |  40 ++
 kexec/arch/arm64/crashdump-arm64.c      |  21 +
 kexec/arch/arm64/crashdump-arm64.h      |  12 +
 kexec/arch/arm64/image-header.h         |  98 +++++
 kexec/arch/arm64/include/arch/options.h |  39 ++
 kexec/arch/arm64/kexec-arm64.c          | 704 ++++++++++++++++++++++++++++++++
 kexec/arch/arm64/kexec-arm64.h          |  70 ++++
 kexec/arch/arm64/kexec-elf-arm64.c      | 130 ++++++
 kexec/arch/arm64/kexec-image-arm64.c    |  63 +++
 kexec/dt-ops.c                          | 139 +++++++
 kexec/dt-ops.h                          |  13 +
 kexec/fs2dt.c                           |   5 +-
 kexec/kexec-syscall.h                   |   8 +-
 purgatory/Makefile                      |   1 +
 purgatory/arch/arm64/Makefile           |  18 +
 purgatory/arch/arm64/entry.S            |  51 +++
 purgatory/arch/arm64/purgatory-arm64.c  |  19 +
 19 files changed, 1435 insertions(+), 4 deletions(-)
 create mode 100644 kexec/arch/arm64/Makefile
 create mode 100644 kexec/arch/arm64/crashdump-arm64.c
 create mode 100644 kexec/arch/arm64/crashdump-arm64.h
 create mode 100644 kexec/arch/arm64/image-header.h
 create mode 100644 kexec/arch/arm64/include/arch/options.h
 create mode 100644 kexec/arch/arm64/kexec-arm64.c
 create mode 100644 kexec/arch/arm64/kexec-arm64.h
 create mode 100644 kexec/arch/arm64/kexec-elf-arm64.c
 create mode 100644 kexec/arch/arm64/kexec-image-arm64.c
 create mode 100644 kexec/dt-ops.c
 create mode 100644 kexec/dt-ops.h
 create mode 100644 purgatory/arch/arm64/Makefile
 create mode 100644 purgatory/arch/arm64/entry.S
 create mode 100644 purgatory/arch/arm64/purgatory-arm64.c

-- 
2.5.0

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v2 0/4] arm64 kexec-tools patches
@ 2016-07-26 20:18 ` Geoff Levand
  0 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-26 20:18 UTC (permalink / raw)
  To: Simon Horman; +Cc: Pratyush Anand, AKASHI Takahiro, kexec, linux-arm-kernel

This series adds the core support for kexec re-boot on ARM64.

Linux kernel support for kexec reboot [1] has been merged to the ARM64
for-next/core branch with the expectation that it will be included in the v4.8
stable kernel release.

For ARM64 kdump support see Takahiro's patches [2].

[1] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-June/438780.html
[2] http://lists.infradead.org/pipermail/kexec/2016-July/016642.html

Changes for v2 (July 26, 2016, 0m):

  o Inline some small routines.
  o Reformat some dbgprintf messages.
  o Remove debug_brk from entry.S
  o Change arm64_image_header.flags to uint64_t.
  o Look in iomem then dt for mem info.
  o Remove check_cpu_nodes.
  o Remove purgatory printing.

First submission v1 (July 20, 2016).

-Geoff

The following changes since commit 8d614008609f6ad5d09263767ebc771e06a173f0:

  arm: use zImage size from header (2016-07-15 13:12:28 +0900)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/geoff/kexec-tools.git for-merge-arm64-v2

for you to fetch changes up to f352dcfc827a4cbb3878dd1043877a4154b1bd08:

  arm64: Add support for binary image files (2016-07-26 11:48:01 -0700)

----------------------------------------------------------------
AKASHI Takahiro (1):
      kexec: (bugfix) calc correct end address of memory ranges in device tree

Geoff Levand (2):
      kexec: Add common device tree routines
      arm64: Add arm64 kexec support

Pratyush Anand (1):
      arm64: Add support for binary image files

 configure.ac                            |   3 +
 kexec/Makefile                          |   5 +
 kexec/arch/arm64/Makefile               |  40 ++
 kexec/arch/arm64/crashdump-arm64.c      |  21 +
 kexec/arch/arm64/crashdump-arm64.h      |  12 +
 kexec/arch/arm64/image-header.h         |  98 +++++
 kexec/arch/arm64/include/arch/options.h |  39 ++
 kexec/arch/arm64/kexec-arm64.c          | 704 ++++++++++++++++++++++++++++++++
 kexec/arch/arm64/kexec-arm64.h          |  70 ++++
 kexec/arch/arm64/kexec-elf-arm64.c      | 130 ++++++
 kexec/arch/arm64/kexec-image-arm64.c    |  63 +++
 kexec/dt-ops.c                          | 139 +++++++
 kexec/dt-ops.h                          |  13 +
 kexec/fs2dt.c                           |   5 +-
 kexec/kexec-syscall.h                   |   8 +-
 purgatory/Makefile                      |   1 +
 purgatory/arch/arm64/Makefile           |  18 +
 purgatory/arch/arm64/entry.S            |  51 +++
 purgatory/arch/arm64/purgatory-arm64.c  |  19 +
 19 files changed, 1435 insertions(+), 4 deletions(-)
 create mode 100644 kexec/arch/arm64/Makefile
 create mode 100644 kexec/arch/arm64/crashdump-arm64.c
 create mode 100644 kexec/arch/arm64/crashdump-arm64.h
 create mode 100644 kexec/arch/arm64/image-header.h
 create mode 100644 kexec/arch/arm64/include/arch/options.h
 create mode 100644 kexec/arch/arm64/kexec-arm64.c
 create mode 100644 kexec/arch/arm64/kexec-arm64.h
 create mode 100644 kexec/arch/arm64/kexec-elf-arm64.c
 create mode 100644 kexec/arch/arm64/kexec-image-arm64.c
 create mode 100644 kexec/dt-ops.c
 create mode 100644 kexec/dt-ops.h
 create mode 100644 purgatory/arch/arm64/Makefile
 create mode 100644 purgatory/arch/arm64/entry.S
 create mode 100644 purgatory/arch/arm64/purgatory-arm64.c

-- 
2.5.0


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v2 4/4] arm64: Add support for binary image files
  2016-07-26 20:18 ` Geoff Levand
@ 2016-07-26 20:18   ` Geoff Levand
  -1 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-26 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

From: Pratyush Anand <panand@redhat.com>

Signed-off-by: Pratyush Anand <panand@redhat.com>
[Reworked and cleaned up]
Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 kexec/arch/arm64/kexec-image-arm64.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
index 84386f7..cad7c73 100644
--- a/kexec/arch/arm64/kexec-image-arm64.c
+++ b/kexec/arch/arm64/kexec-image-arm64.c
@@ -24,21 +24,40 @@ int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
 		return -1;
 	}
 
-	fprintf(stderr, "kexec: ARM64 binary image files are currently NOT SUPPORTED.\n");
-
-	return -1;
+	return 0;
 }
 
 int image_arm64_load(int argc, char **argv, const char *kernel_buf,
 	off_t kernel_size, struct kexec_info *info)
 {
-	return -EFAILED;
+	const struct arm64_image_header *h;
+	unsigned long image_base;
+
+	h = (const struct arm64_image_header *)(kernel_buf);
+
+	if (arm64_process_image_header(h))
+		return -EINVAL;
+
+	dbgprintf("%s: text_offset:   %016lx\n", __func__,
+		arm64_mem.text_offset);
+	dbgprintf("%s: image_size:    %016lx\n", __func__,
+		arm64_mem.image_size);
+	dbgprintf("%s: phys_offset:   %016lx\n", __func__,
+		arm64_mem.phys_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;
+	
+	add_segment_phys_virt(info, kernel_buf, kernel_size, image_base,
+		arm64_mem.image_size, 0);
+
+	return arm64_load_other_segments(info, image_base);
 }
 
 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"
-"     This file type is currently NOT SUPPORTED.\n\n");
+"     Typically an Image, Image.gz or Image.lzma file.\n\n");
 }
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v2 2/4] kexec: Add common device tree routines
  2016-07-26 20:18 ` Geoff Levand
@ 2016-07-26 20:18   ` Geoff Levand
  -1 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-26 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

Common device tree routines that can be shared between all arches
that have device tree support.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 kexec/Makefile |   4 ++
 kexec/dt-ops.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 kexec/dt-ops.h |  13 ++++++
 3 files changed, 156 insertions(+)
 create mode 100644 kexec/dt-ops.c
 create mode 100644 kexec/dt-ops.h

diff --git a/kexec/Makefile b/kexec/Makefile
index e2aee84..cc3f08b 100644
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -73,6 +73,10 @@ dist				+= kexec/mem_regions.c kexec/mem_regions.h
 $(ARCH)_MEM_REGIONS		=
 KEXEC_SRCS			+= $($(ARCH)_MEM_REGIONS)
 
+dist				+= kexec/dt-ops.c kexec/dt-ops.h
+$(ARCH)_DT_OPS		=
+KEXEC_SRCS			+= $($(ARCH)_DT_OPS)
+
 include $(srcdir)/kexec/arch/alpha/Makefile
 include $(srcdir)/kexec/arch/arm/Makefile
 include $(srcdir)/kexec/arch/i386/Makefile
diff --git a/kexec/dt-ops.c b/kexec/dt-ops.c
new file mode 100644
index 0000000..060776a
--- /dev/null
+++ b/kexec/dt-ops.c
@@ -0,0 +1,139 @@
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <libfdt.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "kexec.h"
+#include "dt-ops.h"
+
+static const char n_chosen[] = "/chosen";
+
+static const char p_bootargs[] = "bootargs";
+static const char p_initrd_start[] = "linux,initrd-start";
+static const char p_initrd_end[] = "linux,initrd-end";
+
+int dtb_set_initrd(char **dtb, off_t *dtb_size, off_t start, off_t end)
+{
+	int result;
+	uint64_t value;
+
+	dbgprintf("%s: start %jd, end %jd, size %jd (%jd KiB)\n",
+		__func__, (intmax_t)start, (intmax_t)end,
+		(intmax_t)(end - start),
+		(intmax_t)(end - start) / 1024);
+
+	value = cpu_to_fdt64(start);
+
+	result = dtb_set_property(dtb, dtb_size, n_chosen, p_initrd_start,
+		&value, sizeof(value));
+
+	if (result)
+		return result;
+
+	value = cpu_to_fdt64(end);
+
+	result = dtb_set_property(dtb, dtb_size, n_chosen, p_initrd_end,
+		&value, sizeof(value));
+
+	if (result) {
+		dtb_delete_property(*dtb, n_chosen, p_initrd_start);
+		return result;
+	}
+
+	return 0;
+}
+
+int dtb_set_bootargs(char **dtb, off_t *dtb_size, const char *command_line)
+{
+	return dtb_set_property(dtb, dtb_size, n_chosen, p_bootargs,
+		command_line, strlen(command_line) + 1);
+}
+
+int dtb_set_property(char **dtb, off_t *dtb_size, const char *node,
+	const char *prop, const void *value, int value_len)
+{
+	int result;
+	int nodeoffset;
+	void *new_dtb;
+	int new_size;
+
+	value_len = FDT_TAGALIGN(value_len);
+
+	new_size = FDT_TAGALIGN(*dtb_size + fdt_node_len(node)
+		+ fdt_prop_len(prop, value_len));
+
+	new_dtb = malloc(new_size);
+
+	if (!new_dtb) {
+		dbgprintf("%s: malloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	result = fdt_open_into(*dtb, new_dtb, new_size);
+
+	if (result) {
+		dbgprintf("%s: fdt_open_into failed: %s\n", __func__,
+			fdt_strerror(result));
+		goto on_error;
+	}
+
+	nodeoffset = fdt_path_offset(new_dtb, node);
+	
+	if (nodeoffset == -FDT_ERR_NOTFOUND) {
+		result = fdt_add_subnode(new_dtb, nodeoffset, node);
+
+		if (result) {
+			dbgprintf("%s: fdt_add_subnode failed: %s\n", __func__,
+				fdt_strerror(result));
+			goto on_error;
+		}
+	} else if (nodeoffset < 0) {
+		dbgprintf("%s: fdt_path_offset failed: %s\n", __func__,
+			fdt_strerror(nodeoffset));
+		goto on_error;
+	}
+
+	result = fdt_setprop(new_dtb, nodeoffset, prop, value, value_len);
+
+	if (result) {
+		dbgprintf("%s: fdt_setprop failed: %s\n", __func__,
+			fdt_strerror(result));
+		goto on_error;
+	}
+
+	/*
+	 * Can't call free on dtb since dtb may have been mmaped by
+	 * slurp_file().
+	 */
+
+	*dtb = new_dtb;
+	*dtb_size = new_size;
+
+	return 0;
+
+on_error:
+	free(new_dtb);
+	return result;
+}
+
+int dtb_delete_property(char *dtb, const char *node, const char *prop)
+{
+	int result;
+	int nodeoffset = fdt_path_offset(dtb, node);
+
+	if (nodeoffset < 0) {
+		dbgprintf("%s: fdt_path_offset failed: %s\n", __func__,
+			fdt_strerror(nodeoffset));
+		return nodeoffset;
+	}
+
+	result = fdt_delprop(dtb, nodeoffset, prop);
+
+	if (result)
+		dbgprintf("%s: fdt_delprop failed: %s\n", __func__,
+			fdt_strerror(nodeoffset));
+
+	return result;
+}
diff --git a/kexec/dt-ops.h b/kexec/dt-ops.h
new file mode 100644
index 0000000..e70d15d
--- /dev/null
+++ b/kexec/dt-ops.h
@@ -0,0 +1,13 @@
+#if !defined(KEXEC_DT_OPS_H)
+#define KEXEC_DT_OPS_H
+
+#include <sys/types.h>
+
+int dtb_set_initrd(char **dtb, off_t *dtb_size, off_t start, off_t end);
+int dtb_set_bootargs(char **dtb, off_t *dtb_size, const char *command_line);
+int dtb_set_property(char **dtb, off_t *dtb_size, const char *node,
+	const char *prop, const void *value, int value_len);
+
+int dtb_delete_property(char *dtb, const char *node, const char *prop);
+
+#endif
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v2 3/4] arm64: Add arm64 kexec support
  2016-07-26 20:18 ` Geoff Levand
@ 2016-07-26 20:18   ` Geoff Levand
  -1 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-26 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

Add kexec reboot support for ARM64 platforms.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 configure.ac                            |   3 +
 kexec/Makefile                          |   1 +
 kexec/arch/arm64/Makefile               |  40 ++
 kexec/arch/arm64/crashdump-arm64.c      |  21 +
 kexec/arch/arm64/crashdump-arm64.h      |  12 +
 kexec/arch/arm64/image-header.h         |  98 +++++
 kexec/arch/arm64/include/arch/options.h |  39 ++
 kexec/arch/arm64/kexec-arm64.c          | 704 ++++++++++++++++++++++++++++++++
 kexec/arch/arm64/kexec-arm64.h          |  70 ++++
 kexec/arch/arm64/kexec-elf-arm64.c      | 130 ++++++
 kexec/arch/arm64/kexec-image-arm64.c    |  44 ++
 kexec/kexec-syscall.h                   |   8 +-
 purgatory/Makefile                      |   1 +
 purgatory/arch/arm64/Makefile           |  18 +
 purgatory/arch/arm64/entry.S            |  51 +++
 purgatory/arch/arm64/purgatory-arm64.c  |  19 +
 16 files changed, 1257 insertions(+), 2 deletions(-)
 create mode 100644 kexec/arch/arm64/Makefile
 create mode 100644 kexec/arch/arm64/crashdump-arm64.c
 create mode 100644 kexec/arch/arm64/crashdump-arm64.h
 create mode 100644 kexec/arch/arm64/image-header.h
 create mode 100644 kexec/arch/arm64/include/arch/options.h
 create mode 100644 kexec/arch/arm64/kexec-arm64.c
 create mode 100644 kexec/arch/arm64/kexec-arm64.h
 create mode 100644 kexec/arch/arm64/kexec-elf-arm64.c
 create mode 100644 kexec/arch/arm64/kexec-image-arm64.c
 create mode 100644 purgatory/arch/arm64/Makefile
 create mode 100644 purgatory/arch/arm64/entry.S
 create mode 100644 purgatory/arch/arm64/purgatory-arm64.c

diff --git a/configure.ac b/configure.ac
index ca3a9d5..8858c94 100644
--- a/configure.ac
+++ b/configure.ac
@@ -34,6 +34,9 @@ case $target_cpu in
 		ARCH="ppc64"
 		SUBARCH="LE"
 		;;
+	aarch64* )
+		ARCH="arm64"
+		;;
 	arm* )
 		ARCH="arm"
 		;;
diff --git a/kexec/Makefile b/kexec/Makefile
index cc3f08b..39f365f 100644
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -79,6 +79,7 @@ KEXEC_SRCS			+= $($(ARCH)_DT_OPS)
 
 include $(srcdir)/kexec/arch/alpha/Makefile
 include $(srcdir)/kexec/arch/arm/Makefile
+include $(srcdir)/kexec/arch/arm64/Makefile
 include $(srcdir)/kexec/arch/i386/Makefile
 include $(srcdir)/kexec/arch/ia64/Makefile
 include $(srcdir)/kexec/arch/m68k/Makefile
diff --git a/kexec/arch/arm64/Makefile b/kexec/arch/arm64/Makefile
new file mode 100644
index 0000000..37414dc
--- /dev/null
+++ b/kexec/arch/arm64/Makefile
@@ -0,0 +1,40 @@
+
+arm64_FS2DT += kexec/fs2dt.c
+arm64_FS2DT_INCLUDE += -include $(srcdir)/kexec/arch/arm64/kexec-arm64.h \
+	-include $(srcdir)/kexec/arch/arm64/crashdump-arm64.h
+
+arm64_DT_OPS += kexec/dt-ops.c
+
+arm64_CPPFLAGS += -I $(srcdir)/kexec/
+
+arm64_KEXEC_SRCS += \
+	kexec/arch/arm64/kexec-arm64.c \
+	kexec/arch/arm64/kexec-image-arm64.c \
+	kexec/arch/arm64/kexec-elf-arm64.c \
+	kexec/arch/arm64/crashdump-arm64.c
+
+arm64_ARCH_REUSE_INITRD =
+arm64_ADD_SEGMENT =
+arm64_VIRT_TO_PHYS =
+arm64_PHYS_TO_VIRT =
+
+dist += $(arm64_KEXEC_SRCS) \
+	kexec/arch/arm64/Makefile \
+	kexec/arch/arm64/kexec-arm64.h \
+	kexec/arch/arm64/crashdump-arm64.h
+
+ifdef HAVE_LIBFDT
+
+LIBS += -lfdt
+
+else
+
+include $(srcdir)/kexec/libfdt/Makefile.libfdt
+
+libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%)
+
+arm64_CPPFLAGS += -I$(srcdir)/kexec/libfdt
+
+arm64_KEXEC_SRCS += $(libfdt_SRCS)
+
+endif
diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
new file mode 100644
index 0000000..d2272c8
--- /dev/null
+++ b/kexec/arch/arm64/crashdump-arm64.c
@@ -0,0 +1,21 @@
+/*
+ * ARM64 crashdump.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <linux/elf.h>
+
+#include "kexec.h"
+#include "crashdump.h"
+#include "crashdump-arm64.h"
+#include "kexec-arm64.h"
+#include "kexec-elf.h"
+
+struct memory_ranges usablemem_rgns = {};
+
+int is_crashkernel_mem_reserved(void)
+{
+	return 0;
+}
diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
new file mode 100644
index 0000000..f33c7a2
--- /dev/null
+++ b/kexec/arch/arm64/crashdump-arm64.h
@@ -0,0 +1,12 @@
+/*
+ * ARM64 crashdump.
+ */
+
+#if !defined(CRASHDUMP_ARM64_H)
+#define CRASHDUMP_ARM64_H
+
+#include "kexec.h"
+
+extern struct memory_ranges usablemem_rgns;
+
+#endif
diff --git a/kexec/arch/arm64/image-header.h b/kexec/arch/arm64/image-header.h
new file mode 100644
index 0000000..e9a6db8
--- /dev/null
+++ b/kexec/arch/arm64/image-header.h
@@ -0,0 +1,98 @@
+/*
+ * ARM64 binary image header.
+ */
+
+#if !defined(__ARM64_IMAGE_HEADER_H)
+#define __ARM64_IMAGE_HEADER_H
+
+#include <endian.h>
+#include <stdint.h>
+
+/**
+ * struct arm64_image_header - arm64 kernel image header.
+ *
+ * @pe_sig: Optional PE format 'MZ' signature.
+ * @branch_code: Reserved for instructions to branch to stext.
+ * @text_offset: The image load offset in LSB byte order.
+ * @image_size: An estimated size of the memory image size in LSB byte order.
+ * @flags: Bit flags in LSB byte order:
+ *   Bit 0: Image byte order, 1=MSB.
+ * @reserved_1: Reserved.
+ * @magic: Magic number, "ARM\x64".
+ * @pe_header: Optional offset to a PE format header.
+ **/
+
+struct arm64_image_header {
+	uint8_t pe_sig[2];
+	uint16_t branch_code[3];
+	uint64_t text_offset;
+	uint64_t image_size;
+	uint64_t flags;
+	uint64_t reserved_1[3];
+	uint8_t magic[4];
+	uint32_t pe_header;
+};
+
+static const uint8_t arm64_image_magic[4] = {'A', 'R', 'M', 0x64U};
+static const uint8_t arm64_image_pe_sig[2] = {'M', 'Z'};
+static const uint64_t arm64_image_flag_be = (1UL << 0);
+
+/**
+ * arm64_header_check_magic - Helper to check the arm64 image header.
+ *
+ * Returns non-zero if header is OK.
+ */
+
+static inline int arm64_header_check_magic(const struct arm64_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return (h->magic[0] == arm64_image_magic[0]
+		&& h->magic[1] == arm64_image_magic[1]
+		&& h->magic[2] == arm64_image_magic[2]
+		&& h->magic[3] == arm64_image_magic[3]);
+}
+
+/**
+ * arm64_header_check_pe_sig - Helper to check the arm64 image header.
+ *
+ * Returns non-zero if 'MZ' signature is found.
+ */
+
+static inline int arm64_header_check_pe_sig(const struct arm64_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return (h->pe_sig[0] == arm64_image_pe_sig[0]
+		&& h->pe_sig[1] == arm64_image_pe_sig[1]);
+}
+
+/**
+ * arm64_header_check_msb - Helper to check the arm64 image header.
+ *
+ * Returns non-zero if the image was built as big endian.
+ */
+
+static inline int arm64_header_check_msb(const struct arm64_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return le64toh(h->flags) & arm64_image_flag_be;
+}
+
+static inline uint64_t arm64_header_text_offset(
+	const struct arm64_image_header *h)
+{
+	return le64toh(h->text_offset);
+}
+
+static inline uint64_t arm64_header_image_size(
+	const struct arm64_image_header *h)
+{
+	return le64toh(h->image_size);
+}
+
+#endif
diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h
new file mode 100644
index 0000000..d6f08ad
--- /dev/null
+++ b/kexec/arch/arm64/include/arch/options.h
@@ -0,0 +1,39 @@
+#if !defined(KEXEC_ARCH_ARM64_OPTIONS_H)
+#define KEXEC_ARCH_ARM64_OPTIONS_H
+
+#define OPT_APPEND		((OPT_MAX)+0)
+#define OPT_DTB			((OPT_MAX)+1)
+#define OPT_INITRD		((OPT_MAX)+2)
+#define OPT_REUSE_CMDLINE	((OPT_MAX)+4)
+#define OPT_ARCH_MAX		((OPT_MAX)+5)
+
+#define KEXEC_ARCH_OPTIONS \
+	KEXEC_OPTIONS \
+	{ "append",        1, NULL, OPT_APPEND }, \
+	{ "command-line",  1, NULL, OPT_APPEND }, \
+	{ "dtb",           1, NULL, OPT_DTB }, \
+	{ "initrd",        1, NULL, OPT_INITRD }, \
+	{ "ramdisk",       1, NULL, OPT_INITRD }, \
+	{ "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \
+
+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */
+#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS
+#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR
+
+static const char arm64_opts_usage[] __attribute__ ((unused)) =
+"     --append=STRING       Set the kernel command line to STRING.\n"
+"     --command-line=STRING Set the kernel command line to STRING.\n"
+"     --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";
+
+struct arm64_opts {
+	const char *command_line;
+	const char *dtb;
+	const char *initrd;
+};
+
+extern struct arm64_opts arm64_opts;
+
+#endif
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
new file mode 100644
index 0000000..940cddb
--- /dev/null
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -0,0 +1,704 @@
+/*
+ * ARM64 kexec.
+ */
+
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <errno.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <libfdt.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <linux/elf.h>
+
+#include "kexec.h"
+#include "kexec-arm64.h"
+#include "crashdump.h"
+#include "crashdump-arm64.h"
+#include "dt-ops.h"
+#include "fs2dt.h"
+#include "kexec-syscall.h"
+#include "arch/options.h"
+
+/* Global varables the core kexec routines expect. */
+
+unsigned char reuse_initrd;
+
+off_t initrd_base;
+off_t initrd_size;
+
+const struct arch_map_entry arches[] = {
+	{ "aarch64", KEXEC_ARCH_ARM64 },
+	{ "aarch64_be", KEXEC_ARCH_ARM64 },
+	{ NULL, 0 },
+};
+
+struct file_type file_type[] = {
+	{"vmlinux", elf_arm64_probe, elf_arm64_load, elf_arm64_usage},
+	{"Image", image_arm64_probe, image_arm64_load, image_arm64_usage},
+};
+
+int file_types = sizeof(file_type) / sizeof(file_type[0]);
+
+/* arm64 global varables. */
+
+struct arm64_opts arm64_opts;
+struct arm64_mem arm64_mem = {
+	.phys_offset = arm64_mem_ngv,
+	.page_offset = arm64_mem_ngv,
+};
+
+uint64_t get_phys_offset(void)
+{
+	assert(arm64_mem.phys_offset != arm64_mem_ngv);
+	return arm64_mem.phys_offset;
+}
+
+uint64_t get_page_offset(void)
+{
+	assert(arm64_mem.page_offset != arm64_mem_ngv);
+	return arm64_mem.page_offset;
+}
+
+/**
+ * arm64_process_image_header - Process the arm64 image header.
+ *
+ * Make a guess that KERNEL_IMAGE_SIZE will be enough for older kernels.
+ */
+
+int arm64_process_image_header(const struct arm64_image_header *h)
+{
+#if !defined(KERNEL_IMAGE_SIZE)
+# define KERNEL_IMAGE_SIZE MiB(16)
+#endif
+
+	if (!arm64_header_check_magic(h))
+		return -EFAILED;
+
+	if (h->image_size) {
+		arm64_mem.text_offset = arm64_header_text_offset(h);
+		arm64_mem.image_size = arm64_header_image_size(h);
+	} else {
+		/* For 3.16 and older kernels. */
+		arm64_mem.text_offset = 0x80000;
+		arm64_mem.image_size = KERNEL_IMAGE_SIZE;
+		fprintf(stderr,
+			"kexec: %s: Warning: Kernel image size set to %lu MiB.\n"
+			"  Please verify compatability with lodaed kernel.\n",
+			__func__, KERNEL_IMAGE_SIZE / 1024UL / 1024UL);
+	}
+
+	return 0;
+}
+
+void arch_usage(void)
+{
+	printf(arm64_opts_usage);
+}
+
+int arch_process_options(int argc, char **argv)
+{
+	static const char short_options[] = KEXEC_OPT_STR "";
+	static const struct option options[] = {
+		KEXEC_ARCH_OPTIONS
+		{ 0 }
+	};
+	int opt;
+	char *cmdline = NULL;
+	const char *append = NULL;
+
+	for (opt = 0; opt != -1; ) {
+		opt = getopt_long(argc, argv, short_options, options, 0);
+
+		switch (opt) {
+		case OPT_APPEND:
+			append = optarg;
+			break;
+		case OPT_REUSE_CMDLINE:
+			cmdline = get_command_line();
+			break;
+		case OPT_DTB:
+			arm64_opts.dtb = optarg;
+			break;
+		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. */
+		}
+	}
+
+	arm64_opts.command_line = concat_cmdline(cmdline, append);
+
+	dbgprintf("%s:%d: command_line: %s\n", __func__, __LINE__,
+		arm64_opts.command_line);
+	dbgprintf("%s:%d: initrd: %s\n", __func__, __LINE__,
+		arm64_opts.initrd);
+	dbgprintf("%s:%d: dtb: %s\n", __func__, __LINE__, arm64_opts.dtb);
+
+	return 0;
+}
+
+/**
+ * struct dtb - Info about a binary device tree.
+ *
+ * @buf: Device tree data.
+ * @size: Device tree data size.
+ * @name: Shorthand name of this dtb for messages.
+ * @path: Filesystem path.
+ */
+
+struct dtb {
+	char *buf;
+	off_t size;
+	const char *name;
+	const char *path;
+};
+
+/**
+ * dump_reservemap - Dump the dtb's reservemap.
+ */
+
+static void dump_reservemap(const struct dtb *dtb)
+{
+	int i;
+
+	for (i = 0; ; i++) {
+		uint64_t address;
+		uint64_t size;
+
+		fdt_get_mem_rsv(dtb->buf, i, &address, &size);
+
+		if (!size)
+			break;
+
+		dbgprintf("%s: %s {%" PRIx64 ", %" PRIx64 "}\n", __func__,
+			dtb->name, address, size);
+	}
+}
+
+/**
+ * set_bootargs - Set the dtb's bootargs.
+ */
+
+static int set_bootargs(struct dtb *dtb, const char *command_line)
+{
+	int result;
+
+	if (!command_line || !command_line[0])
+		return 0;
+
+	result = dtb_set_bootargs(&dtb->buf, &dtb->size, command_line);
+
+	if (result) {
+		fprintf(stderr,
+			"kexec: Set device tree bootargs failed.\n");
+		return -EFAILED;
+	}
+
+	return 0;
+}
+
+/**
+ * read_proc_dtb - Read /proc/device-tree.
+ */
+
+static int read_proc_dtb(struct dtb *dtb)
+{
+	int result;
+	struct stat s;
+	static const char path[] = "/proc/device-tree";
+
+	result = stat(path, &s);
+
+	if (result) {
+		dbgprintf("%s: %s\n", __func__, strerror(errno));
+		return -EFAILED;
+	}
+
+	dtb->path = path;
+	create_flatten_tree((char **)&dtb->buf, &dtb->size, NULL);
+
+	return 0;
+}
+
+/**
+ * read_sys_dtb - Read /sys/firmware/fdt.
+ */
+
+static int read_sys_dtb(struct dtb *dtb)
+{
+	int result;
+	struct stat s;
+	static const char path[] = "/sys/firmware/fdt";
+
+	result = stat(path, &s);
+
+	if (result) {
+		dbgprintf("%s: %s\n", __func__, strerror(errno));
+		return -EFAILED;
+	}
+
+	dtb->path = path;
+	dtb->buf = slurp_file(path, &dtb->size);
+
+	return 0;
+}
+
+/**
+ * read_1st_dtb - Read the 1st stage kernel's dtb.
+ */
+
+static int read_1st_dtb(struct dtb *dtb)
+{
+	int result;
+
+	result = read_sys_dtb(dtb);
+
+	if (!result)
+		goto on_success;
+
+	result = read_proc_dtb(dtb);
+
+	if (!result)
+		goto on_success;
+
+	dbgprintf("%s: not found\n", __func__);
+	return -EFAILED;
+
+on_success:
+	dbgprintf("%s: found %s\n", __func__, dtb->path);
+	return 0;
+}
+
+/**
+ * setup_2nd_dtb - Setup the 2nd stage kernel's dtb.
+ */
+
+static int setup_2nd_dtb(struct dtb *dtb, char *command_line)
+{
+	int result;
+
+	result = fdt_check_header(dtb->buf);
+
+	if (result) {
+		fprintf(stderr, "kexec: Invalid 2nd device tree.\n");
+		return -EFAILED;
+	}
+
+	result = set_bootargs(dtb, command_line);
+
+	dump_reservemap(dtb);
+
+	return result;
+}
+
+/**
+ * arm64_load_other_segments - Prepare the dtb, initrd and purgatory segments.
+ */
+
+int arm64_load_other_segments(struct kexec_info *info,
+	uint64_t kernel_entry)
+{
+	int result;
+	uint64_t dtb_base;
+	uint64_t image_base;
+	unsigned long hole_min;
+	unsigned long hole_max;
+	char *initrd_buf = NULL;
+	struct dtb dtb;
+	char command_line[COMMAND_LINE_SIZE] = "";
+
+	if (arm64_opts.command_line) {
+		strncpy(command_line, arm64_opts.command_line,
+			sizeof(command_line));
+		command_line[sizeof(command_line) - 1] = 0;
+	}
+
+	if (arm64_opts.dtb) {
+		dtb.name = "dtb_2";
+		dtb.buf = slurp_file(arm64_opts.dtb, &dtb.size);
+	} else {
+		dtb.name = "dtb_1";
+		result = read_1st_dtb(&dtb);
+
+		if (result) {
+			fprintf(stderr,
+				"kexec: Error: No device tree available.\n");
+			return -EFAILED;
+		}
+	}
+
+	result = setup_2nd_dtb(&dtb, command_line);
+
+	if (result)
+		return -EFAILED;
+
+	/* Put the other segments after the image. */
+
+	image_base = arm64_mem.phys_offset + arm64_mem.text_offset;
+	hole_min = image_base + arm64_mem.image_size;
+	hole_max = ULONG_MAX;
+
+	if (arm64_opts.initrd) {
+		initrd_buf = slurp_file(arm64_opts.initrd, &initrd_size);
+
+		if (!initrd_buf)
+			fprintf(stderr, "kexec: Empty ramdisk file.\n");
+		else {
+			/*
+			 * Put the initrd after the kernel.  As specified in
+			 * booting.txt, align to 1 GiB.
+			 */
+
+			initrd_base = add_buffer_phys_virt(info, initrd_buf,
+				initrd_size, initrd_size, GiB(1),
+				hole_min, hole_max, 1, 0);
+
+			/* initrd_base is valid if we got here. */
+
+			dbgprintf("initrd: base %lx, size %lxh (%ld)\n",
+				initrd_base, initrd_size, initrd_size);
+
+			/* Check size limit as specified in booting.txt. */
+
+			if (initrd_base - image_base + initrd_size > GiB(32)) {
+				fprintf(stderr, "kexec: Error: image + initrd too big.\n");
+				return -EFAILED;
+			}
+
+			result = dtb_set_initrd((char **)&dtb.buf,
+				&dtb.size, initrd_base,
+				initrd_base + initrd_size);
+
+			if (result)
+				return -EFAILED;
+		}
+	}
+
+	/* Check size limit as specified in booting.txt. */
+
+	if (dtb.size > MiB(2)) {
+		fprintf(stderr, "kexec: Error: dtb too big.\n");
+		return -EFAILED;
+	}
+
+	dtb_base = add_buffer_phys_virt(info, dtb.buf, dtb.size, dtb.size,
+		0, hole_min, hole_max, 1, 0);
+
+	/* dtb_base is valid if we got here. */
+
+	dbgprintf("dtb:    base %lx, size %lxh (%ld)\n", dtb_base, dtb.size,
+		dtb.size);
+
+	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+		hole_min, hole_max, 1, 0);
+
+	info->entry = (void *)elf_rel_get_addr(&info->rhdr, "purgatory_start");
+
+	elf_rel_set_symbol(&info->rhdr, "arm64_kernel_entry", &kernel_entry,
+		sizeof(kernel_entry));
+
+	elf_rel_set_symbol(&info->rhdr, "arm64_dtb_addr", &dtb_base,
+		sizeof(dtb_base));
+
+	return 0;
+}
+
+/**
+ * virt_to_phys - For processing elf file values.
+ */
+
+unsigned long virt_to_phys(unsigned long v)
+{
+	unsigned long p;
+
+	p = v - get_page_offset() + get_phys_offset();
+
+	return p;
+}
+
+/**
+ * phys_to_virt - For crashdump setup.
+ */
+
+unsigned long phys_to_virt(struct crash_elf_info *elf_info,
+	unsigned long long p)
+{
+	unsigned long v;
+
+	v = p - get_phys_offset() + elf_info->page_offset;
+
+	return v;
+}
+
+/**
+ * add_segment - Use virt_to_phys when loading elf files.
+ */
+
+void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
+	unsigned long base, size_t memsz)
+{
+	add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
+}
+
+/**
+ * get_memory_ranges_iomem_cb - Helper for get_memory_ranges_iomem.
+ */
+
+static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
+	unsigned long long base, unsigned long long length)
+{
+	struct memory_range *r;
+
+	if (nr >= KEXEC_SEGMENT_MAX)
+		return -1;
+
+	r = (struct memory_range *)data + nr;
+	r->type = RANGE_RAM;
+	r->start = base;
+	r->end = base + length - 1;
+
+	set_phys_offset(r->start);
+
+	dbgprintf("%s: %016llx - %016llx : %s", __func__, r->start,
+		r->end, str);
+
+	return 0;
+}
+
+/**
+ * get_memory_ranges_iomem - Try to get the memory ranges from /proc/iomem.
+ */
+
+static int get_memory_ranges_iomem(struct memory_range *array,
+	unsigned int *count)
+{
+	*count = kexec_iomem_for_each_line("System RAM\n",
+		get_memory_ranges_iomem_cb, array);
+
+	if (!*count) {
+		dbgprintf("%s: failed: No RAM found.\n", __func__);
+		return -EFAILED;
+	}
+
+	return 0;
+}
+
+/**
+ * get_memory_ranges_dt - Try to get the memory ranges from the 1st stage dtb.
+ */
+
+static int get_memory_ranges_dt(struct memory_range *array, unsigned int *count)
+{
+	struct region {uint64_t base; uint64_t size;};
+	struct dtb dtb = {.name = "range_dtb"};
+	int offset;
+	int result;
+
+	*count = 0;
+
+	result = read_1st_dtb(&dtb);
+
+	if (result) {
+		goto on_error;
+	}
+
+	result = fdt_check_header(dtb.buf);
+
+	if (result) {
+		dbgprintf("%s:%d: %s: fdt_check_header failed:%s\n", __func__,
+			__LINE__, dtb.path, fdt_strerror(result));
+		goto on_error;
+	}
+
+	for (offset = 0; ; ) {
+		const struct region *region;
+		const struct region *end;
+		int len;
+
+		offset = fdt_subnode_offset(dtb.buf, offset, "memory");
+
+		if (offset == -FDT_ERR_NOTFOUND)
+			break;
+
+		if (offset <= 0) {
+			dbgprintf("%s:%d: fdt_subnode_offset failed: %d %s\n",
+				__func__, __LINE__, offset,
+				fdt_strerror(offset));
+			goto on_error;
+		}
+
+		dbgprintf("%s:%d: node_%d %s\n", __func__, __LINE__, offset,
+			fdt_get_name(dtb.buf, offset, NULL));
+
+		region = fdt_getprop(dtb.buf, offset, "reg", &len);
+
+		if (region <= 0) {
+			dbgprintf("%s:%d: fdt_getprop failed: %d %s\n",
+				__func__, __LINE__, offset,
+				fdt_strerror(offset));
+			goto on_error;
+		}
+
+		for (end = region + len / sizeof(*region);
+			region < end && *count < KEXEC_SEGMENT_MAX;
+			region++) {
+			struct memory_range r;
+
+			r.type = RANGE_RAM;
+			r.start = fdt64_to_cpu(region->base);
+			r.end = r.start + fdt64_to_cpu(region->size) - 1;
+
+			if (!region->size) {
+				dbgprintf("%s:%d: SKIP: %016llx - %016llx\n",
+					__func__, __LINE__, r.start, r.end);
+				continue;
+			}
+
+			dbgprintf("%s:%d:  RAM: %016llx - %016llx\n", __func__,
+				__LINE__, r.start, r.end);
+
+			array[(*count)++] = r;
+
+			set_phys_offset(r.start);
+		}
+	}
+
+	if (!*count) {
+		dbgprintf("%s:%d: %s: No RAM found.\n", __func__, __LINE__,
+			dtb.path);
+		goto on_error;
+	}
+
+	dbgprintf("%s:%d: %s: Success\n", __func__, __LINE__, dtb.path);
+	result = 0;
+	goto on_exit;
+
+on_error:
+	fprintf(stderr, "%s:%d: %s: Unusable device-tree file\n", __func__,
+		__LINE__, dtb.path);
+	result = -1;
+
+on_exit:
+	free(dtb.buf);
+	return -EFAILED;
+}
+
+/**
+ * get_memory_ranges - Try to get the memory ranges some how.
+ */
+
+int get_memory_ranges(struct memory_range **range, int *ranges,
+	unsigned long kexec_flags)
+{
+	static struct memory_range array[KEXEC_SEGMENT_MAX];
+	unsigned int count;
+	int result;
+
+	result = get_memory_ranges_iomem(array, &count);
+
+	if (result)
+		result = get_memory_ranges_dt(array, &count);
+
+	*range = result ? NULL : array;
+	*ranges = result ? 0 : count;
+
+	return -EFAILED;
+}
+
+int arch_compat_trampoline(struct kexec_info *info)
+{
+	return 0;
+}
+
+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
+{
+	return (ehdr->e_machine == EM_AARCH64);
+}
+
+void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
+	unsigned long r_type, void *ptr, unsigned long address,
+	unsigned long value)
+{
+#if !defined(R_AARCH64_ABS64)
+# define R_AARCH64_ABS64 257
+#endif
+
+#if !defined(R_AARCH64_LD_PREL_LO19)
+# define R_AARCH64_LD_PREL_LO19 273
+#endif
+
+#if !defined(R_AARCH64_ADR_PREL_LO21)
+# define R_AARCH64_ADR_PREL_LO21 274
+#endif
+
+#if !defined(R_AARCH64_JUMP26)
+# define R_AARCH64_JUMP26 282
+#endif
+
+#if !defined(R_AARCH64_CALL26)
+# define R_AARCH64_CALL26 283
+#endif
+
+	uint64_t *loc64;
+	uint32_t *loc32;
+	uint64_t *location = (uint64_t *)ptr;
+	uint64_t data = *location;
+	const char *type = NULL;
+
+	switch(r_type) {
+	case R_AARCH64_ABS64:
+		type = "ABS64";
+		loc64 = ptr;
+		*loc64 = cpu_to_elf64(ehdr, elf64_to_cpu(ehdr, *loc64) + value);
+		break;
+	case R_AARCH64_LD_PREL_LO19:
+		type = "LD_PREL_LO19";
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ (((value - address) << 3) & 0xffffe0));
+		break;
+	case R_AARCH64_ADR_PREL_LO21:
+		if (value & 3)
+			die("%s: ERROR Unaligned value: %lx\n", __func__,
+				value);
+		type = "ADR_PREL_LO21";
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ (((value - address) << 3) & 0xffffe0));
+		break;
+	case R_AARCH64_JUMP26:
+		type = "JUMP26";
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ (((value - address) >> 2) & 0x3ffffff));
+		break;
+	case R_AARCH64_CALL26:
+		type = "CALL26";
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ (((value - address) >> 2) & 0x3ffffff));
+		break;
+	default:
+		die("%s: ERROR Unknown type: %lu\n", __func__, r_type);
+		break;
+	}
+
+	dbgprintf("%s: %s %016lx->%016lx\n", __func__, type, data, *location);
+}
+
+void arch_reuse_initrd(void)
+{
+	reuse_initrd = 1;
+}
+
+void arch_update_purgatory(struct kexec_info *UNUSED(info))
+{
+}
diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
new file mode 100644
index 0000000..0fb03a8
--- /dev/null
+++ b/kexec/arch/arm64/kexec-arm64.h
@@ -0,0 +1,70 @@
+/*
+ * ARM64 kexec.
+ */
+
+#if !defined(KEXEC_ARM64_H)
+#define KEXEC_ARM64_H
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "image-header.h"
+#include "kexec.h"
+
+#define KEXEC_SEGMENT_MAX 16
+
+#define BOOT_BLOCK_VERSION 17
+#define BOOT_BLOCK_LAST_COMP_VERSION 16
+#define COMMAND_LINE_SIZE 512
+
+#define KiB(x) ((x) * 1024UL)
+#define MiB(x) (KiB(x) * 1024UL)
+#define GiB(x) (MiB(x) * 1024UL)
+
+int elf_arm64_probe(const char *kernel_buf, off_t kernel_size);
+int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
+	off_t kernel_size, struct kexec_info *info);
+void elf_arm64_usage(void);
+
+int image_arm64_probe(const char *kernel_buf, off_t kernel_size);
+int image_arm64_load(int argc, char **argv, const char *kernel_buf,
+	off_t kernel_size, struct kexec_info *info);
+void image_arm64_usage(void);
+
+off_t initrd_base;
+off_t initrd_size;
+
+/**
+ * struct arm64_mem - Memory layout info.
+ */
+
+struct arm64_mem {
+	uint64_t phys_offset;
+	uint64_t text_offset;
+	uint64_t image_size;
+	uint64_t page_offset;
+};
+
+#define arm64_mem_ngv UINT64_MAX
+struct arm64_mem arm64_mem;
+
+uint64_t get_phys_offset(void);
+uint64_t get_page_offset(void);
+
+static inline void reset_page_offset(void)
+{
+	arm64_mem.page_offset = arm64_mem_ngv;
+}
+
+static inline void set_phys_offset(uint64_t v)
+{
+	if (arm64_mem.phys_offset == arm64_mem_ngv
+		|| v < arm64_mem.phys_offset)
+		arm64_mem.phys_offset = v;
+}
+
+int arm64_process_image_header(const struct arm64_image_header *h);
+int arm64_load_other_segments(struct kexec_info *info,
+	uint64_t kernel_entry);
+
+#endif
diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
new file mode 100644
index 0000000..fcac9bb
--- /dev/null
+++ b/kexec/arch/arm64/kexec-elf-arm64.c
@@ -0,0 +1,130 @@
+/*
+ * ARM64 kexec elf support.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <stdlib.h>
+#include <linux/elf.h>
+
+#include "kexec-arm64.h"
+#include "kexec-elf.h"
+#include "kexec-syscall.h"
+
+int elf_arm64_probe(const char *kernel_buf, off_t kernel_size)
+{
+	struct mem_ehdr ehdr;
+	int result;
+
+	result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0);
+
+	if (result < 0) {
+		dbgprintf("%s: Not an ELF executable.\n", __func__);
+		goto on_exit;
+	}
+
+	if (ehdr.e_machine != EM_AARCH64) {
+		dbgprintf("%s: Not an AARCH64 ELF executable.\n", __func__);
+		result = -1;
+		goto on_exit;
+	}
+
+	result = 0;
+on_exit:
+	free_elf_info(&ehdr);
+	return result;
+}
+
+int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
+	off_t kernel_size, struct kexec_info *info)
+{
+	struct mem_ehdr ehdr;
+	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) {
+		dbgprintf("%s: build_elf_exec_info failed\n", __func__);
+		goto exit;
+	}
+
+	/* Find and process the arm64 image header. */
+
+	for (i = 0; i < ehdr.e_phnum; i++) {
+		struct mem_phdr *phdr = &ehdr.e_phdr[i];
+		const struct arm64_image_header *h;
+		unsigned long header_offset;
+
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		/*
+		 * When CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET=y the image header
+		 * could be offset in the elf segment.  The linker script sets
+		 * ehdr.e_entry to the start of text.
+		 */
+
+		header_offset = ehdr.e_entry - phdr->p_vaddr;
+
+		h = (const struct arm64_image_header *)(
+			kernel_buf + phdr->p_offset + header_offset);
+
+		if (arm64_process_image_header(h))
+			continue;
+
+		arm64_mem.page_offset = ehdr.e_entry - arm64_mem.text_offset;
+
+		dbgprintf("%s: e_entry:       %016llx -> %016lx\n", __func__,
+			ehdr.e_entry,
+			virt_to_phys(ehdr.e_entry));
+		dbgprintf("%s: p_vaddr:       %016llx -> %016lx\n", __func__,
+			phdr->p_vaddr,
+			virt_to_phys(phdr->p_vaddr));
+		dbgprintf("%s: header_offset: %016lx\n", __func__,
+			header_offset);
+		dbgprintf("%s: text_offset:   %016lx\n", __func__,
+			arm64_mem.text_offset);
+		dbgprintf("%s: image_size:    %016lx\n", __func__,
+			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"));
+
+		result = elf_exec_load(&ehdr, info);
+
+		if (result) {
+			fprintf(stderr, "kexec: Elf load failed.\n");
+			goto exit;
+		}
+
+		result = arm64_load_other_segments(info,
+			virt_to_phys(ehdr.e_entry));
+		goto exit;
+	}
+
+	fprintf(stderr, "kexec: Bad arm64 image header.\n");
+	result = -EFAILED;
+	goto exit;
+
+exit:
+	reset_page_offset();
+	free_elf_info(&ehdr);
+	return result;
+}
+
+void elf_arm64_usage(void)
+{
+	printf(
+"     An ARM64 ELF image, big or little endian.\n"
+"     Typically vmlinux or a stripped version of vmlinux.\n\n");
+}
diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
new file mode 100644
index 0000000..84386f7
--- /dev/null
+++ b/kexec/arch/arm64/kexec-image-arm64.c
@@ -0,0 +1,44 @@
+/*
+ * ARM64 kexec binary image support.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+
+#include "kexec-arm64.h"
+
+int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
+{
+	const struct arm64_image_header *h;
+
+	if (kernel_size < sizeof(struct arm64_image_header)) {
+		dbgprintf("%s: No arm64 image header.\n", __func__);
+		return -1;
+	}
+
+	h = (const struct arm64_image_header *)(kernel_buf);
+
+	if (!arm64_header_check_magic(h)) {
+		dbgprintf("%s: Bad arm64 image header.\n", __func__);
+		return -1;
+	}
+
+	fprintf(stderr, "kexec: ARM64 binary image files are currently NOT SUPPORTED.\n");
+
+	return -1;
+}
+
+int image_arm64_load(int argc, char **argv, const char *kernel_buf,
+	off_t kernel_size, struct kexec_info *info)
+{
+	return -EFAILED;
+}
+
+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"
+"     This file type is currently NOT SUPPORTED.\n\n");
+}
diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
index ce2e20b..c0d0bea 100644
--- a/kexec/kexec-syscall.h
+++ b/kexec/kexec-syscall.h
@@ -39,8 +39,8 @@
 #ifdef __s390__
 #define __NR_kexec_load		277
 #endif
-#ifdef __arm__
-#define __NR_kexec_load		__NR_SYSCALL_BASE + 347  
+#if defined(__arm__) || defined(__arm64__)
+#define __NR_kexec_load		__NR_SYSCALL_BASE + 347
 #endif
 #if defined(__mips__)
 #define __NR_kexec_load                4311
@@ -108,6 +108,7 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd,
 #define KEXEC_ARCH_PPC64   (21 << 16)
 #define KEXEC_ARCH_IA_64   (50 << 16)
 #define KEXEC_ARCH_ARM     (40 << 16)
+#define KEXEC_ARCH_ARM64   (183 << 16)
 #define KEXEC_ARCH_S390    (22 << 16)
 #define KEXEC_ARCH_SH      (42 << 16)
 #define KEXEC_ARCH_MIPS_LE (10 << 16)
@@ -153,5 +154,8 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd,
 #ifdef __m68k__
 #define KEXEC_ARCH_NATIVE	KEXEC_ARCH_68K
 #endif
+#if defined(__arm64__)
+#define KEXEC_ARCH_NATIVE	KEXEC_ARCH_ARM64
+#endif
 
 #endif /* KEXEC_SYSCALL_H */
diff --git a/purgatory/Makefile b/purgatory/Makefile
index 2b5c061..ca0443c 100644
--- a/purgatory/Makefile
+++ b/purgatory/Makefile
@@ -19,6 +19,7 @@ dist += purgatory/Makefile $(PURGATORY_SRCS)				\
 
 include $(srcdir)/purgatory/arch/alpha/Makefile
 include $(srcdir)/purgatory/arch/arm/Makefile
+include $(srcdir)/purgatory/arch/arm64/Makefile
 include $(srcdir)/purgatory/arch/i386/Makefile
 include $(srcdir)/purgatory/arch/ia64/Makefile
 include $(srcdir)/purgatory/arch/mips/Makefile
diff --git a/purgatory/arch/arm64/Makefile b/purgatory/arch/arm64/Makefile
new file mode 100644
index 0000000..636abea
--- /dev/null
+++ b/purgatory/arch/arm64/Makefile
@@ -0,0 +1,18 @@
+
+arm64_PURGATORY_EXTRA_CFLAGS = \
+	-mcmodel=large \
+	-fno-stack-protector \
+	-fno-asynchronous-unwind-tables \
+	-Wundef \
+	-Werror-implicit-function-declaration \
+	-Wdeclaration-after-statement \
+	-Werror=implicit-int \
+	-Werror=strict-prototypes
+
+arm64_PURGATORY_SRCS += \
+	purgatory/arch/arm64/entry.S \
+	purgatory/arch/arm64/purgatory-arm64.c
+
+dist += \
+	$(arm64_PURGATORY_SRCS) \
+	purgatory/arch/arm64/Makefile
diff --git a/purgatory/arch/arm64/entry.S b/purgatory/arch/arm64/entry.S
new file mode 100644
index 0000000..adf16f4
--- /dev/null
+++ b/purgatory/arch/arm64/entry.S
@@ -0,0 +1,51 @@
+/*
+ * ARM64 purgatory.
+ */
+
+.macro	size, sym:req
+	.size \sym, . - \sym
+.endm
+
+.text
+
+.globl purgatory_start
+purgatory_start:
+
+	adr	x19, .Lstack
+	mov	sp, x19
+
+	bl	purgatory
+
+	/* Start new image. */
+	ldr	x17, arm64_kernel_entry
+	ldr	x0, arm64_dtb_addr
+	mov	x1, xzr
+	mov	x2, xzr
+	mov	x3, xzr
+	br	x17
+
+size purgatory_start
+
+.ltorg
+
+.align 4
+	.rept	256
+	.quad	0
+	.endr
+.Lstack:
+
+.data
+
+.align 3
+
+.globl arm64_kernel_entry
+arm64_kernel_entry:
+	.quad	0
+size arm64_kernel_entry
+
+.globl arm64_dtb_addr
+arm64_dtb_addr:
+	.quad	0
+size arm64_dtb_addr
+
+.end
\ No newline@end of file
diff --git a/purgatory/arch/arm64/purgatory-arm64.c b/purgatory/arch/arm64/purgatory-arm64.c
new file mode 100644
index 0000000..fe50fcf
--- /dev/null
+++ b/purgatory/arch/arm64/purgatory-arm64.c
@@ -0,0 +1,19 @@
+/*
+ * ARM64 purgatory.
+ */
+
+#include <stdint.h>
+#include <purgatory.h>
+
+void putchar(int ch)
+{
+	/* Nothing for now */
+}
+
+void post_verification_setup_arch(void)
+{
+}
+
+void setup_arch(void)
+{
+}
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v2 1/4] kexec: (bugfix) calc correct end address of memory ranges in device tree
  2016-07-26 20:18 ` Geoff Levand
@ 2016-07-26 20:18   ` Geoff Levand
  -1 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-26 20:18 UTC (permalink / raw)
  To: linux-arm-kernel

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

The end address of "reg" attribute in device tree's memory should be
inclusive.

From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 kexec/fs2dt.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/kexec/fs2dt.c b/kexec/fs2dt.c
index 6ed2399..f00fd98 100644
--- a/kexec/fs2dt.c
+++ b/kexec/fs2dt.c
@@ -236,7 +236,8 @@ static void add_dyn_reconf_usable_mem_property__(int fd)
 						    ranges_size*8);
 				}
 				ranges[rlen++] = cpu_to_be64(loc_base);
-				ranges[rlen++] = cpu_to_be64(loc_end - loc_base);
+				ranges[rlen++] = cpu_to_be64(loc_end
+								- loc_base + 1);
 				rngs_cnt++;
 			}
 		}
@@ -350,7 +351,7 @@ static void add_usable_mem_property(int fd, size_t len)
 					    ranges_size*sizeof(*ranges));
 			}
 			ranges[rlen++] = cpu_to_be64(loc_base);
-			ranges[rlen++] = cpu_to_be64(loc_end - loc_base);
+			ranges[rlen++] = cpu_to_be64(loc_end - loc_base + 1);
 		}
 	}
 
-- 
2.5.0

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v2 1/4] kexec: (bugfix) calc correct end address of memory ranges in device tree
@ 2016-07-26 20:18   ` Geoff Levand
  0 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-26 20:18 UTC (permalink / raw)
  To: Simon Horman; +Cc: Pratyush Anand, AKASHI Takahiro, kexec, linux-arm-kernel

From: AKASHI Takahiro <takahiro.akashi@linaro.org>

The end address of "reg" attribute in device tree's memory should be
inclusive.

From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 kexec/fs2dt.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/kexec/fs2dt.c b/kexec/fs2dt.c
index 6ed2399..f00fd98 100644
--- a/kexec/fs2dt.c
+++ b/kexec/fs2dt.c
@@ -236,7 +236,8 @@ static void add_dyn_reconf_usable_mem_property__(int fd)
 						    ranges_size*8);
 				}
 				ranges[rlen++] = cpu_to_be64(loc_base);
-				ranges[rlen++] = cpu_to_be64(loc_end - loc_base);
+				ranges[rlen++] = cpu_to_be64(loc_end
+								- loc_base + 1);
 				rngs_cnt++;
 			}
 		}
@@ -350,7 +351,7 @@ static void add_usable_mem_property(int fd, size_t len)
 					    ranges_size*sizeof(*ranges));
 			}
 			ranges[rlen++] = cpu_to_be64(loc_base);
-			ranges[rlen++] = cpu_to_be64(loc_end - loc_base);
+			ranges[rlen++] = cpu_to_be64(loc_end - loc_base + 1);
 		}
 	}
 
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v2 4/4] arm64: Add support for binary image files
@ 2016-07-26 20:18   ` Geoff Levand
  0 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-26 20:18 UTC (permalink / raw)
  To: Simon Horman; +Cc: Pratyush Anand, AKASHI Takahiro, kexec, linux-arm-kernel

From: Pratyush Anand <panand@redhat.com>

Signed-off-by: Pratyush Anand <panand@redhat.com>
[Reworked and cleaned up]
Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 kexec/arch/arm64/kexec-image-arm64.c | 31 +++++++++++++++++++++++++------
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
index 84386f7..cad7c73 100644
--- a/kexec/arch/arm64/kexec-image-arm64.c
+++ b/kexec/arch/arm64/kexec-image-arm64.c
@@ -24,21 +24,40 @@ int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
 		return -1;
 	}
 
-	fprintf(stderr, "kexec: ARM64 binary image files are currently NOT SUPPORTED.\n");
-
-	return -1;
+	return 0;
 }
 
 int image_arm64_load(int argc, char **argv, const char *kernel_buf,
 	off_t kernel_size, struct kexec_info *info)
 {
-	return -EFAILED;
+	const struct arm64_image_header *h;
+	unsigned long image_base;
+
+	h = (const struct arm64_image_header *)(kernel_buf);
+
+	if (arm64_process_image_header(h))
+		return -EINVAL;
+
+	dbgprintf("%s: text_offset:   %016lx\n", __func__,
+		arm64_mem.text_offset);
+	dbgprintf("%s: image_size:    %016lx\n", __func__,
+		arm64_mem.image_size);
+	dbgprintf("%s: phys_offset:   %016lx\n", __func__,
+		arm64_mem.phys_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;
+	
+	add_segment_phys_virt(info, kernel_buf, kernel_size, image_base,
+		arm64_mem.image_size, 0);
+
+	return arm64_load_other_segments(info, image_base);
 }
 
 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"
-"     This file type is currently NOT SUPPORTED.\n\n");
+"     Typically an Image, Image.gz or Image.lzma file.\n\n");
 }
-- 
2.5.0


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v2 2/4] kexec: Add common device tree routines
@ 2016-07-26 20:18   ` Geoff Levand
  0 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-26 20:18 UTC (permalink / raw)
  To: Simon Horman; +Cc: Pratyush Anand, AKASHI Takahiro, kexec, linux-arm-kernel

Common device tree routines that can be shared between all arches
that have device tree support.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 kexec/Makefile |   4 ++
 kexec/dt-ops.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 kexec/dt-ops.h |  13 ++++++
 3 files changed, 156 insertions(+)
 create mode 100644 kexec/dt-ops.c
 create mode 100644 kexec/dt-ops.h

diff --git a/kexec/Makefile b/kexec/Makefile
index e2aee84..cc3f08b 100644
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -73,6 +73,10 @@ dist				+= kexec/mem_regions.c kexec/mem_regions.h
 $(ARCH)_MEM_REGIONS		=
 KEXEC_SRCS			+= $($(ARCH)_MEM_REGIONS)
 
+dist				+= kexec/dt-ops.c kexec/dt-ops.h
+$(ARCH)_DT_OPS		=
+KEXEC_SRCS			+= $($(ARCH)_DT_OPS)
+
 include $(srcdir)/kexec/arch/alpha/Makefile
 include $(srcdir)/kexec/arch/arm/Makefile
 include $(srcdir)/kexec/arch/i386/Makefile
diff --git a/kexec/dt-ops.c b/kexec/dt-ops.c
new file mode 100644
index 0000000..060776a
--- /dev/null
+++ b/kexec/dt-ops.c
@@ -0,0 +1,139 @@
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <libfdt.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "kexec.h"
+#include "dt-ops.h"
+
+static const char n_chosen[] = "/chosen";
+
+static const char p_bootargs[] = "bootargs";
+static const char p_initrd_start[] = "linux,initrd-start";
+static const char p_initrd_end[] = "linux,initrd-end";
+
+int dtb_set_initrd(char **dtb, off_t *dtb_size, off_t start, off_t end)
+{
+	int result;
+	uint64_t value;
+
+	dbgprintf("%s: start %jd, end %jd, size %jd (%jd KiB)\n",
+		__func__, (intmax_t)start, (intmax_t)end,
+		(intmax_t)(end - start),
+		(intmax_t)(end - start) / 1024);
+
+	value = cpu_to_fdt64(start);
+
+	result = dtb_set_property(dtb, dtb_size, n_chosen, p_initrd_start,
+		&value, sizeof(value));
+
+	if (result)
+		return result;
+
+	value = cpu_to_fdt64(end);
+
+	result = dtb_set_property(dtb, dtb_size, n_chosen, p_initrd_end,
+		&value, sizeof(value));
+
+	if (result) {
+		dtb_delete_property(*dtb, n_chosen, p_initrd_start);
+		return result;
+	}
+
+	return 0;
+}
+
+int dtb_set_bootargs(char **dtb, off_t *dtb_size, const char *command_line)
+{
+	return dtb_set_property(dtb, dtb_size, n_chosen, p_bootargs,
+		command_line, strlen(command_line) + 1);
+}
+
+int dtb_set_property(char **dtb, off_t *dtb_size, const char *node,
+	const char *prop, const void *value, int value_len)
+{
+	int result;
+	int nodeoffset;
+	void *new_dtb;
+	int new_size;
+
+	value_len = FDT_TAGALIGN(value_len);
+
+	new_size = FDT_TAGALIGN(*dtb_size + fdt_node_len(node)
+		+ fdt_prop_len(prop, value_len));
+
+	new_dtb = malloc(new_size);
+
+	if (!new_dtb) {
+		dbgprintf("%s: malloc failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	result = fdt_open_into(*dtb, new_dtb, new_size);
+
+	if (result) {
+		dbgprintf("%s: fdt_open_into failed: %s\n", __func__,
+			fdt_strerror(result));
+		goto on_error;
+	}
+
+	nodeoffset = fdt_path_offset(new_dtb, node);
+	
+	if (nodeoffset == -FDT_ERR_NOTFOUND) {
+		result = fdt_add_subnode(new_dtb, nodeoffset, node);
+
+		if (result) {
+			dbgprintf("%s: fdt_add_subnode failed: %s\n", __func__,
+				fdt_strerror(result));
+			goto on_error;
+		}
+	} else if (nodeoffset < 0) {
+		dbgprintf("%s: fdt_path_offset failed: %s\n", __func__,
+			fdt_strerror(nodeoffset));
+		goto on_error;
+	}
+
+	result = fdt_setprop(new_dtb, nodeoffset, prop, value, value_len);
+
+	if (result) {
+		dbgprintf("%s: fdt_setprop failed: %s\n", __func__,
+			fdt_strerror(result));
+		goto on_error;
+	}
+
+	/*
+	 * Can't call free on dtb since dtb may have been mmaped by
+	 * slurp_file().
+	 */
+
+	*dtb = new_dtb;
+	*dtb_size = new_size;
+
+	return 0;
+
+on_error:
+	free(new_dtb);
+	return result;
+}
+
+int dtb_delete_property(char *dtb, const char *node, const char *prop)
+{
+	int result;
+	int nodeoffset = fdt_path_offset(dtb, node);
+
+	if (nodeoffset < 0) {
+		dbgprintf("%s: fdt_path_offset failed: %s\n", __func__,
+			fdt_strerror(nodeoffset));
+		return nodeoffset;
+	}
+
+	result = fdt_delprop(dtb, nodeoffset, prop);
+
+	if (result)
+		dbgprintf("%s: fdt_delprop failed: %s\n", __func__,
+			fdt_strerror(nodeoffset));
+
+	return result;
+}
diff --git a/kexec/dt-ops.h b/kexec/dt-ops.h
new file mode 100644
index 0000000..e70d15d
--- /dev/null
+++ b/kexec/dt-ops.h
@@ -0,0 +1,13 @@
+#if !defined(KEXEC_DT_OPS_H)
+#define KEXEC_DT_OPS_H
+
+#include <sys/types.h>
+
+int dtb_set_initrd(char **dtb, off_t *dtb_size, off_t start, off_t end);
+int dtb_set_bootargs(char **dtb, off_t *dtb_size, const char *command_line);
+int dtb_set_property(char **dtb, off_t *dtb_size, const char *node,
+	const char *prop, const void *value, int value_len);
+
+int dtb_delete_property(char *dtb, const char *node, const char *prop);
+
+#endif
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v2 3/4] arm64: Add arm64 kexec support
@ 2016-07-26 20:18   ` Geoff Levand
  0 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-26 20:18 UTC (permalink / raw)
  To: Simon Horman; +Cc: Pratyush Anand, AKASHI Takahiro, kexec, linux-arm-kernel

Add kexec reboot support for ARM64 platforms.

Signed-off-by: Geoff Levand <geoff@infradead.org>
---
 configure.ac                            |   3 +
 kexec/Makefile                          |   1 +
 kexec/arch/arm64/Makefile               |  40 ++
 kexec/arch/arm64/crashdump-arm64.c      |  21 +
 kexec/arch/arm64/crashdump-arm64.h      |  12 +
 kexec/arch/arm64/image-header.h         |  98 +++++
 kexec/arch/arm64/include/arch/options.h |  39 ++
 kexec/arch/arm64/kexec-arm64.c          | 704 ++++++++++++++++++++++++++++++++
 kexec/arch/arm64/kexec-arm64.h          |  70 ++++
 kexec/arch/arm64/kexec-elf-arm64.c      | 130 ++++++
 kexec/arch/arm64/kexec-image-arm64.c    |  44 ++
 kexec/kexec-syscall.h                   |   8 +-
 purgatory/Makefile                      |   1 +
 purgatory/arch/arm64/Makefile           |  18 +
 purgatory/arch/arm64/entry.S            |  51 +++
 purgatory/arch/arm64/purgatory-arm64.c  |  19 +
 16 files changed, 1257 insertions(+), 2 deletions(-)
 create mode 100644 kexec/arch/arm64/Makefile
 create mode 100644 kexec/arch/arm64/crashdump-arm64.c
 create mode 100644 kexec/arch/arm64/crashdump-arm64.h
 create mode 100644 kexec/arch/arm64/image-header.h
 create mode 100644 kexec/arch/arm64/include/arch/options.h
 create mode 100644 kexec/arch/arm64/kexec-arm64.c
 create mode 100644 kexec/arch/arm64/kexec-arm64.h
 create mode 100644 kexec/arch/arm64/kexec-elf-arm64.c
 create mode 100644 kexec/arch/arm64/kexec-image-arm64.c
 create mode 100644 purgatory/arch/arm64/Makefile
 create mode 100644 purgatory/arch/arm64/entry.S
 create mode 100644 purgatory/arch/arm64/purgatory-arm64.c

diff --git a/configure.ac b/configure.ac
index ca3a9d5..8858c94 100644
--- a/configure.ac
+++ b/configure.ac
@@ -34,6 +34,9 @@ case $target_cpu in
 		ARCH="ppc64"
 		SUBARCH="LE"
 		;;
+	aarch64* )
+		ARCH="arm64"
+		;;
 	arm* )
 		ARCH="arm"
 		;;
diff --git a/kexec/Makefile b/kexec/Makefile
index cc3f08b..39f365f 100644
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -79,6 +79,7 @@ KEXEC_SRCS			+= $($(ARCH)_DT_OPS)
 
 include $(srcdir)/kexec/arch/alpha/Makefile
 include $(srcdir)/kexec/arch/arm/Makefile
+include $(srcdir)/kexec/arch/arm64/Makefile
 include $(srcdir)/kexec/arch/i386/Makefile
 include $(srcdir)/kexec/arch/ia64/Makefile
 include $(srcdir)/kexec/arch/m68k/Makefile
diff --git a/kexec/arch/arm64/Makefile b/kexec/arch/arm64/Makefile
new file mode 100644
index 0000000..37414dc
--- /dev/null
+++ b/kexec/arch/arm64/Makefile
@@ -0,0 +1,40 @@
+
+arm64_FS2DT += kexec/fs2dt.c
+arm64_FS2DT_INCLUDE += -include $(srcdir)/kexec/arch/arm64/kexec-arm64.h \
+	-include $(srcdir)/kexec/arch/arm64/crashdump-arm64.h
+
+arm64_DT_OPS += kexec/dt-ops.c
+
+arm64_CPPFLAGS += -I $(srcdir)/kexec/
+
+arm64_KEXEC_SRCS += \
+	kexec/arch/arm64/kexec-arm64.c \
+	kexec/arch/arm64/kexec-image-arm64.c \
+	kexec/arch/arm64/kexec-elf-arm64.c \
+	kexec/arch/arm64/crashdump-arm64.c
+
+arm64_ARCH_REUSE_INITRD =
+arm64_ADD_SEGMENT =
+arm64_VIRT_TO_PHYS =
+arm64_PHYS_TO_VIRT =
+
+dist += $(arm64_KEXEC_SRCS) \
+	kexec/arch/arm64/Makefile \
+	kexec/arch/arm64/kexec-arm64.h \
+	kexec/arch/arm64/crashdump-arm64.h
+
+ifdef HAVE_LIBFDT
+
+LIBS += -lfdt
+
+else
+
+include $(srcdir)/kexec/libfdt/Makefile.libfdt
+
+libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%)
+
+arm64_CPPFLAGS += -I$(srcdir)/kexec/libfdt
+
+arm64_KEXEC_SRCS += $(libfdt_SRCS)
+
+endif
diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
new file mode 100644
index 0000000..d2272c8
--- /dev/null
+++ b/kexec/arch/arm64/crashdump-arm64.c
@@ -0,0 +1,21 @@
+/*
+ * ARM64 crashdump.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <linux/elf.h>
+
+#include "kexec.h"
+#include "crashdump.h"
+#include "crashdump-arm64.h"
+#include "kexec-arm64.h"
+#include "kexec-elf.h"
+
+struct memory_ranges usablemem_rgns = {};
+
+int is_crashkernel_mem_reserved(void)
+{
+	return 0;
+}
diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
new file mode 100644
index 0000000..f33c7a2
--- /dev/null
+++ b/kexec/arch/arm64/crashdump-arm64.h
@@ -0,0 +1,12 @@
+/*
+ * ARM64 crashdump.
+ */
+
+#if !defined(CRASHDUMP_ARM64_H)
+#define CRASHDUMP_ARM64_H
+
+#include "kexec.h"
+
+extern struct memory_ranges usablemem_rgns;
+
+#endif
diff --git a/kexec/arch/arm64/image-header.h b/kexec/arch/arm64/image-header.h
new file mode 100644
index 0000000..e9a6db8
--- /dev/null
+++ b/kexec/arch/arm64/image-header.h
@@ -0,0 +1,98 @@
+/*
+ * ARM64 binary image header.
+ */
+
+#if !defined(__ARM64_IMAGE_HEADER_H)
+#define __ARM64_IMAGE_HEADER_H
+
+#include <endian.h>
+#include <stdint.h>
+
+/**
+ * struct arm64_image_header - arm64 kernel image header.
+ *
+ * @pe_sig: Optional PE format 'MZ' signature.
+ * @branch_code: Reserved for instructions to branch to stext.
+ * @text_offset: The image load offset in LSB byte order.
+ * @image_size: An estimated size of the memory image size in LSB byte order.
+ * @flags: Bit flags in LSB byte order:
+ *   Bit 0: Image byte order, 1=MSB.
+ * @reserved_1: Reserved.
+ * @magic: Magic number, "ARM\x64".
+ * @pe_header: Optional offset to a PE format header.
+ **/
+
+struct arm64_image_header {
+	uint8_t pe_sig[2];
+	uint16_t branch_code[3];
+	uint64_t text_offset;
+	uint64_t image_size;
+	uint64_t flags;
+	uint64_t reserved_1[3];
+	uint8_t magic[4];
+	uint32_t pe_header;
+};
+
+static const uint8_t arm64_image_magic[4] = {'A', 'R', 'M', 0x64U};
+static const uint8_t arm64_image_pe_sig[2] = {'M', 'Z'};
+static const uint64_t arm64_image_flag_be = (1UL << 0);
+
+/**
+ * arm64_header_check_magic - Helper to check the arm64 image header.
+ *
+ * Returns non-zero if header is OK.
+ */
+
+static inline int arm64_header_check_magic(const struct arm64_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return (h->magic[0] == arm64_image_magic[0]
+		&& h->magic[1] == arm64_image_magic[1]
+		&& h->magic[2] == arm64_image_magic[2]
+		&& h->magic[3] == arm64_image_magic[3]);
+}
+
+/**
+ * arm64_header_check_pe_sig - Helper to check the arm64 image header.
+ *
+ * Returns non-zero if 'MZ' signature is found.
+ */
+
+static inline int arm64_header_check_pe_sig(const struct arm64_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return (h->pe_sig[0] == arm64_image_pe_sig[0]
+		&& h->pe_sig[1] == arm64_image_pe_sig[1]);
+}
+
+/**
+ * arm64_header_check_msb - Helper to check the arm64 image header.
+ *
+ * Returns non-zero if the image was built as big endian.
+ */
+
+static inline int arm64_header_check_msb(const struct arm64_image_header *h)
+{
+	if (!h)
+		return 0;
+
+	return le64toh(h->flags) & arm64_image_flag_be;
+}
+
+static inline uint64_t arm64_header_text_offset(
+	const struct arm64_image_header *h)
+{
+	return le64toh(h->text_offset);
+}
+
+static inline uint64_t arm64_header_image_size(
+	const struct arm64_image_header *h)
+{
+	return le64toh(h->image_size);
+}
+
+#endif
diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h
new file mode 100644
index 0000000..d6f08ad
--- /dev/null
+++ b/kexec/arch/arm64/include/arch/options.h
@@ -0,0 +1,39 @@
+#if !defined(KEXEC_ARCH_ARM64_OPTIONS_H)
+#define KEXEC_ARCH_ARM64_OPTIONS_H
+
+#define OPT_APPEND		((OPT_MAX)+0)
+#define OPT_DTB			((OPT_MAX)+1)
+#define OPT_INITRD		((OPT_MAX)+2)
+#define OPT_REUSE_CMDLINE	((OPT_MAX)+4)
+#define OPT_ARCH_MAX		((OPT_MAX)+5)
+
+#define KEXEC_ARCH_OPTIONS \
+	KEXEC_OPTIONS \
+	{ "append",        1, NULL, OPT_APPEND }, \
+	{ "command-line",  1, NULL, OPT_APPEND }, \
+	{ "dtb",           1, NULL, OPT_DTB }, \
+	{ "initrd",        1, NULL, OPT_INITRD }, \
+	{ "ramdisk",       1, NULL, OPT_INITRD }, \
+	{ "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \
+
+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */
+#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS
+#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR
+
+static const char arm64_opts_usage[] __attribute__ ((unused)) =
+"     --append=STRING       Set the kernel command line to STRING.\n"
+"     --command-line=STRING Set the kernel command line to STRING.\n"
+"     --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";
+
+struct arm64_opts {
+	const char *command_line;
+	const char *dtb;
+	const char *initrd;
+};
+
+extern struct arm64_opts arm64_opts;
+
+#endif
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
new file mode 100644
index 0000000..940cddb
--- /dev/null
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -0,0 +1,704 @@
+/*
+ * ARM64 kexec.
+ */
+
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <errno.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <libfdt.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <linux/elf.h>
+
+#include "kexec.h"
+#include "kexec-arm64.h"
+#include "crashdump.h"
+#include "crashdump-arm64.h"
+#include "dt-ops.h"
+#include "fs2dt.h"
+#include "kexec-syscall.h"
+#include "arch/options.h"
+
+/* Global varables the core kexec routines expect. */
+
+unsigned char reuse_initrd;
+
+off_t initrd_base;
+off_t initrd_size;
+
+const struct arch_map_entry arches[] = {
+	{ "aarch64", KEXEC_ARCH_ARM64 },
+	{ "aarch64_be", KEXEC_ARCH_ARM64 },
+	{ NULL, 0 },
+};
+
+struct file_type file_type[] = {
+	{"vmlinux", elf_arm64_probe, elf_arm64_load, elf_arm64_usage},
+	{"Image", image_arm64_probe, image_arm64_load, image_arm64_usage},
+};
+
+int file_types = sizeof(file_type) / sizeof(file_type[0]);
+
+/* arm64 global varables. */
+
+struct arm64_opts arm64_opts;
+struct arm64_mem arm64_mem = {
+	.phys_offset = arm64_mem_ngv,
+	.page_offset = arm64_mem_ngv,
+};
+
+uint64_t get_phys_offset(void)
+{
+	assert(arm64_mem.phys_offset != arm64_mem_ngv);
+	return arm64_mem.phys_offset;
+}
+
+uint64_t get_page_offset(void)
+{
+	assert(arm64_mem.page_offset != arm64_mem_ngv);
+	return arm64_mem.page_offset;
+}
+
+/**
+ * arm64_process_image_header - Process the arm64 image header.
+ *
+ * Make a guess that KERNEL_IMAGE_SIZE will be enough for older kernels.
+ */
+
+int arm64_process_image_header(const struct arm64_image_header *h)
+{
+#if !defined(KERNEL_IMAGE_SIZE)
+# define KERNEL_IMAGE_SIZE MiB(16)
+#endif
+
+	if (!arm64_header_check_magic(h))
+		return -EFAILED;
+
+	if (h->image_size) {
+		arm64_mem.text_offset = arm64_header_text_offset(h);
+		arm64_mem.image_size = arm64_header_image_size(h);
+	} else {
+		/* For 3.16 and older kernels. */
+		arm64_mem.text_offset = 0x80000;
+		arm64_mem.image_size = KERNEL_IMAGE_SIZE;
+		fprintf(stderr,
+			"kexec: %s: Warning: Kernel image size set to %lu MiB.\n"
+			"  Please verify compatability with lodaed kernel.\n",
+			__func__, KERNEL_IMAGE_SIZE / 1024UL / 1024UL);
+	}
+
+	return 0;
+}
+
+void arch_usage(void)
+{
+	printf(arm64_opts_usage);
+}
+
+int arch_process_options(int argc, char **argv)
+{
+	static const char short_options[] = KEXEC_OPT_STR "";
+	static const struct option options[] = {
+		KEXEC_ARCH_OPTIONS
+		{ 0 }
+	};
+	int opt;
+	char *cmdline = NULL;
+	const char *append = NULL;
+
+	for (opt = 0; opt != -1; ) {
+		opt = getopt_long(argc, argv, short_options, options, 0);
+
+		switch (opt) {
+		case OPT_APPEND:
+			append = optarg;
+			break;
+		case OPT_REUSE_CMDLINE:
+			cmdline = get_command_line();
+			break;
+		case OPT_DTB:
+			arm64_opts.dtb = optarg;
+			break;
+		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. */
+		}
+	}
+
+	arm64_opts.command_line = concat_cmdline(cmdline, append);
+
+	dbgprintf("%s:%d: command_line: %s\n", __func__, __LINE__,
+		arm64_opts.command_line);
+	dbgprintf("%s:%d: initrd: %s\n", __func__, __LINE__,
+		arm64_opts.initrd);
+	dbgprintf("%s:%d: dtb: %s\n", __func__, __LINE__, arm64_opts.dtb);
+
+	return 0;
+}
+
+/**
+ * struct dtb - Info about a binary device tree.
+ *
+ * @buf: Device tree data.
+ * @size: Device tree data size.
+ * @name: Shorthand name of this dtb for messages.
+ * @path: Filesystem path.
+ */
+
+struct dtb {
+	char *buf;
+	off_t size;
+	const char *name;
+	const char *path;
+};
+
+/**
+ * dump_reservemap - Dump the dtb's reservemap.
+ */
+
+static void dump_reservemap(const struct dtb *dtb)
+{
+	int i;
+
+	for (i = 0; ; i++) {
+		uint64_t address;
+		uint64_t size;
+
+		fdt_get_mem_rsv(dtb->buf, i, &address, &size);
+
+		if (!size)
+			break;
+
+		dbgprintf("%s: %s {%" PRIx64 ", %" PRIx64 "}\n", __func__,
+			dtb->name, address, size);
+	}
+}
+
+/**
+ * set_bootargs - Set the dtb's bootargs.
+ */
+
+static int set_bootargs(struct dtb *dtb, const char *command_line)
+{
+	int result;
+
+	if (!command_line || !command_line[0])
+		return 0;
+
+	result = dtb_set_bootargs(&dtb->buf, &dtb->size, command_line);
+
+	if (result) {
+		fprintf(stderr,
+			"kexec: Set device tree bootargs failed.\n");
+		return -EFAILED;
+	}
+
+	return 0;
+}
+
+/**
+ * read_proc_dtb - Read /proc/device-tree.
+ */
+
+static int read_proc_dtb(struct dtb *dtb)
+{
+	int result;
+	struct stat s;
+	static const char path[] = "/proc/device-tree";
+
+	result = stat(path, &s);
+
+	if (result) {
+		dbgprintf("%s: %s\n", __func__, strerror(errno));
+		return -EFAILED;
+	}
+
+	dtb->path = path;
+	create_flatten_tree((char **)&dtb->buf, &dtb->size, NULL);
+
+	return 0;
+}
+
+/**
+ * read_sys_dtb - Read /sys/firmware/fdt.
+ */
+
+static int read_sys_dtb(struct dtb *dtb)
+{
+	int result;
+	struct stat s;
+	static const char path[] = "/sys/firmware/fdt";
+
+	result = stat(path, &s);
+
+	if (result) {
+		dbgprintf("%s: %s\n", __func__, strerror(errno));
+		return -EFAILED;
+	}
+
+	dtb->path = path;
+	dtb->buf = slurp_file(path, &dtb->size);
+
+	return 0;
+}
+
+/**
+ * read_1st_dtb - Read the 1st stage kernel's dtb.
+ */
+
+static int read_1st_dtb(struct dtb *dtb)
+{
+	int result;
+
+	result = read_sys_dtb(dtb);
+
+	if (!result)
+		goto on_success;
+
+	result = read_proc_dtb(dtb);
+
+	if (!result)
+		goto on_success;
+
+	dbgprintf("%s: not found\n", __func__);
+	return -EFAILED;
+
+on_success:
+	dbgprintf("%s: found %s\n", __func__, dtb->path);
+	return 0;
+}
+
+/**
+ * setup_2nd_dtb - Setup the 2nd stage kernel's dtb.
+ */
+
+static int setup_2nd_dtb(struct dtb *dtb, char *command_line)
+{
+	int result;
+
+	result = fdt_check_header(dtb->buf);
+
+	if (result) {
+		fprintf(stderr, "kexec: Invalid 2nd device tree.\n");
+		return -EFAILED;
+	}
+
+	result = set_bootargs(dtb, command_line);
+
+	dump_reservemap(dtb);
+
+	return result;
+}
+
+/**
+ * arm64_load_other_segments - Prepare the dtb, initrd and purgatory segments.
+ */
+
+int arm64_load_other_segments(struct kexec_info *info,
+	uint64_t kernel_entry)
+{
+	int result;
+	uint64_t dtb_base;
+	uint64_t image_base;
+	unsigned long hole_min;
+	unsigned long hole_max;
+	char *initrd_buf = NULL;
+	struct dtb dtb;
+	char command_line[COMMAND_LINE_SIZE] = "";
+
+	if (arm64_opts.command_line) {
+		strncpy(command_line, arm64_opts.command_line,
+			sizeof(command_line));
+		command_line[sizeof(command_line) - 1] = 0;
+	}
+
+	if (arm64_opts.dtb) {
+		dtb.name = "dtb_2";
+		dtb.buf = slurp_file(arm64_opts.dtb, &dtb.size);
+	} else {
+		dtb.name = "dtb_1";
+		result = read_1st_dtb(&dtb);
+
+		if (result) {
+			fprintf(stderr,
+				"kexec: Error: No device tree available.\n");
+			return -EFAILED;
+		}
+	}
+
+	result = setup_2nd_dtb(&dtb, command_line);
+
+	if (result)
+		return -EFAILED;
+
+	/* Put the other segments after the image. */
+
+	image_base = arm64_mem.phys_offset + arm64_mem.text_offset;
+	hole_min = image_base + arm64_mem.image_size;
+	hole_max = ULONG_MAX;
+
+	if (arm64_opts.initrd) {
+		initrd_buf = slurp_file(arm64_opts.initrd, &initrd_size);
+
+		if (!initrd_buf)
+			fprintf(stderr, "kexec: Empty ramdisk file.\n");
+		else {
+			/*
+			 * Put the initrd after the kernel.  As specified in
+			 * booting.txt, align to 1 GiB.
+			 */
+
+			initrd_base = add_buffer_phys_virt(info, initrd_buf,
+				initrd_size, initrd_size, GiB(1),
+				hole_min, hole_max, 1, 0);
+
+			/* initrd_base is valid if we got here. */
+
+			dbgprintf("initrd: base %lx, size %lxh (%ld)\n",
+				initrd_base, initrd_size, initrd_size);
+
+			/* Check size limit as specified in booting.txt. */
+
+			if (initrd_base - image_base + initrd_size > GiB(32)) {
+				fprintf(stderr, "kexec: Error: image + initrd too big.\n");
+				return -EFAILED;
+			}
+
+			result = dtb_set_initrd((char **)&dtb.buf,
+				&dtb.size, initrd_base,
+				initrd_base + initrd_size);
+
+			if (result)
+				return -EFAILED;
+		}
+	}
+
+	/* Check size limit as specified in booting.txt. */
+
+	if (dtb.size > MiB(2)) {
+		fprintf(stderr, "kexec: Error: dtb too big.\n");
+		return -EFAILED;
+	}
+
+	dtb_base = add_buffer_phys_virt(info, dtb.buf, dtb.size, dtb.size,
+		0, hole_min, hole_max, 1, 0);
+
+	/* dtb_base is valid if we got here. */
+
+	dbgprintf("dtb:    base %lx, size %lxh (%ld)\n", dtb_base, dtb.size,
+		dtb.size);
+
+	elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+		hole_min, hole_max, 1, 0);
+
+	info->entry = (void *)elf_rel_get_addr(&info->rhdr, "purgatory_start");
+
+	elf_rel_set_symbol(&info->rhdr, "arm64_kernel_entry", &kernel_entry,
+		sizeof(kernel_entry));
+
+	elf_rel_set_symbol(&info->rhdr, "arm64_dtb_addr", &dtb_base,
+		sizeof(dtb_base));
+
+	return 0;
+}
+
+/**
+ * virt_to_phys - For processing elf file values.
+ */
+
+unsigned long virt_to_phys(unsigned long v)
+{
+	unsigned long p;
+
+	p = v - get_page_offset() + get_phys_offset();
+
+	return p;
+}
+
+/**
+ * phys_to_virt - For crashdump setup.
+ */
+
+unsigned long phys_to_virt(struct crash_elf_info *elf_info,
+	unsigned long long p)
+{
+	unsigned long v;
+
+	v = p - get_phys_offset() + elf_info->page_offset;
+
+	return v;
+}
+
+/**
+ * add_segment - Use virt_to_phys when loading elf files.
+ */
+
+void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
+	unsigned long base, size_t memsz)
+{
+	add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
+}
+
+/**
+ * get_memory_ranges_iomem_cb - Helper for get_memory_ranges_iomem.
+ */
+
+static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
+	unsigned long long base, unsigned long long length)
+{
+	struct memory_range *r;
+
+	if (nr >= KEXEC_SEGMENT_MAX)
+		return -1;
+
+	r = (struct memory_range *)data + nr;
+	r->type = RANGE_RAM;
+	r->start = base;
+	r->end = base + length - 1;
+
+	set_phys_offset(r->start);
+
+	dbgprintf("%s: %016llx - %016llx : %s", __func__, r->start,
+		r->end, str);
+
+	return 0;
+}
+
+/**
+ * get_memory_ranges_iomem - Try to get the memory ranges from /proc/iomem.
+ */
+
+static int get_memory_ranges_iomem(struct memory_range *array,
+	unsigned int *count)
+{
+	*count = kexec_iomem_for_each_line("System RAM\n",
+		get_memory_ranges_iomem_cb, array);
+
+	if (!*count) {
+		dbgprintf("%s: failed: No RAM found.\n", __func__);
+		return -EFAILED;
+	}
+
+	return 0;
+}
+
+/**
+ * get_memory_ranges_dt - Try to get the memory ranges from the 1st stage dtb.
+ */
+
+static int get_memory_ranges_dt(struct memory_range *array, unsigned int *count)
+{
+	struct region {uint64_t base; uint64_t size;};
+	struct dtb dtb = {.name = "range_dtb"};
+	int offset;
+	int result;
+
+	*count = 0;
+
+	result = read_1st_dtb(&dtb);
+
+	if (result) {
+		goto on_error;
+	}
+
+	result = fdt_check_header(dtb.buf);
+
+	if (result) {
+		dbgprintf("%s:%d: %s: fdt_check_header failed:%s\n", __func__,
+			__LINE__, dtb.path, fdt_strerror(result));
+		goto on_error;
+	}
+
+	for (offset = 0; ; ) {
+		const struct region *region;
+		const struct region *end;
+		int len;
+
+		offset = fdt_subnode_offset(dtb.buf, offset, "memory");
+
+		if (offset == -FDT_ERR_NOTFOUND)
+			break;
+
+		if (offset <= 0) {
+			dbgprintf("%s:%d: fdt_subnode_offset failed: %d %s\n",
+				__func__, __LINE__, offset,
+				fdt_strerror(offset));
+			goto on_error;
+		}
+
+		dbgprintf("%s:%d: node_%d %s\n", __func__, __LINE__, offset,
+			fdt_get_name(dtb.buf, offset, NULL));
+
+		region = fdt_getprop(dtb.buf, offset, "reg", &len);
+
+		if (region <= 0) {
+			dbgprintf("%s:%d: fdt_getprop failed: %d %s\n",
+				__func__, __LINE__, offset,
+				fdt_strerror(offset));
+			goto on_error;
+		}
+
+		for (end = region + len / sizeof(*region);
+			region < end && *count < KEXEC_SEGMENT_MAX;
+			region++) {
+			struct memory_range r;
+
+			r.type = RANGE_RAM;
+			r.start = fdt64_to_cpu(region->base);
+			r.end = r.start + fdt64_to_cpu(region->size) - 1;
+
+			if (!region->size) {
+				dbgprintf("%s:%d: SKIP: %016llx - %016llx\n",
+					__func__, __LINE__, r.start, r.end);
+				continue;
+			}
+
+			dbgprintf("%s:%d:  RAM: %016llx - %016llx\n", __func__,
+				__LINE__, r.start, r.end);
+
+			array[(*count)++] = r;
+
+			set_phys_offset(r.start);
+		}
+	}
+
+	if (!*count) {
+		dbgprintf("%s:%d: %s: No RAM found.\n", __func__, __LINE__,
+			dtb.path);
+		goto on_error;
+	}
+
+	dbgprintf("%s:%d: %s: Success\n", __func__, __LINE__, dtb.path);
+	result = 0;
+	goto on_exit;
+
+on_error:
+	fprintf(stderr, "%s:%d: %s: Unusable device-tree file\n", __func__,
+		__LINE__, dtb.path);
+	result = -1;
+
+on_exit:
+	free(dtb.buf);
+	return -EFAILED;
+}
+
+/**
+ * get_memory_ranges - Try to get the memory ranges some how.
+ */
+
+int get_memory_ranges(struct memory_range **range, int *ranges,
+	unsigned long kexec_flags)
+{
+	static struct memory_range array[KEXEC_SEGMENT_MAX];
+	unsigned int count;
+	int result;
+
+	result = get_memory_ranges_iomem(array, &count);
+
+	if (result)
+		result = get_memory_ranges_dt(array, &count);
+
+	*range = result ? NULL : array;
+	*ranges = result ? 0 : count;
+
+	return -EFAILED;
+}
+
+int arch_compat_trampoline(struct kexec_info *info)
+{
+	return 0;
+}
+
+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
+{
+	return (ehdr->e_machine == EM_AARCH64);
+}
+
+void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
+	unsigned long r_type, void *ptr, unsigned long address,
+	unsigned long value)
+{
+#if !defined(R_AARCH64_ABS64)
+# define R_AARCH64_ABS64 257
+#endif
+
+#if !defined(R_AARCH64_LD_PREL_LO19)
+# define R_AARCH64_LD_PREL_LO19 273
+#endif
+
+#if !defined(R_AARCH64_ADR_PREL_LO21)
+# define R_AARCH64_ADR_PREL_LO21 274
+#endif
+
+#if !defined(R_AARCH64_JUMP26)
+# define R_AARCH64_JUMP26 282
+#endif
+
+#if !defined(R_AARCH64_CALL26)
+# define R_AARCH64_CALL26 283
+#endif
+
+	uint64_t *loc64;
+	uint32_t *loc32;
+	uint64_t *location = (uint64_t *)ptr;
+	uint64_t data = *location;
+	const char *type = NULL;
+
+	switch(r_type) {
+	case R_AARCH64_ABS64:
+		type = "ABS64";
+		loc64 = ptr;
+		*loc64 = cpu_to_elf64(ehdr, elf64_to_cpu(ehdr, *loc64) + value);
+		break;
+	case R_AARCH64_LD_PREL_LO19:
+		type = "LD_PREL_LO19";
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ (((value - address) << 3) & 0xffffe0));
+		break;
+	case R_AARCH64_ADR_PREL_LO21:
+		if (value & 3)
+			die("%s: ERROR Unaligned value: %lx\n", __func__,
+				value);
+		type = "ADR_PREL_LO21";
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ (((value - address) << 3) & 0xffffe0));
+		break;
+	case R_AARCH64_JUMP26:
+		type = "JUMP26";
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ (((value - address) >> 2) & 0x3ffffff));
+		break;
+	case R_AARCH64_CALL26:
+		type = "CALL26";
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ (((value - address) >> 2) & 0x3ffffff));
+		break;
+	default:
+		die("%s: ERROR Unknown type: %lu\n", __func__, r_type);
+		break;
+	}
+
+	dbgprintf("%s: %s %016lx->%016lx\n", __func__, type, data, *location);
+}
+
+void arch_reuse_initrd(void)
+{
+	reuse_initrd = 1;
+}
+
+void arch_update_purgatory(struct kexec_info *UNUSED(info))
+{
+}
diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
new file mode 100644
index 0000000..0fb03a8
--- /dev/null
+++ b/kexec/arch/arm64/kexec-arm64.h
@@ -0,0 +1,70 @@
+/*
+ * ARM64 kexec.
+ */
+
+#if !defined(KEXEC_ARM64_H)
+#define KEXEC_ARM64_H
+
+#include <stdbool.h>
+#include <sys/types.h>
+
+#include "image-header.h"
+#include "kexec.h"
+
+#define KEXEC_SEGMENT_MAX 16
+
+#define BOOT_BLOCK_VERSION 17
+#define BOOT_BLOCK_LAST_COMP_VERSION 16
+#define COMMAND_LINE_SIZE 512
+
+#define KiB(x) ((x) * 1024UL)
+#define MiB(x) (KiB(x) * 1024UL)
+#define GiB(x) (MiB(x) * 1024UL)
+
+int elf_arm64_probe(const char *kernel_buf, off_t kernel_size);
+int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
+	off_t kernel_size, struct kexec_info *info);
+void elf_arm64_usage(void);
+
+int image_arm64_probe(const char *kernel_buf, off_t kernel_size);
+int image_arm64_load(int argc, char **argv, const char *kernel_buf,
+	off_t kernel_size, struct kexec_info *info);
+void image_arm64_usage(void);
+
+off_t initrd_base;
+off_t initrd_size;
+
+/**
+ * struct arm64_mem - Memory layout info.
+ */
+
+struct arm64_mem {
+	uint64_t phys_offset;
+	uint64_t text_offset;
+	uint64_t image_size;
+	uint64_t page_offset;
+};
+
+#define arm64_mem_ngv UINT64_MAX
+struct arm64_mem arm64_mem;
+
+uint64_t get_phys_offset(void);
+uint64_t get_page_offset(void);
+
+static inline void reset_page_offset(void)
+{
+	arm64_mem.page_offset = arm64_mem_ngv;
+}
+
+static inline void set_phys_offset(uint64_t v)
+{
+	if (arm64_mem.phys_offset == arm64_mem_ngv
+		|| v < arm64_mem.phys_offset)
+		arm64_mem.phys_offset = v;
+}
+
+int arm64_process_image_header(const struct arm64_image_header *h);
+int arm64_load_other_segments(struct kexec_info *info,
+	uint64_t kernel_entry);
+
+#endif
diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
new file mode 100644
index 0000000..fcac9bb
--- /dev/null
+++ b/kexec/arch/arm64/kexec-elf-arm64.c
@@ -0,0 +1,130 @@
+/*
+ * ARM64 kexec elf support.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <stdlib.h>
+#include <linux/elf.h>
+
+#include "kexec-arm64.h"
+#include "kexec-elf.h"
+#include "kexec-syscall.h"
+
+int elf_arm64_probe(const char *kernel_buf, off_t kernel_size)
+{
+	struct mem_ehdr ehdr;
+	int result;
+
+	result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0);
+
+	if (result < 0) {
+		dbgprintf("%s: Not an ELF executable.\n", __func__);
+		goto on_exit;
+	}
+
+	if (ehdr.e_machine != EM_AARCH64) {
+		dbgprintf("%s: Not an AARCH64 ELF executable.\n", __func__);
+		result = -1;
+		goto on_exit;
+	}
+
+	result = 0;
+on_exit:
+	free_elf_info(&ehdr);
+	return result;
+}
+
+int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
+	off_t kernel_size, struct kexec_info *info)
+{
+	struct mem_ehdr ehdr;
+	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) {
+		dbgprintf("%s: build_elf_exec_info failed\n", __func__);
+		goto exit;
+	}
+
+	/* Find and process the arm64 image header. */
+
+	for (i = 0; i < ehdr.e_phnum; i++) {
+		struct mem_phdr *phdr = &ehdr.e_phdr[i];
+		const struct arm64_image_header *h;
+		unsigned long header_offset;
+
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		/*
+		 * When CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET=y the image header
+		 * could be offset in the elf segment.  The linker script sets
+		 * ehdr.e_entry to the start of text.
+		 */
+
+		header_offset = ehdr.e_entry - phdr->p_vaddr;
+
+		h = (const struct arm64_image_header *)(
+			kernel_buf + phdr->p_offset + header_offset);
+
+		if (arm64_process_image_header(h))
+			continue;
+
+		arm64_mem.page_offset = ehdr.e_entry - arm64_mem.text_offset;
+
+		dbgprintf("%s: e_entry:       %016llx -> %016lx\n", __func__,
+			ehdr.e_entry,
+			virt_to_phys(ehdr.e_entry));
+		dbgprintf("%s: p_vaddr:       %016llx -> %016lx\n", __func__,
+			phdr->p_vaddr,
+			virt_to_phys(phdr->p_vaddr));
+		dbgprintf("%s: header_offset: %016lx\n", __func__,
+			header_offset);
+		dbgprintf("%s: text_offset:   %016lx\n", __func__,
+			arm64_mem.text_offset);
+		dbgprintf("%s: image_size:    %016lx\n", __func__,
+			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"));
+
+		result = elf_exec_load(&ehdr, info);
+
+		if (result) {
+			fprintf(stderr, "kexec: Elf load failed.\n");
+			goto exit;
+		}
+
+		result = arm64_load_other_segments(info,
+			virt_to_phys(ehdr.e_entry));
+		goto exit;
+	}
+
+	fprintf(stderr, "kexec: Bad arm64 image header.\n");
+	result = -EFAILED;
+	goto exit;
+
+exit:
+	reset_page_offset();
+	free_elf_info(&ehdr);
+	return result;
+}
+
+void elf_arm64_usage(void)
+{
+	printf(
+"     An ARM64 ELF image, big or little endian.\n"
+"     Typically vmlinux or a stripped version of vmlinux.\n\n");
+}
diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
new file mode 100644
index 0000000..84386f7
--- /dev/null
+++ b/kexec/arch/arm64/kexec-image-arm64.c
@@ -0,0 +1,44 @@
+/*
+ * ARM64 kexec binary image support.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+
+#include "kexec-arm64.h"
+
+int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
+{
+	const struct arm64_image_header *h;
+
+	if (kernel_size < sizeof(struct arm64_image_header)) {
+		dbgprintf("%s: No arm64 image header.\n", __func__);
+		return -1;
+	}
+
+	h = (const struct arm64_image_header *)(kernel_buf);
+
+	if (!arm64_header_check_magic(h)) {
+		dbgprintf("%s: Bad arm64 image header.\n", __func__);
+		return -1;
+	}
+
+	fprintf(stderr, "kexec: ARM64 binary image files are currently NOT SUPPORTED.\n");
+
+	return -1;
+}
+
+int image_arm64_load(int argc, char **argv, const char *kernel_buf,
+	off_t kernel_size, struct kexec_info *info)
+{
+	return -EFAILED;
+}
+
+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"
+"     This file type is currently NOT SUPPORTED.\n\n");
+}
diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
index ce2e20b..c0d0bea 100644
--- a/kexec/kexec-syscall.h
+++ b/kexec/kexec-syscall.h
@@ -39,8 +39,8 @@
 #ifdef __s390__
 #define __NR_kexec_load		277
 #endif
-#ifdef __arm__
-#define __NR_kexec_load		__NR_SYSCALL_BASE + 347  
+#if defined(__arm__) || defined(__arm64__)
+#define __NR_kexec_load		__NR_SYSCALL_BASE + 347
 #endif
 #if defined(__mips__)
 #define __NR_kexec_load                4311
@@ -108,6 +108,7 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd,
 #define KEXEC_ARCH_PPC64   (21 << 16)
 #define KEXEC_ARCH_IA_64   (50 << 16)
 #define KEXEC_ARCH_ARM     (40 << 16)
+#define KEXEC_ARCH_ARM64   (183 << 16)
 #define KEXEC_ARCH_S390    (22 << 16)
 #define KEXEC_ARCH_SH      (42 << 16)
 #define KEXEC_ARCH_MIPS_LE (10 << 16)
@@ -153,5 +154,8 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd,
 #ifdef __m68k__
 #define KEXEC_ARCH_NATIVE	KEXEC_ARCH_68K
 #endif
+#if defined(__arm64__)
+#define KEXEC_ARCH_NATIVE	KEXEC_ARCH_ARM64
+#endif
 
 #endif /* KEXEC_SYSCALL_H */
diff --git a/purgatory/Makefile b/purgatory/Makefile
index 2b5c061..ca0443c 100644
--- a/purgatory/Makefile
+++ b/purgatory/Makefile
@@ -19,6 +19,7 @@ dist += purgatory/Makefile $(PURGATORY_SRCS)				\
 
 include $(srcdir)/purgatory/arch/alpha/Makefile
 include $(srcdir)/purgatory/arch/arm/Makefile
+include $(srcdir)/purgatory/arch/arm64/Makefile
 include $(srcdir)/purgatory/arch/i386/Makefile
 include $(srcdir)/purgatory/arch/ia64/Makefile
 include $(srcdir)/purgatory/arch/mips/Makefile
diff --git a/purgatory/arch/arm64/Makefile b/purgatory/arch/arm64/Makefile
new file mode 100644
index 0000000..636abea
--- /dev/null
+++ b/purgatory/arch/arm64/Makefile
@@ -0,0 +1,18 @@
+
+arm64_PURGATORY_EXTRA_CFLAGS = \
+	-mcmodel=large \
+	-fno-stack-protector \
+	-fno-asynchronous-unwind-tables \
+	-Wundef \
+	-Werror-implicit-function-declaration \
+	-Wdeclaration-after-statement \
+	-Werror=implicit-int \
+	-Werror=strict-prototypes
+
+arm64_PURGATORY_SRCS += \
+	purgatory/arch/arm64/entry.S \
+	purgatory/arch/arm64/purgatory-arm64.c
+
+dist += \
+	$(arm64_PURGATORY_SRCS) \
+	purgatory/arch/arm64/Makefile
diff --git a/purgatory/arch/arm64/entry.S b/purgatory/arch/arm64/entry.S
new file mode 100644
index 0000000..adf16f4
--- /dev/null
+++ b/purgatory/arch/arm64/entry.S
@@ -0,0 +1,51 @@
+/*
+ * ARM64 purgatory.
+ */
+
+.macro	size, sym:req
+	.size \sym, . - \sym
+.endm
+
+.text
+
+.globl purgatory_start
+purgatory_start:
+
+	adr	x19, .Lstack
+	mov	sp, x19
+
+	bl	purgatory
+
+	/* Start new image. */
+	ldr	x17, arm64_kernel_entry
+	ldr	x0, arm64_dtb_addr
+	mov	x1, xzr
+	mov	x2, xzr
+	mov	x3, xzr
+	br	x17
+
+size purgatory_start
+
+.ltorg
+
+.align 4
+	.rept	256
+	.quad	0
+	.endr
+.Lstack:
+
+.data
+
+.align 3
+
+.globl arm64_kernel_entry
+arm64_kernel_entry:
+	.quad	0
+size arm64_kernel_entry
+
+.globl arm64_dtb_addr
+arm64_dtb_addr:
+	.quad	0
+size arm64_dtb_addr
+
+.end
\ No newline at end of file
diff --git a/purgatory/arch/arm64/purgatory-arm64.c b/purgatory/arch/arm64/purgatory-arm64.c
new file mode 100644
index 0000000..fe50fcf
--- /dev/null
+++ b/purgatory/arch/arm64/purgatory-arm64.c
@@ -0,0 +1,19 @@
+/*
+ * ARM64 purgatory.
+ */
+
+#include <stdint.h>
+#include <purgatory.h>
+
+void putchar(int ch)
+{
+	/* Nothing for now */
+}
+
+void post_verification_setup_arch(void)
+{
+}
+
+void setup_arch(void)
+{
+}
-- 
2.5.0



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v2 4/4] arm64: Add support for binary image files
  2016-07-26 20:18   ` Geoff Levand
@ 2016-07-28  4:01     ` Pratyush Anand
  -1 siblings, 0 replies; 30+ messages in thread
From: Pratyush Anand @ 2016-07-28  4:01 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Geoff,

On 26/07/2016:08:18:57 PM, Geoff Levand wrote:
> From: Pratyush Anand <panand@redhat.com>
> 
> Signed-off-by: Pratyush Anand <panand@redhat.com>
> [Reworked and cleaned up]

You removed page_offset calculation in rework.
I am unable to understand that how arm64_mem.page_offset will be filled up now
for binary image case.

I think, we still need to keep page_offset user input. You may take following
two patches which does this, or you may leave binary image support patch which I
will send after your patches are merged.

https://github.com/pratyushanand/kexec-tools/commit/5b7e49a75d1d6cd4ac846f50ff10275fd54cb545
https://github.com/pratyushanand/kexec-tools/commit/a0ce0ce673755c4061c1f081170a3a75dfa1d1fb

~Pratyush

> Signed-off-by: Geoff Levand <geoff@infradead.org>
> ---
>  kexec/arch/arm64/kexec-image-arm64.c | 31 +++++++++++++++++++++++++------
>  1 file changed, 25 insertions(+), 6 deletions(-)
> 
> diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
> index 84386f7..cad7c73 100644
> --- a/kexec/arch/arm64/kexec-image-arm64.c
> +++ b/kexec/arch/arm64/kexec-image-arm64.c
> @@ -24,21 +24,40 @@ int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
>  		return -1;
>  	}
>  
> -	fprintf(stderr, "kexec: ARM64 binary image files are currently NOT SUPPORTED.\n");
> -
> -	return -1;
> +	return 0;
>  }
>  
>  int image_arm64_load(int argc, char **argv, const char *kernel_buf,
>  	off_t kernel_size, struct kexec_info *info)
>  {
> -	return -EFAILED;
> +	const struct arm64_image_header *h;
> +	unsigned long image_base;
> +
> +	h = (const struct arm64_image_header *)(kernel_buf);
> +
> +	if (arm64_process_image_header(h))
> +		return -EINVAL;
> +
> +	dbgprintf("%s: text_offset:   %016lx\n", __func__,
> +		arm64_mem.text_offset);
> +	dbgprintf("%s: image_size:    %016lx\n", __func__,
> +		arm64_mem.image_size);
> +	dbgprintf("%s: phys_offset:   %016lx\n", __func__,
> +		arm64_mem.phys_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;
> +	
> +	add_segment_phys_virt(info, kernel_buf, kernel_size, image_base,
> +		arm64_mem.image_size, 0);
> +
> +	return arm64_load_other_segments(info, image_base);
>  }
>  
>  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"
> -"     This file type is currently NOT SUPPORTED.\n\n");
> +"     Typically an Image, Image.gz or Image.lzma file.\n\n");
>  }
> -- 
> 2.5.0

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v2 4/4] arm64: Add support for binary image files
@ 2016-07-28  4:01     ` Pratyush Anand
  0 siblings, 0 replies; 30+ messages in thread
From: Pratyush Anand @ 2016-07-28  4:01 UTC (permalink / raw)
  To: Geoff Levand; +Cc: AKASHI Takahiro, Simon Horman, kexec, linux-arm-kernel

Hi Geoff,

On 26/07/2016:08:18:57 PM, Geoff Levand wrote:
> From: Pratyush Anand <panand@redhat.com>
> 
> Signed-off-by: Pratyush Anand <panand@redhat.com>
> [Reworked and cleaned up]

You removed page_offset calculation in rework.
I am unable to understand that how arm64_mem.page_offset will be filled up now
for binary image case.

I think, we still need to keep page_offset user input. You may take following
two patches which does this, or you may leave binary image support patch which I
will send after your patches are merged.

https://github.com/pratyushanand/kexec-tools/commit/5b7e49a75d1d6cd4ac846f50ff10275fd54cb545
https://github.com/pratyushanand/kexec-tools/commit/a0ce0ce673755c4061c1f081170a3a75dfa1d1fb

~Pratyush

> Signed-off-by: Geoff Levand <geoff@infradead.org>
> ---
>  kexec/arch/arm64/kexec-image-arm64.c | 31 +++++++++++++++++++++++++------
>  1 file changed, 25 insertions(+), 6 deletions(-)
> 
> diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
> index 84386f7..cad7c73 100644
> --- a/kexec/arch/arm64/kexec-image-arm64.c
> +++ b/kexec/arch/arm64/kexec-image-arm64.c
> @@ -24,21 +24,40 @@ int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
>  		return -1;
>  	}
>  
> -	fprintf(stderr, "kexec: ARM64 binary image files are currently NOT SUPPORTED.\n");
> -
> -	return -1;
> +	return 0;
>  }
>  
>  int image_arm64_load(int argc, char **argv, const char *kernel_buf,
>  	off_t kernel_size, struct kexec_info *info)
>  {
> -	return -EFAILED;
> +	const struct arm64_image_header *h;
> +	unsigned long image_base;
> +
> +	h = (const struct arm64_image_header *)(kernel_buf);
> +
> +	if (arm64_process_image_header(h))
> +		return -EINVAL;
> +
> +	dbgprintf("%s: text_offset:   %016lx\n", __func__,
> +		arm64_mem.text_offset);
> +	dbgprintf("%s: image_size:    %016lx\n", __func__,
> +		arm64_mem.image_size);
> +	dbgprintf("%s: phys_offset:   %016lx\n", __func__,
> +		arm64_mem.phys_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;
> +	
> +	add_segment_phys_virt(info, kernel_buf, kernel_size, image_base,
> +		arm64_mem.image_size, 0);
> +
> +	return arm64_load_other_segments(info, image_base);
>  }
>  
>  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"
> -"     This file type is currently NOT SUPPORTED.\n\n");
> +"     Typically an Image, Image.gz or Image.lzma file.\n\n");
>  }
> -- 
> 2.5.0

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v2 3/4] arm64: Add arm64 kexec support
  2016-07-26 20:18   ` Geoff Levand
@ 2016-07-28  4:10     ` Pratyush Anand
  -1 siblings, 0 replies; 30+ messages in thread
From: Pratyush Anand @ 2016-07-28  4:10 UTC (permalink / raw)
  To: linux-arm-kernel

On 26/07/2016:08:18:57 PM, Geoff Levand wrote:
> Add kexec reboot support for ARM64 platforms.
> 
> Signed-off-by: Geoff Levand <geoff@infradead.org>
> ---

[...]

> +
> +#define OPT_APPEND		((OPT_MAX)+0)
> +#define OPT_DTB			((OPT_MAX)+1)
> +#define OPT_INITRD		((OPT_MAX)+2)
> +#define OPT_REUSE_CMDLINE	((OPT_MAX)+4)

Option count 3 is missing. 

> +#define OPT_ARCH_MAX		((OPT_MAX)+5)

~Pratyush

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v2 3/4] arm64: Add arm64 kexec support
@ 2016-07-28  4:10     ` Pratyush Anand
  0 siblings, 0 replies; 30+ messages in thread
From: Pratyush Anand @ 2016-07-28  4:10 UTC (permalink / raw)
  To: Geoff Levand; +Cc: AKASHI Takahiro, Simon Horman, kexec, linux-arm-kernel

On 26/07/2016:08:18:57 PM, Geoff Levand wrote:
> Add kexec reboot support for ARM64 platforms.
> 
> Signed-off-by: Geoff Levand <geoff@infradead.org>
> ---

[...]

> +
> +#define OPT_APPEND		((OPT_MAX)+0)
> +#define OPT_DTB			((OPT_MAX)+1)
> +#define OPT_INITRD		((OPT_MAX)+2)
> +#define OPT_REUSE_CMDLINE	((OPT_MAX)+4)

Option count 3 is missing. 

> +#define OPT_ARCH_MAX		((OPT_MAX)+5)

~Pratyush

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v2 3/4] arm64: Add arm64 kexec support
  2016-07-28  4:10     ` Pratyush Anand
@ 2016-07-28 17:33       ` Geoff Levand
  -1 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-28 17:33 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, 2016-07-28 at 09:40 +0530, Pratyush Anand wrote:
> On 26/07/2016:08:18:57 PM, Geoff Levand wrote:
> > Add kexec reboot support for ARM64 platforms.
> > 
> > Signed-off-by: Geoff Levand <geoff@infradead.org>
> > ---
> 
> [...]
> 
> > +
> > +#define OPT_APPEND		((OPT_MAX)+0)
> > +#define OPT_DTB			((OPT_MAX)+1)
> > +#define OPT_INITRD		((OPT_MAX)+2)
> > +#define OPT_REUSE_CMDLINE	((OPT_MAX)+4)
> 
> Option count 3 is missing. 

>From the recently removed OPT_PORT.

Thanks for checking.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v2 3/4] arm64: Add arm64 kexec support
@ 2016-07-28 17:33       ` Geoff Levand
  0 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-28 17:33 UTC (permalink / raw)
  To: Pratyush Anand; +Cc: AKASHI Takahiro, Simon Horman, kexec, linux-arm-kernel

On Thu, 2016-07-28 at 09:40 +0530, Pratyush Anand wrote:
> On 26/07/2016:08:18:57 PM, Geoff Levand wrote:
> > Add kexec reboot support for ARM64 platforms.
> > 
> > Signed-off-by: Geoff Levand <geoff@infradead.org>
> > ---
> 
> [...]
> 
> > +
> > +#define OPT_APPEND		((OPT_MAX)+0)
> > +#define OPT_DTB			((OPT_MAX)+1)
> > +#define OPT_INITRD		((OPT_MAX)+2)
> > +#define OPT_REUSE_CMDLINE	((OPT_MAX)+4)
> 
> Option count 3 is missing. 

From the recently removed OPT_PORT.

Thanks for checking.

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v2 4/4] arm64: Add support for binary image files
  2016-07-28  4:01     ` Pratyush Anand
@ 2016-07-28 18:04       ` Geoff Levand
  -1 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-28 18:04 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Pratyush,

On Thu, 2016-07-28 at 09:31 +0530, Pratyush Anand wrote:
> On 26/07/2016:08:18:57 PM, Geoff Levand wrote:

> You removed page_offset calculation in rework.
> I am unable to understand that how arm64_mem.page_offset will be filled up now
> for binary image case.
> 
> I think, we still need to keep page_offset user input. 

The current kernel linker scripts are setup to output virtual
address values to the vmlinux elf file.  

To load the elf sections of vmlinux using the provided elf
file loader, elf_exec_load(), we need to convert those elf
header values to physical addresses since we work with
physical addresses in the kernel's kimage structure.

That conversion is 

  p = v - page_offset + phys_offset;

We get phys_offset from the memory ranges, and we calculate
page_offset from the elf header info.

As for the binary image file, we load that with
add_segment_phys_virt(), which can put the binary data of the
Image file into memory at a physical address we specify:

  image_base = phys_offset + text_offset.

phys_offset is again from the memory ranges, and text_offset
from the arm64 image header.


> You may take following
> two patches which does this, or you may leave binary image support patch which I
> will send after your patches are merged.
> 
> https://github.com/pratyushanand/kexec-tools/commit/5b7e49a75d1d6cd4ac846f50ff10275fd54cb545

This one may be useful, for debugging if anything.

> https://github.com/pratyushanand/kexec-tools/commit/a0ce0ce673755c4061c1f081170a3a75dfa1d1fb

We do not need, nor want, a PAGE_OFFSET option.

-Geoff

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v2 4/4] arm64: Add support for binary image files
@ 2016-07-28 18:04       ` Geoff Levand
  0 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-28 18:04 UTC (permalink / raw)
  To: Pratyush Anand, Mark Rutland
  Cc: AKASHI Takahiro, Simon Horman, kexec, linux-arm-kernel

Hi Pratyush,

On Thu, 2016-07-28 at 09:31 +0530, Pratyush Anand wrote:
> On 26/07/2016:08:18:57 PM, Geoff Levand wrote:

> You removed page_offset calculation in rework.
> I am unable to understand that how arm64_mem.page_offset will be filled up now
> for binary image case.
> 
> I think, we still need to keep page_offset user input. 

The current kernel linker scripts are setup to output virtual
address values to the vmlinux elf file.  

To load the elf sections of vmlinux using the provided elf
file loader, elf_exec_load(), we need to convert those elf
header values to physical addresses since we work with
physical addresses in the kernel's kimage structure.

That conversion is 

  p = v - page_offset + phys_offset;

We get phys_offset from the memory ranges, and we calculate
page_offset from the elf header info.

As for the binary image file, we load that with
add_segment_phys_virt(), which can put the binary data of the
Image file into memory at a physical address we specify:

  image_base = phys_offset + text_offset.

phys_offset is again from the memory ranges, and text_offset
from the arm64 image header.


> You may take following
> two patches which does this, or you may leave binary image support patch which I
> will send after your patches are merged.
> 
> https://github.com/pratyushanand/kexec-tools/commit/5b7e49a75d1d6cd4ac846f50ff10275fd54cb545

This one may be useful, for debugging if anything.

> https://github.com/pratyushanand/kexec-tools/commit/a0ce0ce673755c4061c1f081170a3a75dfa1d1fb

We do not need, nor want, a PAGE_OFFSET option.

-Geoff


_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v2 4/4] arm64: Add support for binary image files
  2016-07-28 18:04       ` Geoff Levand
@ 2016-07-29  3:35         ` Pratyush Anand
  -1 siblings, 0 replies; 30+ messages in thread
From: Pratyush Anand @ 2016-07-29  3:35 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Geoff,

On 28/07/2016:11:04:43 AM, Geoff Levand wrote:
> Hi Pratyush,
> 
> On Thu, 2016-07-28 at 09:31 +0530, Pratyush Anand wrote:
> > On 26/07/2016:08:18:57 PM, Geoff Levand wrote:
> 
> > You removed page_offset calculation in rework.
> > I am unable to understand that how arm64_mem.page_offset will be filled up now
> > for binary image case.
> > 
> > I think, we still need to keep page_offset user input. 
> 
> The current kernel linker scripts are setup to output virtual
> address values to the vmlinux elf file.  
> 
> To load the elf sections of vmlinux using the provided elf
> file loader, elf_exec_load(), we need to convert those elf
> header values to physical addresses since we work with
> physical addresses in the kernel's kimage structure.
> 
> That conversion is 
> 
>   p = v - page_offset + phys_offset;
> 
> We get phys_offset from the memory ranges, and we calculate
> page_offset from the elf header info.
> 
> As for the binary image file, we load that with
> add_segment_phys_virt(), which can put the binary data of the
> Image file into memory at a physical address we specify:
> 
>   image_base = phys_offset + text_offset.
> 
> phys_offset is again from the memory ranges, and text_offset
> from the arm64 image header.
> 
> 
> > You may take following
> > two patches which does this, or you may leave binary image support patch which I
> > will send after your patches are merged.
> > 
> > https://github.com/pratyushanand/kexec-tools/commit/5b7e49a75d1d6cd4ac846f50ff10275fd54cb545
> 
> This one may be useful, for debugging if anything.
> 
> > https://github.com/pratyushanand/kexec-tools/commit/a0ce0ce673755c4061c1f081170a3a75dfa1d1fb
> 
> We do not need, nor want, a PAGE_OFFSET option.

See kexec/crashdump-elf.c:FUNC()
We have:
223                 phdr->p_vaddr = phys_to_virt(elf_info, mstart);

Now, if we do not have page_offset then we will not have correct p_vaddr, and
then vmcore-dmesg/vmcore-dmesg.c:vaddr_to_offset() fails with

No program header covering vaddr 0xfffffc0008c312f0found kexec bug?

~Pratyush

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v2 4/4] arm64: Add support for binary image files
@ 2016-07-29  3:35         ` Pratyush Anand
  0 siblings, 0 replies; 30+ messages in thread
From: Pratyush Anand @ 2016-07-29  3:35 UTC (permalink / raw)
  To: Geoff Levand
  Cc: Mark Rutland, AKASHI Takahiro, Simon Horman, kexec, linux-arm-kernel

Hi Geoff,

On 28/07/2016:11:04:43 AM, Geoff Levand wrote:
> Hi Pratyush,
> 
> On Thu, 2016-07-28 at 09:31 +0530, Pratyush Anand wrote:
> > On 26/07/2016:08:18:57 PM, Geoff Levand wrote:
> 
> > You removed page_offset calculation in rework.
> > I am unable to understand that how arm64_mem.page_offset will be filled up now
> > for binary image case.
> > 
> > I think, we still need to keep page_offset user input. 
> 
> The current kernel linker scripts are setup to output virtual
> address values to the vmlinux elf file.  
> 
> To load the elf sections of vmlinux using the provided elf
> file loader, elf_exec_load(), we need to convert those elf
> header values to physical addresses since we work with
> physical addresses in the kernel's kimage structure.
> 
> That conversion is 
> 
>   p = v - page_offset + phys_offset;
> 
> We get phys_offset from the memory ranges, and we calculate
> page_offset from the elf header info.
> 
> As for the binary image file, we load that with
> add_segment_phys_virt(), which can put the binary data of the
> Image file into memory at a physical address we specify:
> 
>   image_base = phys_offset + text_offset.
> 
> phys_offset is again from the memory ranges, and text_offset
> from the arm64 image header.
> 
> 
> > You may take following
> > two patches which does this, or you may leave binary image support patch which I
> > will send after your patches are merged.
> > 
> > https://github.com/pratyushanand/kexec-tools/commit/5b7e49a75d1d6cd4ac846f50ff10275fd54cb545
> 
> This one may be useful, for debugging if anything.
> 
> > https://github.com/pratyushanand/kexec-tools/commit/a0ce0ce673755c4061c1f081170a3a75dfa1d1fb
> 
> We do not need, nor want, a PAGE_OFFSET option.

See kexec/crashdump-elf.c:FUNC()
We have:
223                 phdr->p_vaddr = phys_to_virt(elf_info, mstart);

Now, if we do not have page_offset then we will not have correct p_vaddr, and
then vmcore-dmesg/vmcore-dmesg.c:vaddr_to_offset() fails with

No program header covering vaddr 0xfffffc0008c312f0found kexec bug?

~Pratyush

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v2 4/4] arm64: Add support for binary image files
  2016-07-29  3:35         ` Pratyush Anand
@ 2016-07-29 17:02           ` Geoff Levand
  -1 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-29 17:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2016-07-29 at 09:05 +0530, Pratyush Anand wrote:

> See kexec/crashdump-elf.c:FUNC()
> We have:
> 223                 phdr->p_vaddr = phys_to_virt(elf_info, mstart);
> 

These patches don't support kdump.

-Geoff

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v2 4/4] arm64: Add support for binary image files
@ 2016-07-29 17:02           ` Geoff Levand
  0 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-29 17:02 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: Mark Rutland, AKASHI Takahiro, Simon Horman, kexec, linux-arm-kernel

On Fri, 2016-07-29 at 09:05 +0530, Pratyush Anand wrote:

> See kexec/crashdump-elf.c:FUNC()
> We have:
> 223                 phdr->p_vaddr = phys_to_virt(elf_info, mstart);
> 

These patches don't support kdump.

-Geoff

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v2 4/4] arm64: Add support for binary image files
  2016-07-29 17:02           ` Geoff Levand
@ 2016-07-29 17:15             ` Pratyush Anand
  -1 siblings, 0 replies; 30+ messages in thread
From: Pratyush Anand @ 2016-07-29 17:15 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Geoff,

On 29/07/2016:10:02:40 AM, Geoff Levand wrote:
> On Fri, 2016-07-29 at 09:05 +0530, Pratyush Anand wrote:
> 
> > See kexec/crashdump-elf.c:FUNC()
> > We have:
> > 223                 phdr->p_vaddr = phys_to_virt(elf_info, mstart);
> > 
> 
> These patches don't support kdump.

OK, so you suggest that I should keep this patch as it is and add --page-offset
in corresponding kdump patch. I can do that, no issue.

~Pratyush

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v2 4/4] arm64: Add support for binary image files
@ 2016-07-29 17:15             ` Pratyush Anand
  0 siblings, 0 replies; 30+ messages in thread
From: Pratyush Anand @ 2016-07-29 17:15 UTC (permalink / raw)
  To: Geoff Levand
  Cc: Mark Rutland, AKASHI Takahiro, Simon Horman, kexec, linux-arm-kernel

Hi Geoff,

On 29/07/2016:10:02:40 AM, Geoff Levand wrote:
> On Fri, 2016-07-29 at 09:05 +0530, Pratyush Anand wrote:
> 
> > See kexec/crashdump-elf.c:FUNC()
> > We have:
> > 223                 phdr->p_vaddr = phys_to_virt(elf_info, mstart);
> > 
> 
> These patches don't support kdump.

OK, so you suggest that I should keep this patch as it is and add --page-offset
in corresponding kdump patch. I can do that, no issue.

~Pratyush

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v2 4/4] arm64: Add support for binary image files
  2016-07-29 17:15             ` Pratyush Anand
@ 2016-07-29 17:19               ` Geoff Levand
  -1 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-29 17:19 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2016-07-29 at 22:45 +0530, Pratyush Anand wrote:
> Hi Geoff,
> 
> On 29/07/2016:10:02:40 AM, Geoff Levand wrote:
> > On Fri, 2016-07-29 at 09:05 +0530, Pratyush Anand wrote:
> > 
> > > See kexec/crashdump-elf.c:FUNC()
> > > We have:
> > > 223                 phdr->p_vaddr = phys_to_virt(elf_info,
> > > mstart);
> > > 
> > 
> > These patches don't support kdump.
> 
> OK, so you suggest that I should keep this patch as it is and add -
> -page-offset
> in corresponding kdump patch. I can do that, no issue.

Yes, this is an issue related to kdump, so let's discuss it in that
context.

-Geoff

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v2 4/4] arm64: Add support for binary image files
@ 2016-07-29 17:19               ` Geoff Levand
  0 siblings, 0 replies; 30+ messages in thread
From: Geoff Levand @ 2016-07-29 17:19 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: Mark Rutland, AKASHI Takahiro, Simon Horman, kexec, linux-arm-kernel

On Fri, 2016-07-29 at 22:45 +0530, Pratyush Anand wrote:
> Hi Geoff,
> 
> On 29/07/2016:10:02:40 AM, Geoff Levand wrote:
> > On Fri, 2016-07-29 at 09:05 +0530, Pratyush Anand wrote:
> > 
> > > See kexec/crashdump-elf.c:FUNC()
> > > We have:
> > > 223                 phdr->p_vaddr = phys_to_virt(elf_info,
> > > mstart);
> > > 
> > 
> > These patches don't support kdump.
> 
> OK, so you suggest that I should keep this patch as it is and add -
> -page-offset
> in corresponding kdump patch. I can do that, no issue.

Yes, this is an issue related to kdump, so let's discuss it in that
context.

-Geoff

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v2 4/4] arm64: Add support for binary image files
  2016-07-29 17:15             ` Pratyush Anand
@ 2016-08-04  4:51               ` AKASHI Takahiro
  -1 siblings, 0 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2016-08-04  4:51 UTC (permalink / raw)
  To: linux-arm-kernel

Pratyush,

On Fri, Jul 29, 2016 at 10:45:52PM +0530, Pratyush Anand wrote:
> Hi Geoff,
> 
> On 29/07/2016:10:02:40 AM, Geoff Levand wrote:
> > On Fri, 2016-07-29 at 09:05 +0530, Pratyush Anand wrote:
> > 
> > > See kexec/crashdump-elf.c:FUNC()
> > > We have:
> > > 223                 phdr->p_vaddr = phys_to_virt(elf_info, mstart);
> > > 
> > 
> > These patches don't support kdump.
> 
> OK, so you suggest that I should keep this patch as it is and add --page-offset
> in corresponding kdump patch. I can do that, no issue.

I will add necessary hunks from your old patch when I submit
a next version of patches for arm64, probably next Monday.

I hope that you don't mind.

Thanks,
-Takahiro AKASHI

> ~Pratyush

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v2 4/4] arm64: Add support for binary image files
@ 2016-08-04  4:51               ` AKASHI Takahiro
  0 siblings, 0 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2016-08-04  4:51 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: Geoff Levand, Mark Rutland, Simon Horman, kexec, linux-arm-kernel

Pratyush,

On Fri, Jul 29, 2016 at 10:45:52PM +0530, Pratyush Anand wrote:
> Hi Geoff,
> 
> On 29/07/2016:10:02:40 AM, Geoff Levand wrote:
> > On Fri, 2016-07-29 at 09:05 +0530, Pratyush Anand wrote:
> > 
> > > See kexec/crashdump-elf.c:FUNC()
> > > We have:
> > > 223                 phdr->p_vaddr = phys_to_virt(elf_info, mstart);
> > > 
> > 
> > These patches don't support kdump.
> 
> OK, so you suggest that I should keep this patch as it is and add --page-offset
> in corresponding kdump patch. I can do that, no issue.

I will add necessary hunks from your old patch when I submit
a next version of patches for arm64, probably next Monday.

I hope that you don't mind.

Thanks,
-Takahiro AKASHI

> ~Pratyush

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v2 4/4] arm64: Add support for binary image files
  2016-08-04  4:51               ` AKASHI Takahiro
@ 2016-08-04  5:11                 ` Pratyush Anand
  -1 siblings, 0 replies; 30+ messages in thread
From: Pratyush Anand @ 2016-08-04  5:11 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Takahiro,

On 04/08/2016:01:51:05 PM, AKASHI Takahiro wrote:
> Pratyush,
> 
> On Fri, Jul 29, 2016 at 10:45:52PM +0530, Pratyush Anand wrote:
> > Hi Geoff,
> > 
> > On 29/07/2016:10:02:40 AM, Geoff Levand wrote:
> > > On Fri, 2016-07-29 at 09:05 +0530, Pratyush Anand wrote:
> > > 
> > > > See kexec/crashdump-elf.c:FUNC()
> > > > We have:
> > > > 223                 phdr->p_vaddr = phys_to_virt(elf_info, mstart);
> > > > 
> > > 
> > > These patches don't support kdump.
> > 
> > OK, so you suggest that I should keep this patch as it is and add --page-offset
> > in corresponding kdump patch. I can do that, no issue.
> 
> I will add necessary hunks from your old patch when I submit
> a next version of patches for arm64, probably next Monday.
> 
> I hope that you don't mind.

Thanks, no issue.

May be you can just cherry-pick following two commits.

https://github.com/pratyushanand/kexec-tools/commit/1e4eea5798de312c7ac90043361a889516da0aaf
https://github.com/pratyushanand/kexec-tools/commit/fd19e4b9c1423d24fcd4355277835f0bf01c33e8

They are in upstream_arm64_devel branch of https://github.com/pratyushanand/kexec-tools.git

~Pratyush

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v2 4/4] arm64: Add support for binary image files
@ 2016-08-04  5:11                 ` Pratyush Anand
  0 siblings, 0 replies; 30+ messages in thread
From: Pratyush Anand @ 2016-08-04  5:11 UTC (permalink / raw)
  To: AKASHI Takahiro, Geoff Levand, Mark Rutland, Simon Horman, kexec,
	linux-arm-kernel

Hi Takahiro,

On 04/08/2016:01:51:05 PM, AKASHI Takahiro wrote:
> Pratyush,
> 
> On Fri, Jul 29, 2016 at 10:45:52PM +0530, Pratyush Anand wrote:
> > Hi Geoff,
> > 
> > On 29/07/2016:10:02:40 AM, Geoff Levand wrote:
> > > On Fri, 2016-07-29 at 09:05 +0530, Pratyush Anand wrote:
> > > 
> > > > See kexec/crashdump-elf.c:FUNC()
> > > > We have:
> > > > 223                 phdr->p_vaddr = phys_to_virt(elf_info, mstart);
> > > > 
> > > 
> > > These patches don't support kdump.
> > 
> > OK, so you suggest that I should keep this patch as it is and add --page-offset
> > in corresponding kdump patch. I can do that, no issue.
> 
> I will add necessary hunks from your old patch when I submit
> a next version of patches for arm64, probably next Monday.
> 
> I hope that you don't mind.

Thanks, no issue.

May be you can just cherry-pick following two commits.

https://github.com/pratyushanand/kexec-tools/commit/1e4eea5798de312c7ac90043361a889516da0aaf
https://github.com/pratyushanand/kexec-tools/commit/fd19e4b9c1423d24fcd4355277835f0bf01c33e8

They are in upstream_arm64_devel branch of https://github.com/pratyushanand/kexec-tools.git

~Pratyush

_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2016-08-04  5:12 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-26 20:18 [PATCH v2 0/4] arm64 kexec-tools patches Geoff Levand
2016-07-26 20:18 ` Geoff Levand
2016-07-26 20:18 ` [PATCH v2 1/4] kexec: (bugfix) calc correct end address of memory ranges in device tree Geoff Levand
2016-07-26 20:18   ` Geoff Levand
2016-07-26 20:18 ` [PATCH v2 2/4] kexec: Add common device tree routines Geoff Levand
2016-07-26 20:18   ` Geoff Levand
2016-07-26 20:18 ` [PATCH v2 3/4] arm64: Add arm64 kexec support Geoff Levand
2016-07-26 20:18   ` Geoff Levand
2016-07-28  4:10   ` Pratyush Anand
2016-07-28  4:10     ` Pratyush Anand
2016-07-28 17:33     ` Geoff Levand
2016-07-28 17:33       ` Geoff Levand
2016-07-26 20:18 ` [PATCH v2 4/4] arm64: Add support for binary image files Geoff Levand
2016-07-26 20:18   ` Geoff Levand
2016-07-28  4:01   ` Pratyush Anand
2016-07-28  4:01     ` Pratyush Anand
2016-07-28 18:04     ` Geoff Levand
2016-07-28 18:04       ` Geoff Levand
2016-07-29  3:35       ` Pratyush Anand
2016-07-29  3:35         ` Pratyush Anand
2016-07-29 17:02         ` Geoff Levand
2016-07-29 17:02           ` Geoff Levand
2016-07-29 17:15           ` Pratyush Anand
2016-07-29 17:15             ` Pratyush Anand
2016-07-29 17:19             ` Geoff Levand
2016-07-29 17:19               ` Geoff Levand
2016-08-04  4:51             ` AKASHI Takahiro
2016-08-04  4:51               ` AKASHI Takahiro
2016-08-04  5:11               ` Pratyush Anand
2016-08-04  5:11                 ` Pratyush Anand

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.