[Crash-utility] [PATCH v2 2/3] [ppc] Support for platform based Virtual address translation

Suzuki K. Poulose suzuki at in.ibm.com
Thu Feb 2 08:45:51 UTC 2012


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 the PGDIRSHIT, PTRS_PER_PTE and the size of a
physical address.

I have not modified the size of the machdep->pgd allocation. Instead,
we always read a PAGESIZE() which contains the entry.

Signed-off-by: Suzuki K. Poulose <suzuki at in.ibm.com>
---

 defs.h |   14 +++++++++--
 ppc.c  |   80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 83 insertions(+), 11 deletions(-)

diff --git a/defs.h b/defs.h
index 82d51e5..aba13ea 100755
--- a/defs.h
+++ b/defs.h
@@ -2603,9 +2603,17 @@ struct load_module {
 #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)
+/* Default values for PPC */
+#define DEFAULT_PGDIR_SHIFT	(22)
+#define DEFAULT_PTRS_PER_PTE	(1024)
+#define DEFAULT_PTRS_PER_PGD	(1024)
+#define DEFAULT_PTE_SIZE	sizeof(ulong)
+
+
+#define PGDIR_SHIFT		(base_platform->pgdir_shift)
+#define PTRS_PER_PTE		(base_platform->ptrs_per_pte)
+#define PTRS_PER_PGD		(base_platform->ptrs_per_pgd)
+#define PTE_SIZE		(base_platform->pte_size)
 
 #define _PAGE_PRESENT   0x001   /* software: pte contains a translation */
 #define _PAGE_USER      0x002   /* matches one of the PP bits */
diff --git a/ppc.c b/ppc.c
index cfa3f5f..600df34 100755
--- a/ppc.c
+++ b/ppc.c
@@ -67,10 +67,59 @@ static void ppc_display_machine_stats(void);
 static void ppc_dump_line_number(ulong);
 static struct line_number_hook ppc_line_number_hooks[];
 
+struct platform {
+	char 	*name;
+	int	pgdir_shift;
+	int	ptrs_per_pgd;
+	int	ptrs_per_pte;
+	int	pte_size;
+} ppc_boards[] = {
+	{
+		/* Always keep the default as the first entry */
+		.name = "default",
+		.pgdir_shift = DEFAULT_PGDIR_SHIFT,
+		.ptrs_per_pgd = DEFAULT_PTRS_PER_PGD,
+		.ptrs_per_pte = DEFAULT_PTRS_PER_PTE,
+		.pte_size = DEFAULT_PTE_SIZE,
+	},
+	{
+		/* Keep this at the end */
+		.name = NULL,
+	}
+};
+
+struct platform *base_platform;
+static struct platform *ppc_get_base_platform(void);
+
 /* Defined in diskdump.c */
 extern void process_elf32_notes(void *, ulong);
 
 /*
+ * Find the platform of the crashing system and set the
+ * base_platform accordingly.
+ */
+struct platform*
+ppc_get_base_platform(void)
+{
+	char platform[32];
+	struct platform *tmp = &ppc_boards[1]; /* start at 1 */
+	ulong ppc_platform;
+
+	if(!try_get_symbol_data("powerpc_base_platform", sizeof(ulong), &ppc_platform))
+		return &ppc_boards[0];
+
+	if (read_string(ppc_platform, platform, 31) == 0)
+		return &ppc_boards[0];
+
+	for (; tmp->name!= NULL; tmp++)
+		if (!strcmp(tmp->name, platform))
+			return tmp;
+
+	/* Use default definitions */
+	return &ppc_boards[0];
+}
+
+/*
  *  Do all necessary machine-specific setup here.  This is called twice,
  *  before and after GDB has been initialized.
  */
@@ -104,7 +153,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:
@@ -130,6 +178,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 */
+		base_platform = ppc_get_base_platform();
+
+		machdep->ptrs_per_pgd = PTRS_PER_PGD;
+
 		break;
 
 	case POST_GDB:
@@ -269,14 +322,21 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
 	ulong *page_middle;
 	ulong *page_table;
 	ulong pgd_pte;
-	ulong pte;
+	unsigned long long pte;
 
-	if (verbose) 
+	if (verbose) {
+		fprintf(fp, "Using %s board definitions:\n", base_platform->name);
 		fprintf(fp, "PAGE DIRECTORY: %lx\n", (ulong)pgd);
+	}
 
 	page_dir = pgd + (vaddr >> PGDIR_SHIFT);
 
-        FILL_PGD(PAGEBASE(pgd), KVADDR, PAGESIZE());
+	/*
+ 	 * 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(page_dir), KVADDR, PAGESIZE());
         pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir));
 
 	if (verbose)
@@ -288,10 +348,10 @@ 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)
@@ -299,10 +359,14 @@ ppc_pgd_vtop(ulong *pgd, ulong vaddr, physaddr_t *paddr, int verbose)
 			(ulong)page_table);
 
         FILL_PTBL(PAGEBASE(page_table), KVADDR, PAGESIZE());
-        pte = ULONG(machdep->ptbl + PAGEOFFSET(page_table));
+	if (PTE_SIZE == sizeof(unsigned long long))
+		pte = ULONGLONG(machdep->ptbl + PAGEOFFSET(page_table));
+
+	else	/* Defaults to ulong */
+	        pte = ULONG(machdep->ptbl + PAGEOFFSET(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) {




More information about the Crash-utility mailing list