Here is the updated version with the following changes : * ppc_translate_pte(ulong pte32, void *physaddr, ulonglong pte64); * Updates the machdep->flags with PAE flag to indicate we have a 64bit PTE. * Sets the platform string to '(unknown)' if we are unable to read the string from the kernel. --- 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 | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 192 insertions(+), 49 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..64fa4db 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 */ + strcpy(platform_name, "(unknown)"); + + 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,14 @@ 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; + /* Check if we have 64bit PTE on 32bit system */ + if (PTE_SIZE == sizeof(ulonglong)) + machdep->flags |= PAE; + break; case POST_GDB: @@ -201,6 +277,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 +289,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 +333,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 +346,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 +370,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((ulong)pte, 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((ulong)pte, 0, pte); } *paddr = PAGEBASE(pte) + PAGEOFFSET(vaddr); @@ -623,7 +712,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 pte32, void *physaddr, ulonglong pte64) { int c, len1, len2, len3, others, page_present; char buf[BUFSIZE]; @@ -632,22 +721,25 @@ ppc_translate_pte(ulong pte, void *physaddr, ulonglong unused) char ptebuf[BUFSIZE]; char physbuf[BUFSIZE]; char *arglist[MAXARGS]; - ulong paddr; + ulonglong paddr; + + if (!(machdep->flags & PAE)) + pte64 = pte32; - paddr = PAGEBASE(pte); - page_present = (pte & _PAGE_PRESENT); + paddr = PAGEBASE(pte64); + page_present = (pte64 & _PAGE_PRESENT); if (physaddr) { *((ulong *)physaddr) = paddr; return page_present; } - sprintf(ptebuf, "%lx", pte); + sprintf(ptebuf, "%llx", pte64); len1 = MAX(strlen(ptebuf), strlen("PTE")); fprintf(fp, "%s ", mkstring(buf, len1, CENTER|LJUST, "PTE")); - if (!page_present && pte) { - swap_location(pte, buf); + if (!page_present && pte64) { + swap_location(pte64, buf); if ((c = parse_line(buf, arglist)) != 3) error(FATAL, "cannot determine swap location\n"); @@ -668,7 +760,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")); @@ -680,26 +772,26 @@ ppc_translate_pte(ulong pte, void *physaddr, ulonglong unused) fprintf(fp, "("); others = 0; - if (pte) { - if (pte & _PAGE_PRESENT) + if (pte64) { + if (pte64 & _PAGE_PRESENT) fprintf(fp, "%sPRESENT", others++ ? "|" : ""); - if (pte & _PAGE_USER) + if (pte64 & _PAGE_USER) fprintf(fp, "%sUSER", others++ ? "|" : ""); - if (pte & _PAGE_RW) + if (pte64 & _PAGE_RW) fprintf(fp, "%sRW", others++ ? "|" : ""); - if (pte & _PAGE_GUARDED) + if (pte64 & _PAGE_GUARDED) fprintf(fp, "%sGUARDED", others++ ? "|" : ""); - if (pte & _PAGE_COHERENT) + if (pte64 & _PAGE_COHERENT) fprintf(fp, "%sCOHERENT", others++ ? "|" : ""); - if (pte & _PAGE_NO_CACHE) + if (pte64 & _PAGE_NO_CACHE) fprintf(fp, "%sNO_CACHE", others++ ? "|" : ""); - if (pte & _PAGE_WRITETHRU) + if (pte64 & _PAGE_WRITETHRU) fprintf(fp, "%sWRITETHRU", others++ ? "|" : ""); - if (pte & _PAGE_DIRTY) + if (pte64 & _PAGE_DIRTY) fprintf(fp, "%sDIRTY", others++ ? "|" : ""); - if (pte & _PAGE_ACCESSED) + if (pte64 & _PAGE_ACCESSED) fprintf(fp, "%sACCESSED", others++ ? "|" : ""); - if (pte & _PAGE_HWWRITE) + if (pte64 & _PAGE_HWWRITE) fprintf(fp, "%sHWWRITE", others++ ? "|" : ""); } else fprintf(fp, "no mapping"); @@ -1509,6 +1601,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