arm64 kexec-tools patches
Subsystems (2)
v4 cover arm64 kexec-tools patches
This series adds the core support for kexec re-boot on ARM64.
Linux kernel support for ARM64 kexec reboot has been merged in v4.8-rc1 with the expectation that it will be included in the v4.8 stable kernel release.
For ARM64 kdump support see Takahiro's latest kdump patches [1].
[1] http://lists.infradead.org/pipermail/kexec/2016-August/016779.html
Changes for v4 (Aug 18, 2016, 1m):
o Fix some error return values and error messages.
o Add enum arm64_header_page_size.
o Rename page_offset to vp_offset.
Changes for v3 (Aug 10, 2016, 1m):
o Rebase to 2.0.13.
o Add support for flag bits 1-3 to arm64 image-header.h.
o Fix OPT_ARCH_MAX value.
o Use fdt_pack() in dtb_set_property().
o Remove patch ("kexec: (bugfix) calc correct end address of memory ranges in device tree").
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 67488beb0a6ee8ad2c0b05f721a9e00041fab93a:
kexec-tools 2.0.13 (2016-08-08 12:26:44 +0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/geoff/kexec-tools.git for-merge-arm64-v4
for you to fetch changes up to 7b17bc40e62e90fd92207d4385a0a99aec958d26:
arm64: Add support for binary image files (2016-08-18 11:09:39 -0700)
----------------------------------------------------------------
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 | 146 +++++++ kexec/arch/arm64/include/arch/options.h | 39 ++ kexec/arch/arm64/kexec-arm64.c | 705 ++++++++++++++++++++++++++++++++ kexec/arch/arm64/kexec-arm64.h | 70 ++++ kexec/arch/arm64/kexec-elf-arm64.c | 132 ++++++ kexec/arch/arm64/kexec-image-arm64.c | 60 +++ kexec/dt-ops.c | 145 +++++++ kexec/dt-ops.h | 13 + 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 + 18 files changed, 1486 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 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
Signature · 7 lines
2.7.4 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH v4 1/3 kexec: Add common device tree routines
Common device tree routines that can be shared between all arches that have device tree support.
--- 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
kexec/Makefile +4 -0
@@ -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
kexec/dt-ops.c new file +145 -0
145 lines not on this page · raw message
kexec/dt-ops.h new file +13 -0
@@ -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
Signature · 8 lines
2.7.4 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
PATCH v4 2/3 arm64: Add arm64 kexec support
In reply to Geoff LevandAdd kexec reboot support for ARM64 platforms.
--- 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 | 705 ++++++++++++++++++++++++++++++++ kexec/arch/arm64/kexec-arm64.h | 70 ++++ kexec/arch/arm64/kexec-elf-arm64.c | 132 ++++++ 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, 1305 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
configure.ac +3 -0
@@ -34,6 +34,9 @@ case $target_cpu in ARCH="ppc64" SUBARCH="LE" ;; + aarch64* ) + ARCH="arm64" + ;; arm* ) ARCH="arm" ;;
kexec/Makefile +1 -0
@@ -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
kexec/arch/arm64/Makefile new file +40 -0
@@ -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
kexec/arch/arm64/crashdump-arm64.c new file +21 -0
@@ -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 ; +}
kexec/arch/arm64/crashdump-arm64.h new file +12 -0
@@ -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
kexec/arch/arm64/image-header.h new file +146 -0
146 lines not on this page · raw message
kexec/arch/arm64/include/arch/options.h new file +39 -0
@@ -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
kexec/arch/arm64/kexec-arm64.c new file +705 -0
705 lines not on this page · raw message
kexec/arch/arm64/kexec-arm64.h new file +70 -0
70 lines not on this page · raw message
kexec/arch/arm64/kexec-elf-arm64.c new file +132 -0
132 lines not on this page · raw message
kexec/arch/arm64/kexec-image-arm64.c new file +41 -0
41 lines not on this page · raw message
kexec/kexec-syscall.h +6 -2
@@ -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 */
purgatory/Makefile +1 -0
@@ -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
purgatory/arch/arm64/Makefile new file +18 -0
@@ -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
purgatory/arch/arm64/entry.S new file +51 -0
52 lines not on this page · raw message
purgatory/arch/arm64/purgatory-arm64.c new file +19 -0
@@ -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 ) +{ +}
Signature · 8 lines
2.7.4 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec
Re: [PATCH v4 2/3] arm64: Add arm64 kexec support
Quoted 784 lines · Geoff Levand
Add kexec reboot support for ARM64 platforms.
Signed-off-by Geoff Levand <[email protected]>--- 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 | 705 ++++++++++++++++++++++++++++++++ kexec/arch/arm64/kexec-arm64.h | 70 ++++ kexec/arch/arm64/kexec-elf-arm64.c | 132 ++++++ 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, 1305 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.cconfigure.ac +3
-0@@ -34,6 +34,9 @@ case $target_cpu in ARCH="ppc64" SUBARCH="LE" ;; + aarch64* ) + ARCH="arm64" + ;; arm* ) ARCH="arm" ;;kexec/Makefile +1
-0@@ -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/Makefilekexec/arch/arm64/Makefile new file +40
-0@@ -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) + +endifkexec/arch/arm64/crashdump-arm64.c new file +21
-0@@ -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 ; +}kexec/arch/arm64/crashdump-arm64.h new file +12
-0@@ -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 kexec/arch/arm64/image-header.h new file +146
-0@@ -0,0 +1,146 @@ +/* +* 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. +* 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 kexec/arch/arm64/include/arch/options.h new file +39
-0@@ -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 kexec/arch/arm64/kexec-arm64.c new file +430
-0@@ -0,0 +1,705 @@ +/* +* 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-em.h> +#include <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, + .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; + + 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_vp_offset () +get_phys_offset (); + +return p; +} + +/** +* phys_to_virt - For crashdump setup. +*/
kexec/arch/arm64/kexec-arm64.c line 440
Quoted 10 lines
kexec/arch/arm64/kexec-arm64.c new file +10
-0+ +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; +}
phys_to_virt() is used only in case of kdump. Though it doesn't matter that this function is here, elf_info->page_offset is not set in this patch series.
Quoted 198 lines
kexec/arch/arm64/kexec-arm64.c new file +198
-0+/** +* 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 = -EFAILED ; + +on_exit: +free (dtb.buf); +return result; +} + +/** +* 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 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 )
kexec/arch/arm64/kexec-arm64.c line 649
Quoted 10 lines
kexec/arch/arm64/kexec-arm64.c new file +10
-0+# 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
What I meant is kexec-tools' include/elf.h, where all the relocation types for other architectures are defined.
Thanks,
-Takahiro AKASHI
Quoted 472 lines
kexec/arch/arm64/kexec-arm64.c new file +56
-0+ +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 )) +{ +}kexec/arch/arm64/kexec-arm64.h new file +70
-0@@ -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 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); +int arm64_load_other_segments (struct kexec_info *info, +uint64_t kernel_entry); + +#endif kexec/arch/arm64/kexec-elf-arm64.c new file +132
-0@@ -0,0 +1,132 @@ +/* +* 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.vp_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: vp_offset: %016lx\n" , __func__, + arm64_mem.vp_offset); +dbgprintf ("%s: PE format: %s\n" , __func__, + (arm64_header_check_pe_sig (h) ?"yes" :"no" )); + + result =elf_exec_load (&ehdr, info); + +if (result) { +dbgprintf ("%s: elf_exec_load failed\n" , __func__); + goto exit; + } + + result =arm64_load_other_segments (info, +virt_to_phys (ehdr.e_entry)); + goto exit; + } + +dbgprintf ("%s: Bad arm64 image header\n" , __func__); + result = -EFAILED ; + goto exit; + +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" ); +}kexec/arch/arm64/kexec-image-arm64.c new file +41
-0@@ -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" ); +}kexec/kexec-syscall.h +6
-2@@ -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 */ purgatory/Makefile +1
-0@@ -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/Makefilepurgatory/arch/arm64/Makefile new file +18
-0@@ -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/Makefilepurgatory/arch/arm64/entry.S new file +51
-0@@ -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 + +.endpurgatory/arch/arm64/purgatory-arm64.c new file +19
-0@@ -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 ) +{ +}Signature · 1 line
2.7.4
_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec
PATCH v4 3/3 arm64: Add support for binary image files
In reply to Geoff LevandFrom: Pratyush Anand <[email protected]>
--- kexec/arch/arm64/kexec-image-arm64.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-)
kexec/arch/arm64/kexec-image-arm64.c +24 -5
@@ -21,14 +21,35 @@ 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 *h; +unsigned long image_base; + + h = (const struct arm64_image_header *)(kernel_buf); + +if (arm64_process_image_header (h)) +return -1 ; + +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 )
@@ -36,6 +57,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" ); }
Signature · 7 lines
2.7.4 _______________________________________________ kexec mailing list [email protected] http://lists.infradead.org/mailman/listinfo/kexec