diff --git a/kexec-tools-2.0.13-arm64-Add-arm64-kexec-support.patch b/kexec-tools-2.0.13-arm64-Add-arm64-kexec-support.patch deleted file mode 100644 index 0c14b1b..0000000 --- a/kexec-tools-2.0.13-arm64-Add-arm64-kexec-support.patch +++ /dev/null @@ -1,1407 +0,0 @@ -From 522df5f7217fda01ece3f6ac3e9987b0320c2bb0 Mon Sep 17 00:00:00 2001 -From: Geoff Levand -Date: Wed, 21 Sep 2016 18:14:25 +0000 -Subject: [PATCH 2/3] arm64: Add arm64 kexec support - -Add kexec reboot support for ARM64 platforms. - -Signed-off-by: Geoff Levand -Tested-By: Pratyush Anand -Tested-By: Matthias Brugger -Signed-off-by: Simon Horman ---- - 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 | 146 ++++++++ - kexec/arch/arm64/include/arch/options.h | 39 ++ - kexec/arch/arm64/kexec-arm64.c | 615 ++++++++++++++++++++++++++++++++ - kexec/arch/arm64/kexec-arm64.h | 71 ++++ - kexec/arch/arm64/kexec-elf-arm64.c | 146 ++++++++ - kexec/arch/arm64/kexec-image-arm64.c | 41 +++ - 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, 1230 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 2bc5767..252b048 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 -+#include -+ -+#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..158d411 ---- /dev/null -+++ b/kexec/arch/arm64/image-header.h -@@ -0,0 +1,146 @@ -+/* -+ * ARM64 binary image header. -+ */ -+ -+#if !defined(__ARM64_IMAGE_HEADER_H) -+#define __ARM64_IMAGE_HEADER_H -+ -+#include -+#include -+ -+/** -+ * 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. -+ * Bit 1-2: Kernel page size: 1=4K, 2=16K, 3=64K. -+ * Bit 3: Image placement: 0=low. -+ * @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); -+static const uint64_t arm64_image_flag_page_size = (3UL << 1); -+static const uint64_t arm64_image_flag_placement = (1UL << 3); -+ -+/** -+ * enum arm64_header_page_size -+ */ -+ -+enum arm64_header_page_size { -+ arm64_header_page_size_invalid = 0, -+ arm64_header_page_size_4k, -+ arm64_header_page_size_16k, -+ arm64_header_page_size_64k -+}; -+ -+/** -+ * 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) >> 0; -+} -+ -+/** -+ * arm64_header_page_size -+ */ -+ -+static inline enum arm64_header_page_size arm64_header_page_size( -+ const struct arm64_image_header *h) -+{ -+ if (!h) -+ return 0; -+ -+ return (le64toh(h->flags) & arm64_image_flag_page_size) >> 1; -+} -+ -+/** -+ * arm64_header_placement -+ * -+ * Returns non-zero if the image has no physical placement restrictions. -+ */ -+ -+static inline int arm64_header_placement(const struct arm64_image_header *h) -+{ -+ if (!h) -+ return 0; -+ -+ return (le64toh(h->flags) & arm64_image_flag_placement) >> 3; -+} -+ -+static inline uint64_t arm64_header_text_offset( -+ const struct arm64_image_header *h) -+{ -+ if (!h) -+ return 0; -+ -+ return le64toh(h->text_offset); -+} -+ -+static inline uint64_t arm64_header_image_size( -+ const struct arm64_image_header *h) -+{ -+ if (!h) -+ return 0; -+ -+ 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..a17d933 ---- /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)+3) -+#define OPT_ARCH_MAX ((OPT_MAX)+4) -+ -+#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..2e8839a ---- /dev/null -+++ b/kexec/arch/arm64/kexec-arm64.c -@@ -0,0 +1,615 @@ -+/* -+ * ARM64 kexec. -+ */ -+ -+#define _GNU_SOURCE -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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, -+ .vp_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_vp_offset(void) -+{ -+ assert(arm64_mem.vp_offset != arm64_mem_ngv); -+ return arm64_mem.vp_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; -+ -+ dtb->name = "dtb_sys"; -+ result = read_sys_dtb(dtb); -+ -+ if (!result) -+ goto on_success; -+ -+ dtb->name = "dtb_proc"; -+ 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; -+} -+ -+unsigned long arm64_locate_kernel_segment(struct kexec_info *info) -+{ -+ unsigned long hole; -+ -+ hole = locate_hole(info, -+ arm64_mem.text_offset + arm64_mem.image_size, -+ MiB(2), 0, ULONG_MAX, 1); -+ -+ if (hole == ULONG_MAX) -+ dbgprintf("%s: locate_hole failed\n", __func__); -+ -+ return hole; -+} -+ -+/** -+ * arm64_load_other_segments - Prepare the dtb, initrd and purgatory segments. -+ */ -+ -+int arm64_load_other_segments(struct kexec_info *info, -+ unsigned long image_base) -+{ -+ int result; -+ unsigned long dtb_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_user"; -+ dtb.buf = slurp_file(arm64_opts.dtb, &dtb.size); -+ } else { -+ 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. */ -+ -+ 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", &image_base, -+ sizeof(image_base)); -+ -+ 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_vp_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 - 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); -+ -+ *range = result ? NULL : array; -+ *ranges = result ? 0 : count; -+ -+ return result; -+} -+ -+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..bac62f8 ---- /dev/null -+++ b/kexec/arch/arm64/kexec-arm64.h -@@ -0,0 +1,71 @@ -+/* -+ * ARM64 kexec. -+ */ -+ -+#if !defined(KEXEC_ARM64_H) -+#define KEXEC_ARM64_H -+ -+#include -+#include -+ -+#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 vp_offset; -+}; -+ -+#define arm64_mem_ngv UINT64_MAX -+struct arm64_mem arm64_mem; -+ -+uint64_t get_phys_offset(void); -+uint64_t get_vp_offset(void); -+ -+static inline void reset_vp_offset(void) -+{ -+ arm64_mem.vp_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); -+unsigned long arm64_locate_kernel_segment(struct kexec_info *info); -+int arm64_load_other_segments(struct kexec_info *info, -+ unsigned long image_base); -+ -+#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..daf8bf0 ---- /dev/null -+++ b/kexec/arch/arm64/kexec-elf-arm64.c -@@ -0,0 +1,146 @@ -+/* -+ * ARM64 kexec elf support. -+ */ -+ -+#define _GNU_SOURCE -+ -+#include -+#include -+#include -+#include -+ -+#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) -+{ -+ const struct arm64_image_header *header = NULL; -+ unsigned long kernel_segment; -+ 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]; -+ 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; -+ -+ header = (const struct arm64_image_header *)( -+ kernel_buf + phdr->p_offset + header_offset); -+ -+ if (!arm64_process_image_header(header)) { -+ dbgprintf("%s: e_entry: %016llx\n", __func__, -+ ehdr.e_entry); -+ dbgprintf("%s: p_vaddr: %016llx\n", __func__, -+ phdr->p_vaddr); -+ dbgprintf("%s: header_offset: %016lx\n", __func__, -+ header_offset); -+ -+ break; -+ } -+ } -+ -+ if (i == ehdr.e_phnum) { -+ dbgprintf("%s: Valid arm64 header not found\n", __func__); -+ result = -EFAILED; -+ goto exit; -+ } -+ -+ kernel_segment = arm64_locate_kernel_segment(info); -+ -+ if (kernel_segment == ULONG_MAX) { -+ dbgprintf("%s: Kernel segment is not allocated\n", __func__); -+ result = -EFAILED; -+ goto exit; -+ } -+ -+ arm64_mem.vp_offset = _ALIGN_DOWN(ehdr.e_entry, MiB(2)); -+ arm64_mem.vp_offset -= kernel_segment - get_phys_offset(); -+ -+ dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment); -+ dbgprintf("%s: text_offset: %016lx\n", __func__, -+ 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: vp_offset: %016lx\n", __func__, -+ arm64_mem.vp_offset); -+ dbgprintf("%s: PE format: %s\n", __func__, -+ (arm64_header_check_pe_sig(header) ? "yes" : "no")); -+ -+ /* load the kernel */ -+ result = elf_exec_load(&ehdr, info); -+ -+ if (result) { -+ dbgprintf("%s: elf_exec_load failed\n", __func__); -+ goto exit; -+ } -+ -+ result = arm64_load_other_segments(info, kernel_segment -+ + arm64_mem.text_offset); -+ -+exit: -+ reset_vp_offset(); -+ free_elf_info(&ehdr); -+ if (result) -+ fprintf(stderr, "kexec: Bad elf image file, load failed.\n"); -+ 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..42d2ea7 ---- /dev/null -+++ b/kexec/arch/arm64/kexec-image-arm64.c -@@ -0,0 +1,41 @@ -+/* -+ * ARM64 kexec binary image support. -+ */ -+ -+#define _GNU_SOURCE -+#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 -1; -+} -+ -+void image_arm64_usage(void) -+{ -+ printf( -+" An ARM64 binary image, compressed or not, big or little endian.\n" -+" Typically an Image, Image.gz or Image.lzma file.\n\n"); -+ printf( -+" ARM64 binary image files are 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 -+#include -+ -+void putchar(int ch) -+{ -+ /* Nothing for now */ -+} -+ -+void post_verification_setup_arch(void) -+{ -+} -+ -+void setup_arch(void) -+{ -+} --- -2.9.3 - diff --git a/kexec-tools-2.0.13-arm64-Add-support-for-additional-relocations-in-the-kexec-purgatory-code.patch b/kexec-tools-2.0.13-arm64-Add-support-for-additional-relocations-in-the-kexec-purgatory-code.patch deleted file mode 100644 index ef52b79..0000000 --- a/kexec-tools-2.0.13-arm64-Add-support-for-additional-relocations-in-the-kexec-purgatory-code.patch +++ /dev/null @@ -1,106 +0,0 @@ -From patchwork Thu Oct 20 10:43:31 2016 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -Subject: [v2] arm64: Add support for additional relocations in the kexec - purgatory code -From: Catalin Marinas -X-Patchwork-Id: 9386541 -Message-Id: <1476960211-25594-1-git-send-email-catalin.marinas@arm.com> -To: Simon Horman -Cc: Geoff Levand , kexec@lists.infradead.org, - linux-arm-kernel@lists.infradead.org -Date: Thu, 20 Oct 2016 11:43:31 +0100 - -When compiling the kexec-tools with gcc6, the following additional -reolcations are generated in the purgatory.ro file: - -R_AARCH64_ADR_PREL_PG_HI21 -R_AARCH64_ADD_ABS_LO12_NC -R_AARCH64_LDST64_ABS_LO12_NC - -This patch modifies the arm64 machine_apply_elf_rel() function to handle -these relocations. - -Cc: Geoff Levand -Signed-off-by: Catalin Marinas -Reviewed-by: Geoff Levand ---- - -Changes for v2: -- Fixed the type string to drop the "R_AARCH64_" prefix - - kexec/arch/arm64/kexec-arm64.c | 35 +++++++++++++++++++++++++++++++++++ - 1 file changed, 35 insertions(+) - -diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c -index 2e8839a..e067a23 100644 ---- a/kexec/arch/arm64/kexec-arm64.c -+++ b/kexec/arch/arm64/kexec-arm64.c -@@ -550,6 +550,14 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym), - # define R_AARCH64_ADR_PREL_LO21 274 - #endif - -+#if !defined(R_AARCH64_ADR_PREL_PG_HI21) -+# define R_AARCH64_ADR_PREL_PG_HI21 275 -+#endif -+ -+#if !defined(R_AARCH64_ADD_ABS_LO12_NC) -+# define R_AARCH64_ADD_ABS_LO12_NC 277 -+#endif -+ - #if !defined(R_AARCH64_JUMP26) - # define R_AARCH64_JUMP26 282 - #endif -@@ -558,10 +566,15 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym), - # define R_AARCH64_CALL26 283 - #endif - -+#if !defined(R_AARCH64_LDST64_ABS_LO12_NC) -+# define R_AARCH64_LDST64_ABS_LO12_NC 286 -+#endif -+ - uint64_t *loc64; - uint32_t *loc32; - uint64_t *location = (uint64_t *)ptr; - uint64_t data = *location; -+ uint64_t imm; - const char *type = NULL; - - switch(r_type) { -@@ -585,6 +598,19 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym), - *loc32 = cpu_to_le32(le32_to_cpu(*loc32) - + (((value - address) << 3) & 0xffffe0)); - break; -+ case R_AARCH64_ADR_PREL_PG_HI21: -+ type = "ADR_PREL_PG_HI21"; -+ imm = ((value & ~0xfff) - (address & ~0xfff)) >> 12; -+ loc32 = ptr; -+ *loc32 = cpu_to_le32(le32_to_cpu(*loc32) -+ + ((imm & 3) << 29) + ((imm & 0x1ffffc) << (5 - 2))); -+ break; -+ case R_AARCH64_ADD_ABS_LO12_NC: -+ type = "ADD_ABS_LO12_NC"; -+ loc32 = ptr; -+ *loc32 = cpu_to_le32(le32_to_cpu(*loc32) -+ + ((value & 0xfff) << 10)); -+ break; - case R_AARCH64_JUMP26: - type = "JUMP26"; - loc32 = ptr; -@@ -597,6 +623,15 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym), - *loc32 = cpu_to_le32(le32_to_cpu(*loc32) - + (((value - address) >> 2) & 0x3ffffff)); - break; -+ case R_AARCH64_LDST64_ABS_LO12_NC: -+ if (value & 7) -+ die("%s: ERROR Unaligned value: %lx\n", __func__, -+ value); -+ type = "LDST64_ABS_LO12_NC"; -+ loc32 = ptr; -+ *loc32 = cpu_to_le32(le32_to_cpu(*loc32) -+ + ((value & 0xff8) << (10 - 3))); -+ break; - default: - die("%s: ERROR Unknown type: %lu\n", __func__, r_type); - break; diff --git a/kexec-tools-2.0.13-arm64-Add-support-for-binary-image-files.patch b/kexec-tools-2.0.13-arm64-Add-support-for-binary-image-files.patch deleted file mode 100644 index 8e8dde0..0000000 --- a/kexec-tools-2.0.13-arm64-Add-support-for-binary-image-files.patch +++ /dev/null @@ -1,96 +0,0 @@ -From abdfe97736f89d9bc73662b9134604b0229a599e Mon Sep 17 00:00:00 2001 -From: Pratyush Anand -Date: Wed, 21 Sep 2016 18:14:25 +0000 -Subject: [PATCH 3/3] arm64: Add support for binary image files - -Signed-off-by: Pratyush Anand -[Reworked and cleaned up] -Signed-off-by: Geoff Levand -Tested-By: Pratyush Anand -Tested-By: Matthias Brugger -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/kexec-image-arm64.c | 49 ++++++++++++++++++++++++++++++++---- - 1 file changed, 44 insertions(+), 5 deletions(-) - -diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c -index 42d2ea7..960ed96 100644 ---- a/kexec/arch/arm64/kexec-image-arm64.c -+++ b/kexec/arch/arm64/kexec-image-arm64.c -@@ -3,7 +3,9 @@ - */ - - #define _GNU_SOURCE -+ - #include "kexec-arm64.h" -+#include - - int image_arm64_probe(const char *kernel_buf, off_t kernel_size) - { -@@ -21,14 +23,53 @@ 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 -1; -+ const struct arm64_image_header *header; -+ unsigned long kernel_segment; -+ int result; -+ -+ header = (const struct arm64_image_header *)(kernel_buf); -+ -+ if (arm64_process_image_header(header)) -+ return -1; -+ -+ kernel_segment = arm64_locate_kernel_segment(info); -+ -+ if (kernel_segment == ULONG_MAX) { -+ dbgprintf("%s: Kernel segment is not allocated\n", __func__); -+ result = -EFAILED; -+ goto exit; -+ } -+ -+ dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment); -+ 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: vp_offset: %016lx\n", __func__, -+ arm64_mem.vp_offset); -+ dbgprintf("%s: PE format: %s\n", __func__, -+ (arm64_header_check_pe_sig(header) ? "yes" : "no")); -+ -+ /* load the kernel */ -+ add_segment_phys_virt(info, kernel_buf, kernel_size, -+ kernel_segment + arm64_mem.text_offset, -+ arm64_mem.image_size, 0); -+ -+ result = arm64_load_other_segments(info, kernel_segment -+ + arm64_mem.text_offset); -+ -+exit: -+ if (result) -+ fprintf(stderr, "kexec: load failed.\n"); -+ return result; - } - - void image_arm64_usage(void) -@@ -36,6 +77,4 @@ void image_arm64_usage(void) - printf( - " An ARM64 binary image, compressed or not, big or little endian.\n" - " Typically an Image, Image.gz or Image.lzma file.\n\n"); -- printf( --" ARM64 binary image files are currently NOT SUPPORTED.\n\n"); - } --- -2.9.3 - diff --git a/kexec-tools-2.0.13-arm64-Add-support-of-R_AARCH64_PREL32-relocation-in-.patch b/kexec-tools-2.0.13-arm64-Add-support-of-R_AARCH64_PREL32-relocation-in-.patch deleted file mode 100644 index a1b55e9..0000000 --- a/kexec-tools-2.0.13-arm64-Add-support-of-R_AARCH64_PREL32-relocation-in-.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 3a3c61cb7f129936e5752d1ccc304c183575a8b0 Mon Sep 17 00:00:00 2001 -Message-Id: <3a3c61cb7f129936e5752d1ccc304c183575a8b0.1477402102.git.panand@redhat.com> -From: Pratyush Anand -Date: Tue, 25 Oct 2016 18:55:49 +0530 -Subject: [PATCH] arm64: Add support of R_AARCH64_PREL32 relocation in - purgatory - -Signed-off-by: Pratyush Anand ---- - kexec/arch/arm64/kexec-arm64.c | 9 +++++++++ - 1 file changed, 9 insertions(+) - -diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c -index 218f0bc832cd..b12de4772412 100644 ---- a/kexec/arch/arm64/kexec-arm64.c -+++ b/kexec/arch/arm64/kexec-arm64.c -@@ -720,6 +720,10 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym), - # define R_AARCH64_ABS64 257 - #endif - -+#if !defined(R_AARCH64_PREL32) -+# define R_AARCH64_PREL32 261 -+#endif -+ - #if !defined(R_AARCH64_LD_PREL_LO19) - # define R_AARCH64_LD_PREL_LO19 273 - #endif -@@ -761,6 +765,11 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym), - loc64 = ptr; - *loc64 = cpu_to_elf64(ehdr, elf64_to_cpu(ehdr, *loc64) + value); - break; -+ case R_AARCH64_PREL32: -+ type = "PREL32"; -+ loc32 = ptr; -+ *loc32 = cpu_to_elf32(ehdr, elf32_to_cpu(ehdr, *loc32) + value - address); -+ break; - case R_AARCH64_LD_PREL_LO19: - type = "LD_PREL_LO19"; - loc32 = ptr; --- -2.7.4 - diff --git a/kexec-tools-2.0.13-fix-armv7-build-failure.patch b/kexec-tools-2.0.13-fix-armv7-build-failure.patch deleted file mode 100644 index 9c1d482..0000000 --- a/kexec-tools-2.0.13-fix-armv7-build-failure.patch +++ /dev/null @@ -1,28 +0,0 @@ -Upstream kexec-tools 2.0.13 does not pack arm phys_to_virt.h and iomem.h, -include them here for a temporary fix - -diff -uprN kexec-tools/kexec/arch/arm/iomem.h kexec-tools.1/kexec/arch/arm/iomem.h ---- kexec-tools/kexec/arch/arm/iomem.h 1970-01-01 08:00:00.000000000 +0800 -+++ kexec-tools.1/kexec/arch/arm/iomem.h 2016-08-09 15:38:26.938594379 +0800 -@@ -0,0 +1,9 @@ -+#ifndef IOMEM_H -+#define IOMEM_H -+ -+#define SYSTEM_RAM "System RAM\n" -+#define SYSTEM_RAM_BOOT "System RAM (boot alias)\n" -+#define CRASH_KERNEL "Crash kernel\n" -+#define CRASH_KERNEL_BOOT "Crash kernel (boot alias)\n" -+ -+#endif -diff -uprN kexec-tools/kexec/arch/arm/phys_to_virt.h kexec-tools.1/kexec/arch/arm/phys_to_virt.h ---- kexec-tools/kexec/arch/arm/phys_to_virt.h 1970-01-01 08:00:00.000000000 +0800 -+++ kexec-tools.1/kexec/arch/arm/phys_to_virt.h 2016-08-09 14:50:30.104143361 +0800 -@@ -0,0 +1,8 @@ -+#ifndef PHYS_TO_VIRT_H -+#define PHYS_TO_VIRT_H -+ -+#include -+ -+extern uint64_t phys_offset; -+ -+#endif diff --git a/kexec-tools-2.0.13-kexec-Add-common-device-tree-routines.patch b/kexec-tools-2.0.13-kexec-Add-common-device-tree-routines.patch deleted file mode 100644 index 87897f0..0000000 --- a/kexec-tools-2.0.13-kexec-Add-common-device-tree-routines.patch +++ /dev/null @@ -1,208 +0,0 @@ -From 217bcc00c9309416a6c6cd0584196559d28a9259 Mon Sep 17 00:00:00 2001 -From: Geoff Levand -Date: Wed, 21 Sep 2016 18:14:25 +0000 -Subject: [PATCH 1/3] kexec: Add common device tree routines - -Common device tree routines that can be shared between all arches -that have device tree support. - -Signed-off-by: Geoff Levand -Tested-By: Pratyush Anand -Tested-By: Matthias Brugger -Signed-off-by: Simon Horman ---- - kexec/Makefile | 4 ++ - kexec/dt-ops.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - kexec/dt-ops.h | 13 ++++++ - 3 files changed, 162 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..915dbf5 ---- /dev/null -+++ b/kexec/dt-ops.c -@@ -0,0 +1,145 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#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(). -+ */ -+ -+ result = fdt_pack(new_dtb); -+ -+ if (result) -+ dbgprintf("%s: Unable to pack device tree: %s\n", __func__, -+ fdt_strerror(result)); -+ -+ *dtb = new_dtb; -+ *dtb_size = fdt_totalsize(*dtb); -+ -+ 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 -+ -+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.9.3 - diff --git a/kexec-tools-2.0.13-kexec-arch-i386-Add-support-for-KASLR-memory-randomi.patch b/kexec-tools-2.0.13-kexec-arch-i386-Add-support-for-KASLR-memory-randomi.patch deleted file mode 100644 index a5474cb..0000000 --- a/kexec-tools-2.0.13-kexec-arch-i386-Add-support-for-KASLR-memory-randomi.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 9f62cbddddfc93d78d9aafbddf3e1208cb242f7b Mon Sep 17 00:00:00 2001 -From: Thomas Garnier -Date: Tue, 13 Sep 2016 15:10:05 +0800 -Subject: [PATCH] kexec/arch/i386: Add support for KASLR memory randomization - -Multiple changes were made on KASLR (right now in linux-next). One of -them is randomizing the virtual address of the physical mapping, vmalloc -and vmemmap memory sections. It breaks kdump ability to read physical -memory. - -This change identifies if KASLR memories randomization is used by -checking if the page_offset_base variable exists. It search for the -correct PAGE_OFFSET value by looking at the loaded memory section and -find the lowest aligned on PUD (the randomization level). - -Related commits on linux-next: - - 0483e1fa6e09d4948272680f691dccb1edb9677f: Base for randomization - - 021182e52fe01c1f7b126f97fd6ba048dc4234fd: Enable for PAGE_OFFSET - -Signed-off-by: Thomas Garnier -Signed-off-by: Simon Horman ---- - kexec/arch/i386/crashdump-x86.c | 29 ++++++++++++++++++++++------- - 1 file changed, 22 insertions(+), 7 deletions(-) - -diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c -index bbc0f35..ab833d4 100644 ---- a/kexec/arch/i386/crashdump-x86.c -+++ b/kexec/arch/i386/crashdump-x86.c -@@ -102,11 +102,10 @@ static int get_kernel_paddr(struct kexec_info *UNUSED(info), - return -1; - } - --/* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */ --static unsigned long long get_kernel_stext_sym(void) -+/* Retrieve kernel symbol virtual address from /proc/kallsyms */ -+static unsigned long long get_kernel_sym(const char *symbol) - { - const char *kallsyms = "/proc/kallsyms"; -- const char *stext = "_stext"; - char sym[128]; - char line[128]; - FILE *fp; -@@ -122,13 +121,13 @@ static unsigned long long get_kernel_stext_sym(void) - while(fgets(line, sizeof(line), fp) != NULL) { - if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3) - continue; -- if (strcmp(sym, stext) == 0) { -- dbgprintf("kernel symbol %s vaddr = %16llx\n", stext, vaddr); -+ if (strcmp(sym, symbol) == 0) { -+ dbgprintf("kernel symbol %s vaddr = %16llx\n", symbol, vaddr); - return vaddr; - } - } - -- fprintf(stderr, "Cannot get kernel %s symbol address\n", stext); -+ fprintf(stderr, "Cannot get kernel %s symbol address\n", symbol); - return 0; - } - -@@ -151,6 +150,8 @@ static int get_kernel_vaddr_and_size(struct kexec_info *UNUSED(info), - off_t size; - uint32_t elf_flags = 0; - uint64_t stext_sym; -+ const unsigned long long pud_mask = ~((1 << 30) - 1); -+ unsigned long long vaddr, lowest_vaddr = 0; - - if (elf_info->machine != EM_X86_64) - return 0; -@@ -180,9 +181,23 @@ static int get_kernel_vaddr_and_size(struct kexec_info *UNUSED(info), - - end_phdr = &ehdr.e_phdr[ehdr.e_phnum]; - -+ /* Search for the real PAGE_OFFSET when KASLR memory randomization -+ * is enabled */ -+ if (get_kernel_sym("page_offset_base") != 0) { -+ for(phdr = ehdr.e_phdr; phdr != end_phdr; phdr++) { -+ if (phdr->p_type == PT_LOAD) { -+ vaddr = phdr->p_vaddr & pud_mask; -+ if (lowest_vaddr == 0 || lowest_vaddr > vaddr) -+ lowest_vaddr = vaddr; -+ } -+ } -+ if (lowest_vaddr != 0) -+ elf_info->page_offset = lowest_vaddr; -+ } -+ - /* Traverse through the Elf headers and find the region where - * _stext symbol is located in. That's where kernel is mapped */ -- stext_sym = get_kernel_stext_sym(); -+ stext_sym = get_kernel_sym("_stext"); - for(phdr = ehdr.e_phdr; stext_sym && phdr != end_phdr; phdr++) { - if (phdr->p_type == PT_LOAD) { - unsigned long long saddr = phdr->p_vaddr; --- -2.10.1 -