(2012/02/20 20:06), Suzuki K. Poulose wrote:
> This patch adds infrastructure for defining Virtual address translation bits
> for each platform and use the specific definition for the platform depending 
> on
> the 'powerpc_base_platform' variable. If a matching platform is not found,
> fallbacks to the default definition.
> 
> Each platform can define a probe function which can identify the 'kernel
> platform string' to one of its variant. It can then update PGDIR_SHIFT,
> PTRS_PER_PGD, PTRS_PER_PTE, the size of a PTE and also the various Page flags.
> 
> This patch also changes the pte to ulonglong type.
> 
> mach command now displays the platform string read from the kernel.
> 
> crash>  mach
>         MACHINE TYPE: ppc
>             PLATFORM: ppc440gp
>          MEMORY SIZE: 128 MB
>       ...
> 
> Signed-off-by: Suzuki K. Poulose<[email protected]>
> ---
> 
>   defs.h |   82 ++++++++++++++++++++++++++++++++++---------
>   ppc.c  |  123 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
>   2 files changed, 171 insertions(+), 34 deletions(-)
> 
> diff --git a/defs.h b/defs.h
> index a942dbb..0c5558e 100755
> --- a/defs.h
> +++ b/defs.h
> @@ -2635,27 +2635,50 @@ struct load_module {
>   #define _32BIT_
>   #define MACHINE_TYPE       "PPC"
> 
> -#define PAGEBASE(X)  (((ulong)(X))&  (ulong)machdep->pagemask)
> +#define PAGEBASE(X)          ((X)&  machdep->pagemask)
> 
>   #define PTOV(X)            ((unsigned long)(X)+(machdep->kvbase))
>   #define VTOP(X)            ((unsigned long)(X)-(machdep->kvbase))
>   #define IS_VMALLOC_ADDR(X) (vt->vmalloc_start&&  (ulong)(X)>= 
> vt->vmalloc_start)
> 
> -#define PGDIR_SHIFT   (22)
> -#define PTRS_PER_PTE  (1024)
> -#define PTRS_PER_PGD  (1024)
> -
> -#define _PAGE_PRESENT   0x001   /* software: pte contains a translation */
> -#define _PAGE_USER      0x002   /* matches one of the PP bits */
> -#define _PAGE_RW        0x004   /* software: user write access allowed */
> -#define _PAGE_GUARDED   0x008
> -#define _PAGE_COHERENT  0x010   /* M: enforce memory coherence (SMP systems) 
> */
> -#define _PAGE_NO_CACHE  0x020   /* I: cache inhibit */
> -#define _PAGE_WRITETHRU 0x040   /* W: cache write-through */
> -#define _PAGE_DIRTY     0x080   /* C: page changed */
> -#define _PAGE_ACCESSED  0x100   /* R: page referenced */
> -#define _PAGE_HWWRITE   0x200   /* software: _PAGE_RW&  _PAGE_DIRTY */
> -#define _PAGE_SHARED    0
> +/* Page translation bits */
> +#define PPC_PLATFORM         (machdep->machspec->platform)
> +#define PGDIR_SHIFT          (machdep->machspec->pgdir_shift)
> +#define PTRS_PER_PTE         (machdep->machspec->ptrs_per_pte)
> +#define PTRS_PER_PGD         (machdep->machspec->ptrs_per_pgd)
> +#define PTE_SIZE             (machdep->machspec->pte_size)
> +
> +/* Default values for Page translation */
> +#define DEFAULT_PGDIR_SHIFT  (22)
> +#define DEFAULT_PTRS_PER_PTE (1024)
> +#define DEFAULT_PTRS_PER_PGD (1024)
> +#define DEFAULT_PTE_SIZE     sizeof(ulong)
> +
> +/* PAGE flags */
> +#define _PAGE_PRESENT   (machdep->machspec->_page_present)   /* software: 
> pte contains a translation */
> +#define _PAGE_USER      (machdep->machspec->_page_user)              /* 
> matches one of the PP bits */
> +#define _PAGE_RW        (machdep->machspec->_page_rw)                /* 
> software: user write access allowed */
> +#define _PAGE_GUARDED   (machdep->machspec->_page_guarded)
> +#define _PAGE_COHERENT  (machdep->machspec->_page_coherent   /* M: enforce 
> memory coherence (SMP systems) */)
> +#define _PAGE_NO_CACHE  (machdep->machspec->_page_no_cache)  /* I: cache 
> inhibit */
> +#define _PAGE_WRITETHRU (machdep->machspec->_page_writethru) /* W: cache 
> write-through */
> +#define _PAGE_DIRTY     (machdep->machspec->_page_dirty)     /* C: page 
> changed */
> +#define _PAGE_ACCESSED  (machdep->machspec->_page_accessed)  /* R: page 
> referenced */
> +#define _PAGE_HWWRITE   (machdep->machspec->_page_hwwrite)   /* software: 
> _PAGE_RW&  _PAGE_DIRTY */
> +#define _PAGE_SHARED    (machdep->machspec->_page_shared)
> +
> +/* Default values for PAGE flags */
> +#define DEFAULT_PAGE_PRESENT   0x001
> +#define DEFAULT_PAGE_USER      0x002
> +#define DEFAULT_PAGE_RW        0x004
> +#define DEFAULT_PAGE_GUARDED   0x008
> +#define DEFAULT_PAGE_COHERENT  0x010
> +#define DEFAULT_PAGE_NO_CACHE  0x020
> +#define DEFAULT_PAGE_WRITETHRU 0x040
> +#define DEFAULT_PAGE_DIRTY     0x080
> +#define DEFAULT_PAGE_ACCESSED  0x100
> +#define DEFAULT_PAGE_HWWRITE   0x200
> +#define DEFAULT_PAGE_SHARED    0
> 
>   #define SWP_TYPE(entry) (((entry)>>  1)&  0x7f)
>   #define SWP_OFFSET(entry) ((entry)>>  8)
> @@ -4533,6 +4556,33 @@ void ppc64_dump_machdep_table(ulong);
>    *  ppc.c
>    */
>   #ifdef PPC
> +
> +/* Holds the platform specific info for page translation */
> +struct machine_specific {
> +
> +     char *platform;
> +
> +     /* page address translation bits */
> +     int pgdir_shift;
> +     int ptrs_per_pgd;
> +     int ptrs_per_pte;
> +     int pte_size;
> +
> +     /* page flags */
> +     ulong _page_present;
> +     ulong _page_user;
> +     ulong _page_rw;
> +     ulong _page_guarded;
> +     ulong _page_coherent;
> +     ulong _page_no_cache;
> +     ulong _page_writethru;
> +     ulong _page_dirty;
> +     ulong _page_accessed;
> +     ulong _page_hwwrite;
> +     ulong _page_shared;
> +
> +};
> +     
>   void ppc_init(int);
>   void ppc_dump_machdep_table(ulong);
>   #define display_idt_table() \
> diff --git a/ppc.c b/ppc.c
> index 3834e7f..9f765b6 100755
> --- a/ppc.c
> +++ b/ppc.c
> @@ -17,6 +17,9 @@
>   #ifdef PPC
>   #include "defs.h"
> 
> +
> +#define MAX_PLATFORM_LEN     32      /* length for platform string */
> +
>   /*
>    *  This structure was copied from kernel source
>    *  in include/asm-ppc/ptrace.h
> @@ -67,6 +70,71 @@ static void ppc_display_machine_stats(void);
>   static void ppc_dump_line_number(ulong);
>   static struct line_number_hook ppc_line_number_hooks[];
> 
> +
> +static struct machine_specific ppc_machine_specific = { 0 };
> +static int probe_default_platform(char *);
> +static void ppc_probe_base_platform(void);
> +
> +typedef int (*probe_func_t) (char *);
> +
> +probe_func_t probe_platforms[] = {
> +     probe_default_platform, /* This should be at the end */
> +     NULL
> +};
> +
> +static int
> +probe_default_platform(char *name)
> +{
> +     struct machine_specific *machspec = machdep->machspec;
> +
> +     /* Use the default definitions */
> +     machspec->platform = strdup(name);
> +
> +     machspec->pgdir_shift   = DEFAULT_PGDIR_SHIFT;
> +     machspec->ptrs_per_pgd  = DEFAULT_PTRS_PER_PGD;
> +     machspec->ptrs_per_pte  = DEFAULT_PTRS_PER_PTE;
> +     machspec->pte_size      = DEFAULT_PTE_SIZE;
> +
> +     machspec->_page_present         = DEFAULT_PAGE_PRESENT;
> +     machspec->_page_user            = DEFAULT_PAGE_USER;
> +     machspec->_page_rw              = DEFAULT_PAGE_RW;
> +     machspec->_page_guarded         = DEFAULT_PAGE_GUARDED;
> +     machspec->_page_coherent        = DEFAULT_PAGE_COHERENT;
> +     machspec->_page_no_cache        = DEFAULT_PAGE_NO_CACHE;
> +     machspec->_page_writethru       = DEFAULT_PAGE_WRITETHRU;
> +     machspec->_page_dirty           = DEFAULT_PAGE_DIRTY;
> +     machspec->_page_accessed        = DEFAULT_PAGE_ACCESSED;
> +     machspec->_page_hwwrite         = DEFAULT_PAGE_HWWRITE;
> +     machspec->_page_shared          = DEFAULT_PAGE_SHARED;
> +     
> +
> +     return TRUE;
> +}
> +
> +/*
> + * Find the platform of the crashing system and set the
> + * base_platform accordingly.
> + */
> +void
> +ppc_probe_base_platform(void)
> +{
> +     probe_func_t probe;
> +     char platform_name[MAX_PLATFORM_LEN];
> +     ulong ptr;
> +     int i;
> +
> +     if(!try_get_symbol_data("powerpc_base_platform", sizeof(ulong),&ptr) ||
> +             read_string(ptr, platform_name, MAX_PLATFORM_LEN - 1) == 0)
> +             /* Let us fallback to default definitions */
> +             platform_name[0] = '\0';

Could you give some fallback message at PLATFORM: via 'mach' command
like "undetectable" or any good phrase?

> +     for (i = 0; probe_platforms[i] != NULL; i++) {
> +             probe = probe_platforms[i];
> +             if (probe(platform_name))
> +                     break;
> +     }
> +}
> +
>   /*
>    *  Do all necessary machine-specific setup here.  This is called twice,
>    *  before and after GDB has been initialized.
> @@ -80,6 +148,7 @@ ppc_init(int when)
>       switch (when)
>       {
>       case SETUP_ENV:
> +             machdep->machspec =&ppc_machine_specific;
>               machdep->process_elf_notes = process_elf32_notes;
>               break;
> 
> @@ -101,7 +170,6 @@ ppc_init(int when)
>                   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:
> @@ -127,6 +195,11 @@ ppc_init(int when)
>               machdep->line_number_hooks = ppc_line_number_hooks;
>               machdep->value_to_symbol = generic_machdep_value_to_symbol;
>                   machdep->init_kernel_pgd = NULL;
> +
> +             /* Find the platform where we crashed */
> +             ppc_probe_base_platform();
> +             machdep->ptrs_per_pgd = PTRS_PER_PGD;
> +
>               break;
> 
>       case POST_GDB:
> @@ -201,6 +274,7 @@ ppc_dump_machdep_table(ulong arg)
>           int others;
> 
>           others = 0;
> +     fprintf(fp, "           platform: %s\n", PPC_PLATFORM);
>           fprintf(fp, "              flags: %lx (", machdep->flags);
>       if (machdep->flags&  KSYMS_START)
>               fprintf(fp, "%sKSYMS_START", others++ ? "|" : "");
> @@ -212,6 +286,10 @@ ppc_dump_machdep_table(ulong arg)
>           fprintf(fp, "          pageshift: %d\n", machdep->pageshift);
>           fprintf(fp, "           pagemask: %llx\n", machdep->pagemask);
>           fprintf(fp, "         pageoffset: %lx\n", machdep->pageoffset);
> +     fprintf(fp, "        pgdir_shift: %d\n", PGDIR_SHIFT);
> +     fprintf(fp, "       ptrs_per_pgd: %d\n", PTRS_PER_PGD);
> +     fprintf(fp, "       ptrs_per_pte: %d\n", PTRS_PER_PTE);
> +     fprintf(fp, "           pte_size: %d\n", PTE_SIZE);
>       fprintf(fp, "          stacksize: %ld\n", machdep->stacksize);
>           fprintf(fp, "                 hz: %d\n", machdep->hz);
>           fprintf(fp, "                mhz: %ld\n", machdep->mhz);
> @@ -252,7 +330,6 @@ ppc_dump_machdep_table(ulong arg)
>           fprintf(fp, "                pgd: %lx\n", (ulong)machdep->pgd);
>           fprintf(fp, "                pmd: %lx\n", (ulong)machdep->pmd);
>           fprintf(fp, "               ptbl: %lx\n", (ulong)machdep->ptbl);
> -     fprintf(fp, "       ptrs_per_pgd: %d\n", machdep->ptrs_per_pgd);
>           fprintf(fp, "  section_size_bits: %ld\n", 
> machdep->section_size_bits);
>           fprintf(fp, "   max_physmem_bits: %ld\n", 
> machdep->max_physmem_bits);
>           fprintf(fp, "  sections_per_root: %ld\n", 
> machdep->sections_per_root);
> @@ -266,15 +343,20 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t 
> *paddr, int verbose)
>       ulong *page_middle;
>       ulong *page_table;
>       ulong pgd_pte;
> -     ulong pte;
> +     ulonglong pte;
> 
> -     if (verbose)
> +     if (verbose)
>               fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
> 
>       page_dir = pgd + (vaddr>>  PGDIR_SHIFT);
> 
> -        FILL_PGD(PAGEBASE(pgd), KVADDR, PAGESIZE());
> -        pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir));
> +     /*
> +      * Size of a pgd could be more than a PAGE.
> +      * So use PAGEBASE(page_dir), instead of
> +      * PAGEBASE(pgd) for FILL_PGD()
> +      */
> +        FILL_PGD(PAGEBASE((ulong)page_dir), KVADDR, PAGESIZE());
> +        pgd_pte = ULONG(machdep->pgd + PAGEOFFSET((ulong)page_dir));
> 
>       if (verbose)
>               fprintf(fp, "  PGD: %lx =>  %lx\n", (ulong)page_dir, pgd_pte);
> @@ -285,33 +367,37 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t 
> *paddr, int verbose)
>       page_middle = (ulong *)pgd_pte;
> 
>       if (machdep->flags&  CPU_BOOKE)
> -             page_table = page_middle + (BTOP(vaddr)&  (PTRS_PER_PTE - 1));
> +             page_table = (ulong *)((ulong)page_middle + 
> ((ulong)BTOP(vaddr)&  (PTRS_PER_PTE - 1)) * PTE_SIZE);
>       else {
>               page_table = (ulong *)((pgd_pte&  (ulong)machdep->pagemask) + 
> machdep->kvbase);
> -             page_table += ((ulong)BTOP(vaddr)&  (PTRS_PER_PTE-1));
> +             page_table = (ulong *)((ulong)page_table + ((ulong)BTOP(vaddr)& 
>  (PTRS_PER_PTE-1)) * PTE_SIZE);
>       }
> 
>       if (verbose)
>               fprintf(fp, "  PMD: %lx =>  %lx\n", (ulong)page_middle,
>                       (ulong)page_table);
> 
> -        FILL_PTBL(PAGEBASE(page_table), KVADDR, PAGESIZE());
> -        pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table));
> +        FILL_PTBL(PAGEBASE((ulong)page_table), KVADDR, PAGESIZE());
> +     if (PTE_SIZE == sizeof(ulonglong))
> +             pte = ULONGLONG(machdep->ptbl + PAGEOFFSET((ulong)page_table));
> +
> +     else    /* Defaults to ulong */
> +             pte = ULONG(machdep->ptbl + PAGEOFFSET((ulong)page_table));
> 
>       if (verbose)
> -             fprintf(fp, "  PTE: %lx =>  %lx\n", (ulong)page_table, pte);
> +             fprintf(fp, "  PTE: %lx =>  %llx\n", (ulong)page_table, pte);
> 
>       if (!(pte&  _PAGE_PRESENT)) {
>               if (pte&&  verbose) {
>                       fprintf(fp, "\n");
> -                     ppc_translate_pte(pte, 0, 0);
> +                     ppc_translate_pte(0, 0, pte);
>               }
>               goto no_page;
>       }
> 
>       if (verbose) {
> -             fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(pte));
> -             ppc_translate_pte(pte, 0, 0);
> +             fprintf(fp, " PAGE: %llx\n\n", PAGEBASE(pte));
> +             ppc_translate_pte(0, 0, pte);
>       }
> 
>       *paddr = PAGEBASE(pte) + PAGEOFFSET(vaddr);
> @@ -623,7 +709,7 @@ ppc_get_task_pgd(ulong task)
>    *  If a physaddr pointer is passed in, don't print anything.
>    */
>   static int
> -ppc_translate_pte(ulong pte, void *physaddr, ulonglong unused)
> +ppc_translate_pte(ulong unused, void *physaddr, ulonglong pte)

