[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Google
  Web www.spinics.net

[PATCH v3 2/3] [ppc] Support for platform based Virtual address translation



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 <suzuki@xxxxxxxxxx>
---

 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
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility


[Home]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Red Hat 9 Bible]     [Fedora Bible]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]

Add to Google

Powered by Linux