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(a)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) {