--- crash/defs.h	2005-11-17 10:45:13.000000000 -0800
+++ new/defs.h	2005-11-17 11:23:18.000000000 -0800
@@ -2101,23 +2101,14 @@ struct efi_memory_desc_t {
 #define PGD_OFFSET(vaddr)       ((vaddr >> PGDIR_SHIFT) & 0x7ff)
 #define PMD_OFFSET(vaddr)       ((vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
 
-/* 4-level page table changes */
-#define PGDIR_SHIFT_L4	(PMD_SHIFT + (machdep->pageshift - 5))
-#define L4_SHIFT	(PGDIR_SHIFT_L4 + (machdep->pageshift - 5))
-
-#define PTE_SHIFT_L4 17
-
-#define PTE_INDEX_SIZE_L4  9
-#define PMD_INDEX_SIZE_L4  7
-#define PGD_INDEX_SIZE_L4  7
-
-#define PTRS_PER_PTE_L4		(1 << PTE_INDEX_SIZE_L4)
-#define PTRS_PER_PMD_L4		(1 << PMD_INDEX_SIZE_L4)
-#define PTRS_PER_PGD_L4		(1 << PGD_INDEX_SIZE_L4)
-
-#define L4_OFFSET(vaddr)	((vaddr >> L4_SHIFT) & 0x1ff)
-#define PGD_OFFSET_L4(vaddr)	((vaddr >> PGDIR_SHIFT_L4) & (PTRS_PER_PGD_L4 - 1))
-#define PMD_OFFSET_L4(vaddr)	((vaddr >> PMD_SHIFT) & (PTRS_PER_PMD_L4 - 1))
+/* 4-level page table support */
+#define L4_OFFSET(vaddr)  ((vaddr >> (machdep->machspec->l4_shift)) & 0x1ff)
+
+#define PGD_OFFSET_L4(vaddr)	\
+	((vaddr >> (machdep->machspec->l3_shift)) & (machdep->machspec->ptrs_per_l3 - 1))
+
+#define PMD_OFFSET_L4(vaddr)	\
+	((vaddr >> (machdep->machspec->l2_shift)) & (machdep->machspec->ptrs_per_l2 - 1))
 
 #define _PAGE_PRESENT   0x001UL /* software: pte contains a translation */
 #define _PAGE_USER      0x002UL /* matches one of the PP bits */
@@ -3308,6 +3299,23 @@ struct machine_specific {
         uint hwstacksize;
         char *level4;
         ulong last_level4_read;
+
+	uint l4_index_size;
+	uint l3_index_size;
+	uint l2_index_size;
+	uint l1_index_size;
+
+	uint ptrs_per_l3;
+	uint ptrs_per_l2;
+	uint ptrs_per_l1;
+
+	uint l4_shift;
+	uint l3_shift;
+	uint l2_shift;
+	uint l1_shift;
+
+	uint pte_shift;
+	uint l2_masked_bits;
 };
 
 #define IS_LAST_L4_READ(l4)   ((ulong)(l4) == machdep->machspec->last_level4_read)
--- crash/ppc64.c	2005-11-17 10:45:16.000000000 -0800
+++ new/ppc64.c	2005-11-17 11:21:54.000000000 -0800
@@ -122,18 +122,45 @@ ppc64_init(int when)
 				machdep->flags |= VM_ORIG;
 			}
 		}
