From 5b7cdf7f10478070dd676e328b527550aec4b8fd Mon Sep 17 00:00:00 2001 From: zyppe <210hcl@gmail.com> Date: Thu, 29 Feb 2024 16:39:34 +0800 Subject: [PATCH] Removed patch has been merged and add RISC-V support and bump version so newer gcc can build. --- ...Add-support-for-kexec-on-kexec-tools.patch | 1176 +++++++++++++++++ kexec-tools-SYS_getrandom.patch | 25 - ...c-tools-add-variant-helper-functions.patch | 84 -- ...-with-resource-entries-in-proc-iomem.patch | 77 -- ...mory-space-avoiding-reserved-regions.patch | 247 ---- kexec-tools-build-multiboot2-for-i386.patch | 70 - ...s-fix-kexec_file_load-error-handling.patch | 230 ---- ...print-error-if-kexec_file_load-fails.patch | 36 - ...getopt-before-falling-back-to-legacy.patch | 54 - ...-Reset-kernel-command-line-on-syscal.patch | 31 - kexec-tools-video-capability.patch | 25 - kexec-tools.spec | 60 +- 12 files changed, 1191 insertions(+), 924 deletions(-) create mode 100644 RISC-V-Add-support-for-kexec-on-kexec-tools.patch delete mode 100644 kexec-tools-SYS_getrandom.patch delete mode 100644 kexec-tools-add-variant-helper-functions.patch delete mode 100644 kexec-tools-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch delete mode 100644 kexec-tools-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch delete mode 100644 kexec-tools-build-multiboot2-for-i386.patch delete mode 100644 kexec-tools-fix-kexec_file_load-error-handling.patch delete mode 100644 kexec-tools-print-error-if-kexec_file_load-fails.patch delete mode 100644 kexec-tools-reset-getopt-before-falling-back-to-legacy.patch delete mode 100644 kexec-tools-s390-Reset-kernel-command-line-on-syscal.patch delete mode 100644 kexec-tools-video-capability.patch diff --git a/RISC-V-Add-support-for-kexec-on-kexec-tools.patch b/RISC-V-Add-support-for-kexec-on-kexec-tools.patch new file mode 100644 index 0000000..ba08d51 --- /dev/null +++ b/RISC-V-Add-support-for-kexec-on-kexec-tools.patch @@ -0,0 +1,1176 @@ +From patchwork Tue Apr 16 12:32:33 2019 +Content-Type: text/plain; charset="utf-8" +MIME-Version: 1.0 +Content-Transfer-Encoding: 7bit +X-Patchwork-Submitter: Nick Kossifidis +X-Patchwork-Id: 10902923 +Return-Path: + +Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org + [172.30.200.125]) + by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A6106139A + for ; + Tue, 16 Apr 2019 12:32:59 +0000 (UTC) +Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) + by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 69ED428947 + for ; + Tue, 16 Apr 2019 12:32:59 +0000 (UTC) +Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) + id 67BF1289EB; Tue, 16 Apr 2019 12:32:59 +0000 (UTC) +X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on + pdx-wl-mail.web.codeaurora.org +X-Spam-Level: +X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, + DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 +Received: from bombadil.infradead.org (bombadil.infradead.org + [198.137.202.133]) + (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) + (No client certificate requested) + by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7660828947 + for ; + Tue, 16 Apr 2019 12:32:56 +0000 (UTC) +DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; + d=lists.infradead.org; s=bombadil.20170209; h=Sender: + Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: + List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-Id:Date:Subject:To + :From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: + Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: + List-Owner; bh=bVaz2qf+pdqHQbaLqHKrRQa2jYTkBAObofgtNsLrdWA=; b=LnueSkO/6mncL2 + 5NzTPBXvv+JLFAnax3AaV9WXPt99dbBpWrkMaC1mxHushNGv/zzj5KvtfQ8dQpc5zGKUVQn7Y71xw + C2expvPdG5CijZ2AE6jiTlibqthLVCKKFIiBEiT7XpbxNxx9l8zj+t6WyLUQeDTY91JwJRB8Q8Saj + ridsvgG38xoKzZZBpC5Mk+aNQ0UykfVPjL7iTO660EgxbpX6O/e3uSRjGQbNrqrZvJAu6o4Zz3fNJ + woomnB7QiWp7sxf6irM6bVfCmb3jOn85sS5tMT8FiXJA3MEgV3pQX0g2kgEnLfuYeIz0kMAN5PpM0 + rkH1aLH299yU2dcEh/sg==; +Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) + by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) + id 1hGNGe-0001xW-VI; Tue, 16 Apr 2019 12:32:52 +0000 +Received: from mailgate-2.ics.forth.gr ([139.91.1.5]) + by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) + id 1hGNGY-0001ws-S9; Tue, 16 Apr 2019 12:32:51 +0000 +Received: from av1.ics.forth.gr (av3in [139.91.1.77]) + by mailgate-2.ics.forth.gr (8.14.4/ICS-FORTH/V10-1.8-GATE) with ESMTP id + x3GCWc4e019120; Tue, 16 Apr 2019 12:32:40 GMT +X-AuditID: 8b5b9d4d-8f5ff7000000235c-72-5cb5cb66eff6 +Received: from enigma.ics.forth.gr (enigma.ics.forth.gr [139.91.1.35]) + by av1.ics.forth.gr (SMTP Outbound / FORTH / ICS) with SMTP id + 6F.1D.09052.66BC5BC5; Tue, 16 Apr 2019 15:32:38 +0300 (EEST) +Received: from trampakoulas.ics.forth.gr (trampakoulas.ics.forth.gr + [139.91.92.59]) (authenticated bits=0) + by enigma.ics.forth.gr (8.15.1//ICS-FORTH/V10.5.0C-EXTNULL-SSL-SASL) with + ESMTPSA id x3GCWYxg012723 + (version=TLSv1.2 cipher=DHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); + Tue, 16 Apr 2019 15:32:37 +0300 +X-ICS-AUTH-INFO: Authenticated user: mick@ics.forth.gr at ics.forth.gr +From: Nick Kossifidis +To: horms@verge.net.au +Subject: [PATCH] RISC-V: Add support for kexec on kexec-tools +Date: Tue, 16 Apr 2019 15:32:33 +0300 +Message-Id: <20190416123233.4779-1-mick@ics.forth.gr> +X-Mailer: git-send-email 2.21.0 +MIME-Version: 1.0 +X-Greylist: inspected by milter-greylist-4.6.2 (mailgate-2.ics.forth.gr + [139.91.1.5]); + Tue, 16 Apr 2019 12:32:40 +0000 (GMT) for IP:'139.91.1.77' DOMAIN:'av3in' + HELO:'av1.ics.forth.gr' FROM:'mick@ics.forth.gr' RCPT:'' +X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.6.2 + (mailgate-2.ics.forth.gr [139.91.1.5]); Tue, 16 Apr 2019 12:32:40 +0000 (GMT) +X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 +X-CRM114-CacheID: sfid-20190416_053247_465442_0666DD49 +X-CRM114-Status: GOOD ( 28.51 ) +X-BeenThere: linux-riscv@lists.infradead.org +X-Mailman-Version: 2.1.21 +Precedence: list +List-Id: +List-Unsubscribe: , + +List-Archive: +List-Post: +List-Help: +List-Subscribe: , + +Cc: Nick Kossifidis , linux-riscv@lists.infradead.org, + palmer@sifive.com, kexec@lists.infradead.org +Sender: "linux-riscv" +Errors-To: + linux-riscv-bounces+patchwork-linux-riscv=patchwork.kernel.org@lists.infradead.org +X-Virus-Scanned: ClamAV using ClamSMTP + +This patch adds kexec support for RISC-V on kexec-tools. +For now this only includes support for the kexec call, no +kexec_file or kdump / crashkernel. The only supported image +type is an ELF image such as vmlinux. When the new kernel +starts a0 will contain the current hart id and a1 the +pointer to the dtb (PA). + +Note: Until we have CPU suspend support on RISC-V we can't +fully recover on an SMP system, the kernel side will call +smp_send_stop(), so at this point we pass "nosmp" to the +next kernel as a temporary workaround. + +I tested this on riscv64 QEMU on both smp and non-smp +setups and works as expected. + +Signed-off-by: Nick Kossifidis +--- + configure.ac | 3 + + include/elf.h | 3 +- + kexec/Makefile | 1 + + kexec/arch/riscv/Makefile | 34 ++ + kexec/arch/riscv/include/arch/options.h | 43 ++ + kexec/arch/riscv/kexec-elf-riscv.c | 281 ++++++++++++ + kexec/arch/riscv/kexec-riscv.c | 545 ++++++++++++++++++++++++ + kexec/arch/riscv/kexec-riscv.h | 24 ++ + kexec/kexec-syscall.h | 4 + + purgatory/Makefile | 1 + + purgatory/arch/riscv/Makefile | 7 + + 12 files changed, 947 insertions(+), 3 deletions(-) + create mode 100644 kexec/arch/riscv/Makefile + create mode 100644 kexec/arch/riscv/include/arch/options.h + create mode 100644 kexec/arch/riscv/kexec-elf-riscv.c + create mode 100644 kexec/arch/riscv/kexec-riscv.c + create mode 100644 kexec/arch/riscv/kexec-riscv.h + create mode 100644 purgatory/arch/riscv/Makefile + +diff --git a/configure.ac b/configure.ac +index 19c99db..4f53054 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -55,6 +55,9 @@ case $target_cpu in + ia64|x86_64|alpha|m68k ) + ARCH="$target_cpu" + ;; ++ riscv32|riscv64 ) ++ ARCH="riscv" ++ ;; + * ) + AC_MSG_ERROR([unsupported architecture $target_cpu]) + ;; +diff --git a/include/elf.h b/include/elf.h +index b7677a2..3e42449 100644 +--- a/include/elf.h ++++ b/include/elf.h +@@ -259,7 +259,8 @@ typedef struct + #define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ + #define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ + #define EM_AARCH64 183 /* ARM AARCH64 */ +-#define EM_NUM 184 ++#define EM_RISCV 243 /* RISC-V */ ++#define EM_NUM 244 + + /* If it is necessary to assign new unofficial EM_* values, please + pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the +diff --git a/kexec/Makefile b/kexec/Makefile +index 4db84d8..c8978f2 100644 +--- a/kexec/Makefile ++++ b/kexec/Makefile +@@ -89,6 +89,7 @@ include $(srcdir)/kexec/arch/mips/Makefile + include $(srcdir)/kexec/arch/cris/Makefile + include $(srcdir)/kexec/arch/ppc/Makefile + include $(srcdir)/kexec/arch/ppc64/Makefile ++include $(srcdir)/kexec/arch/riscv/Makefile + include $(srcdir)/kexec/arch/s390/Makefile + include $(srcdir)/kexec/arch/sh/Makefile + include $(srcdir)/kexec/arch/x86_64/Makefile +diff --git a/kexec/arch/riscv/Makefile b/kexec/arch/riscv/Makefile +new file mode 100644 +index 0000000..13d8fea +--- /dev/null ++++ b/kexec/arch/riscv/Makefile +@@ -0,0 +1,34 @@ ++# ++# kexec riscv ++# ++riscv_KEXEC_SRCS = kexec/arch/riscv/kexec-riscv.c ++riscv_KEXEC_SRCS += kexec/arch/riscv/kexec-elf-riscv.c ++ ++riscv_MEM_REGIONS = kexec/mem_regions.c ++ ++riscv_DT_OPS += kexec/dt-ops.c ++ ++riscv_ARCH_REUSE_INITRD = ++ ++riscv_CPPFLAGS += -I $(srcdir)/kexec/ ++ ++dist += kexec/arch/riscv/Makefile $(riscv_KEXEC_SRCS) \ ++ kexec/arch/riscv/kexec-riscv.h \ ++ kexec/arch/riscv/include/arch/options.h ++ ++ifdef HAVE_LIBFDT ++ ++LIBS += -lfdt ++ ++else ++ ++include $(srcdir)/kexec/libfdt/Makefile.libfdt ++ ++libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) ++ ++riscv_CPPFLAGS += -I$(srcdir)/kexec/libfdt ++ ++riscv_KEXEC_SRCS += $(libfdt_SRCS) ++ ++endif ++ +diff --git a/kexec/arch/riscv/include/arch/options.h b/kexec/arch/riscv/include/arch/options.h +new file mode 100644 +index 0000000..52a0801 +--- /dev/null ++++ b/kexec/arch/riscv/include/arch/options.h +@@ -0,0 +1,43 @@ ++#ifndef KEXEC_ARCH_RISCV_OPTIONS_H ++#define KEXEC_ARCH_RISCV_OPTIONS_H ++ ++#define OPT_APPEND ((OPT_MAX)+0) ++#define OPT_DTB ((OPT_MAX)+1) ++#define OPT_INITRD ((OPT_MAX)+2) ++#define OPT_CMDLINE ((OPT_MAX)+3) ++#define OPT_REUSE_CMDLINE ((OPT_MAX)+4) ++#define OPT_ARCH_MAX ((OPT_MAX)+5) ++ ++/* Options relevant to the architecture (excluding loader-specific ones), ++ * in this case none: ++ */ ++#define KEXEC_ARCH_OPTIONS \ ++ KEXEC_OPTIONS \ ++ { "append", 1, 0, OPT_APPEND}, \ ++ { "dtb", 1, 0, OPT_DTB }, \ ++ { "initrd", 1, 0, OPT_INITRD }, \ ++ { "command-line", 1, 0, OPT_CMDLINE}, \ ++ { "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \ ++ ++ ++#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" ++ ++/* The following two #defines list ALL of the options added by all of the ++ * architecture's loaders. ++ * o main() uses this complete list to scan for its options, ignoring ++ * arch-specific/loader-specific ones. ++ * o Then, arch_process_options() uses this complete list to scan for its ++ * options, ignoring general/loader-specific ones. ++ * o Then, the file_type[n].load re-scans for options, using ++ * KEXEC_ARCH_OPTIONS plus its loader-specific options subset. ++ * Any unrecognised options cause an error here. ++ * ++ * This is done so that main()'s/arch_process_options()'s getopt_long() calls ++ * don't choose a kernel filename from random arguments to options they don't ++ * recognise -- as they now recognise (if not act upon) all possible options. ++ */ ++#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS ++ ++#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR ++ ++#endif /* KEXEC_ARCH_RISCV_OPTIONS_H */ +diff --git a/kexec/arch/riscv/kexec-elf-riscv.c b/kexec/arch/riscv/kexec-elf-riscv.c +new file mode 100644 +index 0000000..094a058 +--- /dev/null ++++ b/kexec/arch/riscv/kexec-elf-riscv.c +@@ -0,0 +1,281 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2019 FORTH-ICS/CARV ++ * Nick Kossifidis ++ */ ++ ++#include "kexec.h" ++#include "dt-ops.h" /* For dtb_set/clear_initrd() */ ++#include /* For ELF header handling */ ++#include /* For EFBIG/EINVAL */ ++#include /* For getpagesize() */ ++#include "kexec-riscv.h" ++ ++extern struct riscv_opts arch_options; ++ ++/*********\ ++* HELPERS * ++\*********/ ++ ++/* ++ * Go through the available physical memory regions and ++ * find one that can hold an image of the specified size. ++ * Note: This is called after get_memory_ranges so ++ * info->memory_range[] should be populated. Also note that ++ * memory ranges are sorted, so we'll return the first region ++ * that's big enough for holding the image. ++ */ ++static int elf_riscv_find_pbase(struct kexec_info *info, off_t *addr, ++ off_t size) ++{ ++ int i = 0; ++ off_t start = 0; ++ off_t end = 0; ++ ++ for (i = 0; i < info->memory_ranges; i++) { ++ if (info->memory_range[i].type != RANGE_RAM) ++ continue; ++ ++ start = info->memory_range[i].start; ++ end = info->memory_range[i].end; ++ ++ /* ++ * Kernel should be aligned to the nearest ++ * hugepage (2MB for RV64, 4MB for RV32). ++ * ++ * XXX: Region's base address may be already aligned but ++ * firmware may be loaded there and we'll overwrite it (or ++ * get a fault due to PMP). Until BBL / OpenSBI update the ++ * device tree to mark their memory as reserved the assumption ++ * is that the kernel won't use any memory below its load ++ * address, that the firmware will be < 2MB in size and that ++ * the kernel will not use the first hugepage (where the ++ * firmware is), hence the + 1 below. ++ */ ++#if __riscv_xlen == 64 ++ start = _ALIGN_UP(start + 1, 0x200000); ++#else ++ start = _ALIGN_UP(start + 1, 0x400000); ++#endif ++ ++ if (end > start && ((end - start) >= size)) { ++ *addr = start; ++ return 0; ++ } ++ } ++ ++ return -EFBIG; ++} ++ ++/**************\ ++* ENTRY POINTS * ++\**************/ ++ ++int elf_riscv_probe(const char *buf, off_t len) ++{ ++ struct mem_ehdr ehdr = {0}; ++ int ret = 0; ++ ++ ret = build_elf_exec_info(buf, len, &ehdr, 0); ++ if (ret < 0) ++ goto cleanup; ++ ++ if (ehdr.e_machine != EM_RISCV) { ++ fprintf(stderr, "Not for this architecture.\n"); ++ ret = -EINVAL; ++ goto cleanup; ++ } ++ ++ ret = 0; ++ ++ cleanup: ++ free_elf_info(&ehdr); ++ return ret; ++} ++ ++void elf_riscv_usage(void) ++{ ++} ++ ++int elf_riscv_load(int argc, char **argv, const char *buf, off_t len, ++ struct kexec_info *info) ++{ ++ struct mem_ehdr ehdr = {0}; ++ struct mem_phdr *phdr = NULL; ++ struct fdt_image *fdt = arch_options.fdt; ++ char *initrd_buf = NULL; ++ off_t initrd_size = 0; ++ unsigned long initrd_base = 0; ++ off_t new_base_addr = 0; ++ off_t kernel_size = 0; ++ off_t page_size = getpagesize(); ++ off_t max_addr = 0; ++ off_t old_base_addr = 0; ++ off_t old_start_addr = 0; ++ int i = 0; ++ int ret = 0; ++ ++ if (info->file_mode) { ++ fprintf(stderr, "kexec_file not supported on this " ++ "architecture\n"); ++ return -EINVAL; ++ } ++ ++ /* Parse the ELF file */ ++ ret = build_elf_exec_info(buf, len, &ehdr, 0); ++ if (ret < 0) { ++ fprintf(stderr, "ELF exec parse failed\n"); ++ return -EINVAL; ++ } ++ ++ max_addr = elf_max_addr(&ehdr); ++ old_base_addr = max_addr; ++ old_start_addr = max_addr; ++ ++ /* ++ * Get the memory footprint, base physical ++ * and start address of the ELF image ++ */ ++ for (i = 0; i < ehdr.e_phnum; i++) { ++ phdr = &ehdr.e_phdr[i]; ++ if (phdr->p_type != PT_LOAD) ++ continue; ++ ++ /* ++ * Note: According to ELF spec the loadable regions ++ * are sorted on p_vaddr, not p_paddr. ++ */ ++ if (old_base_addr > phdr->p_paddr) ++ old_base_addr = phdr->p_paddr; ++ ++ if (phdr->p_vaddr == ehdr.e_entry || ++ phdr->p_paddr == ehdr.e_entry) ++ old_start_addr = phdr->p_paddr; ++ ++ kernel_size += _ALIGN_UP(phdr->p_memsz, page_size); ++ } ++ ++ if (old_base_addr == max_addr || kernel_size == 0) { ++ fprintf(stderr, "No loadable segments present on the " ++ "provided ELF image\n"); ++ return -EINVAL; ++ } ++ ++ if (old_start_addr == max_addr) { ++ fprintf(stderr, "Could not find the entry point address of " ++ "provided ELF image\n"); ++ return -EINVAL; ++ } ++ ++ dbgprintf("Got ELF with total memsz %luKB\n" ++ "Base paddr: 0x%lX, start_addr: 0x%lX\n", ++ kernel_size / 1024, old_base_addr, old_start_addr); ++ ++ /* Get a continuous physical region that can hold the kernel */ ++ ret = elf_riscv_find_pbase(info, &new_base_addr, kernel_size); ++ if (ret < 0) { ++ fprintf(stderr, "Could not find a memory region for the " ++ "provided ELF image\n"); ++ return ret; ++ } ++ ++ dbgprintf("New base paddr for the ELF: 0x%lX\n", new_base_addr); ++ ++ /* Re-set the base physical address of the ELF */ ++ for (i = 0; i < ehdr.e_phnum; i++) { ++ phdr = &ehdr.e_phdr[i]; ++ if (phdr->p_type != PT_LOAD) ++ continue; ++ ++ phdr->p_paddr -= old_base_addr; ++ phdr->p_paddr += new_base_addr; ++ } ++ ++ /* Re-set the entry point address */ ++ ehdr.e_entry = (old_start_addr - old_base_addr) + new_base_addr; ++ info->entry = (void *) ehdr.e_entry; ++ dbgprintf("New entry point for the ELF: 0x%llX\n", ehdr.e_entry); ++ ++ ++ /* Load the ELF executable */ ++ ret = elf_exec_load(&ehdr, info); ++ if (ret < 0) { ++ fprintf(stderr, "ELF exec load failed\n"); ++ return ret; ++ } ++ ++ /* Do we need to include an initrd image ? */ ++ if (!arch_options.initrd_path && !arch_options.initrd_end) ++ dtb_clear_initrd(&fdt->buf, &fdt->size); ++ else if (arch_options.initrd_path) { ++ if (arch_options.initrd_end) ++ fprintf(stderr, "Warning: An initrd image was provided" ++ ", will ignore reuseinitrd\n"); ++ ++ initrd_buf = slurp_file(arch_options.initrd_path, ++ &initrd_size); ++ ++ /* ++ * Create dummy initrd entries in fdt to get the updated ++ * fdt size ++ */ ++ dtb_set_initrd(&fdt->buf, &fdt->size, max_addr, ++ max_addr + initrd_size); ++ ++ /* Put initrd above kernel + device tree */ ++ initrd_base = add_buffer_virt(info, initrd_buf, initrd_size, ++ initrd_size, sizeof(void *), ++ _ALIGN_UP(ehdr.e_entry + kernel_size ++ + fdt->size, page_size), ++ max_addr, 1); ++ ++ /* ++ * Now that the buffer for initrd is prepared, update the dtb ++ * with an appropriate location ++ */ ++ dtb_set_initrd(&fdt->buf, &fdt->size, initrd_base, ++ initrd_base + initrd_size); ++ ++ dbgprintf("Base addr for initrd image: 0x%lX\n", initrd_base); ++ } ++ ++ add_buffer(info, fdt->buf, fdt->size, fdt->size, 0, ++ _ALIGN_UP(ehdr.e_entry + kernel_size, page_size), ++ max_addr, 1); ++ ++ return 0; ++} ++ ++ ++/*******\ ++* STUBS * ++\*******/ ++ ++int machine_verify_elf_rel(struct mem_ehdr *ehdr) ++{ ++ if (ehdr->ei_data != ELFDATA2MSB) ++ return 0; ++#if __riscv_xlen == 64 ++ if (ehdr->ei_class != ELFCLASS64) ++#else ++ if (ehdr->ei_class != ELFCLASS32) ++#endif ++ return 0; ++ if (ehdr->e_machine != EM_RISCV) ++ return 0; ++ return 1; ++} ++ ++void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), ++ struct mem_sym *UNUSED(sym), ++ unsigned long r_type, ++ void *UNUSED(location), ++ unsigned long UNUSED(address), ++ unsigned long UNUSED(value)) ++{ ++ switch (r_type) { ++ default: ++ die("Unknown rela relocation: %lu\n", r_type); ++ break; ++ } ++} +diff --git a/kexec/arch/riscv/kexec-riscv.c b/kexec/arch/riscv/kexec-riscv.c +new file mode 100644 +index 0000000..dfda729 +--- /dev/null ++++ b/kexec/arch/riscv/kexec-riscv.c +@@ -0,0 +1,545 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2019 FORTH-ICS/CARV ++ * Nick Kossifidis ++ */ ++ ++#include "kexec-syscall.h" /* For KEXEC_ARCH_RISCV */ ++#include "kexec.h" /* For OPT_MAX and concat_cmdline() */ ++#include "mem_regions.h" /* For mem_regions_sort() */ ++#include "dt-ops.h" /* For dtb_set_bootargs() */ ++#include /* For KEXEC_ARCH_OPTIONS */ ++#include /* For struct option */ ++#include /* For stat() and struct stat */ ++#include /* For free() */ ++#include /* For EINVAL */ ++#include /* For DeviceTree handling */ ++#include "kexec-riscv.h" ++ ++const struct arch_map_entry arches[] = { ++ { "riscv32", KEXEC_ARCH_RISCV }, ++ { "riscv64", KEXEC_ARCH_RISCV }, ++ { NULL, 0 }, ++}; ++ ++ ++struct file_type file_type[] = { ++ {"elf-riscv", elf_riscv_probe, elf_riscv_load, elf_riscv_usage}, ++}; ++int file_types = sizeof(file_type) / sizeof(file_type[0]); ++ ++/*****************\ ++* USAGE / OPTIONS * ++\*****************/ ++ ++static const char riscv_opts_usage[] = ++" --append=STRING Append STRING to the kernel command line.\n" ++" --dtb=FILE Use FILE as the device tree blob.\n" ++" --initrd=FILE Use FILE as the kernel initial ramdisk.\n" ++" --cmdline=STRING Use STRING as the kernel's command line.\n" ++" --reuse-cmdline Use kernel command line from running system.\n"; ++ ++struct riscv_opts arch_options = {0}; ++ ++static struct fdt_image fdt = {0}; ++ ++void arch_usage(void) ++{ ++ printf(riscv_opts_usage); ++} ++ ++int arch_process_options(int argc, char **argv) ++{ ++ static const struct option options[] = { ++ KEXEC_ARCH_OPTIONS ++ { 0 }, ++ }; ++ static const char short_options[] = KEXEC_ARCH_OPT_STR; ++ struct stat st = {0}; ++ char *append = NULL; ++ char *cmdline = NULL; ++ void *tmp = NULL; ++ off_t tmp_size = 0; ++ int opt = 0; ++ int ret = 0; ++ ++ while ((opt = getopt_long(argc, argv, short_options, ++ options, 0)) != -1) { ++ switch (opt) { ++ case OPT_APPEND: ++ append = optarg; ++ break; ++ case OPT_CMDLINE: ++ if (cmdline) ++ fprintf(stderr, ++ "Warning: Kernel's cmdline " ++ "set twice !\n"); ++ cmdline = optarg; ++ break; ++ case OPT_REUSE_CMDLINE: ++ if (cmdline) ++ fprintf(stderr, ++ "Warning: Kernel's cmdline " ++ "set twice !\n"); ++ cmdline = get_command_line(); ++ break; ++ case OPT_DTB: ++ ret = stat(optarg, &st); ++ if (ret) { ++ fprintf(stderr, ++ "Could not find the provided dtb !\n"); ++ return -EINVAL; ++ } ++ arch_options.fdt_path = optarg; ++ break; ++ case OPT_INITRD: ++ ret = stat(optarg, &st); ++ if (ret) { ++ fprintf(stderr, ++ "Could not find the provided " ++ "initrd image !\n"); ++ return -EINVAL; ++ } ++ arch_options.initrd_path = optarg; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ /* Handle Kernel's command line */ ++ if (append && !cmdline) ++ fprintf(stderr, "Warning: No cmdline provided, " ++ "using append string as cmdline\n"); ++ if (!append && !cmdline) ++ fprintf(stderr, "Warning: No cmdline or append string " ++ "provided\n"); ++ ++ if (append || cmdline) ++ /* ++ * Note that this also handles the case where "cmdline" ++ * or "append" is NULL. ++ */ ++ arch_options.cmdline = concat_cmdline(cmdline, append); ++ ++ /* ++ * XXX: Until we have suspend ready over SBI, make sure we pass nosmp ++ * to the next kernel. ++ */ ++ arch_options.cmdline = concat_cmdline(arch_options.cmdline, "nosmp"); ++ fprintf(stderr, "Note: Passing nosmp to the next kernel until CPU " ++ "suspend is supported on RISC-V\n"); ++ ++ /* Handle FDT image */ ++ if (!arch_options.fdt_path) { ++ ret = stat("/sys/firmware/fdt", &st); ++ if (ret) { ++ fprintf(stderr, "No dtb provided and " ++ "/sys/firmware/fdt is not present\n"); ++ return -EINVAL; ++ } ++ fprintf(stderr, "Warning: No dtb provided, " ++ "using /sys/firmware/fdt\n"); ++ arch_options.fdt_path = "/sys/firmware/fdt"; ++ } ++ ++ tmp = slurp_file(arch_options.fdt_path, &tmp_size); ++ ret = fdt_check_header(tmp); ++ if (ret) { ++ fprintf(stderr, "Got an ivalid fdt image !\n"); ++ free(tmp); ++ return -EINVAL; ++ } ++ fdt.buf = tmp; ++ fdt.size = tmp_size; ++ ++ arch_options.fdt = &fdt; ++ ++ if (arch_options.cmdline) { ++ ret = dtb_set_bootargs(&fdt.buf, &fdt.size, ++ arch_options.cmdline); ++ if (ret < 0) { ++ fprintf(stderr, "Could not set bootargs on " ++ "the fdt image\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++/* ++ * This one is called after arch_process_options so we already ++ * have an fdt image in place. ++ */ ++void arch_reuse_initrd(void) ++{ ++ uint32_t addr_cells = 0; ++ const uint32_t *prop32 = NULL; ++ const uint64_t *prop64 = NULL; ++ int prop_size = 0; ++ const void *addr = 0; ++ uint64_t initrd_start = 0; ++ uint64_t initrd_end = 0; ++ int chosen_offset = 0; ++ ++ chosen_offset = fdt_subnode_offset(fdt.buf, 0, "chosen"); ++ if (chosen_offset < 0) { ++ fprintf(stderr, "No /chosen node found on fdt image " ++ "unable to reuse initrd\n"); ++ return; ++ } ++ ++ prop32 = fdt_getprop(fdt.buf, 0, "#address-cells", NULL); ++ if (!prop32) { ++ fprintf(stderr, "No #address-cells property on root node\n"); ++ return; ++ } ++ addr_cells = be32_to_cpu(*prop32); ++ ++ addr = fdt_getprop(fdt.buf, chosen_offset, ++ "linux,initrd-start", &prop_size); ++ if (!addr) { ++ fprintf(stderr, "Could not get linux,initrd-start\n"); ++ return; ++ } ++ switch (addr_cells) { ++ case 1: ++ prop32 = (const uint32_t *) addr; ++ initrd_start = (uint64_t) be32_to_cpu(*prop32); ++ break; ++ case 2: ++ prop64 = (const uint64_t *) addr; ++ initrd_start = (uint64_t) be64_to_cpu(*prop64); ++ break; ++ default: ++ fprintf(stderr, "Invalid #address-cells property\n"); ++ return; ++ } ++ ++ ++ addr = fdt_getprop(fdt.buf, chosen_offset, ++ "linux,initrd-end", &prop_size); ++ if (!addr) { ++ fprintf(stderr, "Could not get linux,initrd-end\n"); ++ return; ++ } ++ switch (addr_cells) { ++ case 1: ++ prop32 = (const uint32_t *) addr; ++ initrd_end = (uint64_t) be32_to_cpu(*prop32); ++ break; ++ case 2: ++ prop64 = (const uint64_t *) addr; ++ initrd_end = (uint64_t) be64_to_cpu(*prop64); ++ break; ++ default: ++ fprintf(stderr, "Invalid #address-cells property\n"); ++ return; ++ } ++ ++ arch_options.initrd_start = initrd_start; ++ arch_options.initrd_end = initrd_end; ++ dbgprintf("initrd_start: 0x%lX, initrd_end: 0x%lX\n", ++ initrd_start, initrd_end); ++ ++} ++ ++ ++ ++/***************\ ++* MEMORY RANGES * ++\***************/ ++ ++static struct memory_ranges mem_ranges = {0}; ++ ++static int add_memory_range(uint64_t start, uint64_t end, unsigned type) ++{ ++ struct memory_range *tmp_buf = NULL; ++ struct memory_range *ranges = NULL; ++ size_t tmp_size = mem_ranges.size + 1; ++ ++ tmp_buf = realloc(mem_ranges.ranges, ++ tmp_size * sizeof(struct memory_range)); ++ if (!tmp_buf) { ++ perror("Unable to expand memory ranges array"); ++ return -errno; ++ } ++ ++ mem_ranges.ranges = tmp_buf; ++ mem_ranges.size = tmp_size; ++ mem_ranges.max_size = tmp_size; ++ ++ ranges = mem_ranges.ranges; ++ ++ ranges[mem_ranges.size].start = start; ++ ranges[mem_ranges.size].end = end; ++ ranges[mem_ranges.size].type = type; ++ ++ dbgprintf("mem_ranges[%u]: %016llX - %016llX %s\n", ++ mem_ranges.size, ++ ranges[mem_ranges.size].start, ++ ranges[mem_ranges.size].end, ++ type == RANGE_RESERVED ? "RANGE_RESERVED" : "RANGE_RAM"); ++ ++ mem_ranges.size++; ++ ++ return 0; ++} ++ ++static int parse_memory_region(int node_offset, int type) ++{ ++ uint32_t addr_cells = 0; ++ uint32_t size_cells = 0; ++ const uint32_t *prop32 = NULL; ++ const uint64_t *prop64 = NULL; ++ int prop_size = 0; ++ const char *reg = NULL; ++ uint64_t addr = 0; ++ uint64_t size = 0; ++ int offset = 0; ++ int entry_size = 0; ++ int num_entries = 0; ++ int ret = 0; ++ ++ /* ++ * Get address-cells and size-cells properties (according to ++ * binding spec these are the same as in the root node) ++ */ ++ prop32 = fdt_getprop(fdt.buf, 0, "#address-cells", NULL); ++ if (!prop32) { ++ fprintf(stderr, "No #address-cells property on root node\n"); ++ return -EINVAL; ++ } ++ addr_cells = be32_to_cpu(*prop32); ++ ++ prop32 = fdt_getprop(fdt.buf, 0, "#size-cells", NULL); ++ if (!prop32) { ++ fprintf(stderr, "No #size-cells property on root node\n"); ++ return -EINVAL; ++ } ++ size_cells = be32_to_cpu(*prop32); ++ ++ /* ++ * Parse the reg array, acording to device tree spec it includes ++ * an arbitary number of
pairs ++ */ ++ entry_size = (addr_cells + size_cells) * sizeof(uint32_t); ++ reg = fdt_getprop(fdt.buf, node_offset, "reg", &prop_size); ++ if (!reg) { ++ fprintf(stderr, "Warning: Malformed memory region with no " ++ "reg property (%s) !\n", ++ fdt_get_name(fdt.buf, node_offset, NULL)); ++ return -EINVAL; ++ } ++ ++ num_entries = prop_size / entry_size; ++ dbgprintf("Got region with %i entries: %s\n", num_entries, ++ fdt_get_name(fdt.buf, node_offset, NULL)); ++ ++ for (num_entries--; num_entries >= 0; num_entries--) { ++ offset = num_entries * entry_size; ++ switch (addr_cells) { ++ case 1: ++ prop32 = (const uint32_t *) (reg + offset); ++ addr = (uint64_t) be32_to_cpu(*prop32); ++ break; ++ case 2: ++ prop64 = (const uint64_t *) (reg + offset); ++ addr = be64_to_cpu(*prop64); ++ break; ++ default: ++ fprintf(stderr, "Invalid #address-cells property !\n"); ++ return -EINVAL; ++ } ++ ++ ++ switch (size_cells) { ++ case 1: ++ prop32 = (const uint32_t *) (reg + offset + ++ (addr_cells * sizeof(uint32_t))); ++ size = (uint64_t) be32_to_cpu(*prop32); ++ break; ++ case 2: ++ prop64 = (const uint64_t *) (reg + offset + ++ (addr_cells * sizeof(uint32_t))); ++ size = be64_to_cpu(*prop64); ++ break; ++ default: ++ fprintf(stderr, "Invalid #size-cells property !\n"); ++ return -EINVAL; ++ } ++ ++ ret = add_memory_range(addr, addr + size - 1, type); ++ if (ret) ++ return ret; ++ ++ } ++ ++ return 0; ++} ++ ++static int parse_memory_reservations_table(void) ++{ ++ int total_memrsrv = 0; ++ uint64_t addr = 0; ++ uint64_t size = 0; ++ int ret = 0; ++ int i = 0; ++ ++ total_memrsrv = fdt_num_mem_rsv(fdt.buf); ++ for (i = 0; i < total_memrsrv; i++) { ++ ret = fdt_get_mem_rsv(fdt.buf, i, &addr, &size); ++ if (ret) ++ continue; ++ ret = add_memory_range(addr, addr + size - 1, ++ RANGE_RESERVED); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int parse_reserved_memory_regions(void) ++{ ++ int node_offset = 0; ++ int node_depth = 0; ++ int parent_depth = 0; ++ int ranges_size = 0; ++ int ret = 0; ++ ++ /* This calls fdt_next_node internaly */ ++ node_offset = fdt_subnode_offset(fdt.buf, 0, "reserved-memory"); ++ if (node_offset == -FDT_ERR_NOTFOUND) ++ return 0; ++ else { ++ fprintf(stderr, "Error while looking for reserved-memory: %s\n", ++ fdt_strerror(node_offset)); ++ return node_offset; ++ } ++ ++ parent_depth = fdt_node_depth(fdt.buf, node_offset); ++ if (parent_depth < 0) { ++ fprintf(stderr, "Error while looking for reserved-memory: %s\n", ++ fdt_strerror(parent_depth)); ++ return parent_depth; ++ } ++ ++ /* Look for the ranges property */ ++ fdt_getprop(fdt.buf, node_offset, "ranges", &ranges_size); ++ if (ranges_size < 0) { ++ fprintf(stderr, "Malformed reserved-memory node !\n"); ++ return -EINVAL; ++ } ++ ++ /* Got the parent node, check for sub-nodes */ ++ ++ /* fdt_next_node() increases or decreases depth */ ++ node_depth = parent_depth; ++ node_offset = fdt_next_node(fdt.buf, node_offset, &node_depth); ++ if (ret < 0) { ++ fprintf(stderr, "Unable to get next node: %s\n", ++ fdt_strerror(ret)); ++ return -EINVAL; ++ } ++ ++ while (node_depth != parent_depth) { ++ ret = parse_memory_region(node_offset, RANGE_RESERVED); ++ if (ret) ++ return ret; ++ ++ node_offset = fdt_next_node(fdt.buf, node_offset, &node_depth); ++ if (ret < 0) { ++ fprintf(stderr, "Unable to get next node: %s\n", ++ fdt_strerror(ret)); ++ return -EINVAL; ++ } ++ } ++ ++ return 0; ++} ++ ++static int parse_memory_regions(void) ++{ ++ int node_offset = 0; ++ int num_regions = 0; ++ int ret = 0; ++ ++ for (; ; num_regions++) { ++ node_offset = fdt_subnode_offset(fdt.buf, node_offset, ++ "memory"); ++ if (node_offset < 0) ++ break; ++ ++ ret = parse_memory_region(node_offset, RANGE_RAM); ++ if (ret) ++ return ret; ++ } ++ ++ if (!num_regions) { ++ fprintf(stderr, "Malformed dtb, no /memory nodes present !\n"); ++ return -EINVAL; ++ } ++ ++ dbgprintf("Got %i /memory nodes\n", num_regions); ++ ++ return 0; ++} ++ ++ ++int get_memory_ranges(struct memory_range **range, int *ranges, ++ unsigned long kexec_flags) ++{ ++ int ret = 0; ++ ++ ret = parse_memory_regions(); ++ if (ret) ++ return ret; ++ ++ ret = parse_reserved_memory_regions(); ++ if (ret) ++ return ret; ++ ++ ret = parse_memory_reservations_table(); ++ if (ret) ++ return ret; ++ ++ if (arch_options.initrd_start && arch_options.initrd_end) { ++ dbgprintf("Marking current intird image as reserved\n"); ++ add_memory_range(arch_options.initrd_start, ++ arch_options.initrd_end, RANGE_RESERVED); ++ } ++ ++ ++ mem_regions_sort(&mem_ranges); ++ ++ *range = mem_ranges.ranges; ++ *ranges = mem_ranges.size; ++ ++ return 0; ++} ++ ++/*******\ ++* STUBS * ++\*******/ ++ ++int arch_compat_trampoline(struct kexec_info *UNUSED(info)) ++{ ++ return 0; ++} ++ ++void arch_update_purgatory(struct kexec_info *UNUSED(info)) ++{ ++} ++ ++int is_crashkernel_mem_reserved(void) ++{ ++ return 0; ++} ++ ++int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) ++{ ++ return 0; ++} ++ +diff --git a/kexec/arch/riscv/kexec-riscv.h b/kexec/arch/riscv/kexec-riscv.h +new file mode 100644 +index 0000000..547b109 +--- /dev/null ++++ b/kexec/arch/riscv/kexec-riscv.h +@@ -0,0 +1,24 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2019 FORTH-ICS/CARV ++ * Nick Kossifidis ++ */ ++ ++struct fdt_image { ++ char *buf; ++ off_t size; ++}; ++ ++struct riscv_opts { ++ char *cmdline; ++ char *fdt_path; ++ char *initrd_path; ++ uint64_t initrd_start; ++ uint64_t initrd_end; ++ struct fdt_image *fdt; ++}; ++ ++int elf_riscv_probe(const char *buf, off_t len); ++void elf_riscv_usage(void); ++int elf_riscv_load(int argc, char **argv, const char *buf, off_t len, ++ struct kexec_info *info); +diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h +index dac1c1f..74b93d8 100644 +--- a/kexec/kexec-syscall.h ++++ b/kexec/kexec-syscall.h +@@ -126,6 +126,7 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd, + #define KEXEC_ARCH_MIPS_LE (10 << 16) + #define KEXEC_ARCH_MIPS ( 8 << 16) + #define KEXEC_ARCH_CRIS (76 << 16) ++#define KEXEC_ARCH_RISCV (243 << 16) + + #define KEXEC_MAX_SEGMENTS 16 + +@@ -169,5 +170,8 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd, + #if defined(__arm64__) + #define KEXEC_ARCH_NATIVE KEXEC_ARCH_ARM64 + #endif ++#if defined(__riscv__) || defined(__riscv) ++#define KEXEC_ARCH_NATIVE KEXEC_ARCH_RISCV ++#endif + + #endif /* KEXEC_SYSCALL_H */ +diff --git a/purgatory/Makefile b/purgatory/Makefile +index 2dd6c47..0a9d1c1 100644 +--- a/purgatory/Makefile ++++ b/purgatory/Makefile +@@ -25,6 +25,7 @@ include $(srcdir)/purgatory/arch/ia64/Makefile + include $(srcdir)/purgatory/arch/mips/Makefile + include $(srcdir)/purgatory/arch/ppc/Makefile + include $(srcdir)/purgatory/arch/ppc64/Makefile ++include $(srcdir)/purgatory/arch/riscv/Makefile + include $(srcdir)/purgatory/arch/s390/Makefile + include $(srcdir)/purgatory/arch/sh/Makefile + include $(srcdir)/purgatory/arch/x86_64/Makefile +diff --git a/purgatory/arch/riscv/Makefile b/purgatory/arch/riscv/Makefile +new file mode 100644 +index 0000000..8bded71 +--- /dev/null ++++ b/purgatory/arch/riscv/Makefile +@@ -0,0 +1,7 @@ ++# ++# Purgatory riscv ++# ++ ++riscv_PURGATORY_SRCS = ++ ++dist += purgatory/arch/sh/Makefile $(riscv_PURGATORY_SRCS) diff --git a/kexec-tools-SYS_getrandom.patch b/kexec-tools-SYS_getrandom.patch deleted file mode 100644 index 7f444ae..0000000 --- a/kexec-tools-SYS_getrandom.patch +++ /dev/null @@ -1,25 +0,0 @@ -From: Petr Tesarik -Subject: Define SYS_getrandom if needed -Upstream: never, build fix for SLE12 - -SLE12 did not provide a definition for SYS_getrandom. - -Signed-off-by: Petr Tesarik ---- - kexec/arch/arm64/kexec-arm64.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/kexec/arch/arm64/kexec-arm64.c -+++ b/kexec/arch/arm64/kexec-arm64.c -@@ -34,6 +34,11 @@ - #include "mem_regions.h" - #include "arch/options.h" - -+#ifndef __NR_getrandom -+#define __NR_getrandom 278 -+__SYSCALL(__NR_getrandom, sys_getrandom) -+#endif -+ - #define ROOT_NODE_ADDR_CELLS_DEFAULT 1 - #define ROOT_NODE_SIZE_CELLS_DEFAULT 1 - diff --git a/kexec-tools-add-variant-helper-functions.patch b/kexec-tools-add-variant-helper-functions.patch deleted file mode 100644 index f71cbc6..0000000 --- a/kexec-tools-add-variant-helper-functions.patch +++ /dev/null @@ -1,84 +0,0 @@ -From: AKASHI Takahiro -Date: Fri, 11 Jan 2019 01:59:44 +0900 -Subject: kexec: add variant helper functions for handling memory regions -References: jsc#SLE-9943 -Upstream: not yet, it's under review in upstream - -mem_regions_alloc_and_add() and mem_regions_alloc_and_exclude() are -functionally equivalent to, respectively, mem_regions_add() and -mem_regions_exclude() except the formers will re-allocate memory -dynamically when no more entries are available in 'ranges' array. - -Signed-off-by: AKASHI Takahiro -Signed-off-by: Chester Lin ---- - kexec/mem_regions.c | 42 ++++++++++++++++++++++++++++++++++++++++++ - kexec/mem_regions.h | 7 +++++++ - 2 files changed, 49 insertions(+) - -diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c -index 50c8abccb93a..ad7d3f13fd84 100644 ---- a/kexec/mem_regions.c -+++ b/kexec/mem_regions.c -@@ -125,3 +125,45 @@ int mem_regions_exclude(struct memory_ranges *ranges, - } - return 0; - } -+ -+#define KEXEC_MEMORY_RANGES 16 -+ -+int mem_regions_alloc_and_add(struct memory_ranges *ranges, -+ unsigned long long base, -+ unsigned long long length, int type) -+{ -+ void *new_ranges; -+ -+ if (ranges->size >= ranges->max_size) { -+ new_ranges = realloc(ranges->ranges, -+ sizeof(struct memory_range) * -+ (ranges->max_size + KEXEC_MEMORY_RANGES)); -+ if (!new_ranges) -+ return -1; -+ -+ ranges->ranges = new_ranges; -+ ranges->max_size += KEXEC_MEMORY_RANGES; -+ } -+ -+ return mem_regions_add(ranges, base, length, type); -+} -+ -+int mem_regions_alloc_and_exclude(struct memory_ranges *ranges, -+ const struct memory_range *range) -+{ -+ void *new_ranges; -+ -+ /* for safety, we should have at least one free entry in ranges */ -+ if (ranges->size >= ranges->max_size) { -+ new_ranges = realloc(ranges->ranges, -+ sizeof(struct memory_range) * -+ (ranges->max_size + KEXEC_MEMORY_RANGES)); -+ if (!new_ranges) -+ return -1; -+ -+ ranges->ranges = new_ranges; -+ ranges->max_size += KEXEC_MEMORY_RANGES; -+ } -+ -+ return mem_regions_exclude(ranges, range); -+} -diff --git a/kexec/mem_regions.h b/kexec/mem_regions.h -index ae9e972b0206..e306d67e3261 100644 ---- a/kexec/mem_regions.h -+++ b/kexec/mem_regions.h -@@ -12,4 +12,11 @@ int mem_regions_exclude(struct memory_ranges *ranges, - int mem_regions_add(struct memory_ranges *ranges, unsigned long long base, - unsigned long long length, int type); - -+int mem_regions_alloc_and_exclude(struct memory_ranges *ranges, -+ const struct memory_range *range); -+ -+int mem_regions_alloc_and_add(struct memory_ranges *ranges, -+ unsigned long long base, -+ unsigned long long length, int type); -+ - #endif diff --git a/kexec-tools-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch b/kexec-tools-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch deleted file mode 100644 index 4516d1a..0000000 --- a/kexec-tools-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch +++ /dev/null @@ -1,77 +0,0 @@ -From: AKASHI Takahiro -Date: Fri, 11 Jan 2019 01:59:46 +0900 -Subject: arm64: kdump: deal with a lot of resource entries in /proc/iomem -References: jsc#SLE-9943 -Upstream: not yet, it's under review in upstream - -As described in the commit ("arm64: kexec: allocate memory space avoiding -reserved regions"), /proc/iomem now has a lot of "reserved" entries, and -it's not just enough to have a fixed size of memory range array. - -With this patch, kdump is allowed to handle arbitrary number of memory -ranges, using mem_regions_alloc_and_xxx() functions. - -Signed-off-by: AKASHI Takahiro -Signed-off-by: Chester Lin ---- - kexec/arch/arm64/crashdump-arm64.c | 25 ++++++++++--------------- - 1 file changed, 10 insertions(+), 15 deletions(-) - -diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c -index 4fd7aa8fd43c..38d1a0f3000d 100644 ---- a/kexec/arch/arm64/crashdump-arm64.c -+++ b/kexec/arch/arm64/crashdump-arm64.c -@@ -23,13 +23,8 @@ - #include "kexec-elf.h" - #include "mem_regions.h" - --/* memory ranges on crashed kernel */ --static struct memory_range system_memory_ranges[CRASH_MAX_MEMORY_RANGES]; --static struct memory_ranges system_memory_rgns = { -- .size = 0, -- .max_size = CRASH_MAX_MEMORY_RANGES, -- .ranges = system_memory_ranges, --}; -+/* memory ranges of crashed kernel */ -+static struct memory_ranges system_memory_rgns; - - /* memory range reserved for crashkernel */ - struct memory_range crash_reserved_mem; -@@ -82,7 +77,7 @@ static uint64_t get_kernel_page_offset(void) - * - * This function is called once for each memory region found in /proc/iomem. - * It locates system RAM and crashkernel reserved memory and places these to -- * variables, respectively, system_memory_ranges and crash_reserved_mem. -+ * variables, respectively, system_memory_rgns and usablemem_rgns. - */ - - static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr), -@@ -90,11 +85,11 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr), - unsigned long long length) - { - if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) -- return mem_regions_add(&usablemem_rgns, -- base, length, RANGE_RAM); -+ return mem_regions_alloc_and_add(&usablemem_rgns, -+ base, length, RANGE_RAM); - else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) -- return mem_regions_add(&system_memory_rgns, -- base, length, RANGE_RAM); -+ return mem_regions_alloc_and_add(&system_memory_rgns, -+ base, length, RANGE_RAM); - else if (strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) == 0) - elf_info.kern_paddr_start = base; - else if (strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) == 0) -@@ -135,9 +130,9 @@ static int crash_get_memory_ranges(void) - - dbgprint_mem_range("Reserved memory range", &crash_reserved_mem, 1); - -- if (mem_regions_exclude(&system_memory_rgns, &crash_reserved_mem)) { -- fprintf(stderr, -- "Error: Number of crash memory ranges excedeed the max limit\n"); -+ if (mem_regions_alloc_and_exclude(&system_memory_rgns, -+ &crash_reserved_mem)) { -+ fprintf(stderr, "Cannot allocate memory for ranges\n"); - return -ENOMEM; - } - diff --git a/kexec-tools-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch b/kexec-tools-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch deleted file mode 100644 index a4f95a2..0000000 --- a/kexec-tools-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch +++ /dev/null @@ -1,247 +0,0 @@ -From: AKASHI Takahiro -Date: Fri, 11 Jan 2019 01:59:45 +0900 -Subject: arm64: kexec: allocate memory space avoiding reserved regions -References: jsc#SLE-9943 -Upstream: not yet, it's under review in upstream - -On UEFI/ACPI-only system, some memory regions, including but not limited -to UEFI memory map and ACPI tables, must be preserved across kexec'ing. -Otherwise, they can be corrupted and result in early failure in booting -a new kernel. - -In recent kernels, /proc/iomem now has an extended file format like: - 40000000-5871ffff : System RAM - 41800000-426affff : Kernel code - 426b0000-42aaffff : reserved - 42ab0000-42c64fff : Kernel data - 54400000-583fffff : Crash kernel - 58590000-585effff : reserved - 58700000-5871ffff : reserved - 58720000-58b5ffff : reserved - 58b60000-5be3ffff : System RAM - 58b61000-58b61fff : reserved - 59a77000-59a77fff : reserved - 5be40000-5becffff : reserved - 5bed0000-5bedffff : System RAM - 5bee0000-5bffffff : reserved - 5c000000-5fffffff : System RAM - 5da00000-5e9fffff : reserved - 5ec00000-5edfffff : reserved - 5ef6a000-5ef6afff : reserved - 5ef6b000-5efcafff : reserved - 5efcd000-5efcffff : reserved - 5efd0000-5effffff : reserved - 5f000000-5fffffff : reserved - -where the "reserved" entries at the top level or under System RAM (and -its descendant resources) are ones of such kind and should not be regarded -as usable memory ranges where several free spaces for loading kexec data -will be allocated. - -With this patch, get_memory_ranges() will handle this format of file -correctly. Note that, for safety, unknown regions, in addition to -"reserved" ones, will also be excluded. - -Signed-off-by: AKASHI Takahiro -Signed-off-by: Chester Lin ---- - kexec/arch/arm64/kexec-arm64.c | 146 ++++++++++++++++++++------------- - 1 file changed, 87 insertions(+), 59 deletions(-) - -diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c -index 1cde75d1a771..2e923b54f5b1 100644 ---- a/kexec/arch/arm64/kexec-arm64.c -+++ b/kexec/arch/arm64/kexec-arm64.c -@@ -10,7 +10,9 @@ - #include - #include - #include -+#include - #include -+#include - #include - #include - #include -@@ -29,6 +31,7 @@ - #include "fs2dt.h" - #include "iomem.h" - #include "kexec-syscall.h" -+#include "mem_regions.h" - #include "arch/options.h" - - #define ROOT_NODE_ADDR_CELLS_DEFAULT 1 -@@ -899,19 +902,33 @@ int get_phys_base_from_pt_load(unsigned long *phys_offset) - return 0; - } - -+static bool to_be_excluded(char *str) -+{ -+ if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) || -+ !strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) || -+ !strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) || -+ !strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL))) -+ return false; -+ else -+ return true; -+} -+ - /** -- * get_memory_ranges_iomem_cb - Helper for get_memory_ranges_iomem. -+ * get_memory_ranges - Try to get the memory ranges from -+ * /proc/iomem. - */ -- --static int get_memory_ranges_iomem_cb(void *data, int nr, char *str, -- unsigned long long base, unsigned long long length) -+int get_memory_ranges(struct memory_range **range, int *ranges, -+ unsigned long kexec_flags) - { -- int ret; - unsigned long phys_offset = UINT64_MAX; -- struct memory_range *r; -- -- if (nr >= KEXEC_SEGMENT_MAX) -- return -1; -+ FILE *fp; -+ const char *iomem = proc_iomem(); -+ char line[MAX_LINE], *str; -+ unsigned long long start, end; -+ int n, consumed; -+ struct memory_ranges memranges; -+ struct memory_range *last, excl_range; -+ int ret; - - if (!try_read_phys_offset_from_kcore) { - /* Since kernel version 4.19, 'kcore' contains -@@ -945,17 +962,65 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str, - try_read_phys_offset_from_kcore = true; - } - -- r = (struct memory_range *)data + nr; -+ fp = fopen(iomem, "r"); -+ if (!fp) -+ die("Cannot open %s\n", iomem); -+ -+ memranges.ranges = NULL; -+ memranges.size = memranges.max_size = 0; -+ -+ while (fgets(line, sizeof(line), fp) != 0) { -+ n = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed); -+ if (n != 2) -+ continue; -+ str = line + consumed; -+ -+ if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM))) { -+ ret = mem_regions_alloc_and_add(&memranges, -+ start, end - start + 1, RANGE_RAM); -+ if (ret) { -+ fprintf(stderr, -+ "Cannot allocate memory for ranges\n"); -+ return -ENOMEM; -+ } - -- if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM))) -- r->type = RANGE_RAM; -- else if (!strncmp(str, IOMEM_RESERVED, strlen(IOMEM_RESERVED))) -- r->type = RANGE_RESERVED; -- else -- return 1; -+ dbgprintf("%s:+[%d] %016llx - %016llx\n", __func__, -+ memranges.size - 1, -+ memranges.ranges[memranges.size - 1].start, -+ memranges.ranges[memranges.size - 1].end); -+ } else if (to_be_excluded(str)) { -+ if (!memranges.size) -+ continue; -+ -+ /* -+ * Note: mem_regions_exclude() doesn't guarantee -+ * that the ranges are sorted out, but as long as -+ * we cope with /proc/iomem, we only operate on -+ * the last entry and so it is safe. -+ */ - -- r->start = base; -- r->end = base + length - 1; -+ /* The last System RAM range */ -+ last = &memranges.ranges[memranges.size - 1]; -+ -+ if (last->end < start) -+ /* New resource outside of System RAM */ -+ continue; -+ if (end < last->start) -+ /* Already excluded by parent resource */ -+ continue; -+ -+ excl_range.start = start; -+ excl_range.end = end; -+ mem_regions_alloc_and_exclude(&memranges, &excl_range); -+ dbgprintf("%s:- %016llx - %016llx\n", -+ __func__, start, end); -+ } -+ } -+ -+ fclose(fp); -+ -+ *range = memranges.ranges; -+ *ranges = memranges.size; - - /* As a fallback option, we can try determining the PHYS_OFFSET - * value from the '/proc/iomem' entries as well. -@@ -976,52 +1041,15 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str, - * between the user-space and kernel space 'PHYS_OFFSET' - * value. - */ -- set_phys_offset(r->start, "iomem"); -+ if (memranges.size) -+ set_phys_offset(memranges.ranges[0].start, "iomem"); - -- dbgprintf("%s: %016llx - %016llx : %s", __func__, r->start, -- r->end, str); -+ dbgprint_mem_range("System RAM ranges;", -+ memranges.ranges, memranges.size); - - 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(NULL, -- 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; diff --git a/kexec-tools-build-multiboot2-for-i386.patch b/kexec-tools-build-multiboot2-for-i386.patch deleted file mode 100644 index 3f162a0..0000000 --- a/kexec-tools-build-multiboot2-for-i386.patch +++ /dev/null @@ -1,70 +0,0 @@ -From: Chris Packham -Date: Sun, 17 Nov 2019 15:52:15 -0800 -Subject: kexec: build multiboot2 for i386 -References: jsc#SLE-9943 -Upstream: Queued, http://lists.infradead.org/pipermail/kexec/2020-January/024311.html - -This addresses the following compilation issues when building for i386. - - kexec/arch/i386/kexec-x86.c:39:22: error: 'multiboot2_x86_probe' undeclared here (not in a function); did you mean 'multiboot_x86_probe'? - { "multiboot2-x86", multiboot2_x86_probe, multiboot2_x86_load, - ^~~~~~~~~~~~~~~~~~~~ - multiboot_x86_probe - kexec/arch/i386/kexec-x86.c:39:44: error: 'multiboot2_x86_load' undeclared here (not in a function); did you mean 'multiboot_x86_load'? - { "multiboot2-x86", multiboot2_x86_probe, multiboot2_x86_load, - ^~~~~~~~~~~~~~~~~~~ - multiboot_x86_load - kexec/arch/i386/kexec-x86.c:40:4: error: 'multiboot2_x86_usage' undeclared here (not in a function); did you mean 'multiboot_x86_usage'? - multiboot2_x86_usage }, - ^~~~~~~~~~~~~~~~~~~~ - multiboot_x86_usage - make: *** [Makefile:114: kexec/arch/i386/kexec-x86.o] Error 1 - make: *** Waiting for unfinished jobs.... - -Signed-off-by: Chris Packham -Signed-off-by: Chester Lin ---- -I wasn't sure whether this should be fixed by linking with kexec-mb2-x86.o or -by removing the code from kexec-x86.c. I went for the former but I'd happily -change to the latter. - - kexec/arch/i386/Makefile | 2 +- - kexec/arch/i386/kexec-x86.h | 5 +++++ - 2 files changed, 6 insertions(+), 1 deletion(-) - -diff --git a/kexec/arch/i386/Makefile b/kexec/arch/i386/Makefile -index 105cefd..f486103 100644 ---- a/kexec/arch/i386/Makefile -+++ b/kexec/arch/i386/Makefile -@@ -7,6 +7,7 @@ i386_KEXEC_SRCS += kexec/arch/i386/kexec-elf-x86.c - i386_KEXEC_SRCS += kexec/arch/i386/kexec-elf-rel-x86.c - i386_KEXEC_SRCS += kexec/arch/i386/kexec-bzImage.c - i386_KEXEC_SRCS += kexec/arch/i386/kexec-multiboot-x86.c -+i386_KEXEC_SRCS += kexec/arch/i386/kexec-mb2-x86.c - i386_KEXEC_SRCS += kexec/arch/i386/kexec-beoboot-x86.c - i386_KEXEC_SRCS += kexec/arch/i386/kexec-nbi.c - i386_KEXEC_SRCS += kexec/arch/i386/x86-linux-setup.c -@@ -14,7 +15,6 @@ i386_KEXEC_SRCS += kexec/arch/i386/crashdump-x86.c - - dist += kexec/arch/i386/Makefile $(i386_KEXEC_SRCS) \ - kexec/arch/i386/crashdump-x86.h \ -- kexec/arch/i386/kexec-mb2-x86.c \ - kexec/arch/i386/kexec-x86.h \ - kexec/arch/i386/x86-linux-setup.h \ - kexec/arch/i386/include/arch/options.h -diff --git a/kexec/arch/i386/kexec-x86.h b/kexec/arch/i386/kexec-x86.h -index 1b58c3b..0f941df 100644 ---- a/kexec/arch/i386/kexec-x86.h -+++ b/kexec/arch/i386/kexec-x86.h -@@ -60,6 +60,11 @@ int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len, - struct kexec_info *info); - void multiboot_x86_usage(void); - -+int multiboot2_x86_load(int argc, char **argv, const char *buf, off_t len, -+ struct kexec_info *info); -+void multiboot2_x86_usage(void); -+int multiboot2_x86_probe(const char *buf, off_t buf_len); -+ - int elf_x86_probe(const char *buf, off_t len); - int elf_x86_load(int argc, char **argv, const char *buf, off_t len, - struct kexec_info *info); diff --git a/kexec-tools-fix-kexec_file_load-error-handling.patch b/kexec-tools-fix-kexec_file_load-error-handling.patch deleted file mode 100644 index 9a24ebb..0000000 --- a/kexec-tools-fix-kexec_file_load-error-handling.patch +++ /dev/null @@ -1,230 +0,0 @@ -From 0ec1fd23847ba103f967e3377e2a1b13712cff6e Mon Sep 17 00:00:00 2001 -From: Petr Tesarik -Date: Thu, 12 Mar 2020 20:12:12 +0100 -Upstream: not yet, patch sent 2020-03-12 -Subject: Fix kexec_file_load(2) error handling -References: bsc#1166105 - -The handling of kexec_file_load() error conditions needs some -improvement. - -First, on failure, the system call itself returns -1 and sets -errno. It is wrong to check the return value itself. - -Second, do_kexec_file_load() mixes different types of error -codes (-1, return value of a load method, negative kernel error -number). Let it always return one of the reason codes defined in -kexec/kexec.h. - -Third, the caller of do_kexec_file_load() cannot know what exactly -failed inside that function, so it should not check errno directly. -All it needs to know is whether it makes sense to fall back to the -other syscall. Add an error code for that purpose (EFALLBACK), and -let do_kexec_file_load() decide. - -Fourth, do_kexec_file_load() should not print any error message if -it returns EFALLBACK, because the fallback syscall may succeed -later, and the user is confused whether the command failed, or not. -Move the error message towards the end of main(). - -Signed-off-by: Petr Tesarik ---- - kexec/kexec.c | 114 ++++++++++++++++++++++++++++++---------------------------- - kexec/kexec.h | 1 + - 2 files changed, 61 insertions(+), 54 deletions(-) - -diff --git a/kexec/kexec.c b/kexec/kexec.c -index bc6ab3d..33c1b4b 100644 ---- a/kexec/kexec.c -+++ b/kexec/kexec.c -@@ -836,11 +836,21 @@ static int kexec_file_unload(unsigned long kexec_file_flags) - { - int ret = 0; - -+ if (!is_kexec_file_load_implemented()) -+ return EFALLBACK; -+ - ret = kexec_file_load(-1, -1, 0, NULL, kexec_file_flags); - if (ret != 0) { -- /* The unload failed, print some debugging information */ -- fprintf(stderr, "kexec_file_load(unload) failed\n: %s\n", -- strerror(errno)); -+ if (errno == ENOSYS) { -+ ret = EFALLBACK; -+ } else { -+ /* -+ * The unload failed, print some debugging -+ * information */ -+ fprintf(stderr, "kexec_file_load(unload) failed: %s\n", -+ strerror(errno)); -+ ret = EFAILED; -+ } - } - return ret; - } -@@ -1182,15 +1192,13 @@ static int do_kexec_file_load(int fileind, int argc, char **argv, - info.file_mode = 1; - info.initrd_fd = -1; - -- if (!is_kexec_file_load_implemented()) { -- fprintf(stderr, "syscall kexec_file_load not available.\n"); -- return -ENOSYS; -- } -+ if (!is_kexec_file_load_implemented()) -+ return EFALLBACK; - - if (argc - fileind <= 0) { - fprintf(stderr, "No kernel specified\n"); - usage(); -- return -1; -+ return EFAILED; - } - - kernel = argv[fileind]; -@@ -1199,7 +1207,7 @@ static int do_kexec_file_load(int fileind, int argc, char **argv, - if (kernel_fd == -1) { - fprintf(stderr, "Failed to open file %s:%s\n", kernel, - strerror(errno)); -- return -1; -+ return EFAILED; - } - - /* slurp in the input kernel */ -@@ -1225,7 +1233,7 @@ static int do_kexec_file_load(int fileind, int argc, char **argv, - if (i == file_types) { - fprintf(stderr, "Cannot determine the file type " "of %s\n", - kernel); -- return -1; -+ return EFAILED; - } - - ret = file_type[i].load(argc, argv, kernel_buf, kernel_size, &info); -@@ -1243,9 +1251,43 @@ static int do_kexec_file_load(int fileind, int argc, char **argv, - - ret = kexec_file_load(kernel_fd, info.initrd_fd, info.command_line_len, - info.command_line, info.kexec_flags); -- if (ret != 0) -- fprintf(stderr, "kexec_file_load failed: %s\n", -- strerror(errno)); -+ if (ret != 0) { -+ switch (errno) { -+ /* -+ * Something failed with signature verification. -+ * Reject the image. -+ */ -+ case ELIBBAD: -+ case EKEYREJECTED: -+ case ENOPKG: -+ case ENOKEY: -+ case EBADMSG: -+ case EMSGSIZE: -+ /* Reject by default. */ -+ default: -+ ret = EFAILED; -+ break; -+ -+ /* Not implemented. */ -+ case ENOSYS: -+ /* -+ * Parsing image or other options failed -+ * The image may be invalid or image -+ * type may not supported by kernel so -+ * retry parsing in kexec-tools. -+ */ -+ case EINVAL: -+ case ENOEXEC: -+ /* -+ * ENOTSUP can be unsupported image -+ * type or unsupported PE signature -+ * wrapper type, duh. -+ */ -+ case ENOTSUP: -+ ret = EFALLBACK; -+ break; -+ } -+ } - - close(kernel_fd); - return ret; -@@ -1496,7 +1538,7 @@ int main(int argc, char *argv[]) - if (do_unload) { - if (do_kexec_file_syscall) { - result = kexec_file_unload(kexec_file_flags); -- if ((result == -ENOSYS) && do_kexec_fallback) -+ if (result == EFALLBACK && do_kexec_fallback) - do_kexec_file_syscall = 0; - } - if (!do_kexec_file_syscall) -@@ -1506,46 +1548,8 @@ int main(int argc, char *argv[]) - if (do_kexec_file_syscall) { - result = do_kexec_file_load(fileind, argc, argv, - kexec_file_flags); -- if (do_kexec_fallback) switch (result) { -- /* -- * Something failed with signature verification. -- * Reject the image. -- */ -- case -ELIBBAD: -- case -EKEYREJECTED: -- case -ENOPKG: -- case -ENOKEY: -- case -EBADMSG: -- case -EMSGSIZE: -- /* -- * By default reject or do nothing if -- * succeded -- */ -- default: break; -- case -ENOSYS: /* not implemented */ -- /* -- * Parsing image or other options failed -- * The image may be invalid or image -- * type may not supported by kernel so -- * retry parsing in kexec-tools. -- */ -- case -EINVAL: -- case -ENOEXEC: -- /* -- * ENOTSUP can be unsupported image -- * type or unsupported PE signature -- * wrapper type, duh -- * -- * The kernel sometimes wrongly -- * returns ENOTSUPP (524) - ignore -- * that. It is not supposed to be seen -- * by userspace so seeing it is a -- * kernel bug -- */ -- case -ENOTSUP: -- do_kexec_file_syscall = 0; -- break; -- } -+ if (result == EFALLBACK && do_kexec_fallback) -+ do_kexec_file_syscall = 0; - } - if (!do_kexec_file_syscall) - result = my_load(type, fileind, argc, argv, -@@ -1570,6 +1574,8 @@ int main(int argc, char *argv[]) - if ((result == 0) && do_load_jump_back_helper) { - result = my_load_jump_back_helper(kexec_flags, entry); - } -+ if (result == EFALLBACK) -+ fputs("syscall kexec_file_load not available.\n", stderr); - - fflush(stdout); - fflush(stderr); -diff --git a/kexec/kexec.h b/kexec/kexec.h -index a97b9ce..28fd129 100644 ---- a/kexec/kexec.h -+++ b/kexec/kexec.h -@@ -63,6 +63,7 @@ - */ - #define EFAILED -1 /* default error code */ - #define ENOCRASHKERNEL -2 /* no memory reserved for crashkernel */ -+#define EFALLBACK -3 /* fallback to kexec_load(2) may work */ - - /* - * This function doesn't actually exist. The idea is that when someone --- -2.16.4 - diff --git a/kexec-tools-print-error-if-kexec_file_load-fails.patch b/kexec-tools-print-error-if-kexec_file_load-fails.patch deleted file mode 100644 index 9b0c5e6..0000000 --- a/kexec-tools-print-error-if-kexec_file_load-fails.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: Hari Bathini -Date: Wed Mar 16 16:03:05 2022 +0530 -Subject: kexec-tools: print error if kexec_file_load fails -References: bsc#1197176 -Git-commit: 1d7a308bf7349fcf1627e950159029dfccf85891 -Upstream: merged - -Commit 4f77da634035 ("kexec-tools: Fix kexec_file_load(2) error -handling") introduced EFALLBACK for scenarios where fallbacking back -to kexec_load syscall is likely to work and dropped printing error -message for these scenarios. But printing error message for other -failure scenarios was inadvertently dropped. Restore printing error -message for such cases. - -Fixes: 4f77da634035 ("kexec-tools: Fix kexec_file_load(2) error handling") -Cc: Petr Tesarik -Reported-by: Nageswara R Sastry -Tested-by: Nageswara R Sastry -Signed-off-by: Hari Bathini -Reviewed-by: Petr Tesarik -Signed-off-by: Simon Horman - ---- - kexec/kexec.c | 1 + - 1 file changed, 1 insertion(+) - ---- a/kexec/kexec.c -+++ b/kexec/kexec.c -@@ -1265,6 +1265,7 @@ static int do_kexec_file_load(int filein - case EMSGSIZE: - /* Reject by default. */ - default: -+ fprintf(stderr, "kexec_file_load failed: %s\n", strerror(errno)); - ret = EFAILED; - break; - diff --git a/kexec-tools-reset-getopt-before-falling-back-to-legacy.patch b/kexec-tools-reset-getopt-before-falling-back-to-legacy.patch deleted file mode 100644 index 71d4f32..0000000 --- a/kexec-tools-reset-getopt-before-falling-back-to-legacy.patch +++ /dev/null @@ -1,54 +0,0 @@ -From dadafc4664c7b78ea1561ccca33986c9639106ec Mon Sep 17 00:00:00 2001 -From: Petr Tesarik -Date: Fri, 13 Mar 2020 14:54:00 +0100 -Upstream: not yet, patch sent 2020-03-13 -Subject: Reset getopt before falling back to legacy syscall -References: bsc#1166105 - -The modules may need to parse the arguments again after -kexec_file_load(2) failed, but getopt is not reset. - -This change fixes the --initrd option on s390x. Without this patch, -it will fail to load the initrd on kernels that do not implement -kexec_file_load(2). - -Signed-off-by: Petr Tesarik ---- - kexec/kexec.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/kexec/kexec.c b/kexec/kexec.c -index 33c1b4b..6601f1f 100644 ---- a/kexec/kexec.c -+++ b/kexec/kexec.c -@@ -1538,8 +1538,12 @@ int main(int argc, char *argv[]) - if (do_unload) { - if (do_kexec_file_syscall) { - result = kexec_file_unload(kexec_file_flags); -- if (result == EFALLBACK && do_kexec_fallback) -+ if (result == EFALLBACK && do_kexec_fallback) { -+ /* Reset getopt for fallback */ -+ opterr = 1; -+ optind = 1; - do_kexec_file_syscall = 0; -+ } - } - if (!do_kexec_file_syscall) - result = k_unload(kexec_flags); -@@ -1548,8 +1552,12 @@ int main(int argc, char *argv[]) - if (do_kexec_file_syscall) { - result = do_kexec_file_load(fileind, argc, argv, - kexec_file_flags); -- if (result == EFALLBACK && do_kexec_fallback) -+ if (result == EFALLBACK && do_kexec_fallback) { -+ /* Reset getopt for fallback */ -+ opterr = 1; -+ optind = 1; - do_kexec_file_syscall = 0; -+ } - } - if (!do_kexec_file_syscall) - result = my_load(type, fileind, argc, argv, --- -2.16.4 - diff --git a/kexec-tools-s390-Reset-kernel-command-line-on-syscal.patch b/kexec-tools-s390-Reset-kernel-command-line-on-syscal.patch deleted file mode 100644 index 9ecea35..0000000 --- a/kexec-tools-s390-Reset-kernel-command-line-on-syscal.patch +++ /dev/null @@ -1,31 +0,0 @@ -From: Petr Tesarik -Date: Fri, 3 Apr 2020 13:12:00 +0200 -Subject: kexec-tools: s390: Reset kernel command line on syscall fallback -References: bsc#1167868 -Upstream: submitted 2020-04-03 - -The command line is duplicated on s390 if kexec_file_load(2) is not -implemented. That's because the corresponding variable is not reset -to an empty string before re-parsing the kexec command line. - -Fixes: 9cf721279f6c ("Reset getopt before falling back to legacy syscall") -Signed-off-by: Petr Tesarik ---- - kexec/arch/s390/kexec-image.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/kexec/arch/s390/kexec-image.c b/kexec/arch/s390/kexec-image.c -index 8b39566..3c24fdf 100644 ---- a/kexec/arch/s390/kexec-image.c -+++ b/kexec/arch/s390/kexec-image.c -@@ -112,6 +112,7 @@ image_s390_load(int argc, char **argv, const char *kernel_buf, - }; - static const char short_options[] = KEXEC_OPT_STR ""; - -+ command_line[0] = 0; - ramdisk = NULL; - ramdisk_len = 0; - ramdisk_origin = 0; --- -2.16.4 - diff --git a/kexec-tools-video-capability.patch b/kexec-tools-video-capability.patch deleted file mode 100644 index c11b345..0000000 --- a/kexec-tools-video-capability.patch +++ /dev/null @@ -1,25 +0,0 @@ -From: Petr Tesarik -Subject: Make sure VIDEO_CAPABILITY_64BIT_BASE is defined -Upstream: never, build fix for SLE12 - -SLE12 did not provide a definition for VIDEO_CAPABILITY_64BIT_BASE -in . - -Signed-off-by: Petr Tesarik ---- - kexec/arch/i386/x86-linux-setup.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/kexec/arch/i386/x86-linux-setup.c -+++ b/kexec/arch/i386/x86-linux-setup.c -@@ -37,6 +37,10 @@ - #include "x86-linux-setup.h" - #include "../../kexec/kexec-syscall.h" - -+#ifndef VIDEO_CAPABILITY_64BIT_BASE -+#define VIDEO_CAPABILITY_64BIT_BASE (1 << 1) /* Frame buffer base is 64-bit */ -+#endif -+ - void init_linux_parameters(struct x86_linux_param_header *real_mode) - { - /* Fill in the values that are usually provided by the kernel. */ diff --git a/kexec-tools.spec b/kexec-tools.spec index ff423cb..2360317 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -6,28 +6,23 @@ Name: kexec-tools -Version: 2.0.20 -Release: 150500.18.3 +Version: 2.0.24 +Release: 5 Summary: Tools for loading replacement kernels into memory License: GPL-2.0-or-later Group: System/Kernel -Source: https://kernel.org/pub/linux/utils/kernel/kexec/%{name}-%{version}.tar.xz +URL: https://projects.horms.net/projects/kexec/ +Source: https://mirrors.ustc.edu.cn/kernel.org/linux/utils/kernel/kexec/%{name}-%{version}.tar.xz +Source100: https://mirrors.ustc.edu.cn/kernel.org/linux/utils/kernel/kexec/%{name}-%{version}.tar.sign +Source101: kexec-tools.keyring Source1: kexec-bootloader Source2: kexec-bootloader.8 Source3: kexec-load.service Source4: %{name}-rpmlintrc Patch3: %{name}-disable-test.patch Patch4: %{name}-vmcoreinfo-in-xen.patch -Patch5: %{name}-add-variant-helper-functions.patch -Patch6: %{name}-arm64-kexec-allocate-memory-space-avoiding-reserved-regions.patch -Patch7: %{name}-arm64-kdump-deal-with-resource-entries-in-proc-iomem.patch -Patch8: %{name}-build-multiboot2-for-i386.patch -Patch9: %{name}-video-capability.patch -Patch10: %{name}-SYS_getrandom.patch -Patch11: %{name}-fix-kexec_file_load-error-handling.patch -Patch12: %{name}-reset-getopt-before-falling-back-to-legacy.patch -Patch13: %{name}-s390-Reset-kernel-command-line-on-syscal.patch -Patch14: %{name}-print-error-if-kexec_file_load-fails.patch +# https://patchwork.kernel.org/project/linux-riscv/patch/20190416123233.4779-1-mick@ics.forth.gr/ +Patch5: RISC-V-Add-support-for-kexec-on-kexec-tools.patch BuildRequires: autoconf BuildRequires: automake BuildRequires: systemd-rpm-macros @@ -36,7 +31,7 @@ BuildRequires: zlib-devel #!BuildIgnore: gcc-PIE Requires: perl-Bootloader Requires(post): suse-module-tools -Requires(postun): suse-module-tools +Requires(postun):suse-module-tools %{?systemd_requires} %ifarch x86_64 BuildRequires: pkgconfig @@ -51,18 +46,7 @@ the loaded kernel after it panics. %prep %setup -q -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -%patch13 -p1 -%patch14 -p1 +%autopatch -p1 %build autoreconf -fvi @@ -70,7 +54,7 @@ export CFLAGS="%{optflags} -fPIC" export BUILD_CFLAGS="%{optflags}" export LDFLAGS="-pie" %configure -make %{?_smp_mflags} +%make_build %install %make_install @@ -80,10 +64,10 @@ install -m 0755 %{SOURCE1} %{buildroot}/%{_sbindir} mkdir -p %{buildroot}/%{_unitdir} install -m644 %{SOURCE3} %{buildroot}/%{_unitdir} ln -s service %{buildroot}%{_sbindir}/rckexec-load -#UsrMerge +%if 0%{?suse_version} < 1550 mkdir -p %{buildroot}/sbin ln -s %{_sbindir}/kexec %{buildroot}/sbin -#EndUsrMerge +%endif %post %service_add_post kexec-load.service @@ -102,29 +86,15 @@ ln -s %{_sbindir}/kexec %{buildroot}/sbin %posttrans %{?regenerate_initrd_posttrans} -# Compatibility cruft -# there is no %license prior to SLE12 -%if %{undefined _defaultlicensedir} -%define license %doc -%else -# filesystem before SLE12 SP3 lacks /usr/share/licenses -%if 0%(test ! -d %{_defaultlicensedir} && echo 1) -%define _defaultlicensedir %_defaultdocdir -%endif -%endif -# End of compatibility cruft - %files %license COPYING %doc AUTHORS News TODO doc %{_mandir}/man*/* -#UsrMerge +%if 0%{?suse_version} < 1550 /sbin/kexec -#EndUsrMerge +%endif %{_sbindir}/rckexec-load %{_sbindir}/kexec %{_sbindir}/kexec-bootloader %{_sbindir}/vmcore-dmesg %{_unitdir}/kexec-load.service - -%changelog