(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<suzuki@xxxxxxxxxx> > --- > > 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 Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility