--- crash-4.0-2.8/defs.h	2005-10-21 11:36:32.000000000 -0700
+++ crash-4.0-2.8.working/defs.h	2005-11-03 11:05:55.128141480 -0800
@@ -652,9 +652,11 @@ struct machdep_table {
         	char *func;
         	char **file;
 	} *line_number_hooks;
+	char last_pml_read;
 	ulong last_pgd_read;
 	ulong last_pmd_read;
 	ulong last_ptbl_read;
+	char *pml;
 	char *pgd;
  	char *pmd;	
 	char *ptbl;
@@ -676,10 +678,18 @@ struct machdep_table {
 
 extern struct machdep_table *machdep;
 
+#define IS_LAST_PML_READ(pgd)     ((ulong)(pml) == machdep->last_pml_read)
 #define IS_LAST_PGD_READ(pgd)     ((ulong)(pgd) == machdep->last_pgd_read)
 #define IS_LAST_PMD_READ(pmd)     ((ulong)(pmd) == machdep->last_pmd_read)
 #define IS_LAST_PTBL_READ(ptbl)   ((ulong)(ptbl) == machdep->last_ptbl_read)
 
+#define FILL_UPML(PML, TYPE, SIZE) 					    \
+    if (!IS_LAST_PML_READ(PML)) {                                           \
+            readmem((ulonglong)((ulong)(PML)), TYPE, machdep->pml,          \
+                    SIZE, "pml page", FAULT_ON_ERROR);                      \
+            machdep->last_pml_read = (ulong)(PML);                          \
+    }								            
+
 #define FILL_PGD(PGD, TYPE, SIZE) 					    \
     if (!IS_LAST_PGD_READ(PGD)) {                                           \
             readmem((ulonglong)((ulong)(PGD)), TYPE, machdep->pgd,          \
@@ -1740,14 +1750,14 @@ struct load_module {
 #define _64BIT_
 #define MACHINE_TYPE       "X86_64"
 
-#define USERSPACE_TOP         0x0000008000000000
-#define __START_KERNEL_map    0xffffffff80000000
-#define PAGE_OFFSET           0x0000010000000000
+#define USERSPACE_TOP	(x86_64_userspace_top)
+#define PAGE_OFFSET	(x86_64_page_offset)
+#define VMALLOC_START	(x86_64_vmalloc_start_addr)
+#define VMALLOC_END	(x86_64_vmalloc_end)
+#define MODULES_VADDR	(x86_64_modules_vaddr) 
+#define MODULES_END	(x86_64_modules_end)
 
-#define VMALLOC_START   0xffffff0000000000
-#define VMALLOC_END     0xffffff7fffffffff
-#define MODULES_VADDR   0xffffffffa0000000
-#define MODULES_END     0xffffffffafffffff
+#define __START_KERNEL_map    0xffffffff80000000
 #define MODULES_LEN     (MODULES_END - MODULES_VADDR)
 
 #define PTOV(X)               ((unsigned long)(X)+(machdep->kvbase))
--- crash-4.0-2.8/x86_64.c	2005-10-21 11:36:32.000000000 -0700
+++ crash-4.0-2.8.working/x86_64.c	2005-11-03 11:26:31.793139824 -0800
@@ -19,6 +19,7 @@
 
 static int x86_64_kvtop(struct task_context *, ulong, physaddr_t *, int);
 static int x86_64_uvtop(struct task_context *, ulong, physaddr_t *, int);
+static int x86_64_uvtop_level4(struct task_context *, ulong, physaddr_t *, int);
 static ulong x86_64_vmalloc_start(void);
 static int x86_64_is_task_addr(ulong);
 static int x86_64_verify_symbol(const char *, ulong, char);
@@ -65,6 +66,12 @@ static void x86_64_cpu_pda_init(void);
 static void x86_64_ist_init(void);
 static void x86_64_post_init(void);
 
+ulong x86_64_userspace_top;
+ulong x86_64_page_offset;
+ulong x86_64_vmalloc_start_addr;
+ulong x86_64_vmalloc_end;
+ulong x86_64_modules_vaddr;
+ulong x86_64_modules_end;
 
 struct machine_specific x86_64_machine_specific = { 0 };
 
@@ -87,6 +94,8 @@ x86_64_init(int when)
                 machdep->pageoffset = machdep->pagesize - 1;
                 machdep->pagemask = ~((ulonglong)machdep->pageoffset);
 		machdep->stacksize = machdep->pagesize * 2;
+                if ((machdep->pml = (char *)malloc(PAGESIZE())) == NULL)
+                        error(FATAL, "cannot malloc pml space.");
                 if ((machdep->pgd = (char *)malloc(PAGESIZE())) == NULL)
                         error(FATAL, "cannot malloc pgd space.");
                 if ((machdep->pmd = (char *)malloc(PAGESIZE())) == NULL)
@@ -96,6 +105,7 @@ x86_64_init(int when)
 		if ((machdep->machspec->pml4 = 
 			(char *)malloc(PAGESIZE())) == NULL)
                         error(FATAL, "cannot malloc pml4 space.");
+                machdep->last_pml_read = 0;
                 machdep->last_pgd_read = 0;
                 machdep->last_pmd_read = 0;
                 machdep->last_ptbl_read = 0;
@@ -105,6 +115,25 @@ x86_64_init(int when)
 		break;
 
 	case PRE_GDB:
+		if (symbol_exists("boot_vmalloc_pgt")) {
+			/* 2.4 & pre-2.6.11 layout */
+			x86_64_userspace_top = 0x0000008000000000;
+			x86_64_page_offset = 0x0000010000000000;
+			x86_64_vmalloc_start_addr = 0xffffff0000000000;
+			x86_64_vmalloc_end = 0xffffff7fffffffff;
+			x86_64_modules_vaddr = 0xffffffffa0000000;
+			x86_64_modules_end = 0xffffffffafffffff;
+	        	machdep->uvtop = x86_64_uvtop;
+		} else {
+			/* > 2.6.10 layout */
+			x86_64_userspace_top = 0x0000800000000000;
+			x86_64_page_offset = 0xffff810000000000;
+			x86_64_vmalloc_start_addr = 0xffffc20000000000;
+			x86_64_vmalloc_end = 0xffffe1ffffffffff;
+			x86_64_modules_vaddr = 0xffffffff88000000;
+			x86_64_modules_end = 0xfffffffffff00000;
+	        	machdep->uvtop = x86_64_uvtop_level4;
+		}
 	        machdep->kvbase = (ulong)PAGE_OFFSET;
 		machdep->identity_map_base = (ulong)PAGE_OFFSET;
                 machdep->is_kvaddr = x86_64_is_kvaddr;
@@ -112,7 +141,6 @@ x86_64_init(int when)
 	        machdep->eframe_search = x86_64_eframe_search;
 	        machdep->back_trace = x86_64_low_budget_back_trace_cmd;
 	        machdep->processor_speed = x86_64_processor_speed;
-	        machdep->uvtop = x86_64_uvtop;
 	        machdep->kvtop = x86_64_kvtop;
 	        machdep->get_task_pgd = x86_64_get_task_pgd;
 		machdep->get_stack_frame = x86_64_get_stack_frame;
@@ -329,9 +357,13 @@ x86_64_cpu_pda_init(void)
 	for (i = cpus = 0; i < nr_pda; i++) {
 		if (!CPU_PDA_READ(i, cpu_pda_buf))
 			break;
-		level4_pgt = ULONG(cpu_pda_buf + OFFSET(x8664_pda_level4_pgt));
+		if (VALID_MEMBER(x8664_pda_level4_pgt)) {
+			level4_pgt = ULONG(cpu_pda_buf + OFFSET(x8664_pda_level4_pgt));
+			if (!VALID_LEVEL4_PGT_ADDR(level4_pgt))
+				break;
+		}
 		cpunumber = INT(cpu_pda_buf + OFFSET(x8664_pda_cpunumber));
-		if (!VALID_LEVEL4_PGT_ADDR(level4_pgt) || (cpunumber != cpus))
+		if (cpunumber != cpus)
 			break;
 		cpus++;
 
@@ -623,6 +655,114 @@ x86_64_is_uvaddr(ulong addr, struct task
  */
 
 static int
+x86_64_uvtop_level4(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verbose)
+{
+	ulong mm;
+	ulong *pml;
+	ulong pml_paddr;
+	ulong pml_pte;
+	ulong *pgd;
+	ulong pgd_paddr;
+	ulong pgd_pte;
+	ulong *pmd;
+	ulong pmd_paddr;
+	ulong pmd_pte;
+	ulong *ptep;
+	ulong pte_paddr;
+	ulong pte;
+	physaddr_t physpage;
+
+	if (!tc)
+		error(FATAL, "current context invalid\n");
+
+	*paddr = 0;
+
+	if (IS_KVADDR(uvaddr))
+		return x86_64_kvtop(tc, uvaddr, paddr, verbose);
+
+	if ((mm = task_mm(tc->task, TRUE)))
+		pml = ULONG_PTR(tt->mm_struct + OFFSET(mm_struct_pgd));
+	else
+		readmem(tc->mm_struct + OFFSET(mm_struct_pgd), KVADDR, &pml,
+			sizeof(long), "mm_struct pgd", FAULT_ON_ERROR);
+
+	pml_paddr = x86_64_VTOP((ulong)pml);
+	FILL_UPML(pml_paddr, PHYSADDR, PAGESIZE());
+	pml = ((ulong *)pml_paddr) + pml4_index(uvaddr); 
+	pml_pte = ULONG(machdep->pml + PAGEOFFSET(pml));
+	if (verbose) 
+		fprintf(fp, "   PML: %lx => %lx\n", (ulong)pml, pml_pte);
+	if (!(pml_pte & _PAGE_PRESENT))
+		goto no_upage;
+
+	pgd_paddr = pml_pte & PHYSICAL_PAGE_MASK;
+	FILL_PGD(pgd_paddr, PHYSADDR, PAGESIZE());
+	pgd = ((ulong *)pgd_paddr) + pgd_index(uvaddr); 
+	pgd_pte = ULONG(machdep->pgd + PAGEOFFSET(pgd));
+	if (verbose) 
+                fprintf(fp, "   PGD: %lx => %lx\n", (ulong)pgd, pgd_pte);
+	if (!(pgd_pte & _PAGE_PRESENT))
+		goto no_upage;
+
+	/*
+         *  pmd = pmd_offset(pgd, address);
+	 */
+	pmd_paddr = pgd_pte & PHYSICAL_PAGE_MASK;
+	FILL_PMD(pmd_paddr, PHYSADDR, PAGESIZE());
+	pmd = ((ulong *)pmd_paddr) + pmd_index(uvaddr);
+	pmd_pte = ULONG(machdep->pmd + PAGEOFFSET(pmd));
+        if (verbose) 
+                fprintf(fp, "   PMD: %lx => %lx\n", (ulong)pmd, pmd_pte);
+	if (!(pmd_pte & _PAGE_PRESENT))
+		goto no_upage;
+        if (pmd_pte & _PAGE_PSE) {
+                if (verbose) {
+                        fprintf(fp, "  PAGE: %lx  (2MB)\n\n", 
+				PAGEBASE(pmd_pte) & PHYSICAL_PAGE_MASK);
+                        x86_64_translate_pte(pmd_pte, 0, 0);
+                }
+
+                physpage = (PAGEBASE(pmd_pte) & PHYSICAL_PAGE_MASK) + 
+			(uvaddr & ~_2MB_PAGE_MASK);
+                *paddr = physpage;
+                return TRUE;
+        }
+
+        /*
+	 *  ptep = pte_offset_map(pmd, address);
+	 *  pte = *ptep;
+	 */
+	pte_paddr = pmd_pte & PHYSICAL_PAGE_MASK;
+	FILL_PTBL(pte_paddr, PHYSADDR, PAGESIZE());
+	ptep = ((ulong *)pte_paddr) + pte_index(uvaddr);
+	pte = ULONG(machdep->ptbl + PAGEOFFSET(ptep));
+	if (verbose)
+		fprintf(fp, "   PTE: %lx => %lx\n", (ulong)ptep, pte);
+	if (!(pte & (_PAGE_PRESENT))) {
+		if (pte && verbose) {
+			fprintf(fp, "\n");
+			x86_64_translate_pte(pte, 0, 0);
+		}
+		goto no_upage;
+	}
+
+	*paddr = (PAGEBASE(pte) & PHYSICAL_PAGE_MASK) + PAGEOFFSET(uvaddr);
+
+	if (verbose) {
+		fprintf(fp, "  PAGE: %lx\n\n", 
+			PAGEBASE(*paddr) & PHYSICAL_PAGE_MASK);
+		x86_64_translate_pte(pte, 0, 0);
+	}
+
+	return TRUE;
+
+no_upage:
+
+	return FALSE;
+}
+
+
+static int
 x86_64_uvtop(struct task_context *tc, ulong uvaddr, physaddr_t *paddr, int verbose)
 {
        	ulong mm;
@@ -2500,10 +2640,15 @@ x86_64_get_smp_cpus(void)
 	for (i = cpus = 0; i < nr_pda; i++) {
 		if (!CPU_PDA_READ(i, cpu_pda_buf))
 			break;
-		level4_pgt = ULONG(cpu_pda_buf + OFFSET(x8664_pda_level4_pgt));
+
+		if (VALID_MEMBER(x8664_pda_level4_pgt)) {
+			level4_pgt = ULONG(cpu_pda_buf + OFFSET(x8664_pda_level4_pgt));
+			if (!VALID_LEVEL4_PGT_ADDR(level4_pgt))
+				break;
+		}
 		cpunumber = INT(cpu_pda_buf + OFFSET(x8664_pda_cpunumber));
-                if (!VALID_LEVEL4_PGT_ADDR(level4_pgt) || (cpunumber != cpus))
-                        break;
+		if (cpunumber != cpus)
+			break;
                 cpus++;
 	}
 
