[Crash-utility] [UPDATED PATCH v5] [ppc] Support for platform based Virtual address translation

Suzuki K. Poulose suzuki at in.ibm.com
Tue Feb 21 12:19:56 UTC 2012


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 at in.ibm.com>
---

 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: ");




More information about the Crash-utility mailing list