-----Original Message----- > 1. Add mips64_init() implementation, do all necessary machine-specific setup, > which will be called multiple times during initialization. > > 2. Add the implementation of the vtop command, which is used to convert a > virtual address to a physical address. When entering the crash command line, > the corresponding symbols in the kernel will be read, and at the same time, > the conversion of virtual and real addresses will also be used, so the vtop > command is a prerequisite for entering the crash command line. > > 3. Add mips64_get_smp_cpus() implementation, get the number of online cpus. > > 4. Add mips64_get_page_size() implementation, get page size. > > The results after applying patch 01~04 are as follows: > ... > KERNEL: /boot/vmlinux-4.19.161kexec+ > DUMPFILE: /home/tang/vmcore_4.19.161 > CPUS: 4 > DATE: Mon Jan 25 18:54:14 HKT 2021 > UPTIME: (cannot calculate: unknown HZ value) > LOAD AVERAGE: 0.24, 0.21, 0.09 > TASKS: 348 > NODENAME: bogon > RELEASE: 4.19.161kexec+ > VERSION: #15 SMP PREEMPT Mon Jan 25 17:56:16 HKT 2021 > MACHINE: mips64 (unknown Mhz) > MEMORY: 0 > PANIC: "CPU 3 Unable to handle kernel paging request at virtual address 0000000000000000, epc == > ffffffff8085d318, ra == ffffffff8085d308" > PID: 4768 > COMMAND: "bash" > TASK: 9800000243bcf200 [THREAD_INFO: 980000024291c000] > CPU: 3 > STATE: TASK_RUNNING (PANIC) > > crash> > > Signed-off-by: Huacai Chen <chenhuacai@xxxxxxxxxxx> > Signed-off-by: Youling Tang <tangyouling@xxxxxxxxxxx> > --- > mips64.c | 308 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 308 insertions(+) > > diff --git a/mips64.c b/mips64.c > index c3eb03c..21a8206 100644 > --- a/mips64.c > +++ b/mips64.c > @@ -17,11 +17,269 @@ > #include <elf.h> > #include "defs.h" > > +static int mips64_pgd_vtop(ulong *pgd, ulong vaddr, > + physaddr_t *paddr, int verbose); > +static int mips64_uvtop(struct task_context *tc, ulong vaddr, > + physaddr_t *paddr, int verbose); > +static int mips64_kvtop(struct task_context *tc, ulong kvaddr, > + physaddr_t *paddr, int verbose); > + > +/* > + * 3 Levels paging PAGE_SIZE=16KB > + * PGD | PMD | PTE | OFFSET | > + * 11 | 11 | 11 | 14 | > + */ > +/* From arch/mips/include/asm/pgtable{,-64}.h */ > +typedef struct { ulong pgd; } pgd_t; > +typedef struct { ulong pmd; } pmd_t; > +typedef struct { ulong pte; } pte_t; > + > +#define PMD_ORDER 0 > +#define PTE_ORDER 0 > + > +#define PMD_SHIFT (PAGESHIFT() + (PAGESHIFT() + PTE_ORDER - 3)) > +#define PMD_SIZE (1UL << PMD_SHIFT) > +#define PMD_MASK (~(PMD_SIZE - 1)) > + > +#define PGDIR_SHIFT (PMD_SHIFT + (PAGESHIFT() + PMD_ORDER - 3)) > +#define PGDIR_SIZE (1UL << PGDIR_SHIFT) > +#define PGDIR_MASK (~(PGDIR_SIZE - 1)) > + > +#define PTRS_PER_PTE (1UL << (PAGESHIFT() - 3)) > +#define PTRS_PER_PMD PTRS_PER_PTE > +#define PTRS_PER_PGD PTRS_PER_PTE > +#define USER_PTRS_PER_PGD (0x80000000UL/PGDIR_SIZE) > + > +#define pte_index(addr) (((addr) >> PAGESHIFT()) & (PTRS_PER_PTE - 1)) > +#define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) > +#define pgd_index(addr) (((addr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) > + > +#define MIPS64_CPU_RIXI (1UL << 23) /* CPU has TLB Read/eXec Inhibit */ > + > +/* From arch/mips/include/uapi/asm/reg.h */ > +#define MIPS64_EF_R0 0 > +#define MIPS64_EF_R29 29 > +#define MIPS64_EF_R31 31 > +#define MIPS64_EF_LO 32 > +#define MIPS64_EF_HI 33 > +#define MIPS64_EF_CP0_EPC 34 > +#define MIPS64_EF_CP0_BADVADDR 35 > +#define MIPS64_EF_CP0_STATUS 36 > +#define MIPS64_EF_CP0_CAUSE 37 > + > +static struct machine_specific mips64_machine_specific = { 0 }; > + > +/* > + * Holds registers during the crash. > + */ > +static struct mips64_register *panic_task_regs; > + > +/* > + * Virtual to physical memory translation. This function will be called > + * by both mips64_kvtop and mips64_uvtop. > + */ > +static int > +mips64_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose) > +{ > + ulong *pgd_ptr, pgd_val; > + ulong *pmd_ptr, pmd_val; > + ulong *pte_ptr, pte_val; > + > + if (verbose) { > + const char *segment; > + > + if (vaddr < 0x4000000000000000lu) > + segment = "xuseg"; > + else if (vaddr < 0x8000000000000000lu) > + segment = "xsseg"; > + else if (vaddr < 0xc000000000000000lu) > + segment = "xkphys"; > + else if (vaddr < 0xffffffff80000000lu) > + segment = "xkseg"; > + else if (vaddr < 0xffffffffa0000000lu) > + segment = "kseg0"; > + else if (vaddr < 0xffffffffc0000000lu) > + segment = "kseg1"; > + else if (vaddr < 0xffffffffe0000000lu) > + segment = "sseg"; > + else > + segment = "kseg3"; > + > + fprintf(fp, "SEGMENT: %s\n", segment); > + } > + > + if (IS_CKPHYS(vaddr) || IS_XKPHYS(vaddr)) { > + *paddr = VTOP(vaddr); > + return TRUE; > + } > + > + if (verbose) > + fprintf(fp, "PAGE DIRECTORY: %016lx\n", (ulong)pgd); > + > + pgd_ptr = pgd + pgd_index(vaddr); > + FILL_PGD(PAGEBASE(pgd), KVADDR, PAGESIZE()); > + pgd_val = ULONG(machdep->pgd + PAGEOFFSET(pgd_ptr)); > + if (verbose) > + fprintf(fp, " PGD: %16lx => %16lx\n", (ulong)pgd_ptr, pgd_val); > + if (!pgd_val) > + goto no_page; > + > + pmd_ptr = (ulong *)(VTOP(pgd_val) + sizeof(pmd_t) * pmd_index(vaddr)); > + FILL_PMD(PAGEBASE(pmd_ptr), PHYSADDR, PAGESIZE()); > + pmd_val = ULONG(machdep->pmd + PAGEOFFSET(pmd_ptr)); > + if (verbose) > + fprintf(fp, " PMD: %016lx => %016lx\n", (ulong)pmd_ptr, pmd_val); > + if (!pmd_val) > + goto no_page; > + > + pte_ptr = (ulong *)(VTOP(pmd_val) + sizeof(pte_t) * pte_index(vaddr)); > + FILL_PTBL(PAGEBASE(pte_ptr), PHYSADDR, PAGESIZE()); > + pte_val = ULONG(machdep->ptbl + PAGEOFFSET(pte_ptr)); > + if (verbose) > + fprintf(fp, " PTE: %016lx => %016lx\n", (ulong)pte_ptr, pte_val); > + if (!pte_val) > + goto no_page; > + > + return TRUE; > +no_page: > + fprintf(fp, "invalid\n"); > + return FALSE; > +} > + > +/* Translates a user virtual address to its physical address. cmd_vtop() sets > + * the verbose flag so that the pte translation gets displayed; all other > + * callers quietly accept the translation. > + */ > +static int > +mips64_uvtop(struct task_context *tc, ulong vaddr, physaddr_t *paddr, int verbose) > +{ > + ulong mm, active_mm; > + ulong *pgd; > + > + if (!tc) > + error(FATAL, "current context invalid\n"); > + > + *paddr = 0; > + > + if (is_kernel_thread(tc->task) && IS_KVADDR(vaddr)) { > + if (VALID_MEMBER(thread_struct_pg_tables)) > + pgd = (ulong *)machdep->get_task_pgd(tc->task); The machdep->get_task_pgd is not set in this patchset? MIPS defines this: static ulong mips_get_task_pgd(ulong task) { return error(FATAL, "%s: not implemented\n", __func__); } Thanks, Kazu > + else { > + if (INVALID_MEMBER(task_struct_active_mm)) > + error(FATAL, "no pg_tables or active_mm?\n"); > + > + readmem(tc->task + OFFSET(task_struct_active_mm), > + KVADDR, &active_mm, sizeof(void *), > + "task active_mm contents", FAULT_ON_ERROR); > + > + if (!active_mm) > + error(FATAL, > + "no active_mm for this kernel thread\n"); > + > + readmem(active_mm + OFFSET(mm_struct_pgd), > + KVADDR, &pgd, sizeof(long), > + "mm_struct pgd", FAULT_ON_ERROR); > + } > + } else { > + if ((mm = task_mm(tc->task, TRUE))) > + pgd = ULONG_PTR(tt->mm_struct + OFFSET(mm_struct_pgd)); > + else > + readmem(tc->mm_struct + OFFSET(mm_struct_pgd), > + KVADDR, &pgd, sizeof(long), "mm_struct pgd", > + FAULT_ON_ERROR); > + } > + > + return mips64_pgd_vtop(pgd, vaddr, paddr, verbose);; > +} > + > +/* Translates a user virtual address to its physical address. cmd_vtop() sets > + * the verbose flag so that the pte translation gets displayed; all other > + * callers quietly accept the translation. > + */ > +static int > +mips64_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbose) > +{ > + if (!IS_KVADDR(kvaddr)) > + return FALSE; > + > + if (!verbose) { > + if (IS_CKPHYS(kvaddr) || IS_XKPHYS(kvaddr)) { > + *paddr = VTOP(kvaddr); > + return TRUE; > + } > + } > + > + return mips64_pgd_vtop((ulong *)vt->kernel_pgd[0], kvaddr, paddr, > + verbose); > +} > + > +/* > + * Accept or reject a symbol from the kernel namelist. > + */ > +static int > +mips64_verify_symbol(const char *name, ulong value, char type) > +{ > + return TRUE; > +} > + > +/* > + * Override smp_num_cpus if possible and necessary. > + */ > +static int > +mips64_get_smp_cpus(void) > +{ > + return (get_cpus_online() > 0) ? get_cpus_online() : kt->cpus; > +} > + > +static ulong > +mips64_get_page_size(void) > +{ > + return memory_page_size(); > +} > + > +/* > + * Determine where vmalloc'd memory starts. > + */ > +static ulong > +mips64_vmalloc_start(void) > +{ > + return 0; > +} > + > +static ulong > +mips64_processor_speed(void) > +{ > + return 0; > +} > + > +/* > + * Checks whether given task is valid task address. > + */ > +static int > +mips64_is_task_addr(ulong task) > +{ > + if (tt->flags & THREAD_INFO) > + return IS_KVADDR(task); > + > + return (IS_KVADDR(task) && ALIGNED_STACK_OFFSET(task) == 0); > +} > + > void > mips64_dump_machdep_table(ulong arg) > { > } > > +static void > +pt_level_alloc(char **lvl, char *name) > +{ > + size_t sz = PAGESIZE(); > + void *pointer = malloc(sz); > + > + if (!pointer) > + error(FATAL, name); > + *lvl = pointer; > +} > + > /* > * Do all necessary machine-specific setup here. This is called several > * times during initialization. > @@ -33,6 +291,56 @@ mips64_init(int when) > case SETUP_ENV: > machdep->process_elf_notes = process_elf64_notes; > break; > + > + case PRE_SYMTAB: > + machdep->verify_symbol = mips64_verify_symbol; > + machdep->machspec = &mips64_machine_specific; > + if (pc->flags & KERNEL_DEBUG_QUERY) > + return; > + machdep->last_pgd_read = 0; > + machdep->last_pmd_read = 0; > + machdep->last_ptbl_read = 0; > + machdep->verify_paddr = generic_verify_paddr; > + machdep->ptrs_per_pgd = PTRS_PER_PGD; > + break; > + > + case PRE_GDB: > + machdep->pagesize = mips64_get_page_size(); > + machdep->pageshift = ffs(machdep->pagesize) - 1; > + machdep->pageoffset = machdep->pagesize - 1; > + machdep->pagemask = ~((ulonglong)machdep->pageoffset); > + if (machdep->pagesize >= 16384) > + machdep->stacksize = machdep->pagesize; > + else > + machdep->stacksize = machdep->pagesize * 2; > + > + pt_level_alloc(&machdep->pgd, "cannot malloc pgd space."); > + pt_level_alloc(&machdep->pmd, "cannot malloc pmd space."); > + pt_level_alloc(&machdep->ptbl, "cannot malloc ptbl space."); > + machdep->kvbase = 0x8000000000000000lu; > + machdep->identity_map_base = machdep->kvbase; > + machdep->is_kvaddr = generic_is_kvaddr; > + machdep->is_uvaddr = generic_is_uvaddr; > + machdep->uvtop = mips64_uvtop; > + machdep->kvtop = mips64_kvtop; > + machdep->vmalloc_start = mips64_vmalloc_start; > + machdep->processor_speed = mips64_processor_speed; > + machdep->get_stackbase = generic_get_stackbase; > + machdep->get_stacktop = generic_get_stacktop; > + machdep->memory_size = generic_memory_size; > + machdep->is_task_addr = mips64_is_task_addr; > + machdep->get_smp_cpus = mips64_get_smp_cpus; > + machdep->value_to_symbol = generic_machdep_value_to_symbol; > + machdep->init_kernel_pgd = NULL; > + break; > + > + case POST_GDB: > + machdep->section_size_bits = _SECTION_SIZE_BITS; > + machdep->max_physmem_bits = _MAX_PHYSMEM_BITS; > + break; > + > + case POST_VM: > + break; > } > } > > -- > 2.1.0 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility