diff --git a/kexec-tools.spec b/kexec-tools.spec index 81ce631d940926c7e95335304b45fbd208e75025..4a3bb36566b451822ee1c2bd3175d10b1df103ab 100644 --- a/kexec-tools.spec +++ b/kexec-tools.spec @@ -4,7 +4,7 @@ Name: kexec-tools Version: 2.0.26 -Release: 10 +Release: 11 License: GPLv2 Summary: The kexec/kdump userspace component URL: https://www.kernel.org/ @@ -75,8 +75,8 @@ Patch0002: kexec-Add-quick-kexec-support.patch Patch0003: kexec-Quick-kexec-implementation-for-arm64.patch %ifarch sw_64 -Patch0004: sw_64.patch -Patch0005: makedumpfile-1.7.2-sw.patch +Patch0004: sw64.patch +Patch0005: makedumpfile-1.7.4-sw64.patch %endif %ifarch riscv64 @@ -296,6 +296,9 @@ done %endif %changelog +* Mon Mar 31 2025 Gu Zitao - 2.0.26-11 +- kdump: add sw64 support + * Mon Feb 10 2025 chenhaixiang - 2.0.26-10 - Before adding to usablemem_rgns, check if the memory range is already included. diff --git a/makedumpfile-1.7.2-sw.patch b/makedumpfile-1.7.2-sw.patch deleted file mode 100644 index 1d14df279d692f8f6569a302b764d5033db8689b..0000000000000000000000000000000000000000 --- a/makedumpfile-1.7.2-sw.patch +++ /dev/null @@ -1,233 +0,0 @@ -diff -Naru ./makedumpfile-1.7.2/arch/sw_64.c ./makedumpfile-1.7.2-sw/arch/sw_64.c ---- ./makedumpfile-1.7.2/arch/sw_64.c 1970-01-01 00:00:00.000000000 +0000 -+++ ./makedumpfile-1.7.2-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.2/makedumpfile.h ./makedumpfile-1.7.2-sw/makedumpfile.h ---- ./makedumpfile-1.7.2/makedumpfile.h 2021-11-08 00:36:15.000000000 +0000 -+++ ./makedumpfile-1.7.2-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 - - #ifndef _XKPHYS_START_ADDR -@@ -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 */ -+ -+ - #ifdef __loongarch64__ - #define KVBASE (0x8000000000000000ULL) - #define _PAGE_OFFSET (0x9000000000000000ULL) -@@ -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 */ -+ -+ - #ifdef __loongarch64__ /* loongarch64 */ - int get_phys_base_loongarch64(void); - int get_machdep_info_loongarch64(void); -@@ -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 */ -+ -+ - #ifdef __loongarch64__ /* loongarch64 */ - #define kvtop_xen(X) FALSE - #define get_xen_basic_info_arch(X) FALSE -diff -Naru ./makedumpfile-1.7.2/Makefile ./makedumpfile-1.7.2-sw/Makefile ---- ./makedumpfile-1.7.2/Makefile 2021-11-08 00:36:15.000000000 +0000 -+++ ./makedumpfile-1.7.2-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 detect_cycle.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 arch/loongarch64.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/loongarch64.c arch/sw_64.c - OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH)) - - LIBS = -ldw -lbz2 -ldl -lelf -lz diff --git a/makedumpfile-1.7.4-sw64.patch b/makedumpfile-1.7.4-sw64.patch new file mode 100755 index 0000000000000000000000000000000000000000..70b9cd4695d031f63e1ba5903fe3416cf1a1342d --- /dev/null +++ b/makedumpfile-1.7.4-sw64.patch @@ -0,0 +1,430 @@ +diff -Naru ./makedumpfile-1.7.4/arch/sw_64.c ./makedumpfile-1.7.4-sw64/arch/sw_64.c +--- ./makedumpfile-1.7.4/arch/sw_64.c 1970-01-01 08:00:00.000000000 +0800 ++++ ./makedumpfile-1.7.4-sw64/arch/sw_64.c 2025-04-01 08:37:38.886978748 +0800 +@@ -0,0 +1,328 @@ ++/* ++ * arch/sw_64.c ++ * ++ * Copyright (C) 2021 Uniontech, Bai xin ++ * ++ * 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 "../elf_info.h" ++#include "../makedumpfile.h" ++#include "../print_info.h" ++ ++typedef struct { ++ unsigned long pgd; ++} pgd_t; ++ ++typedef struct { ++ pgd_t pgd; ++} pud_t; ++ ++typedef struct { ++ pud_t pud; ++} pmd_t; ++ ++typedef struct { ++ unsigned long pte; ++} pte_t; ++ ++#define __pte(x) ((pte_t) { (x) } ) ++#define __pmd(x) ((pmd_t) { (x) } ) ++#define __pud(x) ((pud_t) { (x) } ) ++#define __pgd(x) ((pgd_t) { (x) } ) ++ ++static int pgtable_level = 4; ++static int va_bits = 53; ++ ++#define pgd_val(x) ((x).pgd) ++#define pud_val(x) (pgd_val((x).pgd)) ++#define pmd_val(x) (pud_val((x).pud)) ++#define pte_val(x) ((x).pte) ++ ++/* See 'include/uapi/linux/const.h' for definitions below */ ++#define __AC(X,Y) (X##Y) ++#define _AC(X,Y) __AC(X,Y) ++#define _AT(T,X) ((T)(X)) ++ ++/* See 'include/asm/pgtable-types.h' for definitions below */ ++typedef unsigned long pteval_t; ++typedef unsigned long pmdval_t; ++typedef unsigned long pudval_t; ++typedef unsigned long pgdval_t; ++ ++#define PAGE_SHIFT 13 ++ ++/* See 'arch/sw_64/include/asm/pgtable-hwdef.h' for definitions below */ ++ ++#define SW_64_HW_PGTABLE_LEVEL_SHIFT(n) ((PAGE_SHIFT - 3) * (4 - (n)) + 3) ++ ++#define PTRS_PER_PTE (1 << (PAGE_SHIFT - 3)) ++ ++/* ++ * PMD_SHIFT determines the size a level 2 page table entry can map. ++ */ ++#define PMD_SHIFT (PAGE_SHIFT + (PAGE_SHIFT - 3)) ++#define PMD_SIZE (_AC(1, UL) << PMD_SHIFT) ++#define PMD_MASK (~(PMD_SIZE-1)) ++#define PTRS_PER_PMD PTRS_PER_PTE ++ ++/* ++ * PUD_SHIFT determines the size a level 1 page table entry can map. ++ */ ++#define PUD_SHIFT (PAGE_SHIFT + 2 * (PAGE_SHIFT - 3)) ++#define PUD_SIZE (_AC(1, UL) << PUD_SHIFT) ++#define PUD_MASK (~(PUD_SIZE-1)) ++#define PTRS_PER_PUD PTRS_PER_PTE ++ ++/* ++ * PGDIR_SHIFT determines the size a top-level page table entry can map ++ * (depending on the configuration, this level can be 0, 1 or 2). ++ */ ++#define PGDIR_SHIFT (PAGE_SHIFT + 3* (PAGE_SHIFT - 3)) ++#define PGDIR_SIZE (_AC(1, UL) << PGDIR_SHIFT) ++#define PGDIR_MASK (~(PGDIR_SIZE-1)) ++#define PTRS_PER_PGD (1UL << (PAGE_SHIFT - 3)) ++ ++#define pgd_index(vaddr) (((vaddr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) ++#define pgd_offset(pgd, vaddr) ((pgd_t *)(pgd) + pgd_index(vaddr)) ++ ++#define __SW_PAGE_OFFSET 0xfff0000000000000 ++#define __START_KERNEL_map __SW_PAGE_OFFSET ++#define __SW_MAX_PHYSMEM_BITS 48 ++#define __SW_SECTION_SIZE_BITS 28 ++ ++static unsigned long long ++__pa(unsigned long x) ++{ ++ unsigned long y = x; ++ ++ if (y >= __START_KERNEL_map) { ++ y -= __START_KERNEL_map; ++ } else { ++ y -= __SW_PAGE_OFFSET; ++ } ++ return y; ++} ++ ++#define _PFN_BITS 40 ++#define _PTE_FLAGS_BITS (64 - _PFN_BITS) ++#define _PFN_MASK 0x7FFFFFFFF000000UL ++#define PAGE_OFFSET 0xfff0000000000000 ++static inline unsigned long pgd_page_vaddr(pgd_t pgd) ++{ ++ return ((pgd_val(pgd) & _PFN_MASK) >> (_PTE_FLAGS_BITS-PAGE_SHIFT)); ++} ++#define PTRS_PER_PAGE (1UL << (PAGE_SHIFT - 3)) ++static inline unsigned long _pud_offset(unsigned long vaddr) ++{ ++ return (vaddr >> PUD_SHIFT) & (PTRS_PER_PAGE - 1); ++} ++static inline pud_t *pud_offset(pgd_t *pgda, pgd_t *pgdv, unsigned long vaddr) ++{ ++ pud_t *ret = (pud_t *) pgd_page_vaddr(*pgdv) ++ + _pud_offset(vaddr); ++ return ret; ++} ++ ++static inline unsigned long pud_page_vaddr(pud_t pud) ++{ ++ return ((pud_val(pud) & _PFN_MASK) >> (_PTE_FLAGS_BITS-PAGE_SHIFT)); ++} ++static inline unsigned long _pmd_offset(unsigned long vaddr) ++{ ++ return ((vaddr >> PMD_SHIFT) & (PTRS_PER_PAGE - 1)); ++} ++static inline pmd_t *pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr) ++{ ++ pmd_t *ret = (pmd_t *) pud_page_vaddr(*pudv) ++ + _pmd_offset(vaddr); ++ return ret; ++} ++ ++static inline unsigned long ++pmd_page_vaddr(pmd_t pmd) ++{ ++ return ((pmd_val(pmd) & _PFN_MASK) >> (_PTE_FLAGS_BITS-PAGE_SHIFT)); ++} ++static inline unsigned long _pte_offset(unsigned long address) ++{ ++ return ((address >> PAGE_SHIFT) & (PTRS_PER_PAGE - 1)); ++} ++static inline pte_t *pte_offset(pmd_t *dir, unsigned long address) ++{ ++ pte_t *ret = (pte_t *) pmd_page_vaddr(*dir) ++ + _pte_offset(address); ++ return ret; ++} ++ ++#define _PAGE_VALID 0x0001 ++static inline int pte_present(pte_t pte) ++{ ++ return pte_val(pte) & _PAGE_VALID; ++} ++ ++ulong ++get_stext_symbol(void) ++{ ++ int found; ++ FILE *fp; ++ char buf[BUFSIZE]; ++ char *kallsyms[MAXARGS]; ++ ulong kallsym; ++ ++ if (!file_exists("/proc/kallsyms")) { ++ ERRMSG("(%s) does not exist, will not be able to read symbols. %s\n", ++ "/proc/kallsyms", strerror(errno)); ++ return FALSE; ++ } ++ ++ if ((fp = fopen("/proc/kallsyms", "r")) == NULL) { ++ ERRMSG("Cannot open (%s) to read symbols. %s\n", ++ "/proc/kallsyms", strerror(errno)); ++ return FALSE; ++ } ++ ++ found = FALSE; ++ kallsym = 0; ++ ++ while (!found && fgets(buf, BUFSIZE, fp) && ++ (parse_line(buf, kallsyms) == 3)) { ++ if (hexadecimal(kallsyms[0], 0) && ++ STREQ(kallsyms[2], "_stext")) { ++ kallsym = htol(kallsyms[0], 0); ++ found = TRUE; ++ break; ++ } ++ } ++ fclose(fp); ++ ++ return(found ? kallsym : FALSE); ++} ++ ++int ++get_machdep_info_sw_64(void) ++{ ++ info->section_size_bits = __SW_SECTION_SIZE_BITS; ++ info->max_physmem_bits = __SW_MAX_PHYSMEM_BITS; ++ return TRUE; ++} ++ ++unsigned long long ++kvtop_xen_sw_64(unsigned long kvaddr) ++{ ++ return ERROR; ++} ++ ++int ++get_xen_basic_info_sw_64(void) ++{ ++ return ERROR; ++} ++ ++int ++get_xen_info_sw_64(void) ++{ ++ return ERROR; ++} ++ ++/* ++ * vaddr_to_paddr_sw_64() - translate arbitrary virtual address to physical ++ * @vaddr: virtual address to translate ++ * ++ * Function translates @vaddr into physical address using page tables. This ++ * address can be any virtual address. Returns physical address of the ++ * corresponding virtual address or %NOT_PADDR when there is no translation. ++ */ ++unsigned long long ++vaddr_to_paddr_sw_64(unsigned long vaddr) ++{ ++ unsigned long long paddr = NOT_PADDR; ++ unsigned long long swapper_phys; ++ pgd_t *pgda, pgdv; ++ pud_t *puda, pudv; ++ pmd_t *pmda, pmdv; ++ pte_t *ptea, ptev; ++ ++ if (vaddr > 0xffffffff80000000){ ++ paddr = vaddr - 0xffffffff80000000; ++ DEBUG_MSG("direct map:%-16lx ----> %-16lx\n", vaddr, paddr); ++ return paddr; ++ } ++ ++ if (vaddr > 0xfff0000000000000 && vaddr < 0xfff0ffffffffffff){ ++ paddr = vaddr - 0xfff0000000000000; ++ DEBUG_MSG("direct map:%-16lx ----> %-16lx\n", vaddr, paddr); ++ return paddr; ++ } ++ ++ if (SYMBOL(swapper_pg_dir) == NOT_FOUND_SYMBOL) { ++ ERRMSG("Can't get the symbol of swapper_pg_dir.\n"); ++ return NOT_PADDR; ++ } ++ ++ swapper_phys = __pa(SYMBOL(swapper_pg_dir)); ++ DEBUG_MSG("start look table vaddr:%-16lx\n", vaddr); ++ DEBUG_MSG("swapper_pg_dir:%-16lx\n", SYMBOL(swapper_pg_dir)); ++ ++ pgda = pgd_offset(swapper_phys, vaddr); ++ DEBUG_MSG("pgd:%-16lx offset:%-16lx pgda:%-16lx", swapper_phys, pgd_index(vaddr) * sizeof(pgd_t), pgda); ++ if (!readmem(PADDR, (unsigned long long)pgda, &pgdv, sizeof(pgdv))) { ++ ERRMSG("Can't read pgd\n"); ++ return NOT_PADDR; ++ } ++ DEBUG_MSG(" pgdv:%-16lx\n", pgdv); ++ ++ puda = pud_offset(pgda, &pgdv, vaddr); ++ DEBUG_MSG("pud:%-16lx offset:%-16lx puda:%-16lx", pgd_page_vaddr(pgdv), _pud_offset(vaddr) * sizeof(pud_t), puda); ++ if (!readmem(PADDR, (unsigned long long)puda, &pudv, sizeof(pudv))) { ++ ERRMSG("Can't read pud\n"); ++ return NOT_PADDR; ++ } ++ DEBUG_MSG(" pudv:%-16lx\n", pudv); ++ ++ if (!pud_val(pudv)) { ++ DEBUG_MSG("addr = %#lx, pgd = %#lx, pud = %#lx\n", ++ vaddr, pgd_val(pgdv), pud_val(pudv)); ++ return 0; ++ } ++ ++ pmda = pmd_offset(puda, &pudv, vaddr); ++ DEBUG_MSG("pmd:%-16lx offset:%-16lx pmda:%-16lx", pud_page_vaddr(pudv), _pmd_offset(vaddr) * sizeof(pgd_t), pmda); ++ if (!readmem(PADDR, (unsigned long long)pmda, &pmdv, sizeof(pmdv))) { ++ ERRMSG("Can't read pmd\n"); ++ return NOT_PADDR; ++ } ++ DEBUG_MSG(" pmdv:%-16lx\n", pmdv); ++ ++ ptea = pte_offset(&pmdv, vaddr); ++ DEBUG_MSG("pte:%-16lx offset:%-16lx ptea:%-16lx", pmd_page_vaddr(pmdv), _pte_offset(vaddr) * sizeof(pgd_t), ptea); ++ if (!readmem(PADDR, (unsigned long long)ptea, &ptev, sizeof(ptev))) { ++ ERRMSG("Can't read pte\n"); ++ return NOT_PADDR; ++ } ++ DEBUG_MSG(" ptev:%-16lx\n", ptev); ++ ++ if (pte_present(ptev)) { ++ paddr = ((pte_val(ptev) & _PFN_MASK) >> (_PTE_FLAGS_BITS-PAGE_SHIFT)) + (vaddr & ((1 << PAGE_SHIFT) - 1)); ++ DEBUG_MSG("paddr:%-16lx", paddr); ++ } ++ pte_val(ptev) = 0; ++ readmem(PADDR, (unsigned long long)paddr, &ptev, sizeof(ptev)); ++ DEBUG_MSG(" value:%-16lx\n", ptev); ++ return paddr; ++} ++ ++#endif /* __sw_64__ */ +diff -Naru ./makedumpfile-1.7.4/makedumpfile.h ./makedumpfile-1.7.4-sw64/makedumpfile.h +--- ./makedumpfile-1.7.4/makedumpfile.h 2025-04-01 08:34:04.990967629 +0800 ++++ ./makedumpfile-1.7.4-sw64/makedumpfile.h 2025-04-01 08:37:38.886978748 +0800 +@@ -829,6 +829,47 @@ + + #endif /* __s390x__ */ + ++#ifdef __sw_64__ ++//#define __PAGE_OFFSET (info->page_size - 1) ++#define KERNELBASE (0) ++#define KVBASE KERNELBASE ++//#define _SECTION_SIZE_BITS (28) ++//#define _MAX_PHYSMEM_BITS_ORIG (42) ++//#define _MAX_PHYSMEM_BITS_3_3 (46) ++// ++///* Bits in the segment/region table address-space-control-element */ ++//#define _ASCE_TYPE_MASK 0x0c ++//#define _ASCE_TABLE_LENGTH 0x03 /* region table length */ ++// ++//#define TABLE_LEVEL(x) (((x) & _ASCE_TYPE_MASK) >> 2) ++//#define TABLE_LENGTH(x) ((x) & _ASCE_TABLE_LENGTH) ++// ++///* Bits in the region table entry */ ++//#define _REGION_ENTRY_ORIGIN ~0xfffUL /* region table origin*/ ++//#define _REGION_ENTRY_TYPE_MASK 0x0c /* region table type mask */ ++//#define _REGION_ENTRY_INVALID 0x20 /* invalid region table entry */ ++//#define _REGION_ENTRY_LENGTH 0x03 /* region table length */ ++//#define _REGION_ENTRY_LARGE 0x400 ++//#define _REGION_OFFSET_MASK 0x7ffUL /* region/segment table offset mask */ ++// ++//#define RSG_TABLE_LEVEL(x) (((x) & _REGION_ENTRY_TYPE_MASK) >> 2) ++//#define RSG_TABLE_LENGTH(x) ((x) & _REGION_ENTRY_LENGTH) ++// ++///* Bits in the segment table entry */ ++//#define _SEGMENT_ENTRY_ORIGIN ~0x7ffUL ++//#define _SEGMENT_ENTRY_LARGE 0x400 ++//#define _SEGMENT_ENTRY_CO 0x100 ++//#define _SEGMENT_PAGE_SHIFT 31 ++//#define _SEGMENT_INDEX_SHIFT 20 ++// ++///* Hardware bits in the page table entry */ ++//#define _PAGE_ZERO 0x800 /* Bit pos 52 must conatin zero */ ++//#define _PAGE_INVALID 0x400 /* HW invalid bit */ ++//#define _PAGE_INDEX_SHIFT 12 ++//#define _PAGE_OFFSET_MASK 0xffUL /* page table offset mask */ ++ ++#endif /* __sw_64__ */ ++ + #ifdef __ia64__ /* ia64 */ + #define REGION_SHIFT (61) + +@@ -1253,6 +1294,21 @@ + #define arch_crashkernel_mem_size() stub_false() + #endif /* s390x */ + ++#ifdef __sw_64__ /* sw_64 */ ++int get_machdep_info_sw_64(void); ++unsigned long long vaddr_to_paddr_sw_64(unsigned long vaddr); ++//int is_iomem_phys_addr_s390x(unsigned long addr); ++#define find_vmemmap() stub_false() ++#define get_phys_base() stub_true() ++#define get_machdep_info() get_machdep_info_sw_64() ++#define get_versiondep_info() stub_true() ++#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 */ ++ + #ifdef __ia64__ /* ia64 */ + int get_phys_base_ia64(void); + int get_machdep_info_ia64(void); +@@ -2504,6 +2560,12 @@ + #define get_xen_info_arch(X) FALSE + #endif /* s390x */ + ++#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 */ ++ + #ifdef __sparc64__ /* sparc64 */ + #define kvtop_xen(X) FALSE + #define get_xen_basic_info_arch(X) FALSE +diff -Naru ./makedumpfile-1.7.4/Makefile ./makedumpfile-1.7.4-sw64/Makefile +--- ./makedumpfile-1.7.4/Makefile 2025-04-01 08:34:04.978967628 +0800 ++++ ./makedumpfile-1.7.4-sw64/Makefile 2025-04-01 08:37:38.886978748 +0800 +@@ -47,7 +48,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 detect_cycle.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 arch/loongarch64.c arch/riscv64.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/loongarch64.c arch/riscv64.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/sw64.patch old mode 100644 new mode 100755 similarity index 60% rename from sw_64.patch rename to sw64.patch index 548f6b842fb74a6c1021d7f1c099b3ad069a27e2..a931e6c5d88c0fb72c82504a7294e4ddb7e64c78 --- a/sw_64.patch +++ b/sw64.patch @@ -1,96 +1,96 @@ -diff -Naru kexec-tools-2.0.26/config/config.guess kexec-tools-2.0.26-sw/config/config.guess ---- kexec-tools-2.0.26/config/config.guess 2020-12-21 08:07:22.000000000 +0000 -+++ kexec-tools-2.0.26-sw/config/config.guess 2022-08-11 02:23:24.056917760 +0000 -@@ -937,6 +937,15 @@ +diff --git a/config/config.guess b/config/config.guess +index c626f7a..b017a9e 100755 +--- a/config/config.guess ++++ b/config/config.guess +@@ -937,6 +937,11 @@ EOF 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 ;; -+ ++ objdump --private-headers /bin/sh | grep -q ld.so.1 ++ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi ++ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ++ exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; -diff -Naru kexec-tools-2.0.26/config/config.sub kexec-tools-2.0.26-sw/config/config.sub ---- kexec-tools-2.0.26/config/config.sub 2020-12-21 08:07:22.000000000 +0000 -+++ kexec-tools-2.0.26-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.26/configure kexec-tools-2.0.26-sw/configure ---- kexec-tools-2.0.26/configure 2021-11-04 14:59:17.000000000 +0000 -+++ kexec-tools-2.0.26-sw/configure 2022-08-18 08:54:34.059090794 +0000 -@@ -3062,6 +3062,9 @@ - loongarch*) - ARCH="loongarch" - ;; -+ sw_64*) -+ ARCH="sw_64" -+ ;; - * ) - as_fn_error $? "unsupported architecture $target_cpu" "$LINENO" 5 - ;; -diff -Naru kexec-tools-2.0.26/configure.ac kexec-tools-2.0.26-sw/configure.ac ---- kexec-tools-2.0.26/configure.ac 2021-11-04 14:57:43.000000000 +0000 -+++ kexec-tools-2.0.26-sw/configure.ac 2022-08-18 08:54:51.039112966 +0000 -@@ -58,6 +58,9 @@ - loongarch*) - ARCH="loongarch" +diff --git a/config/config.sub b/config/config.sub +index dae00e6..d6ff133 100755 +--- a/config/config.sub ++++ b/config/config.sub +@@ -1241,6 +1241,7 @@ case $cpu-$vendor in + | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \ + | spu \ ++ | sw_64 \ + | tahoe \ + | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \ + | tron \ +diff --git a/configure.ac b/configure.ac +index 767574e..ff595f8 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -52,7 +52,7 @@ case $target_cpu in + cris|crisv32 ) + ARCH="cris" ;; -+ sw_64*) -+ ARCH="sw_64" -+ ;; - * ) - AC_MSG_ERROR([unsupported architecture $target_cpu]) +- ia64|x86_64|alpha|m68k ) ++ ia64|x86_64|alpha|m68k|sw_64 ) + ARCH="$target_cpu" ;; -diff -Naru kexec-tools-2.0.26/include/boot/beoboot.h kexec-tools-2.0.26-sw/include/boot/beoboot.h ---- kexec-tools-2.0.26/include/boot/beoboot.h 2010-07-29 09:22:16.000000000 +0000 -+++ kexec-tools-2.0.26-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.26/include/elf.h kexec-tools-2.0.26-sw/include/elf.h ---- kexec-tools-2.0.26/include/elf.h 2020-12-21 08:07:22.000000000 +0000 -+++ kexec-tools-2.0.26-sw/include/elf.h 2022-08-19 01:53:05.572119857 +0000 -@@ -266,6 +266,8 @@ + hppa*) +diff --git a/include/elf.h b/include/elf.h +index 1c8d2cc..93eb69d 100644 +--- a/include/elf.h ++++ b/include/elf.h +@@ -267,6 +267,7 @@ typedef struct chances of collision with official or non-GNU unofficial values. */ #define EM_ALPHA 0x9026 -+#define EM_SW_64 0x9026 -+ ++#define EM_SW_64 0x9916 /* Legal values for e_version (version). */ -diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/crashdump-sw_64.c kexec-tools-2.0.26-sw/kexec/arch/sw_64/crashdump-sw_64.c ---- kexec-tools-2.0.26/kexec/arch/sw_64/crashdump-sw_64.c 1970-01-01 00:00:00.000000000 +0000 -+++ kexec-tools-2.0.26-sw/kexec/arch/sw_64/crashdump-sw_64.c 2022-08-19 01:50:42.851856092 +0000 -@@ -0,0 +1,424 @@ +diff --git a/kexec/Makefile b/kexec/Makefile +index 8a52e8d..5a102b7 100644 +--- a/kexec/Makefile ++++ b/kexec/Makefile +@@ -90,6 +90,7 @@ include $(srcdir)/kexec/arch/ppc/Makefile + include $(srcdir)/kexec/arch/ppc64/Makefile + include $(srcdir)/kexec/arch/s390/Makefile + include $(srcdir)/kexec/arch/sh/Makefile ++include $(srcdir)/kexec/arch/sw_64/Makefile + include $(srcdir)/kexec/arch/x86_64/Makefile + include $(srcdir)/kexec/arch/hppa/Makefile + include $(srcdir)/kexec/arch/loongarch/Makefile +diff --git a/kexec/arch/sw_64/Makefile b/kexec/arch/sw_64/Makefile +new file mode 100644 +index 0000000..753c43c +--- /dev/null ++++ b/kexec/arch/sw_64/Makefile +@@ -0,0 +1,16 @@ ++# ++# 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_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 --git a/kexec/arch/sw_64/crashdump-sw_64.c b/kexec/arch/sw_64/crashdump-sw_64.c +new file mode 100644 +index 0000000..1e8237c +--- /dev/null ++++ b/kexec/arch/sw_64/crashdump-sw_64.c +@@ -0,0 +1,352 @@ +/* + * kexec: Linux boots Linux + * @@ -136,7 +136,7 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/crashdump-sw_64.c kexec-tools-2.0 +struct memory_ranges usablemem_rgns; + +/* Memory region reserved for storing panic kernel and other data. */ -+static struct memory_range crash_reserved_mem; ++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 */ @@ -177,7 +177,7 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/crashdump-sw_64.c kexec-tools-2.0 + 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; +} @@ -317,25 +317,6 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/crashdump-sw_64.c kexec-tools-2.0 + 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, @@ -387,53 +368,14 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/crashdump-sw_64.c kexec-tools-2.0 + 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, ++ data : ELFDATA2LSB, + 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 @@ -447,23 +389,12 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/crashdump-sw_64.c kexec-tools-2.0 + 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; -+ } ++ struct crash_elf_info * elf_info = &elf_info64; + + if (get_kernel_paddr(elf_info)) + return -1; + -+ if (get_kernel_vaddr_and_size(elf_info, start_offset)) ++ if (get_kernel_vaddr_and_size(elf_info, START_OFFSET)) + return -1; + + if (get_crash_memory_ranges(&mem_range, &nr_ranges) < 0) @@ -479,12 +410,9 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/crashdump-sw_64.c kexec-tools-2.0 + 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); ++ if (crash_create_elf64_headers(info, elf_info, crash_memory_range, nr_ranges, ++ &tmp, &sz, ELF_CORE_HEADER_ALIGN) < 0) + return -1; -+ } -+ + elfcorehdr = add_buffer(info, tmp, sz, sz, align, + crash_reserved_mem.start, + crash_reserved_mem.end, -1); @@ -494,7 +422,7 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/crashdump-sw_64.c kexec-tools-2.0 + * kernel's available memory + */ + cmdline_add_mem(mod_cmdline, crash_reserved_mem.start, -+ crash_reserved_mem.end - crash_reserved_mem.start + 1); ++ elfcorehdr - crash_reserved_mem.start); + cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr); + + dbgprintf("CRASH MEMORY RANGES:\n"); @@ -515,73 +443,94 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/crashdump-sw_64.c kexec-tools-2.0 +{ + return parse_iomem_single("Crash kernel\n", start, end); +} -diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/crashdump-sw_64.h kexec-tools-2.0.26-sw/kexec/arch/sw_64/crashdump-sw_64.h ---- kexec-tools-2.0.26/kexec/arch/sw_64/crashdump-sw_64.h 1970-01-01 00:00:00.000000000 +0000 -+++ kexec-tools-2.0.26-sw/kexec/arch/sw_64/crashdump-sw_64.h 2022-08-18 09:22:23.142660576 +0000 -@@ -0,0 +1,23 @@ +diff --git a/kexec/arch/sw_64/crashdump-sw_64.h b/kexec/arch/sw_64/crashdump-sw_64.h +new file mode 100644 +index 0000000..65d92bc +--- /dev/null ++++ b/kexec/arch/sw_64/crashdump-sw_64.h +@@ -0,0 +1,27 @@ +#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 PAGE_OFFSET 0xfff0000000000000UL +#define MAXMEM 0 -+#define __pa(x) ((unsigned long)(X) & 0x7fffffff) ++#define __pa(x) ((unsigned long)(X) & ~PAGE_OFFSET) + + +#define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1) +#define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2) + -+#define COMMAND_LINE_SIZE 512 ++#define COMMAND_LINE_SIZE 2048 + +/* 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) + ++/* Kernel text size */ ++#define SW64_KERNEL_TEXT_SIZE (512UL*1024*1024) ++ +extern struct arch_options_t arch_options; +#endif /* CRASHDUMP_SW_64_H */ -diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/include/arch/options.h kexec-tools-2.0.26-sw/kexec/arch/sw_64/include/arch/options.h ---- kexec-tools-2.0.26/kexec/arch/sw_64/include/arch/options.h 1970-01-01 00:00:00.000000000 +0000 -+++ kexec-tools-2.0.26-sw/kexec/arch/sw_64/include/arch/options.h 2022-08-19 01:48:57.131660708 +0000 -@@ -0,0 +1,30 @@ +diff --git a/kexec/arch/sw_64/include/arch/options.h b/kexec/arch/sw_64/include/arch/options.h +new file mode 100644 +index 0000000..1214d4b +--- /dev/null ++++ b/kexec/arch/sw_64/include/arch/options.h +@@ -0,0 +1,41 @@ +#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) ++#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) + +/* 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 }, ++ KEXEC_OPTIONS \ ++ {"command-line", 1, 0, OPT_APPEND}, \ ++ {"append", 1, 0, OPT_APPEND}, \ ++ {"dtb", 1, 0, OPT_DTB }, \ ++ {"initrd", 1, 0, OPT_RAMDISK }, + + +#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" + -+/* See the other architectures for details of these; Alpha has no -+ * loader-specific options yet. ++/* 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_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.26/kexec/arch/sw_64/kexec-elf-rel-sw_64.c kexec-tools-2.0.26-sw/kexec/arch/sw_64/kexec-elf-rel-sw_64.c ---- kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-rel-sw_64.c 1970-01-01 00:00:00.000000000 +0000 -+++ kexec-tools-2.0.26-sw/kexec/arch/sw_64/kexec-elf-rel-sw_64.c 2022-08-19 01:51:21.131926839 +0000 +diff --git a/kexec/arch/sw_64/kexec-elf-rel-sw_64.c b/kexec/arch/sw_64/kexec-elf-rel-sw_64.c +new file mode 100644 +index 0000000..aeaa966 +--- /dev/null ++++ b/kexec/arch/sw_64/kexec-elf-rel-sw_64.c @@ -0,0 +1,46 @@ +/* -+ * kexec-elf-rel-mips.c - kexec Elf relocation routines ++ * kexec-elf-rel-sw_64.c - kexec Elf relocation routines + * Copyright (C) 2007 Francesco Chiechi, Alessandro Rubini + * Copyright (C) 2007 Tvblob s.r.l. + * @@ -599,10 +548,10 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-rel-sw_64.c kexec-tools + +int machine_verify_elf_rel(struct mem_ehdr *ehdr) +{ -+ if (ehdr->ei_data != ELFDATA2MSB) { ++ if (ehdr->ei_data != ELFDATA2LSB) { + return 0; + } -+ if (ehdr->ei_class != ELFCLASS32) { ++ if (ehdr->ei_class != ELFCLASS64) { + return 0; + } + if (ehdr->e_machine != EM_SW_64) { @@ -626,12 +575,14 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-rel-sw_64.c kexec-tools + } + return; +} -diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-sw_64.c kexec-tools-2.0.26-sw/kexec/arch/sw_64/kexec-elf-sw_64.c ---- kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-sw_64.c 1970-01-01 00:00:00.000000000 +0000 -+++ kexec-tools-2.0.26-sw/kexec/arch/sw_64/kexec-elf-sw_64.c 2022-08-18 09:19:10.592068959 +0000 -@@ -0,0 +1,189 @@ +diff --git a/kexec/arch/sw_64/kexec-elf-sw_64.c b/kexec/arch/sw_64/kexec-elf-sw_64.c +new file mode 100644 +index 0000000..ea99e26 +--- /dev/null ++++ b/kexec/arch/sw_64/kexec-elf-sw_64.c +@@ -0,0 +1,212 @@ +/* -+ * kexec-elf-mips.c - kexec Elf loader for mips ++ * kexec-elf-sw_64.c - kexec Elf loader for sw_64 + * Copyright (C) 2007 Francesco Chiechi, Alessandro Rubini + * Copyright (C) 2007 Tvblob s.r.l. + * @@ -664,6 +615,8 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-sw_64.c kexec-tools-2.0 +#include "../../fs2dt.h" +#include "../../dt-ops.h" + ++extern struct memory_range crash_reserved_mem; ++ +static const int probe_debug = 0; + +#define BOOTLOADER "kexec" @@ -700,6 +653,10 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-sw_64.c kexec-tools-2.0 +{ +} + ++#define INITRD_START_OFFSET 0x100 ++#define INITRD_SIZE_OFFSET 0x108 ++#define COMMAND_LINE_OFFSET 0x1000 ++ +int elf_sw_64_load(int argc, char **argv, const char *buf, off_t len, + struct kexec_info *info) +{ @@ -709,12 +666,19 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-sw_64.c kexec-tools-2.0 + int result; + unsigned long cmdline_addr; + size_t i; -+ off_t dtb_length; -+ char *dtb_buf; ++ off_t dtb_length = 0; ++ //char *dtb_buf = NULL; + char *initrd_buf = NULL; ++ char * param_page = NULL; ++ unsigned long param_page_addr; + unsigned long long kernel_addr = 0, kernel_size = 0; + unsigned long pagesize = getpagesize(); + ++ /* ++ * ZERO_PGE of SW_64, offset is 0x0A000 from CONFIG_PHYSICAL_START ++ */ ++ param_page = xmalloc(pagesize); ++ memset(param_page, 0, pagesize); + /* Need to append some command line parameters internally in case of + * taking crash dumps. + */ @@ -724,7 +688,11 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-sw_64.c kexec-tools-2.0 + } else + crash_cmdline = NULL; + -+ result = build_elf_exec_info(buf, len, &ehdr, 0); ++ if (info->kexec_flags & KEXEC_ON_CRASH) ++ result = build_elf_exec_info(buf, len, &ehdr, 1); ++ else ++ result = build_elf_exec_info(buf, len, &ehdr, 0); ++ + if (result < 0) + die("ELF exec parse failed\n"); + @@ -736,9 +704,11 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-sw_64.c kexec-tools-2.0 + phdr->p_paddr = virt_to_phys(phdr->p_paddr); + kernel_addr = phdr->p_paddr; + kernel_size = phdr->p_memsz; ++ if (!(kernel_size < SW64_KERNEL_TEXT_SIZE)) ++ die("The size of second kernrl is too large, \ ++ reserverd space is not enough!\n"); + } + } -+ + /* Load the Elf data */ + result = elf_exec_load(&ehdr, info); + if (result < 0) @@ -750,8 +720,7 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-sw_64.c kexec-tools-2.0 + 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); ++ result = load_crashdump_segments(info, crash_cmdline, 0, 0); + if (result < 0) { + free(crash_cmdline); + return -1; @@ -761,12 +730,9 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-sw_64.c kexec-tools-2.0 + 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. @@ -776,59 +742,69 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-elf-sw_64.c kexec-tools-2.0 + else + cmdline_addr = 0; + -+ /* MIPS systems that have been converted to use device tree ++ param_page_addr = (unsigned long)info->segment[0].mem - 0x6000; ++ /* sw_64 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 0 + 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)); + } -+ ++#endif + if (arch_options.initrd_file) { + initrd_buf = slurp_file(arch_options.initrd_file, &initrd_size); -+ ++#if 0 + /* 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); -+ ++ dtb_set_initrd(&dtb_buf, &dtb_length, initrd_buf, initrd_buf + initrd_size); ++#endif ++ unsigned long initrd_mem_min = _ALIGN_UP(kernel_addr + kernel_size + dtb_length, pagesize); ++ if (info->kexec_flags & KEXEC_ON_CRASH) ++ initrd_base = add_buffer(info, initrd_buf, initrd_size, ++ initrd_size, sizeof(void *), initrd_mem_min, crash_reserved_mem.end, 1); ++ else ++ initrd_base = add_buffer(info, initrd_buf, initrd_size, ++ initrd_size, sizeof(void *), initrd_mem_min, 0xfffffff, 1); ++ *(unsigned long *)(param_page + INITRD_START_OFFSET) = PAGE_OFFSET + initrd_mem_min; ++ *(unsigned long *)(param_page + INITRD_SIZE_OFFSET) = initrd_size; ++#if 0 + /* 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); ++#endif + } -+ -+ -+ /* This is a legacy method for commandline passing used -+ * currently by Octeon CPUs only */ ++ /* COMMAND_LINE offset 0x1000 from ZERO_PGE */ ++ memcpy(param_page + COMMAND_LINE_OFFSET, cmdline_buf, sizeof(cmdline_buf)); ++ add_buffer(info, param_page, pagesize, pagesize, sizeof(void *), ++ param_page_addr, param_page_addr + pagesize, 1); ++#if 0 + add_buffer(info, cmdline_buf, sizeof(cmdline_buf), + sizeof(cmdline_buf), sizeof(void *), -+ cmdline_addr, 0x0fffffff, 1); ++ cmdline_addr, crash_reserved_mem.end, 1); + + add_buffer(info, dtb_buf, dtb_length, dtb_length, 0, -+ _ALIGN_UP(kernel_addr + kernel_size, pagesize), -+ 0x0fffffff, 1); -+ ++ _ALIGN_UP(kernel_addr + kernel_size, pagesize), ++ crash_reserved_mem.end, 1); ++#endif + return 0; +} + -diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-sw_64.c kexec-tools-2.0.26-sw/kexec/arch/sw_64/kexec-sw_64.c ---- kexec-tools-2.0.26/kexec/arch/sw_64/kexec-sw_64.c 1970-01-01 00:00:00.000000000 +0000 -+++ kexec-tools-2.0.26-sw/kexec/arch/sw_64/kexec-sw_64.c 2022-08-18 09:15:28.891539590 +0000 -@@ -0,0 +1,175 @@ +diff --git a/kexec/arch/sw_64/kexec-sw_64.c b/kexec/arch/sw_64/kexec-sw_64.c +new file mode 100644 +index 0000000..b9fe106 +--- /dev/null ++++ b/kexec/arch/sw_64/kexec-sw_64.c +@@ -0,0 +1,172 @@ +/* + * 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 ++ * derived from ../ppc/kexec-sw_64.c + * Copyright (C) 2004, 2005 Albert Herranz + * + * This source code is licensed under the GNU General Public License, @@ -844,6 +820,7 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-sw_64.c kexec-tools-2.0.26- +#include "../../kexec.h" +#include "../../kexec-syscall.h" +#include "kexec-sw_64.h" ++#include "crashdump-sw_64.h" +#include + +/* Currently not used but required by top-level fs2dt code */ @@ -914,7 +891,6 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-sw_64.c kexec-tools-2.0.26- + " --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" + ); +} + @@ -937,9 +913,6 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-sw_64.c kexec-tools-2.0.26- + 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; @@ -956,9 +929,9 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-sw_64.c kexec-tools-2.0.26- + +const struct arch_map_entry arches[] = { + /* For compatibility with older patches -+ * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_MIPS here. ++ * use KEXEC_ARCH_DEFAULT instead of KEXEC_ARCH_SW_64 here. + */ -+ { "sw_64", KEXEC_ARCH_MIPS }, ++ { "sw_64", KEXEC_ARCH_SW_64 }, + { NULL, 0 }, +}; + @@ -974,7 +947,7 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-sw_64.c kexec-tools-2.0.26- + +unsigned long virt_to_phys(unsigned long addr) +{ -+ return addr & 0x7fffffff; ++ return addr & ~PAGE_OFFSET; +} + +/* @@ -998,9 +971,11 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-sw_64.c kexec-tools-2.0.26- + buf_min, buf_max, buf_end, 1); +} + -diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-sw_64.h kexec-tools-2.0.26-sw/kexec/arch/sw_64/kexec-sw_64.h ---- kexec-tools-2.0.26/kexec/arch/sw_64/kexec-sw_64.h 1970-01-01 00:00:00.000000000 +0000 -+++ kexec-tools-2.0.26-sw/kexec/arch/sw_64/kexec-sw_64.h 2022-08-18 09:10:51.790877939 +0000 +diff --git a/kexec/arch/sw_64/kexec-sw_64.h b/kexec/arch/sw_64/kexec-sw_64.h +new file mode 100644 +index 0000000..1df0bcd +--- /dev/null ++++ b/kexec/arch/sw_64/kexec-sw_64.h @@ -0,0 +1,30 @@ +#ifndef KEXEC_SW_64_H +#define KEXEC_SW_64_H @@ -1032,43 +1007,219 @@ diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/kexec-sw_64.h kexec-tools-2.0.26- +extern off_t initrd_base, initrd_size; + +#endif /* KEXEC_SW_64_H */ -diff -Naru kexec-tools-2.0.26/kexec/arch/sw_64/Makefile kexec-tools-2.0.26-sw/kexec/arch/sw_64/Makefile ---- kexec-tools-2.0.26/kexec/arch/sw_64/Makefile 1970-01-01 00:00:00.000000000 +0000 -+++ kexec-tools-2.0.26-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 +diff --git a/kexec/crashdump.h b/kexec/crashdump.h +index 18bd691..b8a231e 100644 +--- a/kexec/crashdump.h ++++ b/kexec/crashdump.h +@@ -16,6 +16,8 @@ extern int get_xen_vmcoreinfo(uint64_t *addr, uint64_t *len); + */ + #define ELF_CORE_HEADER_ALIGN 1024 + ++#define START_OFFSET 0xfff0000000000000UL + -+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 + /* structure passed to crash_create_elf32/64_headers() */ + + struct crash_elf_info { +diff --git a/kexec/kexec-elf.c b/kexec/kexec-elf.c +index be60bbd..62d8319 100644 +--- a/kexec/kexec-elf.c ++++ b/kexec/kexec-elf.c +@@ -168,7 +168,8 @@ static int build_mem_elf32_ehdr(const char *buf, off_t len, struct mem_ehdr *ehd + return 0; + } + +-static int build_mem_elf64_ehdr(const char *buf, off_t len, struct mem_ehdr *ehdr) ++static int build_mem_elf64_ehdr(const char *buf, off_t len, ++ struct mem_ehdr *ehdr, int64_t offset) + { + Elf64_Ehdr lehdr; + if ((uintmax_t)len < (uintmax_t)sizeof(lehdr)) { +@@ -210,7 +211,7 @@ static int build_mem_elf64_ehdr(const char *buf, off_t len, struct mem_ehdr *ehd + ehdr->e_type = elf16_to_cpu(ehdr, lehdr.e_type); + ehdr->e_machine = elf16_to_cpu(ehdr, lehdr.e_machine); + ehdr->e_version = elf32_to_cpu(ehdr, lehdr.e_version); +- ehdr->e_entry = elf64_to_cpu(ehdr, lehdr.e_entry); ++ ehdr->e_entry = elf64_to_cpu(ehdr, lehdr.e_entry + offset); + ehdr->e_phoff = elf64_to_cpu(ehdr, lehdr.e_phoff); + ehdr->e_shoff = elf64_to_cpu(ehdr, lehdr.e_shoff); + ehdr->e_flags = elf32_to_cpu(ehdr, lehdr.e_flags); +@@ -240,7 +241,8 @@ static int build_mem_elf64_ehdr(const char *buf, off_t len, struct mem_ehdr *ehd + return 0; + } + +-static int build_mem_ehdr(const char *buf, off_t len, struct mem_ehdr *ehdr) ++static int build_mem_ehdr(const char *buf, off_t len, ++ struct mem_ehdr *ehdr, uint64_t offset) + { + unsigned char e_ident[EI_NIDENT]; + int result; +@@ -286,7 +288,7 @@ static int build_mem_ehdr(const char *buf, off_t len, struct mem_ehdr *ehdr) + result = build_mem_elf32_ehdr(buf, len, ehdr); + } + else if (ehdr->ei_class == ELFCLASS64) { +- result = build_mem_elf64_ehdr(buf, len, ehdr); ++ result = build_mem_elf64_ehdr(buf, len, ehdr, offset); + } + if (result < 0) { + return result; +@@ -335,7 +337,8 @@ static int build_mem_elf32_phdr(const char *buf, struct mem_ehdr *ehdr, int idx) + return 0; + } + +-static int build_mem_elf64_phdr(const char *buf, struct mem_ehdr *ehdr, int idx) ++static int build_mem_elf64_phdr(const char *buf, ++ struct mem_ehdr *ehdr, int idx, uint64_t offset) + { + struct mem_phdr *phdr; + const char *pbuf; +@@ -356,8 +359,8 @@ static int build_mem_elf64_phdr(const char *buf, struct mem_ehdr *ehdr, int idx) + } + + phdr->p_type = elf32_to_cpu(ehdr, lphdr.p_type); +- phdr->p_paddr = elf64_to_cpu(ehdr, lphdr.p_paddr); +- phdr->p_vaddr = elf64_to_cpu(ehdr, lphdr.p_vaddr); ++ phdr->p_paddr = elf64_to_cpu(ehdr, lphdr.p_paddr + offset); ++ phdr->p_vaddr = elf64_to_cpu(ehdr, lphdr.p_vaddr + offset); + phdr->p_filesz = elf64_to_cpu(ehdr, lphdr.p_filesz); + phdr->p_memsz = elf64_to_cpu(ehdr, lphdr.p_memsz); + phdr->p_offset = elf64_to_cpu(ehdr, lphdr.p_offset); +@@ -368,7 +371,7 @@ static int build_mem_elf64_phdr(const char *buf, struct mem_ehdr *ehdr, int idx) + } + + static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr, +- uint32_t flags) ++ uint32_t flags, uint64_t offset) + { + size_t phdr_size, mem_phdr_size, i; + +@@ -412,7 +415,7 @@ static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr, + + } + else if (ehdr->ei_class == ELFCLASS64) { +- result = build_mem_elf64_phdr(buf, ehdr, i); ++ result = build_mem_elf64_phdr(buf, ehdr, i, offset); + } + if (result < 0) { + return result; +@@ -515,14 +518,33 @@ static int build_mem_elf32_shdr(const char *buf, struct mem_ehdr *ehdr, int idx) + return 0; + } + +-static int build_mem_elf64_shdr(const char *buf, struct mem_ehdr *ehdr, int idx) ++static int build_mem_elf64_shdr(const char *buf, struct mem_ehdr *ehdr, ++ int idx, uint64_t offset, ++ unsigned long long kernel_start, ++ unsigned long long crash_start) + { + struct mem_shdr *shdr; + const char *sbuf; +- int size_ok; ++ int size_ok, res; + Elf64_Shdr lshdr; ++ uint64_t sh_off, sh_size, *content, count = 1; ++ uint32_t sh_type; + sbuf = buf + ehdr->e_shoff + (idx * sizeof(lshdr)); + shdr = &ehdr->e_shdr[idx]; ++ ++ sh_type = *(unsigned long *)(sbuf + 4); ++ sh_off = *(unsigned long long *)(sbuf + 24); ++ sh_size = *(unsigned long long *)(sbuf + 32); ++ content = (unsigned long long *)(buf + sh_off); ++ if (sh_type == SHT_PROGBITS || sh_type == SHT_SYMTAB) { ++ while (count < (sh_size / 8)) { ++ if (*(content + count) >= kernel_start ++ && *(content + count) < crash_start) ++ *(content + count) += offset; ++ count++; ++ } ++ } + -+sw_64_DT_OPS += kexec/dt-ops.c + memcpy(&lshdr, sbuf, sizeof(lshdr)); + + if ( (elf64_to_cpu(ehdr, lshdr.sh_flags) > UINT64_MAX) || +@@ -585,7 +607,9 @@ static int build_mem_elf64_shdr(const char *buf, struct mem_ehdr *ehdr, int idx) + } + + static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr, +- uint32_t flags) ++ uint32_t flags, uint64_t offset, ++ unsigned long long kernel_start, ++ unsigned long long crash_start) + { + size_t shdr_size, mem_shdr_size, i; + +@@ -625,7 +649,9 @@ static int build_mem_shdrs(const char *buf, off_t len, struct mem_ehdr *ehdr, + result = build_mem_elf32_shdr(buf, ehdr, i); + } + else if (ehdr->ei_class == ELFCLASS64) { +- result = build_mem_elf64_shdr(buf, ehdr, i); ++ result = build_mem_elf64_shdr(buf, ehdr, i, ++ offset, kernel_start, ++ crash_start); + } + if (result < 0) { + return result; +@@ -759,19 +785,52 @@ int build_elf_info(const char *buf, off_t len, struct mem_ehdr *ehdr, + uint32_t flags) + { + int result; +- result = build_mem_ehdr(buf, len, ehdr); ++ const char iomem[] = "/proc/iomem"; ++ char line[160]; ++ uint64_t entry, offset = 0; ++ unsigned long long start, end, kernel_start, crash_start = 0; + -+include $(srcdir)/kexec/libfdt/Makefile.libfdt ++ FILE *io_fp = fopen(iomem, "r"); + -+libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) -+sw_64_CPPFLAGS += -I$(srcdir)/kexec/libfdt -+sw_64_KEXEC_SRCS += $(libfdt_SRCS) ++ if (!io_fp) { ++ fprintf(stderr, "Cannot open %s: %s\n", ++ iomem, strerror(errno)); ++ return -1; ++ } ++ while (fgets(line, sizeof(line), io_fp) != 0) { ++ char *str; ++ int type, consumed, count; + -+sw_64_ADD_BUFFER = -+sw_64_ADD_SEGMENT = -+sw_64_VIRT_TO_PHYS = ++ count = sscanf(line, "%llx-%llx : %n", ++ &start, &end, &consumed); ++ if (count != 2) ++ continue; ++ str = line + consumed; + -+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.26/kexec/kexec-syscall.h kexec-tools-2.0.26-sw/kexec/kexec-syscall.h ---- kexec-tools-2.0.26/kexec/kexec-syscall.h 2020-12-21 08:07:22.000000000 +0000 -+++ kexec-tools-2.0.26-sw/kexec/kexec-syscall.h 2022-08-18 08:44:14.408402498 +0000 -@@ -51,6 +51,9 @@ ++ if (memcmp(str, "Crash kernel\n", 13) == 0 && flags) { ++ crash_start = start + START_OFFSET + 0x10000; ++ break; ++ } ++ } ++ kernel_start = *(unsigned long long *)(buf + 24); ++ if (crash_start != 0) ++ offset = crash_start - kernel_start; ++ ++ flags = 0; ++ result = build_mem_ehdr(buf, len, ehdr, offset); + if (result < 0) { + return result; + } + if ((ehdr->e_phoff > 0) && (ehdr->e_phnum > 0)) { +- result = build_mem_phdrs(buf, len, ehdr, flags); ++ result = build_mem_phdrs(buf, len, ehdr, flags, offset); + if (result < 0) { + free_elf_info(ehdr); + return result; + } + } + if ((ehdr->e_shoff > 0) && (ehdr->e_shnum > 0)) { +- result = build_mem_shdrs(buf, len, ehdr, flags); ++ result = build_mem_shdrs(buf, len, ehdr, flags, ++ offset, kernel_start, crash_start); + if (result < 0) { + free_elf_info(ehdr); + return result; +diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h +index be6ccd5..7d837d5 100644 +--- a/kexec/kexec-syscall.h ++++ b/kexec/kexec-syscall.h +@@ -54,6 +54,9 @@ #ifdef __alpha__ #define __NR_kexec_load 448 #endif @@ -1078,37 +1229,25 @@ diff -Naru kexec-tools-2.0.26/kexec/kexec-syscall.h kexec-tools-2.0.26-sw/kexec/ #ifndef __NR_kexec_load #error Unknown processor architecture. Needs a kexec_load syscall number. #endif -diff -Naru kexec-tools-2.0.26/kexec/Makefile kexec-tools-2.0.26-sw/kexec/Makefile ---- kexec-tools-2.0.26/kexec/Makefile 2021-10-20 09:58:49.000000000 +0000 -+++ kexec-tools-2.0.26-sw/kexec/Makefile 2022-08-18 08:43:24.548411617 +0000 -@@ -92,6 +92,7 @@ - include $(srcdir)/kexec/arch/x86_64/Makefile - include $(srcdir)/kexec/arch/hppa/Makefile - include $(srcdir)/kexec/arch/loongarch/Makefile -+include $(srcdir)/kexec/arch/sw_64/Makefile - - KEXEC_SRCS += $($(ARCH)_KEXEC_SRCS) +@@ -138,6 +141,7 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd, + #define KEXEC_ARCH_MIPS ( 8 << 16) + #define KEXEC_ARCH_CRIS (76 << 16) + #define KEXEC_ARCH_LOONGARCH (258 << 16) ++#define KEXEC_ARCH_SW_64 (0x9916UL << 16) -diff -Naru kexec-tools-2.0.26/purgatory/arch/sw_64/Makefile kexec-tools-2.0.26-sw/purgatory/arch/sw_64/Makefile ---- kexec-tools-2.0.26/purgatory/arch/sw_64/Makefile 1970-01-01 00:00:00.000000000 +0000 -+++ kexec-tools-2.0.26-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.26/purgatory/Makefile kexec-tools-2.0.26-sw/purgatory/Makefile ---- kexec-tools-2.0.26/purgatory/Makefile 2020-12-21 08:07:22.000000000 +0000 -+++ kexec-tools-2.0.26-sw/purgatory/Makefile 2022-08-18 08:45:08.208392658 +0000 -@@ -28,6 +28,7 @@ - include $(srcdir)/purgatory/arch/sh/Makefile - include $(srcdir)/purgatory/arch/x86_64/Makefile - include $(srcdir)/purgatory/arch/loongarch/Makefile -+include $(srcdir)/purgatory/arch/sw_64/Makefile + #define KEXEC_MAX_SEGMENTS 16 - PURGATORY_SRCS+=$($(ARCH)_PURGATORY_SRCS) +diff --git a/kexec/kexec.c b/kexec/kexec.c +index 0e92d96..b75705d 100644 +--- a/kexec/kexec.c ++++ b/kexec/kexec.c +@@ -830,7 +830,8 @@ static int my_load(const char *type, int fileind, int argc, char **argv, + fprintf(stderr, "entry = %p flags = 0x%lx\n", + info.entry, info.kexec_flags); + print_segments(stderr, &info); +- } ++ } else ++ printf("kexec_load success!\n"); + return result; + }