-----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 <chenhua...@loongson.cn>
> Signed-off-by: Youling Tang <tangyoul...@loongson.cn>
> ---
>  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@redhat.com
https://listman.redhat.com/mailman/listinfo/crash-utility

Reply via email to