Patch adds support for LoongArch64 in makedumpfile. It takes care of
vmalloc, module and directly map kernel memory region's translation.
Currently we only support 3 leverl 16K pages and VA_BITS as 48.

The changes were tested on a LoongArch64 Loongson-3A5000 processor.
The dump compression and filtering (for all dump levels 1,2,4,8,16
and 31) tests are succussfull.

Signed-off-by: Youling Tang <[email protected]>
---
Note: kexec/kdump support patch see link [1]:
[1] Link: 
https://lore.kernel.org/loongarch/[email protected]/T/#t

 Makefile           |   2 +-
 arch/loongarch64.c | 113 +++++++++++++++++++++++++++++++++++++++++++++
 makedumpfile.h     |  58 +++++++++++++++++++++++
 3 files changed, 172 insertions(+), 1 deletion(-)
 create mode 100644 arch/loongarch64.c

diff --git a/Makefile b/Makefile
index 370a97c..e07f466 100644
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@ endif
 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
+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
 OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH))
 
 LIBS = -ldw -lbz2 -ldl -lelf -lz
diff --git a/arch/loongarch64.c b/arch/loongarch64.c
new file mode 100644
index 0000000..42a02ab
--- /dev/null
+++ b/arch/loongarch64.c
@@ -0,0 +1,113 @@
+/*
+ * loongarch64.c
+ *
+ * Copyright (C) 2022 Loongson Technology Corporation Limited
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ */
+#ifdef __loongarch64__
+
+#include "../print_info.h"
+#include "../elf_info.h"
+#include "../makedumpfile.h"
+
+int
+get_phys_base_loongarch64(void)
+{
+       info->phys_base = 0ULL;
+
+       DEBUG_MSG("phys_base    : %lx\n", info->phys_base);
+
+       return TRUE;
+}
+
+int
+get_machdep_info_loongarch64(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;
+
+       /* Check if we can get SECTION_SIZE_BITS from vmcoreinfo */
+       if (NUMBER(SECTION_SIZE_BITS) != NOT_FOUND_NUMBER)
+               info->section_size_bits = NUMBER(SECTION_SIZE_BITS);
+       else
+               info->section_size_bits = _SECTION_SIZE_BITS;
+
+       DEBUG_MSG("max_physmem_bits : %ld\n", info->max_physmem_bits);
+       DEBUG_MSG("section_size_bits: %ld\n", info->section_size_bits);
+
+       return TRUE;
+}
+
+int
+get_versiondep_info_loongarch64(void)
+{
+       info->page_offset  = _PAGE_OFFSET;
+
+       DEBUG_MSG("page_offset : %lx\n", info->page_offset);
+
+       return TRUE;
+}
+
+unsigned long long
+vaddr_to_paddr_loongarch64(unsigned long vaddr)
+{
+       unsigned long long paddr = NOT_PADDR;
+       pgd_t *pgda, pgdv;
+       pmd_t *pmda, pmdv;
+       pte_t *ptea, ptev;
+
+       if (vaddr >= _XKPRANGE && vaddr < _XKVRANGE)
+               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(VADDR, (unsigned long long)pgda, &pgdv, sizeof(pgdv))) {
+               ERRMSG("Can't read pgd\n");
+               return NOT_PADDR;
+       }
+
+       pmda = pmd_offset(&pgdv, vaddr);
+       if (!readmem(VADDR, (unsigned long long)pmda, &pmdv, sizeof(pmdv))) {
+               ERRMSG("Can't read pmd\n");
+               return NOT_PADDR;
+       }
+
+       if (pmdv & _PAGE_HUGE) {
+               paddr = (pmdv & PMD_MASK) + (vaddr & (PMD_SIZE - 1));
+               return paddr;
+       }
+
+       ptea = pte_offset(&pmdv, vaddr);
+       if (!readmem(VADDR, (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;
+       }
+
+       paddr = PAGEBASE(ptev) + (vaddr & (PAGESIZE() - 1));
+       return paddr;
+}
+
+#endif /* loongarch64 */
diff --git a/makedumpfile.h b/makedumpfile.h
index 49b9242..a70b1de 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -1013,6 +1013,42 @@ typedef unsigned long pgd_t;
 
 #endif         /* mips64 */
 
+#ifdef __loongarch64__
+#define KVBASE                 (0x8000000000000000ULL)
+#define _PAGE_OFFSET           (0x9000000000000000ULL)
+#define _XKPRANGE              (0x8000000000000000ULL)
+#define _XKVRANGE              (0xc000000000000000ULL)
+#define _SECTION_SIZE_BITS     (29)
+#define _MAX_PHYSMEM_BITS      (48)
+#define _PAGE_HUGE             (1 << 6) /* HUGE is a PMD bit */
+#define _PAGE_PRESENT          (1 << 7)
+
+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          /* loongarch64 */
+
 /*
  * The function of dependence on machine
  */
@@ -1184,6 +1220,22 @@ unsigned long long vaddr_to_paddr_mips64(unsigned long 
vaddr);
 #define arch_crashkernel_mem_size()    stub_false()
 #endif         /* mips64 */
 
+#ifdef __loongarch64__ /* loongarch64 */
+int get_phys_base_loongarch64(void);
+int get_machdep_info_loongarch64(void);
+int get_versiondep_info_loongarch64(void);
+unsigned long long vaddr_to_paddr_loongarch64(unsigned long vaddr);
+#define find_vmemmap()         stub_false()
+#define get_phys_base()                get_phys_base_loongarch64()
+#define get_machdep_info()     get_machdep_info_loongarch64()
+#define get_versiondep_info()   get_versiondep_info_loongarch64()
+#define get_kaslr_offset(X)    stub_false()
+#define vaddr_to_paddr(X)       vaddr_to_paddr_loongarch64(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         /* loongarch64 */
+
 typedef unsigned long long mdf_pfn_t;
 
 #ifndef ARCH_PFN_OFFSET
@@ -2318,6 +2370,12 @@ int get_xen_info_ia64(void);
 #define get_xen_info_arch(X) FALSE
 #endif /* mips64 */
 
+#ifdef __loongarch64__ /* loongarch64 */
+#define kvtop_xen(X)   FALSE
+#define get_xen_basic_info_arch(X) FALSE
+#define get_xen_info_arch(X) FALSE
+#endif /* loongarch64 */
+
 struct cycle {
        mdf_pfn_t start_pfn;
        mdf_pfn_t end_pfn;
-- 
2.36.0


_______________________________________________
kexec mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/kexec

Reply via email to