From 49c64e37ae5ab9226839e2b0c2d2d3b9eedae412 Mon Sep 17 00:00:00 2001 From: "zhixin.zhang" Date: Mon, 12 Dec 2022 15:46:41 +0800 Subject: [PATCH] Add sw patch --- kexec-tools.spec | 26 +- makedumpfile-1.7.0-sw.patch | 233 ++++++++ sw_64.patch | 1114 +++++++++++++++++++++++++++++++++++ 3 files changed, 1365 insertions(+), 8 deletions(-) create mode 100644 makedumpfile-1.7.0-sw.patch create mode 100644 sw_64.patch diff --git a/kexec-tools.spec b/kexec-tools.spec index 9364a6c..b930891 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -4,7 +4,7 @@ Name: kexec-tools Version: 2.0.23 -Release: 9 +Release: 10 License: GPLv2 Summary: The kexec/kdump userspace component URL: https://www.kernel.org/ @@ -82,7 +82,8 @@ Patch0009: arm64-fix-PAGE_OFFSET-calc-for-flipped-mm.patch Patch0010: fix-add-64-bit-loongArch-support-1.patch Patch0011: fix-add-64-bit-loongArch-support-2.patch %endif - +Patch00012: sw_64.patch +Patch00013: makedumpfile-1.7.0-sw.patch %description kexec-tools provides /sbin/kexec binary that facilitates a new kernel to boot using the kernel's kexec feature either on a @@ -122,6 +123,12 @@ tar -z -x -v -f %{SOURCE19} %patch0011 -p1 %endif +%ifarch sw_64 +%patch00012 -p1 +%patch00013 -p1 +%endif + + %build autoreconf %configure --sbindir=/usr/sbin \ @@ -131,7 +138,7 @@ rm -f kexec-tools.spec.in cp %{SOURCE21} %{SOURCE26} %{SOURCE27} . make -%ifarch %{ix86} x86_64 aarch64 loongarch64 +%ifarch %{ix86} x86_64 aarch64 sw_64 loongarch64 make -C eppic-%{eppic_ver}/libeppic make -C makedumpfile-%{mkdf_ver} LINKTYPE=dynamic USELZO=on USESNAPPY=on make -C makedumpfile-%{mkdf_ver} LDFLAGS="$LDFLAGS -I../eppic-%{eppic_ver}/libeppic -L../eppic-%{eppic_ver}/libeppic" eppic_makedumpfile.so @@ -175,7 +182,7 @@ install -m 644 %{SOURCE16} %{buildroot}%{_unitdir}/kdump.service install -m 755 -D %{SOURCE22} %{buildroot}%{_prefix}/lib/systemd/system-generators/kdump-dep-generator.sh install -m 644 %{SOURCE13} $RPM_BUILD_ROOT%{_udevrulesdir}/98-kexec.rules -%ifarch %{ix86} x86_64 aarch64 loongarch64 +%ifarch %{ix86} x86_64 aarch64 sw_64 loongarch64 install -m 755 makedumpfile-%{mkdf_ver}/makedumpfile $RPM_BUILD_ROOT/usr/sbin/makedumpfile install -m 644 makedumpfile-%{mkdf_ver}/makedumpfile.8.gz $RPM_BUILD_ROOT/%{_mandir}/man8/makedumpfile.8.gz install -m 644 makedumpfile-%{mkdf_ver}/makedumpfile.conf.5.gz $RPM_BUILD_ROOT/%{_mandir}/man5/makedumpfile.conf.5.gz @@ -280,14 +287,14 @@ done %{dracutlibdir}/modules.d/* %{_unitdir}/kdump.service %{_prefix}/lib/systemd/system-generators/kdump-dep-generator.sh -%ifarch %{ix86} x86_64 aarch64 loongarch64 +%ifarch %{ix86} x86_64 aarch64 sw_64 loongarch64 %{_libdir}/eppic_makedumpfile.so /usr/share/makedumpfile/ %endif -%ifarch %{ix86} x86_64 aarch64 loongarch64 +%ifarch %{ix86} x86_64 aarch64 sw_64 loongarch64 %{_sysconfdir}/makedumpfile.conf.sample %endif -%ifarch %{ix86} x86_64 aarch64 loongarch64 +%ifarch %{ix86} x86_64 aarch64 sw_64 loongarch64 /usr/sbin/makedumpfile %endif @@ -300,11 +307,14 @@ done %{_mandir}/man8/mkdumprd.8.gz %{_mandir}/man8/vmcore-dmesg.8.gz %{_mandir}/man5/* -%ifarch %{ix86} x86_64 aarch64 loongarch64 +%ifarch %{ix86} x86_64 aarch64 sw_64 loongarch64 %{_mandir}/man8/makedumpfile.8.gz %endif %changelog +* Mon Dec 12 2022 guojiancheng - 2.0.23-10 +- Add sw support + * Tue Nov 17 2022 doupengda - 2.0.23-9 - add loongarch64 support diff --git a/makedumpfile-1.7.0-sw.patch b/makedumpfile-1.7.0-sw.patch new file mode 100644 index 0000000..64ebd90 --- /dev/null +++ b/makedumpfile-1.7.0-sw.patch @@ -0,0 +1,233 @@ +diff -Naru ./makedumpfile-1.7.0/arch/sw_64.c ./makedumpfile-1.7.0-sw/arch/sw_64.c +--- ./makedumpfile-1.7.0/arch/sw_64.c 1970-01-01 00:00:00.000000000 +0000 ++++ ./makedumpfile-1.7.0-sw/arch/sw_64.c 2022-08-19 06:54:24.938438551 +0000 +@@ -0,0 +1,126 @@ ++/* ++ * sw_64.c ++ * ++ * Copyright (C) 2021 Loongson Technology Co., Ltd. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation (version 2 of the License). ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++#ifdef __sw_64__ ++ ++#include "../print_info.h" ++#include "../elf_info.h" ++#include "../makedumpfile.h" ++ ++int ++get_phys_base_sw_64(void) ++{ ++ info->phys_base = 0ULL; ++ ++ DEBUG_MSG("phys_base : %lx\n", info->phys_base); ++ ++ return TRUE; ++} ++ ++int ++get_machdep_info_sw_64(void) ++{ ++ info->section_size_bits = _SECTION_SIZE_BITS; ++ ++ /* Check if we can get MAX_PHYSMEM_BITS from vmcoreinfo */ ++ if (NUMBER(MAX_PHYSMEM_BITS) != NOT_FOUND_NUMBER) ++ info->max_physmem_bits = NUMBER(MAX_PHYSMEM_BITS); ++ else ++ info->max_physmem_bits = _MAX_PHYSMEM_BITS; ++ ++ DEBUG_MSG("max_physmem_bits : %lx\n", info->max_physmem_bits); ++ DEBUG_MSG("section_size_bits: %lx\n", info->section_size_bits); ++ ++ return TRUE; ++} ++ ++int ++get_versiondep_info_sw_64(void) ++{ ++ info->page_offset = 0x9800000000000000ULL; ++ ++ DEBUG_MSG("page_offset : %lx\n", info->page_offset); ++ ++ return TRUE; ++} ++ ++/* ++ * Translate a virtual address to a physical address by using 3 levels paging. ++ */ ++unsigned long long ++vaddr_to_paddr_sw_64(unsigned long vaddr) ++{ ++ unsigned long long paddr = NOT_PADDR; ++ pgd_t *pgda, pgdv; ++ pmd_t *pmda, pmdv; ++ pte_t *ptea, ptev; ++ ++ /* ++ * CKSEG0/CKSEG1 ++ */ ++ if (vaddr >= 0xffffffff80000000ULL && vaddr < 0xffffffffc0000000ULL) ++ return vaddr & 0x1fffffffULL; ++ ++ /* ++ * XKPHYS ++ */ ++ if (vaddr >= 0x9000000000000000ULL && vaddr < 0xc000000000000000ULL) ++ return vaddr & ((1ULL << MAX_PHYSMEM_BITS()) - 1); ++ ++ if (SYMBOL(swapper_pg_dir) == NOT_FOUND_SYMBOL) { ++ ERRMSG("Can't get the symbol of swapper_pg_dir.\n"); ++ return NOT_PADDR; ++ } ++ ++ pgda = pgd_offset(SYMBOL(swapper_pg_dir), vaddr); ++ if (!readmem(PADDR, (unsigned long long)pgda, &pgdv, sizeof(pgdv))) { ++ ERRMSG("Can't read pgd\n"); ++ return NOT_PADDR; ++ } ++ ++ pmda = pmd_offset(&pgdv, vaddr); ++ if (!readmem(PADDR, (unsigned long long)pmda, &pmdv, sizeof(pmdv))) { ++ ERRMSG("Can't read pmd\n"); ++ return NOT_PADDR; ++ } ++ ++ switch (pmdv & (_PAGE_PRESENT|_PAGE_HUGE)) { ++ case _PAGE_PRESENT: ++ ptea = pte_offset(&pmdv, vaddr); ++ /* 64k page */ ++ if (!readmem(PADDR, (unsigned long long)ptea, &ptev, sizeof(ptev))) { ++ ERRMSG("Can't read pte\n"); ++ return NOT_PADDR; ++ } ++ ++ if (!(ptev & _PAGE_PRESENT)) { ++ ERRMSG("Can't get a valid pte.\n"); ++ return NOT_PADDR; ++ } else { ++ paddr = PAGEBASE(ptev) + (vaddr & (PAGESIZE() - 1)); ++ } ++ break; ++ case _PAGE_PRESENT|_PAGE_HUGE: ++ paddr = (pmdv & PMD_MASK) + (vaddr & (PMD_SIZE - 1)); ++ break; ++ } ++ ++ return paddr; ++} ++ ++#endif /* sw_64 */ +diff -Naru ./makedumpfile-1.7.0/makedumpfile.h ./makedumpfile-1.7.0-sw/makedumpfile.h +--- ./makedumpfile-1.7.0/makedumpfile.h 2021-11-08 00:36:15.000000000 +0000 ++++ ./makedumpfile-1.7.0-sw/makedumpfile.h 2022-08-19 07:46:43.093698825 +0000 +@@ -963,7 +963,7 @@ + + #endif /* sparc64 */ + +-#ifdef __mips64__ /* mips64 */ ++#ifdef __mips64__ /* mips64 */ + #define KVBASE PAGE_OFFSET + #define _SECTION_SIZE_BITS (28) + #define _MAX_PHYSMEM_BITS (48) +@@ -996,6 +996,40 @@ + + #endif /* mips64 */ + ++#ifdef __sw_64__ /* sw_64 */ ++#define KVBASE PAGE_OFFSET ++#define _SECTION_SIZE_BITS (28) ++#define _MAX_PHYSMEM_BITS (48) ++#define _PAGE_PRESENT (1 << 0) ++#define _PAGE_HUGE (1 << 4) ++ ++typedef unsigned long pte_t; ++typedef unsigned long pmd_t; ++typedef unsigned long pgd_t; ++ ++#define PAGE_MASK (~(PAGESIZE() - 1)) ++#define PMD_MASK (~(PMD_SIZE - 1)) ++#define PMD_SHIFT ((PAGESHIFT() - 3) * 2 + 3) ++#define PMD_SIZE (1UL << PMD_SHIFT) ++#define PGDIR_SHIFT ((PAGESHIFT() - 3) * 3 + 3) ++#define PTRS_PER_PTE (1 << (PAGESHIFT() - 3)) ++#define PTRS_PER_PMD PTRS_PER_PTE ++#define PTRS_PER_PGD PTRS_PER_PTE ++ ++#define pte_index(vaddr) (((vaddr) >> PAGESHIFT()) & (PTRS_PER_PTE - 1)) ++#define pmd_page_paddr(pmd) (pmd & (int32_t)PAGE_MASK) ++#define pte_offset(dir, vaddr) ((pte_t *)pmd_page_paddr((*dir)) + pte_index(vaddr)) ++ ++#define pmd_index(vaddr) (((vaddr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) ++#define pgd_page_paddr(pgd) (pgd & (int32_t)PAGE_MASK) ++#define pmd_offset(pgd, vaddr) ((pmd_t *)pgd_page_paddr((*pgd)) + pmd_index(vaddr)) ++ ++#define pgd_index(vaddr) (((vaddr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) ++#define pgd_offset(pgdir, vaddr) ((pgd_t *)(pgdir) + pgd_index(vaddr)) ++ ++#endif /* sw_64 */ ++ ++ + /* + * The function of dependence on machine + */ +@@ -1167,6 +1201,23 @@ + #define arch_crashkernel_mem_size() stub_false() + #endif /* mips64 */ + ++#ifdef __sw_64__ /* sw64 */ ++int get_phys_base_sw_64(void); ++int get_machdep_info_sw_64(void); ++int get_versiondep_info_sw_64(void); ++unsigned long long vaddr_to_paddr_sw_64(unsigned long vaddr); ++#define find_vmemmap() stub_false() ++#define get_phys_base() get_phys_base_sw_64() ++#define get_machdep_info() get_machdep_info_sw_64() ++#define get_versiondep_info() get_versiondep_info_sw_64() ++#define get_kaslr_offset(X) stub_false() ++#define vaddr_to_paddr(X) vaddr_to_paddr_sw_64(X) ++#define paddr_to_vaddr(X) paddr_to_vaddr_general(X) ++#define is_phys_addr(X) stub_true_ul(X) ++#define arch_crashkernel_mem_size() stub_false() ++#endif /* sw_64 */ ++ ++ + typedef unsigned long long mdf_pfn_t; + + #ifndef ARCH_PFN_OFFSET +@@ -2301,6 +2352,13 @@ + #define get_xen_info_arch(X) FALSE + #endif /* mips64 */ + ++#ifdef __sw_64__ /* sw_64 */ ++#define kvtop_xen(X) FALSE ++#define get_xen_basic_info_arch(X) FALSE ++#define get_xen_info_arch(X) FALSE ++#endif /* sw_64 */ ++ ++ + struct cycle { + mdf_pfn_t start_pfn; + mdf_pfn_t end_pfn; +diff -Naru ./makedumpfile-1.7.0/Makefile ./makedumpfile-1.7.0-sw/Makefile +--- ./makedumpfile-1.7.0/Makefile 2021-11-08 00:36:15.000000000 +0000 ++++ ./makedumpfile-1.7.0-sw/Makefile 2022-08-19 06:55:54.538591123 +0000 +@@ -47,7 +47,7 @@ + SRC_BASE = makedumpfile.c makedumpfile.h diskdump_mod.h sadump_mod.h sadump_info.h + SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c printk.c + OBJ_PART=$(patsubst %.c,%.o,$(SRC_PART)) +-SRC_ARCH = arch/arm.c arch/arm64.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c arch/sparc64.c arch/mips64.c ++SRC_ARCH = arch/arm.c arch/arm64.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c arch/sparc64.c arch/mips64.c arch/sw_64.c + OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH)) + + LIBS = -ldw -lbz2 -ldl -lelf -lz diff --git a/sw_64.patch b/sw_64.patch new file mode 100644 index 0000000..183373d --- /dev/null +++ b/sw_64.patch @@ -0,0 +1,1114 @@ +diff -Naru kexec-tools-2.0.23/config/config.guess kexec-tools-2.0.23-sw/config/config.guess +--- kexec-tools-2.0.23/config/config.guess 2020-12-21 08:07:22.000000000 +0000 ++++ kexec-tools-2.0.23-sw/config/config.guess 2022-08-11 02:23:24.056917760 +0000 +@@ -937,6 +937,15 @@ + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; ++ sw_64:Linux:*:*) ++ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in ++ sw) UNAME_MACHINE=sw_64 ;; ++ esac ++ objdump --private-headers /bin/sh | grep -q ld.so.1 ++ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi ++ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" ++ exit ;; ++ + arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; +diff -Naru kexec-tools-2.0.23/config/config.sub kexec-tools-2.0.23-sw/config/config.sub +--- kexec-tools-2.0.23/config/config.sub 2020-12-21 08:07:22.000000000 +0000 ++++ kexec-tools-2.0.23-sw/config/config.sub 2022-08-11 02:23:50.316917760 +0000 +@@ -1158,6 +1158,7 @@ + case $cpu in + 1750a | 580 \ + | a29k \ ++ | sw_64 \ + | aarch64 | aarch64_be \ + | abacus \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ +diff -Naru kexec-tools-2.0.23/configure kexec-tools-2.0.23-sw/configure +--- kexec-tools-2.0.23/configure 2021-11-04 14:59:17.000000000 +0000 ++++ kexec-tools-2.0.23-sw/configure 2022-08-18 08:54:34.059090794 +0000 +@@ -3062,6 +3062,9 @@ + hppa*) + ARCH="hppa" + ;; ++ sw_64*) ++ ARCH="sw_64" ++ ;; + * ) + as_fn_error $? "unsupported architecture $target_cpu" "$LINENO" 5 + ;; +diff -Naru kexec-tools-2.0.23/configure.ac kexec-tools-2.0.23-sw/configure.ac +--- kexec-tools-2.0.23/configure.ac 2021-11-04 14:57:43.000000000 +0000 ++++ kexec-tools-2.0.23-sw/configure.ac 2022-08-18 08:54:51.039112966 +0000 +@@ -58,6 +58,9 @@ + hppa*) + ARCH="hppa" + ;; ++ sw_64*) ++ ARCH="sw_64" ++ ;; + * ) + AC_MSG_ERROR([unsupported architecture $target_cpu]) + ;; +diff -Naru kexec-tools-2.0.23/include/boot/beoboot.h kexec-tools-2.0.23-sw/include/boot/beoboot.h +--- kexec-tools-2.0.23/include/boot/beoboot.h 2010-07-29 09:22:16.000000000 +0000 ++++ kexec-tools-2.0.23-sw/include/boot/beoboot.h 2022-08-11 02:36:05.796917760 +0000 +@@ -23,6 +23,8 @@ + #define BEOBOOT_ARCH_ALPHA 2 + #define BEOBOOT_ARCH_PPC 3 + #define BEOBOOT_ARCH_PPC64 4 ++#define BEOBOOT_ARCH_SW_64 5 ++ + #if defined(__i386__) || defined(__x86_64__) + #define BEOBOOT_ARCH BEOBOOT_ARCH_I386 + #elif defined(__alpha__) +@@ -31,6 +33,8 @@ + #define BEOBOOT_ARCH BEOBOOT_ARCH_PPC + #elif defined(__powerpc64__) + #define BEOBOOT_ARCH BEOBOOT_ARCH_PPC64 ++#elif defined(__sw_64__) ++#define BEOBOOT_ARCH BEOBOOT_ARCH_SW_64 + #else + #error Unsupported architecture. + #endif +diff -Naru kexec-tools-2.0.23/include/elf.h kexec-tools-2.0.23-sw/include/elf.h +--- kexec-tools-2.0.23/include/elf.h 2020-12-21 08:07:22.000000000 +0000 ++++ kexec-tools-2.0.23-sw/include/elf.h 2022-08-19 01:53:05.572119857 +0000 +@@ -266,6 +266,8 @@ + chances of collision with official or non-GNU unofficial values. */ + + #define EM_ALPHA 0x9026 ++#define EM_SW_64 0x9026 ++ + + /* Legal values for e_version (version). */ + +diff -Naru kexec-tools-2.0.23/kexec/arch/sw_64/crashdump-sw_64.c kexec-tools-2.0.23-sw/kexec/arch/sw_64/crashdump-sw_64.c +--- kexec-tools-2.0.23/kexec/arch/sw_64/crashdump-sw_64.c 1970-01-01 00:00:00.000000000 +0000 ++++ kexec-tools-2.0.23-sw/kexec/arch/sw_64/crashdump-sw_64.c 2022-08-19 01:50:42.851856092 +0000 +@@ -0,0 +1,424 @@ ++/* ++ * kexec: Linux boots Linux ++ * ++ * 2005 (C) IBM Corporation. ++ * 2008 (C) MontaVista Software, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation (version 2 of the License). ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "../../kexec.h" ++#include "../../kexec-elf.h" ++#include "../../kexec-syscall.h" ++#include "../../crashdump.h" ++#include "kexec-sw_64.h" ++#include "crashdump-sw_64.h" ++#include "unused.h" ++ ++/* Stores a sorted list of RAM memory ranges for which to create elf headers. ++ * A separate program header is created for backup region */ ++static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES]; ++ ++/* Not used currently but required by generic fs2dt code */ ++struct memory_ranges usablemem_rgns; ++ ++/* Memory region reserved for storing panic kernel and other data. */ ++static struct memory_range crash_reserved_mem; ++ ++/* Read kernel physical load addr from the file returned by proc_iomem() ++ * (Kernel Code) and store in kexec_info */ ++static int get_kernel_paddr(struct crash_elf_info *elf_info) ++{ ++ uint64_t start; ++ ++ if (xen_present()) /* Kernel not entity mapped under Xen */ ++ return 0; ++ ++ if (parse_iomem_single("Kernel code\n", &start, NULL) == 0) { ++ elf_info->kern_paddr_start = start; ++ dbgprintf("kernel load physical addr start = 0x%" PRIu64 "\n", start); ++ return 0; ++ } ++ ++ fprintf(stderr, "Cannot determine kernel physical load addr\n"); ++ return -1; ++} ++ ++static int get_kernel_vaddr_and_size(struct crash_elf_info *elf_info, ++ unsigned long start_offset) ++{ ++ uint64_t end; ++ ++ if (!elf_info->kern_paddr_start) ++ return -1; ++ ++ elf_info->kern_vaddr_start = elf_info->kern_paddr_start | ++ start_offset; ++ /* If "Kernel bss" exists, the kernel ends there, else fall ++ * through and say that it ends at "Kernel data" */ ++ if (parse_iomem_single("Kernel bss\n", NULL, &end) == 0 || ++ parse_iomem_single("Kernel data\n", NULL, &end) == 0) { ++ elf_info->kern_size = end - elf_info->kern_paddr_start; ++ dbgprintf("kernel_vaddr= 0x%llx paddr %llx\n", ++ elf_info->kern_vaddr_start, ++ elf_info->kern_paddr_start); ++ dbgprintf("kernel size = 0x%lx\n", elf_info->kern_size); ++ return 0; ++ } ++ fprintf(stderr, "Cannot determine kernel virtual load addr and size\n"); ++ return -1; ++} ++ ++/* Removes crash reserve region from list of memory chunks for whom elf program ++ * headers have to be created. Assuming crash reserve region to be a single ++ * continuous area fully contained inside one of the memory chunks */ ++static int exclude_crash_reserve_region(int *nr_ranges) ++{ ++ int i, j, tidx = -1; ++ unsigned long long cstart, cend; ++ struct memory_range temp_region = { ++ .start = 0, ++ .end = 0 ++ }; ++ ++ /* Crash reserved region. */ ++ cstart = crash_reserved_mem.start; ++ cend = crash_reserved_mem.end; ++ ++ for (i = 0; i < (*nr_ranges); i++) { ++ unsigned long long mstart, mend; ++ mstart = crash_memory_range[i].start; ++ mend = crash_memory_range[i].end; ++ if (cstart < mend && cend > mstart) { ++ if (cstart != mstart && cend != mend) { ++ /* Split memory region */ ++ crash_memory_range[i].end = cstart - 1; ++ temp_region.start = cend + 1; ++ temp_region.end = mend; ++ temp_region.type = RANGE_RAM; ++ tidx = i+1; ++ } else if (cstart != mstart) ++ crash_memory_range[i].end = cstart - 1; ++ else ++ crash_memory_range[i].start = cend + 1; ++ } ++ } ++ /* Insert split memory region, if any. */ ++ if (tidx >= 0) { ++ if (*nr_ranges == CRASH_MAX_MEMORY_RANGES) { ++ /* No space to insert another element. */ ++ fprintf(stderr, "Error: Number of crash memory ranges" ++ " excedeed the max limit\n"); ++ return -1; ++ } ++ for (j = (*nr_ranges - 1); j >= tidx; j--) ++ crash_memory_range[j+1] = crash_memory_range[j]; ++ crash_memory_range[tidx].start = temp_region.start; ++ crash_memory_range[tidx].end = temp_region.end; ++ crash_memory_range[tidx].type = temp_region.type; ++ (*nr_ranges)++; ++ } ++ return 0; ++} ++/* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to ++ * create Elf headers. Keeping it separate from get_memory_ranges() as ++ * requirements are different in the case of normal kexec and crashdumps. ++ * ++ * Normal kexec needs to look at all of available physical memory irrespective ++ * of the fact how much of it is being used by currently running kernel. ++ * Crashdumps need to have access to memory regions actually being used by ++ * running kernel. Expecting a different file/data structure than /proc/iomem ++ * to look into down the line. May be something like /proc/kernelmem or may ++ * be zone data structures exported from kernel. ++ */ ++static int get_crash_memory_ranges(struct memory_range **range, int *ranges) ++{ ++ const char iomem[] = "/proc/iomem"; ++ int memory_ranges = 0; ++ char line[MAX_LINE]; ++ FILE *fp; ++ unsigned long long start, end; ++ ++ fp = fopen(iomem, "r"); ++ if (!fp) { ++ fprintf(stderr, "Cannot open %s: %s\n", ++ iomem, strerror(errno)); ++ return -1; ++ } ++ /* Separate segment for backup region */ ++ crash_memory_range[0].start = BACKUP_SRC_START; ++ crash_memory_range[0].end = BACKUP_SRC_END; ++ crash_memory_range[0].type = RANGE_RAM; ++ memory_ranges++; ++ ++ while (fgets(line, sizeof(line), fp) != 0) { ++ char *str; ++ int type, consumed, count; ++ if (memory_ranges >= CRASH_MAX_MEMORY_RANGES) ++ break; ++ count = sscanf(line, "%llx-%llx : %n", ++ &start, &end, &consumed); ++ if (count != 2) ++ continue; ++ str = line + consumed; ++ ++ /* Only Dumping memory of type System RAM. */ ++ if (memcmp(str, "System RAM\n", 11) == 0) { ++ type = RANGE_RAM; ++ } else if (memcmp(str, "Crash kernel\n", 13) == 0) { ++ /* Reserved memory region. New kernel can ++ * use this region to boot into. */ ++ crash_reserved_mem.start = start; ++ crash_reserved_mem.end = end; ++ crash_reserved_mem.type = RANGE_RAM; ++ continue; ++ } else ++ continue; ++ ++ if (start == BACKUP_SRC_START && end >= (BACKUP_SRC_END + 1)) ++ start = BACKUP_SRC_END + 1; ++ ++ crash_memory_range[memory_ranges].start = start; ++ crash_memory_range[memory_ranges].end = end; ++ crash_memory_range[memory_ranges].type = type; ++ memory_ranges++; ++ ++ /* Segregate linearly mapped region. */ ++ if (MAXMEM && (MAXMEM - 1) >= start && (MAXMEM - 1) <= end) { ++ crash_memory_range[memory_ranges - 1].end = MAXMEM - 1; ++ ++ /* Add segregated region. */ ++ crash_memory_range[memory_ranges].start = MAXMEM; ++ crash_memory_range[memory_ranges].end = end; ++ crash_memory_range[memory_ranges].type = type; ++ memory_ranges++; ++ } ++ } ++ fclose(fp); ++ ++ if (exclude_crash_reserve_region(&memory_ranges) < 0) ++ return -1; ++ ++ *range = crash_memory_range; ++ *ranges = memory_ranges; ++ return 0; ++} ++ ++/* Converts unsigned long to ascii string. */ ++static void ultoa(unsigned long i, char *str) ++{ ++ int j = 0, k; ++ char tmp; ++ ++ do { ++ str[j++] = i % 10 + '0'; ++ } while ((i /= 10) > 0); ++ str[j] = '\0'; ++ ++ /* Reverse the string. */ ++ for (j = 0, k = strlen(str) - 1; j < k; j++, k--) { ++ tmp = str[k]; ++ str[k] = str[j]; ++ str[j] = tmp; ++ } ++} ++ ++/* Adds the appropriate mem= options to command line, indicating the ++ * memory region the new kernel can use to boot into. */ ++static int cmdline_add_mem(char *cmdline, unsigned long addr, ++ unsigned long size) ++{ ++ int cmdlen, len; ++ char str[50], *ptr; ++ ++ addr = addr/1024; ++ size = size/1024; ++ ptr = str; ++ strcpy(str, " mem="); ++ ptr += strlen(str); ++ ultoa(size, ptr); ++ strcat(str, "K@"); ++ ptr = str + strlen(str); ++ ultoa(addr, ptr); ++ strcat(str, "K"); ++ len = strlen(str); ++ cmdlen = strlen(cmdline) + len; ++ if (cmdlen > (COMMAND_LINE_SIZE - 1)) ++ die("Command line overflow\n"); ++ strcat(cmdline, str); ++ ++ return 0; ++} ++ ++/* Adds the elfcorehdr= command line parameter to command line. */ ++static int cmdline_add_elfcorehdr(char *cmdline, unsigned long addr) ++{ ++ int cmdlen, len, align = 1024; ++ char str[30], *ptr; ++ ++ /* Passing in elfcorehdr=xxxK format. Saves space required in cmdline. ++ * Ensure 1K alignment*/ ++ if (addr%align) ++ return -1; ++ addr = addr/align; ++ ptr = str; ++ strcpy(str, " elfcorehdr="); ++ ptr += strlen(str); ++ ultoa(addr, ptr); ++ strcat(str, "K"); ++ len = strlen(str); ++ cmdlen = strlen(cmdline) + len; ++ if (cmdlen > (COMMAND_LINE_SIZE - 1)) ++ die("Command line overflow\n"); ++ strcat(cmdline, str); ++ return 0; ++} ++ ++#if __BYTE_ORDER == __LITTLE_ENDIAN ++# define ELFDATALOCAL ELFDATA2LSB ++#elif __BYTE_ORDER == __BIG_ENDIAN ++# define ELFDATALOCAL ELFDATA2MSB ++#else ++# error Unknown byte order ++#endif ++ ++static struct crash_elf_info elf_info64 = { ++ class: ELFCLASS64, ++ data : ELFDATALOCAL, ++ machine : EM_SW_64, ++ page_offset : PAGE_OFFSET, ++ lowmem_limit : 0, /* 0 == no limit */ ++}; ++ ++static struct crash_elf_info elf_info32 = { ++ class: ELFCLASS32, ++ data : ELFDATALOCAL, ++ machine : EM_SW_64, ++ page_offset : PAGE_OFFSET, ++ lowmem_limit : MAXMEM, ++}; ++ ++static int patch_elf_info(void) ++{ ++ const char cpuinfo[] = "/proc/cpuinfo"; ++ char line[MAX_LINE]; ++ FILE *fp; ++ ++ fp = fopen(cpuinfo, "r"); ++ if (!fp) { ++ fprintf(stderr, "Cannot open %s: %s\n", ++ cpuinfo, strerror(errno)); ++ return -1; ++ } ++ while (fgets(line, sizeof(line), fp) != 0) { ++ if (strncmp(line, "cpu model", 9) == 0) { ++ /* OCTEON uses a different page_offset. */ ++ if (strstr(line, "Octeon")) ++ elf_info64.page_offset = 0x8000000000000000ULL; ++ break; ++ } ++ } ++ fclose(fp); ++ return 0; ++} ++ ++/* Loads additional segments in case of a panic kernel is being loaded. ++ * One segment for backup region, another segment for storing elf headers ++ * for crash memory image. ++ */ ++int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline, ++ unsigned long UNUSED(max_addr), ++ unsigned long UNUSED(min_base)) ++{ ++ void *tmp; ++ unsigned long sz, elfcorehdr; ++ int nr_ranges, align = 1024; ++ struct memory_range *mem_range; ++ crash_create_elf_headers_func crash_create = crash_create_elf32_headers; ++ struct crash_elf_info *elf_info = &elf_info32; ++ unsigned long start_offset = 0x80000000UL; ++ ++ if (patch_elf_info()) ++ return -1; ++ ++ if (arch_options.core_header_type == CORE_TYPE_ELF64) { ++ elf_info = &elf_info64; ++ crash_create = crash_create_elf64_headers; ++ start_offset = (unsigned long)0xffffffff80000000UL; ++ } ++ ++ if (get_kernel_paddr(elf_info)) ++ return -1; ++ ++ if (get_kernel_vaddr_and_size(elf_info, start_offset)) ++ return -1; ++ ++ if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0) ++ return -1; ++ ++ info->backup_src_start = BACKUP_SRC_START; ++ info->backup_src_size = BACKUP_SRC_SIZE; ++ /* Create a backup region segment to store backup data*/ ++ sz = _ALIGN(BACKUP_SRC_SIZE, align); ++ tmp = xmalloc(sz); ++ memset(tmp, 0, sz); ++ info->backup_start = add_buffer(info, tmp, sz, sz, align, ++ crash_reserved_mem.start, ++ crash_reserved_mem.end, -1); ++ ++ if (crash_create(info, elf_info, crash_memory_range, nr_ranges, ++ &tmp, &sz, ELF_CORE_HEADER_ALIGN) < 0) { ++ free(tmp); ++ return -1; ++ } ++ ++ elfcorehdr = add_buffer(info, tmp, sz, sz, align, ++ crash_reserved_mem.start, ++ crash_reserved_mem.end, -1); ++ ++ /* ++ * backup segment is after elfcorehdr, so use elfcorehdr as top of ++ * kernel's available memory ++ */ ++ cmdline_add_mem(mod_cmdline, crash_reserved_mem.start, ++ crash_reserved_mem.end - crash_reserved_mem.start + 1); ++ cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr); ++ ++ dbgprintf("CRASH MEMORY RANGES:\n"); ++ dbgprintf("%016Lx-%016Lx\n", crash_reserved_mem.start, ++ crash_reserved_mem.end); ++ return 0; ++} ++ ++int is_crashkernel_mem_reserved(void) ++{ ++ uint64_t start, end; ++ ++ return parse_iomem_single("Crash kernel\n", &start, &end) == 0 ? ++ (start != end) : 0; ++} ++ ++int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) ++{ ++ return parse_iomem_single("Crash kernel\n", start, end); ++} +diff -Naru kexec-tools-2.0.23/kexec/arch/sw_64/crashdump-sw_64.h kexec-tools-2.0.23-sw/kexec/arch/sw_64/crashdump-sw_64.h +--- kexec-tools-2.0.23/kexec/arch/sw_64/crashdump-sw_64.h 1970-01-01 00:00:00.000000000 +0000 ++++ kexec-tools-2.0.23-sw/kexec/arch/sw_64/crashdump-sw_64.h 2022-08-18 09:22:23.142660576 +0000 +@@ -0,0 +1,23 @@ ++#ifndef CRASHDUMP_SW_64_H ++#define CRASHDUMP_SW_64_H ++ ++struct kexec_info; ++int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline, ++ unsigned long max_addr, unsigned long min_base); ++#define PAGE_OFFSET 0xa800000000000000ULL ++#define MAXMEM 0 ++#define __pa(x) ((unsigned long)(X) & 0x7fffffff) ++ ++ ++#define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1) ++#define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2) ++ ++#define COMMAND_LINE_SIZE 512 ++ ++/* Backup Region, First 1M of System RAM. */ ++#define BACKUP_SRC_START 0x00000000 ++#define BACKUP_SRC_END 0x000fffff ++#define BACKUP_SRC_SIZE (BACKUP_SRC_END - BACKUP_SRC_START + 1) ++ ++extern struct arch_options_t arch_options; ++#endif /* CRASHDUMP_SW_64_H */ +diff -Naru kexec-tools-2.0.23/kexec/arch/sw_64/include/arch/options.h kexec-tools-2.0.23-sw/kexec/arch/sw_64/include/arch/options.h +--- kexec-tools-2.0.23/kexec/arch/sw_64/include/arch/options.h 1970-01-01 00:00:00.000000000 +0000 ++++ kexec-tools-2.0.23-sw/kexec/arch/sw_64/include/arch/options.h 2022-08-19 01:48:57.131660708 +0000 +@@ -0,0 +1,30 @@ ++#ifndef KEXEC_ARCH_SW_64_OPTIONS_H ++#define KEXEC_ARCH_SW_64_OPTIONS_H ++ ++#define OPT_ARCH_MAX (OPT_MAX+0) ++#define OPT_APPEND (OPT_ARCH_MAX+0) ++#define OPT_DTB (OPT_ARCH_MAX+1) ++#define OPT_RAMDISK (OPT_ARCH_MAX+2) ++#define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+3) ++ ++/* Options relevant to the architecture (excluding loader-specific ones), ++ * in this case none: ++ */ ++#define KEXEC_ARCH_OPTIONS \ ++ KEXEC_OPTIONS \ ++ {"command-line", 1, 0, OPT_APPEND}, \ ++ {"append", 1, 0, OPT_APPEND}, \ ++ {"dtb", 1, 0, OPT_DTB }, \ ++ {"initrd", 1, 0, OPT_RAMDISK }, \ ++ { "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, ++ ++ ++#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" ++ ++/* See the other architectures for details of these; Alpha has no ++ * loader-specific options yet. ++ */ ++#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS ++#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR ++ ++#endif /* KEXEC_ARCH_SW_64_OPTIONS_H */ +diff -Naru kexec-tools-2.0.23/kexec/arch/sw_64/kexec-elf-rel-sw_64.c kexec-tools-2.0.23-sw/kexec/arch/sw_64/kexec-elf-rel-sw_64.c +--- kexec-tools-2.0.23/kexec/arch/sw_64/kexec-elf-rel-sw_64.c 1970-01-01 00:00:00.000000000 +0000 ++++ kexec-tools-2.0.23-sw/kexec/arch/sw_64/kexec-elf-rel-sw_64.c 2022-08-19 01:51:21.131926839 +0000 +@@ -0,0 +1,46 @@ ++/* ++ * kexec-elf-rel-mips.c - kexec Elf relocation routines ++ * Copyright (C) 2007 Francesco Chiechi, Alessandro Rubini ++ * Copyright (C) 2007 Tvblob s.r.l. ++ * ++ * derived from ../ppc/kexec-elf-rel-ppc.c ++ * Copyright (C) 2004 Albert Herranz ++ * ++ * This source code is licensed under the GNU General Public License, ++ * Version 2. See the file COPYING for more details. ++*/ ++ ++#include ++#include ++#include "../../kexec.h" ++#include "../../kexec-elf.h" ++ ++int machine_verify_elf_rel(struct mem_ehdr *ehdr) ++{ ++ if (ehdr->ei_data != ELFDATA2MSB) { ++ return 0; ++ } ++ if (ehdr->ei_class != ELFCLASS32) { ++ return 0; ++ } ++ if (ehdr->e_machine != EM_SW_64) { ++ 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; ++ } ++ return; ++} +diff -Naru kexec-tools-2.0.23/kexec/arch/sw_64/kexec-elf-sw_64.c kexec-tools-2.0.23-sw/kexec/arch/sw_64/kexec-elf-sw_64.c +--- kexec-tools-2.0.23/kexec/arch/sw_64/kexec-elf-sw_64.c 1970-01-01 00:00:00.000000000 +0000 ++++ kexec-tools-2.0.23-sw/kexec/arch/sw_64/kexec-elf-sw_64.c 2022-08-18 09:19:10.592068959 +0000 +@@ -0,0 +1,189 @@ ++/* ++ * kexec-elf-mips.c - kexec Elf loader for mips ++ * Copyright (C) 2007 Francesco Chiechi, Alessandro Rubini ++ * Copyright (C) 2007 Tvblob s.r.l. ++ * ++ * derived from ../ppc/kexec-elf-ppc.c ++ * Copyright (C) 2004 Albert Herranz ++ * ++ * This source code is licensed under the GNU General Public License, ++ * Version 2. See the file COPYING for more details. ++*/ ++ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "../../kexec.h" ++#include "../../kexec-elf.h" ++#include "../../kexec-syscall.h" ++#include "kexec-sw_64.h" ++#include "crashdump-sw_64.h" ++#include ++#include "../../fs2dt.h" ++#include "../../dt-ops.h" ++ ++static const int probe_debug = 0; ++ ++#define BOOTLOADER "kexec" ++#define UPSZ(X) _ALIGN_UP(sizeof(X), 4) ++ ++#define CMDLINE_PREFIX "kexec " ++static char cmdline_buf[COMMAND_LINE_SIZE] = CMDLINE_PREFIX; ++ ++int elf_sw_64_probe(const char *buf, off_t len) ++{ ++ struct mem_ehdr ehdr; ++ int result; ++ result = build_elf_exec_info(buf, len, &ehdr, 0); ++ if (result < 0) { ++ goto out; ++ } ++ ++ /* Verify the architecuture specific bits */ ++ if (ehdr.e_machine != EM_SW_64) { ++ /* for a different architecture */ ++ if (probe_debug) { ++ fprintf(stderr, "Not for this architecture.\n"); ++ } ++ result = -1; ++ goto out; ++ } ++ result = 0; ++ out: ++ free_elf_info(&ehdr); ++ return result; ++} ++ ++void elf_sw_64_usage(void) ++{ ++} ++ ++int elf_sw_64_load(int argc, char **argv, const char *buf, off_t len, ++ struct kexec_info *info) ++{ ++ struct mem_ehdr ehdr; ++ int command_line_len = 0; ++ char *crash_cmdline; ++ int result; ++ unsigned long cmdline_addr; ++ size_t i; ++ off_t dtb_length; ++ char *dtb_buf; ++ char *initrd_buf = NULL; ++ unsigned long long kernel_addr = 0, kernel_size = 0; ++ unsigned long pagesize = getpagesize(); ++ ++ /* Need to append some command line parameters internally in case of ++ * taking crash dumps. ++ */ ++ if (info->kexec_flags & KEXEC_ON_CRASH) { ++ crash_cmdline = xmalloc(COMMAND_LINE_SIZE); ++ memset((void *)crash_cmdline, 0, COMMAND_LINE_SIZE); ++ } else ++ crash_cmdline = NULL; ++ ++ result = build_elf_exec_info(buf, len, &ehdr, 0); ++ if (result < 0) ++ die("ELF exec parse failed\n"); ++ ++ /* Read in the PT_LOAD segments and remove CKSEG0 mask from address*/ ++ for (i = 0; i < ehdr.e_phnum; i++) { ++ struct mem_phdr *phdr; ++ phdr = &ehdr.e_phdr[i]; ++ if (phdr->p_type == PT_LOAD) { ++ phdr->p_paddr = virt_to_phys(phdr->p_paddr); ++ kernel_addr = phdr->p_paddr; ++ kernel_size = phdr->p_memsz; ++ } ++ } ++ ++ /* Load the Elf data */ ++ result = elf_exec_load(&ehdr, info); ++ if (result < 0) ++ die("ELF exec load failed\n"); ++ ++ info->entry = (void *)virt_to_phys(ehdr.e_entry); ++ ++ if (arch_options.command_line) ++ command_line_len = strlen(arch_options.command_line) + 1; ++ ++ if (info->kexec_flags & KEXEC_ON_CRASH) { ++ result = load_crashdump_segments(info, crash_cmdline, ++ 0, 0); ++ if (result < 0) { ++ free(crash_cmdline); ++ return -1; ++ } ++ } ++ ++ if (arch_options.command_line) ++ strncat(cmdline_buf, arch_options.command_line, command_line_len); ++ if (crash_cmdline) ++ { ++ strncat(cmdline_buf, crash_cmdline, ++ sizeof(crash_cmdline) - ++ strlen(crash_cmdline) - 1); ++ free(crash_cmdline); ++ } ++ ++ if (info->kexec_flags & KEXEC_ON_CRASH) ++ /* In case of crashdump segment[0] is kernel. ++ * Put cmdline just after it. */ ++ cmdline_addr = (unsigned long)info->segment[0].mem + ++ info->segment[0].memsz; ++ else ++ cmdline_addr = 0; ++ ++ /* MIPS systems that have been converted to use device tree ++ * passed through UHI will use commandline in the DTB and ++ * the DTB passed as a separate buffer. Note that ++ * CMDLINE_PREFIX is skipped here intentionally, as it is ++ * used only in the legacy method */ ++ ++ if (arch_options.dtb_file) { ++ dtb_buf = slurp_file(arch_options.dtb_file, &dtb_length); ++ } else { ++ create_flatten_tree(&dtb_buf, &dtb_length, cmdline_buf + strlen(CMDLINE_PREFIX)); ++ } ++ ++ if (arch_options.initrd_file) { ++ initrd_buf = slurp_file(arch_options.initrd_file, &initrd_size); ++ ++ /* Create initrd entries in dtb - although at this time ++ * they would not point to the correct location */ ++ dtb_set_initrd(&dtb_buf, &dtb_length, (off_t)initrd_buf, (off_t)initrd_buf + initrd_size); ++ ++ initrd_base = add_buffer(info, initrd_buf, initrd_size, ++ initrd_size, sizeof(void *), ++ _ALIGN_UP(kernel_addr + kernel_size + dtb_length, ++ pagesize), 0x0fffffff, 1); ++ ++ /* Now that the buffer for initrd is prepared, update the dtb ++ * with an appropriate location */ ++ dtb_set_initrd(&dtb_buf, &dtb_length, initrd_base, initrd_base + initrd_size); ++ } ++ ++ ++ /* This is a legacy method for commandline passing used ++ * currently by Octeon CPUs only */ ++ add_buffer(info, cmdline_buf, sizeof(cmdline_buf), ++ sizeof(cmdline_buf), sizeof(void *), ++ cmdline_addr, 0x0fffffff, 1); ++ ++ add_buffer(info, dtb_buf, dtb_length, dtb_length, 0, ++ _ALIGN_UP(kernel_addr + kernel_size, pagesize), ++ 0x0fffffff, 1); ++ ++ return 0; ++} ++ +diff -Naru kexec-tools-2.0.23/kexec/arch/sw_64/kexec-sw_64.c kexec-tools-2.0.23-sw/kexec/arch/sw_64/kexec-sw_64.c +--- kexec-tools-2.0.23/kexec/arch/sw_64/kexec-sw_64.c 1970-01-01 00:00:00.000000000 +0000 ++++ kexec-tools-2.0.23-sw/kexec/arch/sw_64/kexec-sw_64.c 2022-08-18 09:15:28.891539590 +0000 +@@ -0,0 +1,175 @@ ++/* ++ * kexec-sw_64.c - kexec for sw_64 ++ * Copyright (C) 2007 Francesco Chiechi, Alessandro Rubini ++ * Copyright (C) 2007 Tvblob s.r.l. ++ * ++ * derived from ../ppc/kexec-ppc.c ++ * Copyright (C) 2004, 2005 Albert Herranz ++ * ++ * This source code is licensed under the GNU General Public License, ++ * Version 2. See the file COPYING for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "../../kexec.h" ++#include "../../kexec-syscall.h" ++#include "kexec-sw_64.h" ++#include ++ ++/* Currently not used but required by top-level fs2dt code */ ++off_t initrd_base = 0; ++off_t initrd_size = 0; ++ ++static struct memory_range memory_range[MAX_MEMORY_RANGES]; ++ ++/* Return a sorted list of memory ranges. */ ++int get_memory_ranges(struct memory_range **range, int *ranges, ++ unsigned long UNUSED(kexec_flags)) ++{ ++ int memory_ranges = 0; ++ ++ const char iomem[] = "/proc/iomem"; ++ char line[MAX_LINE]; ++ FILE *fp; ++ unsigned long long start, end; ++ char *str; ++ int type, consumed, count; ++ ++ fp = fopen(iomem, "r"); ++ if (!fp) { ++ fprintf(stderr, "Cannot open %s: %s\n", iomem, strerror(errno)); ++ return -1; ++ } ++ while (fgets(line, sizeof(line), fp) != 0) { ++ if (memory_ranges >= MAX_MEMORY_RANGES) ++ break; ++ count = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed); ++ if (count != 2) ++ continue; ++ str = line + consumed; ++ end = end + 1; ++ if (memcmp(str, "System RAM\n", 11) == 0) { ++ type = RANGE_RAM; ++ } else if (memcmp(str, "reserved\n", 9) == 0) { ++ type = RANGE_RESERVED; ++ } else { ++ continue; ++ } ++ if (memory_ranges > 0 && ++ memory_range[memory_ranges - 1].end == start && ++ memory_range[memory_ranges - 1].type == type) { ++ memory_range[memory_ranges - 1].end = end; ++ } else { ++ memory_range[memory_ranges].start = start; ++ memory_range[memory_ranges].end = end; ++ memory_range[memory_ranges].type = type; ++ memory_ranges++; ++ } ++ } ++ fclose(fp); ++ *range = memory_range; ++ *ranges = memory_ranges; ++ return 0; ++} ++ ++struct file_type file_type[] = { ++ {"elf-sw_64", elf_sw_64_probe, elf_sw_64_load, elf_sw_64_usage}, ++}; ++int file_types = sizeof(file_type) / sizeof(file_type[0]); ++ ++void arch_usage(void) ++{ ++ printf( ++ " --command-line=STRING Set the kernel command line to STRING.\n" ++ " --append=STRING Set the kernel command line to STRING.\n" ++ " --dtb=FILE Use FILE as the device tree blob.\n" ++ " --initrd=FILE Use FILE as initial ramdisk.\n" ++ " --reuse-cmdline Use kernel command line from running system.\n" ++ ); ++} ++ ++struct arch_options_t arch_options = { ++ .core_header_type = CORE_TYPE_ELF64, ++}; ++ ++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; ++ int opt; ++ ++ while ((opt = getopt_long(argc, argv, short_options, ++ options, 0)) != -1) { ++ switch (opt) { ++ case OPT_APPEND: ++ arch_options.command_line = optarg; ++ break; ++ case OPT_REUSE_CMDLINE: ++ arch_options.command_line = get_command_line(); ++ break; ++ case OPT_DTB: ++ arch_options.dtb_file = optarg; ++ break; ++ case OPT_RAMDISK: ++ arch_options.initrd_file = optarg; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++const struct arch_map_entry arches[] = { ++ /* For compatibility with older patches ++ * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_MIPS here. ++ */ ++ { "sw_64", KEXEC_ARCH_MIPS }, ++ { NULL, 0 }, ++}; ++ ++int arch_compat_trampoline(struct kexec_info *UNUSED(info)) ++{ ++ ++ return 0; ++} ++ ++void arch_update_purgatory(struct kexec_info *UNUSED(info)) ++{ ++} ++ ++unsigned long virt_to_phys(unsigned long addr) ++{ ++ return addr & 0x7fffffff; ++} ++ ++/* ++ * add_segment() should convert base to a physical address on sw_64, ++ * while the default is just to work with base as is */ ++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, virt_to_phys(base), memsz, 1); ++} ++ ++/* ++ * add_buffer() should convert base to a physical address on sw_64, ++ * while the default is just to work with base as is */ ++unsigned long add_buffer(struct kexec_info *info, const void *buf, ++ unsigned long bufsz, unsigned long memsz, ++ unsigned long buf_align, unsigned long buf_min, ++ unsigned long buf_max, int buf_end) ++{ ++ return add_buffer_phys_virt(info, buf, bufsz, memsz, buf_align, ++ buf_min, buf_max, buf_end, 1); ++} ++ +diff -Naru kexec-tools-2.0.23/kexec/arch/sw_64/kexec-sw_64.h kexec-tools-2.0.23-sw/kexec/arch/sw_64/kexec-sw_64.h +--- kexec-tools-2.0.23/kexec/arch/sw_64/kexec-sw_64.h 1970-01-01 00:00:00.000000000 +0000 ++++ kexec-tools-2.0.23-sw/kexec/arch/sw_64/kexec-sw_64.h 2022-08-18 09:10:51.790877939 +0000 +@@ -0,0 +1,30 @@ ++#ifndef KEXEC_SW_64_H ++#define KEXEC_SW_64_H ++ ++#include ++ ++#define BOOT_BLOCK_VERSION 17 ++#define BOOT_BLOCK_LAST_COMP_VERSION 16 ++ ++#define MAX_MEMORY_RANGES 64 ++#define MAX_LINE 160 ++ ++#define CORE_TYPE_ELF32 1 ++#define CORE_TYPE_ELF64 2 ++ ++int elf_sw_64_probe(const char *buf, off_t len); ++int elf_sw_64_load(int argc, char **argv, const char *buf, off_t len, ++ struct kexec_info *info); ++void elf_sw_64_usage(void); ++ ++struct arch_options_t { ++ char *command_line; ++ char *dtb_file; ++ char *initrd_file; ++ int core_header_type; ++}; ++ ++extern struct memory_ranges usablemem_rgns; ++extern off_t initrd_base, initrd_size; ++ ++#endif /* KEXEC_SW_64_H */ +diff -Naru kexec-tools-2.0.23/kexec/arch/sw_64/Makefile kexec-tools-2.0.23-sw/kexec/arch/sw_64/Makefile +--- kexec-tools-2.0.23/kexec/arch/sw_64/Makefile 1970-01-01 00:00:00.000000000 +0000 ++++ kexec-tools-2.0.23-sw/kexec/arch/sw_64/Makefile 2022-08-18 09:47:30.207054276 +0000 +@@ -0,0 +1,29 @@ ++# ++# kexec sw_64 (linux booting linux) ++# ++sw_64_KEXEC_SRCS = kexec/arch/sw_64/kexec-sw_64.c ++sw_64_KEXEC_SRCS += kexec/arch/sw_64/kexec-elf-sw_64.c ++sw_64_KEXEC_SRCS += kexec/arch/sw_64/kexec-elf-rel-sw_64.c ++sw_64_KEXEC_SRCS += kexec/arch/sw_64/crashdump-sw_64.c ++ ++sw_64_FS2DT = kexec/fs2dt.c ++sw_64_FS2DT_INCLUDE = \ ++ -include $(srcdir)/kexec/arch/sw_64/crashdump-sw_64.h \ ++ -include $(srcdir)/kexec/arch/sw_64/kexec-sw_64.h ++ ++sw_64_DT_OPS += kexec/dt-ops.c ++ ++include $(srcdir)/kexec/libfdt/Makefile.libfdt ++ ++libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) ++sw_64_CPPFLAGS += -I$(srcdir)/kexec/libfdt ++sw_64_KEXEC_SRCS += $(libfdt_SRCS) ++ ++sw_64_ADD_BUFFER = ++sw_64_ADD_SEGMENT = ++sw_64_VIRT_TO_PHYS = ++ ++dist += kexec/arch/sw_64/Makefile $(sw_64_KEXEC_SRCS) \ ++ kexec/arch/sw_64/kexec-sw_64.h \ ++ kexec/arch/sw_64/crashdump-sw_64.h \ ++ kexec/arch/sw_64/include/arch/options.h +diff -Naru kexec-tools-2.0.23/kexec/kexec-syscall.h kexec-tools-2.0.23-sw/kexec/kexec-syscall.h +--- kexec-tools-2.0.23/kexec/kexec-syscall.h 2020-12-21 08:07:22.000000000 +0000 ++++ kexec-tools-2.0.23-sw/kexec/kexec-syscall.h 2022-08-18 08:44:14.408402498 +0000 +@@ -51,6 +51,9 @@ + #ifdef __alpha__ + #define __NR_kexec_load 448 + #endif ++#ifdef __sw_64__ ++#define __NR_kexec_load 448 ++#endif + #ifndef __NR_kexec_load + #error Unknown processor architecture. Needs a kexec_load syscall number. + #endif +diff -Naru kexec-tools-2.0.23/kexec/Makefile kexec-tools-2.0.23-sw/kexec/Makefile +--- kexec-tools-2.0.23/kexec/Makefile 2021-10-20 09:58:49.000000000 +0000 ++++ kexec-tools-2.0.23-sw/kexec/Makefile 2022-08-18 08:43:24.548411617 +0000 +@@ -92,6 +92,7 @@ + include $(srcdir)/kexec/arch/sh/Makefile + include $(srcdir)/kexec/arch/x86_64/Makefile + include $(srcdir)/kexec/arch/hppa/Makefile ++include $(srcdir)/kexec/arch/sw_64/Makefile + + KEXEC_SRCS += $($(ARCH)_KEXEC_SRCS) + +diff -Naru kexec-tools-2.0.23/purgatory/arch/sw_64/Makefile kexec-tools-2.0.23-sw/purgatory/arch/sw_64/Makefile +--- kexec-tools-2.0.23/purgatory/arch/sw_64/Makefile 1970-01-01 00:00:00.000000000 +0000 ++++ kexec-tools-2.0.23-sw/purgatory/arch/sw_64/Makefile 2022-08-11 02:32:23.036917760 +0000 +@@ -0,0 +1,8 @@ ++# ++# Purgatory sw_64 ++# ++ ++sw_64_PURGATORY_SRCS = ++ ++dist += purgatory/arch/sw_64/Makefile $(sw_64_PURGATORY_SRCS) ++ +diff -Naru kexec-tools-2.0.23/purgatory/Makefile kexec-tools-2.0.23-sw/purgatory/Makefile +--- kexec-tools-2.0.23/purgatory/Makefile 2020-12-21 08:07:22.000000000 +0000 ++++ kexec-tools-2.0.23-sw/purgatory/Makefile 2022-08-18 08:45:08.208392658 +0000 +@@ -28,6 +28,7 @@ + include $(srcdir)/purgatory/arch/s390/Makefile + include $(srcdir)/purgatory/arch/sh/Makefile + include $(srcdir)/purgatory/arch/x86_64/Makefile ++include $(srcdir)/purgatory/arch/sw_64/Makefile + + PURGATORY_SRCS+=$($(ARCH)_PURGATORY_SRCS) + -- Gitee