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 and the size of a PTE.

The patch also adds support 64bit ptes.

Signed-off-by: Suzuki K. Poulose <[email protected]>
---

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

diff --git a/defs.h b/defs.h
index a942dbb..603a583 100755
--- a/defs.h
+++ b/defs.h
@@ -2641,9 +2641,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 3834e7f..0e934ca 100755
--- a/ppc.c
+++ b/ppc.c
@@ -17,6 +17,21 @@
 #ifdef PPC
 #include "defs.h"
 
+
+#define MAX_PLATFORM_LEN       32      /* length for platform string */
+
+/* 
+ * The following struct would hold the page translation information
+ * for the platform determined at runtime by ppc_probe_base_platform().
+ */
+struct platform {
+       char    *name;
+       int     pgdir_shift;
+       int     ptrs_per_pgd;
+       int     ptrs_per_pte;
+       int     pte_size;
+} base_platform;
+
 /* 
  *  This structure was copied from kernel source
  *  in include/asm-ppc/ptrace.h
@@ -67,6 +82,53 @@ static void ppc_display_machine_stats(void);
 static void ppc_dump_line_number(ulong);
 static struct line_number_hook ppc_line_number_hooks[];
 
+static int probe_default_platform(char *, struct platform *);
+static void ppc_probe_base_platform(void);
+
+typedef int (*probe_func_t) (char *, struct platform *);
+
+probe_func_t probe_platforms[] = {
+       probe_default_platform, /* This should be at the end */
+       NULL
+};
+
+static int
+probe_default_platform(char *name, struct platform *p)
+{
+       /* Use the default definitions */
+       p->pgdir_shift = DEFAULT_PGDIR_SHIFT;
+       p->ptrs_per_pgd = DEFAULT_PTRS_PER_PGD;
+       p->ptrs_per_pte = DEFAULT_PTRS_PER_PTE;
+       p->pte_size = DEFAULT_PTE_SIZE;
+       p->name = strdup("default");
+
+       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';
+
+       for (i = 0; probe_platforms[i] != NULL; i++) {
+               probe = probe_platforms[i];
+               if (probe(platform_name, &base_platform))
+                       break;
+       }
+}
+
 /*
  *  Do all necessary machine-specific setup here.  This is called twice,
  *  before and after GDB has been initialized.
@@ -101,7 +163,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 +188,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:
@@ -266,14 +332,21 @@ 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, "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)
@@ -285,10 +358,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)
@@ -296,10 +369,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(ulonglong))
+               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) {

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

Reply via email to