-		switch (machdep->flags & (VM_ORIG|VM_4_LEVEL)) 
-		{
-			case VM_ORIG:
-				/* pre-2.6.14 layout */
-				free(machdep->machspec->level4);
-				machdep->machspec->level4 = NULL;
-				machdep->ptrs_per_pgd = PTRS_PER_PGD;
-				break;
-			case VM_4_LEVEL:
-				/* 2.6.14 layout */
-				machdep->ptrs_per_pgd = PTRS_PER_PGD_L4;
-				break;
+		if (machdep->flags & VM_ORIG) {
+			/* pre-2.6.14 layout */
+			free(machdep->machspec->level4);
+			machdep->machspec->level4 = NULL;
+			machdep->ptrs_per_pgd = PTRS_PER_PGD;
+		} else {
+			/* 2.6.14 layout */
+			struct machine_specific *m = machdep->machspec;
+			if (machdep->pagesize == 65536) {
+				/* 64K pagesize */
+				m->l1_index_size = 12;
+				m->l2_index_size = 12;
+				m->l3_index_size = 0;
+				m->l4_index_size = 4;
+				m->l1_shift = 16;
+				m->pte_shift = 32; 
+				m->l2_masked_bits = 0x1ff;
+			} else {
+				/* 4K pagesize */
+				m->l1_index_size = 9;
+				m->l2_index_size = 7;
+				m->l3_index_size = 7;
+				m->l4_index_size = 9;
+				m->l1_shift = 12;
+				m->pte_shift = 17; 
+				m->l2_masked_bits = 0;
+			}
+
+			/* Compute ptrs per each level */
+			m->ptrs_per_l1 = (1 << m->l1_index_size);
+			m->ptrs_per_l2 = (1 << m->l2_index_size);
+			m->ptrs_per_l3 = (1 << m->l3_index_size);
+
+			machdep->ptrs_per_pgd = m->ptrs_per_l3;
+
+			/* Compute shifts */
+			m->l2_shift = m->l1_shift + m->l1_index_size;
+			m->l3_shift = m->l2_shift + m->l2_index_size;
+			m->l4_shift = m->l3_shift + m->l3_index_size;
 		}
 		machdep->vmalloc_start = ppc64_vmalloc_start;
 		MEMBER_OFFSET_INIT(thread_struct_pg_tables,
@@ -413,15 +440,19 @@ ppc64_vtop_level4(ulong vaddr, ulong *le
 	if (!level4_pte)
 		return FALSE;
 
-	page_dir = (ulong *)((ulong *)level4_pte + PGD_OFFSET_L4(vaddr));
-	FILL_PGD(PAGEBASE(level4_pte), KVADDR, PAGESIZE());
-	pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir));
-
-	if (verbose)
-		fprintf(fp, "  PGD: %lx => %lx\n", (ulong)page_dir, pgd_pte);
-
-	if (!pgd_pte)
-		return FALSE;
+	/* Sometimes we don't have level3 pagetable entries */
+	if (machdep->machspec->l3_index_size != 0) {
+		page_dir = (ulong *)((ulong *)level4_pte + PGD_OFFSET_L4(vaddr));
+		FILL_PGD(PAGEBASE(level4_pte), KVADDR, PAGESIZE());
+		pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(page_dir));
+
+		if (verbose)
+			fprintf(fp, "  PGD: %lx => %lx\n", (ulong)page_dir, pgd_pte);
+		if (!pgd_pte)
+			return FALSE;
+	} else {
+		pgd_pte = level4_pte;
+	}
 
 	page_middle = (ulong *)((ulong *)pgd_pte + PMD_OFFSET_L4(vaddr));
 	FILL_PMD(PAGEBASE(pgd_pte), KVADDR, PAGESIZE());
@@ -433,7 +464,8 @@ ppc64_vtop_level4(ulong vaddr, ulong *le
 	if (!(pmd_pte))
 		return FALSE;
 
-	page_table = (ulong *)pmd_pte + (BTOP(vaddr) & (PTRS_PER_PTE_L4 - 1));
+	page_table = (ulong *)(pmd_pte & ~(machdep->machspec->l2_masked_bits))
+			 + (BTOP(vaddr) & (machdep->machspec->ptrs_per_l1 - 1));
 	if (verbose)
 		fprintf(fp, "  PMD: %lx => %lx\n",(ulong)page_middle,
 			(ulong)page_table);
@@ -447,7 +479,7 @@ ppc64_vtop_level4(ulong vaddr, ulong *le
 	if (!(pte & _PAGE_PRESENT)) {
 		if (pte && verbose) {
 			fprintf(fp, "\n");
-			ppc64_translate_pte(pte, 0, PTE_SHIFT_L4);
+			ppc64_translate_pte(pte, 0, machdep->machspec->pte_shift);
 		}
 		return FALSE;
 	}
@@ -455,11 +487,12 @@ ppc64_vtop_level4(ulong vaddr, ulong *le
 	if (!pte)
 		return FALSE;
 
-	*paddr = PAGEBASE(PTOB(pte >> PTE_SHIFT_L4)) + PAGEOFFSET(vaddr);
+	*paddr = PAGEBASE(PTOB(pte >> machdep->machspec->pte_shift)) 
+			+ PAGEOFFSET(vaddr);
 
 	if (verbose) {
 		fprintf(fp, " PAGE: %lx\n\n", PAGEBASE(*paddr));
-		ppc64_translate_pte(pte, 0, PTE_SHIFT_L4);
+		ppc64_translate_pte(pte, 0, machdep->machspec->pte_shift);
 	}
 
 	return TRUE;