This change may gives impacts for existing machdep->translate_pte() users
whose external modules are possible to call with legacy prototype
machdep->translate_pte(pte, physaddr, unused) for 32bit pte.
A "unused" should be used for extended 64bit pte support in addition to
first 32bit pte support.

I think it is better for everyone to mark machdep->flags with PAE at PATCH3/4.
Maybe PAE is named for x86 but there are no differences in terms of flag 
handling.

Then declare ppc_translate_pte(ulong pte32, void *physaddr, ulonglong pte64)
so that ppc_pgd_vtop() can call with ppc_translate_pte((ulong)pte, NULL, pte)
and external users can also select similar way.

Thanks,
Toshi

>   {
>       int c, len1, len2, len3, others, page_present;
>       char buf[BUFSIZE];
> @@ -632,7 +718,7 @@ ppc_translate_pte(ulong pte, void *physaddr, ulonglong 
> unused)
>       char ptebuf[BUFSIZE];
>       char physbuf[BUFSIZE];
>           char *arglist[MAXARGS];
> -     ulong paddr;
> +     ulonglong paddr;
> 
>           paddr = PAGEBASE(pte);
>       page_present = (pte&  _PAGE_PRESENT);
> @@ -642,7 +728,7 @@ ppc_translate_pte(ulong pte, void *physaddr, ulonglong 
> unused)
>               return page_present;
>       }
> 
> -     sprintf(ptebuf, "%lx", pte);
> +     sprintf(ptebuf, "%llx", pte);
>       len1 = MAX(strlen(ptebuf), strlen("PTE"));
>       fprintf(fp, "%s  ", mkstring(buf, len1, CENTER|LJUST, "PTE"));
> 
> @@ -668,7 +754,7 @@ ppc_translate_pte(ulong pte, void *physaddr, ulonglong 
> unused)
>                   return page_present;
>           }
> 
> -     sprintf(physbuf, "%lx", paddr);
> +     sprintf(physbuf, "%llx", paddr);
>       len2 = MAX(strlen(physbuf), strlen("PHYSICAL"));
>       fprintf(fp, "%s  ", mkstring(buf, len2, CENTER|LJUST, "PHYSICAL"));
> 
> @@ -1509,6 +1595,7 @@ ppc_display_machine_stats(void)
>           uts =&kt->utsname;
> 
>           fprintf(fp, "       MACHINE TYPE: %s\n", uts->machine);
> +        fprintf(fp, "           PLATFORM: %s\n", PPC_PLATFORM);
>           fprintf(fp, "        MEMORY SIZE: %s\n", get_memory_size(buf));
>           fprintf(fp, "               CPUS: %d\n", kt->cpus);
>           fprintf(fp, "    PROCESSOR SPEED: ");
> 
> 

--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to