M7350/oe-core/meta/recipes-kernel/kexec/kexec-tools/kexec-aarch64.patch
2024-09-09 08:57:42 +00:00

780 lines
20 KiB
Diff

From: Geoff Levand <geoff@infradead.org>
Date: Mon, 15 Jul 2013 23:32:36 +0000 (-0700)
Subject: Add arm64 support
X-Git-Url: https://git.linaro.org/gitweb?p=people%2Fgeoff%2Fkexec-tools.git;a=commitdiff_plain;h=fbf5ac6c2c70ec0f6da2b9ff563e573999752c01
Add arm64 support
Signed-off-by: Geoff Levand <geoff@infradead.org>
Get patch from:
https://fedorapeople.org/~hrw/aarch64/for-fedora/kexec-aarch64.patch
Upstream-Status: Pending
Signed-off-by: Kai Kang <kai.kang@windriver.com>
---
---
configure.ac | 3
kexec/Makefile | 1
kexec/arch/arm64/Makefile | 13 +
kexec/arch/arm64/crashdump-arm64.c | 305 ++++++++++++++++++++++++++++++++
kexec/arch/arm64/include/arch/options.h | 26 ++
kexec/arch/arm64/kexec-arm64.c | 177 ++++++++++++++++++
kexec/arch/arm64/kexec-arm64.h | 20 ++
kexec/arch/arm64/kexec-elf-arm64.c | 114 +++++++++++
kexec/kexec-syscall.h | 9
kexec/kexec.c | 2
purgatory/arch/arm64/Makefile | 7
11 files changed, 675 insertions(+), 2 deletions(-)
--- a/configure.ac
+++ b/configure.ac
@@ -35,6 +35,9 @@ case $target_cpu in
ARCH="ppc64"
SUBARCH="LE"
;;
+ aarch64* )
+ ARCH="arm64"
+ ;;
arm* )
ARCH="arm"
;;
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -71,6 +71,7 @@ KEXEC_SRCS += $($(ARCH)_FS2DT)
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
--- /dev/null
+++ b/kexec/arch/arm64/Makefile
@@ -0,0 +1,13 @@
+
+arm64_KEXEC_SRCS += \
+ kexec/arch/arm64/kexec-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 =
+
+dist += $(arm64_KEXEC_SRCS) \
+ kexec/arch/arm64/Makefile \
+ kexec/arch/arm64/kexec-arm64.h
--- /dev/null
+++ b/kexec/arch/arm64/crashdump-arm64.c
@@ -0,0 +1,305 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation (version 2 of the License).
+ */
+
+#include "../../kexec.h"
+#include "../../kexec-elf.h"
+#include "../../crashdump.h"
+
+int is_crashkernel_mem_reserved(void)
+{
+ return 0;
+}
+
+#if 0
+/*
+ * Used to save various memory ranges/regions needed for the captured
+ * kernel to boot. (lime memmap= option in other archs)
+ */
+static struct memory_range crash_memory_ranges[CRASH_MAX_MEMORY_RANGES];
+struct memory_ranges usablemem_rgns = {
+ .size = 0,
+ .ranges = crash_memory_ranges,
+};
+
+/* memory range reserved for crashkernel */
+static struct memory_range crash_reserved_mem;
+
+static struct crash_elf_info elf_info = {
+ .class = ELFCLASS32,
+ .data = ELFDATA2LSB,
+ .machine = EM_ARM,
+ .page_offset = PAGE_OFFSET,
+};
+
+unsigned long phys_offset;
+
+/**
+ * crash_range_callback() - callback called for each iomem region
+ * @data: not used
+ * @nr: not used
+ * @str: name of the memory region
+ * @base: start address of the memory region
+ * @length: size of the memory region
+ *
+ * This function is called once for each memory region found in /proc/iomem. It
+ * locates system RAM and crashkernel reserved memory and places these to
+ * variables: @crash_memory_ranges and @crash_reserved_mem. Number of memory
+ * regions is placed in @crash_memory_nr_ranges.
+ */
+static int crash_range_callback(void *UNUSED(data), int UNUSED(nr),
+ char *str, unsigned long base,
+ unsigned long length)
+{
+ struct memory_range *range;
+
+ if (usablemem_rgns.size >= CRASH_MAX_MEMORY_RANGES)
+ return 1;
+
+ range = usablemem_rgns.ranges + usablemem_rgns.size;
+
+ if (strncmp(str, "System RAM\n", 11) == 0) {
+ range->start = base;
+ range->end = base + length - 1;
+ range->type = RANGE_RAM;
+ usablemem_rgns.size++;
+ } else if (strncmp(str, "Crash kernel\n", 13) == 0) {
+ crash_reserved_mem.start = base;
+ crash_reserved_mem.end = base + length - 1;
+ crash_reserved_mem.type = RANGE_RAM;
+ }
+
+ return 0;
+}
+
+/**
+ * crash_exclude_range() - excludes memory region reserved for crashkernel
+ *
+ * Function locates where crashkernel reserved memory is and removes that region
+ * from the available memory regions.
+ */
+static void crash_exclude_range(void)
+{
+ const struct memory_range *range = &crash_reserved_mem;
+ int i;
+
+ for (i = 0; i < usablemem_rgns.size; i++) {
+ struct memory_range *r = usablemem_rgns.ranges + i;
+
+ /*
+ * We assume that crash area is fully contained in
+ * some larger memory area.
+ */
+ if (r->start <= range->start && r->end >= range->end) {
+ struct memory_range *new;
+ /*
+ * Let's split this area into 2 smaller ones and
+ * remove excluded range from between. First create
+ * new entry for the remaining area.
+ */
+ new = usablemem_rgns.ranges + usablemem_rgns.size;
+ new->start = range->end + 1;
+ new->end = r->end;
+ usablemem_rgns.size++;
+ /*
+ * Next update this area to end before excluded range.
+ */
+ r->end = range->start - 1;
+ break;
+ }
+ }
+}
+
+static int range_cmp(const void *a1, const void *a2)
+{
+ const struct memory_range *r1 = a1;
+ const struct memory_range *r2 = a2;
+
+ if (r1->start > r2->start)
+ return 1;
+ if (r1->start < r2->start)
+ return -1;
+
+ return 0;
+}
+
+/**
+ * crash_get_memory_ranges() - read system physical memory
+ *
+ * Function reads through system physical memory and stores found memory regions
+ * in @crash_memory_ranges. Number of memory regions found is placed in
+ * @crash_memory_nr_ranges. Regions are sorted in ascending order.
+ *
+ * Returns %0 in case of success and %-1 otherwise (errno is set).
+ */
+static int crash_get_memory_ranges(void)
+{
+ /*
+ * First read all memory regions that can be considered as
+ * system memory including the crash area.
+ */
+ kexec_iomem_for_each_line(NULL, crash_range_callback, NULL);
+
+ if (usablemem_rgns.size < 1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /*
+ * Exclude memory reserved for crashkernel (this may result a split memory
+ * region).
+ */
+ crash_exclude_range();
+
+ /*
+ * Make sure that the memory regions are sorted.
+ */
+ qsort(usablemem_rgns.ranges, usablemem_rgns.size,
+ sizeof(*usablemem_rgns.ranges), range_cmp);
+
+ return 0;
+}
+
+/**
+ * cmdline_add_elfcorehdr() - adds elfcorehdr= to @cmdline
+ * @cmdline: buffer where parameter is placed
+ * @elfcorehdr: physical address of elfcorehdr
+ *
+ * Function appends 'elfcorehdr=start' at the end of the command line given in
+ * @cmdline. Note that @cmdline must be at least %COMMAND_LINE_SIZE bytes long
+ * (inclunding %NUL).
+ */
+static void cmdline_add_elfcorehdr(char *cmdline, unsigned long elfcorehdr)
+{
+ char buf[COMMAND_LINE_SIZE];
+ int buflen;
+
+ buflen = snprintf(buf, sizeof(buf), "%s elfcorehdr=%#lx",
+ cmdline, elfcorehdr);
+ if (buflen < 0)
+ die("Failed to construct elfcorehdr= command line parameter\n");
+ if (buflen >= sizeof(buf))
+ die("Command line overflow\n");
+
+ (void) strncpy(cmdline, buf, COMMAND_LINE_SIZE);
+ cmdline[COMMAND_LINE_SIZE - 1] = '\0';
+}
+
+/**
+ * cmdline_add_mem() - adds mem= parameter to kernel command line
+ * @cmdline: buffer where parameter is placed
+ * @size: size of the kernel reserved memory (in bytes)
+ *
+ * This function appends 'mem=size' at the end of the command line given in
+ * @cmdline. Note that @cmdline must be at least %COMMAND_LINE_SIZE bytes long
+ * (including %NUL).
+ */
+static void cmdline_add_mem(char *cmdline, unsigned long size)
+{
+ char buf[COMMAND_LINE_SIZE];
+ int buflen;
+
+ buflen = snprintf(buf, sizeof(buf), "%s mem=%ldK", cmdline, size >> 10);
+ if (buflen < 0)
+ die("Failed to construct mem= command line parameter\n");
+ if (buflen >= sizeof(buf))
+ die("Command line overflow\n");
+
+ (void) strncpy(cmdline, buf, COMMAND_LINE_SIZE);
+ cmdline[COMMAND_LINE_SIZE - 1] = '\0';
+}
+
+static unsigned long long range_size(const struct memory_range *r)
+{
+ return r->end - r->start + 1;
+}
+
+static void dump_memory_ranges(void)
+{
+ int i;
+
+ if (!kexec_debug)
+ return;
+
+ dbgprintf("crashkernel: [%#llx - %#llx] (%ldM)\n",
+ crash_reserved_mem.start, crash_reserved_mem.end,
+ (unsigned long)range_size(&crash_reserved_mem) >> 20);
+
+ for (i = 0; i < usablemem_rgns.size; i++) {
+ struct memory_range *r = usablemem_rgns.ranges + i;
+ dbgprintf("memory range: [%#llx - %#llx] (%ldM)\n",
+ r->start, r->end, (unsigned long)range_size(r) >> 20);
+ }
+}
+
+/**
+ * load_crashdump_segments() - loads additional segments needed for kdump
+ * @info: kexec info structure
+ * @mod_cmdline: kernel command line
+ *
+ * This function loads additional segments which are needed for the dump capture
+ * kernel. It also updates kernel command line passed in @mod_cmdline to have
+ * right parameters for the dump capture kernel.
+ *
+ * Return %0 in case of success and %-1 in case of error.
+ */
+int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
+{
+ unsigned long elfcorehdr;
+ unsigned long bufsz;
+ void *buf;
+ int err;
+
+ /*
+ * First fetch all the memory (RAM) ranges that we are going to pass to
+ * the crashdump kernel during panic.
+ */
+ err = crash_get_memory_ranges();
+ if (err)
+ return err;
+
+ /*
+ * Now that we have memory regions sorted, we can use first memory
+ * region as PHYS_OFFSET.
+ */
+ phys_offset = usablemem_rgns.ranges->start;
+ dbgprintf("phys_offset: %#lx\n", phys_offset);
+
+ err = crash_create_elf32_headers(info, &elf_info,
+ usablemem_rgns.ranges,
+ usablemem_rgns.size, &buf, &bufsz,
+ ELF_CORE_HEADER_ALIGN);
+ if (err)
+ return err;
+
+ /*
+ * We allocate ELF core header from the end of the memory area reserved
+ * for the crashkernel. We align the header to SECTION_SIZE (which is
+ * 1MB) so that available memory passed in kernel command line will be
+ * aligned to 1MB. This is because kernel create_mapping() wants memory
+ * regions to be aligned to SECTION_SIZE.
+ */
+ elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 1 << 20,
+ crash_reserved_mem.start,
+ crash_reserved_mem.end, -1, 0);
+
+ dbgprintf("elfcorehdr: %#lx\n", elfcorehdr);
+ cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
+
+ /*
+ * Add 'mem=size' parameter to dump capture kernel command line. This
+ * prevents the dump capture kernel from using any other memory regions
+ * which belong to the primary kernel.
+ */
+ cmdline_add_mem(mod_cmdline, elfcorehdr - crash_reserved_mem.start);
+
+ dump_memory_ranges();
+ dbgprintf("kernel command line: \"%s\"\n", mod_cmdline);
+
+ return 0;
+}
+
+#endif
+
--- /dev/null
+++ b/kexec/arch/arm64/include/arch/options.h
@@ -0,0 +1,26 @@
+#ifndef KEXEC_ARCH_ARM64_OPTIONS_H
+#define KEXEC_ARCH_ARM64_OPTIONS_H
+
+//#define OPT_ARCH_MAX ((OPT_MAX)+0)
+
+#define OPT_APPEND ((OPT_MAX)+0)
+#define OPT_RAMDISK ((OPT_MAX)+1)
+#define OPT_DTB ((OPT_MAX)+2)
+
+#define OPT_ARCH_MAX ((OPT_MAX)+3)
+
+
+#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_RAMDISK }, \
+ { "ramdisk", 1, NULL, OPT_RAMDISK }, \
+
+#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
+
+#endif /* KEXEC_ARCH_ARM64_OPTIONS_H */
--- /dev/null
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -0,0 +1,177 @@
+/*
+ * ARM64 kexec support.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <stddef.h>
+
+//#include <linux/kexec.h>
+
+#include "../../kexec.h"
+#include "../../kexec-syscall.h"
+#include "kexec-arm64.h"
+
+
+void arch_usage(void)
+{
+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
+
+ printf(
+" --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");
+
+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
+}
+
+int arch_process_options(int UNUSED(argc), char **UNUSED(argv))
+{
+ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__);
+ return 0;
+}
+
+const struct arch_map_entry arches[] = {
+ { "aarch64", KEXEC_ARCH_ARM64 },
+ { NULL, 0 },
+};
+
+void arch_update_purgatory(struct kexec_info *UNUSED(info))
+{
+ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__);
+}
+
+unsigned long virt_to_phys(unsigned long addr)
+{
+ fprintf(stderr, "%s:%d: %016lx -> %016lx\n", __func__, __LINE__, addr,
+ addr + 0x080000000UL);
+ return addr + 0x080000000UL;
+}
+
+void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
+ unsigned long base, size_t memsz)
+{
+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
+ add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
+}
+
+static int get_memory_ranges_1(struct memory_range **range, int *ranges,
+ unsigned long kexec_flags)
+{
+ static struct memory_range memory_range[KEXEC_SEGMENT_MAX];
+ const char *iomem;
+ int range_count = 0;
+ char line[MAX_LINE];
+ FILE *fp;
+
+ iomem = proc_iomem();
+ fp = fopen(iomem, "r");
+
+ if (!fp) {
+ fprintf(stderr, "Cannot open %s: %s\n",
+ iomem, strerror(errno));
+ return -1;
+ }
+
+ dbgprintf("memory ranges:\n");
+
+ while(fgets(line, sizeof(line), fp) != 0) {
+ struct memory_range r;
+ char *str;
+ int consumed;
+
+ if (range_count >= KEXEC_SEGMENT_MAX)
+ break;
+
+ if (sscanf(line, "%Lx-%Lx : %n", &r.start, &r.end, &consumed)
+ != 2)
+ continue;
+
+ str = line + consumed;
+ r.end++;
+
+ if (memcmp(str, "System RAM\n", 11)) {
+ dbgprintf(" Skip: %016Lx - %016Lx : %s", r.start, r.end,
+ str);
+ continue;
+ }
+
+ r.type = RANGE_RAM;
+ memory_range[range_count] = r;
+ range_count++;
+
+ dbgprintf(" Add: %016Lx - %016Lx : %s", r.start, r.end, str);
+ }
+
+ fclose(fp);
+ *range = memory_range;
+ *ranges = range_count;
+
+ return 0;
+}
+
+static int get_memory_ranges_2(struct memory_range **range, int *ranges,
+ unsigned long UNUSED(kexec_flags))
+{
+ static struct memory_range memory_range[2];
+
+ memory_range[0].start = 0x080000000;
+ memory_range[0].end = 0x100000000;
+ memory_range[0].type = RANGE_RAM;
+
+ memory_range[1].start = 0x900000000;
+ memory_range[1].end = 0x880000000;
+ memory_range[1].type = RANGE_RAM;
+
+ *range = memory_range;
+ *ranges = sizeof(memory_range) / sizeof(memory_range[0]);
+
+ return 0;
+}
+
+int get_memory_ranges(struct memory_range **range, int *ranges,
+ unsigned long kexec_flags)
+{
+ /* FIXME: Should get this info from device tree. */
+
+ return get_memory_ranges_1(range, ranges, kexec_flags);
+}
+
+struct file_type file_type[] = {
+ { "elf-arm64", elf_arm64_probe, elf_arm64_load, elf_arm64_usage },
+};
+
+int file_types = sizeof(file_type) / sizeof(file_type[0]);
+
+int arch_compat_trampoline(struct kexec_info *info)
+{
+ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__);
+ return 0;
+}
+
+void arch_reuse_initrd(void)
+{
+}
+
+int machine_verify_elf_rel(struct mem_ehdr *ehdr)
+{
+ (void)ehdr;
+
+ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__);
+ return 0;
+}
+
+void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
+ void *location, unsigned long address, unsigned long value)
+{
+ (void)ehdr;
+ (void)r_type;
+ (void)location;
+ (void)address;
+ (void)value;
+ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__);
+}
--- /dev/null
+++ b/kexec/arch/arm64/kexec-arm64.h
@@ -0,0 +1,20 @@
+/*
+ * ARM64 kexec support.
+ */
+
+#if !defined(KEXEC_ARM64_H)
+#define KEXEC_ARM64_H
+
+/* #include <linux/kexec.h> FIXME: this is broken */
+#include <sys/types.h>
+
+#include "../../kexec.h"
+
+#define KEXEC_SEGMENT_MAX 16 /* FIXME: this should come from <linux/kexec.h> */
+
+int elf_arm64_probe(const char *buf, off_t len);
+int elf_arm64_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info);
+void elf_arm64_usage(void);
+
+#endif
\ No newline at end of file
--- /dev/null
+++ b/kexec/arch/arm64/kexec-elf-arm64.c
@@ -0,0 +1,114 @@
+/*
+ * ARM64 kexec support.
+ */
+
+#define _GNU_SOURCE
+
+#include <elf.h>
+#include <getopt.h>
+
+#include "../../kexec-syscall.h"
+
+#include "kexec-arm64.h"
+#include "arch/options.h"
+
+#if !defined(EM_AARCH64)
+# define EM_AARCH64 183
+#endif
+
+int elf_arm64_probe(const char *buf, off_t len)
+{
+ int result;
+ struct mem_ehdr ehdr;
+
+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
+
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
+
+ if (result < 0) {
+ dbgprintf("Not an ELF executable\n");
+ goto out;
+ }
+
+ if (ehdr.e_machine != EM_AARCH64) {
+ dbgprintf("Not an AARCH64 executable\n");
+ result = -1;
+ goto out;
+ }
+
+ result = 0;
+
+out:
+ free_elf_info(&ehdr);
+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
+ return result;
+}
+
+int elf_arm64_load(int argc, char **argv, const char *buf, off_t len,
+ struct kexec_info *info)
+{
+ static const struct option options[] = {
+ KEXEC_ARCH_OPTIONS
+ { 0 }
+ };
+ static const char short_options[] = KEXEC_OPT_STR "";
+ const char *command_line = NULL;
+ unsigned int command_line_len = 0;
+ const char *ramdisk = NULL;
+ const char *dtb = NULL;
+ int opt;
+ struct mem_ehdr ehdr;
+ int result;
+
+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
+
+ while ((opt = getopt_long(argc, argv, short_options, options, 0))
+ != -1) {
+ switch (opt) {
+ default:
+ if (opt < OPT_MAX) /* Ignore core options */
+ break;
+ case OPT_APPEND:
+ command_line = optarg;
+ command_line_len = strlen(command_line) + 1;
+ break;
+ case OPT_RAMDISK:
+ ramdisk = optarg;
+ break;
+ case OPT_DTB:
+ dtb = optarg;
+ break;
+ }
+ }
+
+ fprintf(stderr, "%s:%d: command_line: %s\n", __func__, __LINE__, command_line);
+ fprintf(stderr, "%s:%d: ramdisk: %s\n", __func__, __LINE__, ramdisk);
+ fprintf(stderr, "%s:%d: dtb: %s\n", __func__, __LINE__, dtb);
+
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ fprintf(stderr, "kexec: kdump not yet supported on arm64\n");
+ return -1;
+ }
+
+ result = build_elf_exec_info(buf, len, &ehdr, 0);
+
+ if (result < 0) {
+ free_elf_info(&ehdr);
+ fprintf(stderr, "%s:%d: free_elf_info failed\n", __func__,
+ __LINE__);
+ return result;
+ }
+
+ elf_exec_build_load(info, &ehdr, buf, len, 0);
+
+ info->entry = (void*)0x80080000UL; // FIXME
+
+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
+ return 0;
+}
+
+void elf_arm64_usage(void)
+{
+ fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__);
+ fprintf(stderr, "%s:%d: <-\n", __func__, __LINE__);
+}
--- 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,8 @@ static inline long kexec_file_load(int k
#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_AARCH64 (183 << 16) */
#define KEXEC_ARCH_S390 (22 << 16)
#define KEXEC_ARCH_SH (42 << 16)
#define KEXEC_ARCH_MIPS_LE (10 << 16)
@@ -153,5 +155,8 @@ static inline long kexec_file_load(int k
#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 */
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -664,6 +664,8 @@ static int my_load(const char *type, int
memset(&info, 0, sizeof(info));
info.kexec_flags = kexec_flags;
+ fprintf(stderr, "%s:%d: do\n", __func__, __LINE__);
+
result = 0;
if (argc - fileind <= 0) {
fprintf(stderr, "No kernel specified\n");
--- /dev/null
+++ b/purgatory/arch/arm64/Makefile
@@ -0,0 +1,7 @@
+#
+# Purgatory arm64
+#
+
+arm64_PURGATORY_SRCS =
+
+dist += purgatory/arch/arm64/Makefile $(arm64_PURGATORY_SRCS)