Dave, Here is the latest patch to make crash work on 2.6.14 kernel - with fixes for 4-level pagetables also. I changes & naming are kind of hacky (especially with naming) -- but to cleanup it completely and have backward compatibility needs more work. We should get rid of PML4 completely and move to PGD/PUD/PMD/PTE. Thanks, Badari elm3a242:~/crash-4.0-2.8 # ./crash crash 4.0-2.8 Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc. Copyright (C) 2004, 2005 IBM Corporation Copyright (C) 1999-2005 Hewlett-Packard Co Copyright (C) 1999, 2002 Silicon Graphics, Inc. Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. This program is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Enter "help copying" to see the conditions. This program has absolutely no warranty. Enter "help warranty" for details. GNU gdb 6.1 Copyright 2004 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "x86_64-unknown-linux-gnu"... KERNEL: /usr/src/linux-2.6.14.madv/vmlinux DUMPFILE: /dev/mem CPUS: 2 DATE: Thu Nov 3 08:25:50 2005 UPTIME: 07:12:24 LOAD AVERAGE: 0.60, 0.43, 0.18 TASKS: 62 NODENAME: elm3a242 RELEASE: 2.6.14 VERSION: #3 SMP PREEMPT Wed Nov 2 03:08:36 PST 2005 MACHINE: x86_64 (3000 Mhz) MEMORY: 4.6 GB PID: 31320 COMMAND: "crash" TASK: ffff810122f11860 [THREAD_INFO: ffff8100987f6000] CPU: 1 STATE: TASK_RUNNING (ACTIVE) crash> set PID: 31320 COMMAND: "crash" TASK: ffff810122f11860 [THREAD_INFO: ffff8100987f6000] CPU: 1 STATE: TASK_RUNNING (ACTIVE) crash> vm PID: 31320 TASK: ffff810122f11860 CPU: 1 COMMAND: "crash" MM PGD RSS TOTAL_VM ffff810122e93700 ffff810099584000 148044k 86512k VMA START END FLAGS FILE ffff810122438cc0 400000 754000 1875 /root/crash-4.0-2.8/crash ffff810122438590 853000 8b0000 101873 /root/crash-4.0-2.8/crash ffff810122438d78 8b0000 1c2e000 100073 ffff810122438088 2aaaaaaab000 2aaaaaac0000 875 /lib64/ld-2.3.3.so ffff8101224389e0 2aaaaaac0000 2aaaaaac2000 100073 ffff810123caa4d8 2aaaaaac2000 2aaaaaaf5000 71 /usr/lib/locale/en_US.utf8/LC_CTYPE ffff810123caaee8 2aaaaaaf5000 2aaaaaafb000 d1 /usr/lib64/gconv/gconv-modules.cache ffff8101136809e0 2aaaaaafb000 2aaaaaaff000 100073 ffff8101224387b8 2aaaaabc0000 2aaaaabc2000 100873 /lib64/ld-2.3.3.so ffff810122438648 2aaaaabc2000 2aaaaac16000 75 /lib64/tls/libm.so.6 ffff810122438700 2aaaaac16000 2aaaaacc2000 70 /lib64/tls/libm.so.6 ffff8101276f4590 2aaaaacc2000 2aaaaad19000 100073 /lib64/tls/libm.so.6 ffff8101276f4a98 2aaaaad19000 2aaaaad1a000 100073 ffff810120ff1590 2aaaaad1a000 2aaaaad64000 75 /lib64/libncurses.so.5.4 ffff8101276f4b50 2aaaaad64000 2aaaaae1a000 70 /lib64/libncurses.so.5.4 ffff810120ff14d8 2aaaaae1a000 2aaaaae7a000 100073 /lib64/libncurses.so.5.4 ffff810120ff1140 2aaaaae7a000 2aaaaae7b000 100073 crash> rd -u 0x400000 400000: 00010102464c457f .ELF.... crash> rd -u 2aaaaaaab000 2aaaaaaab000: 00010102464c457f .ELF.... crash> mod MODULE NAME SIZE OBJECT FILE ffffffff88012600 dm_mod 70872 (not loaded) [CONFIG_KALLSYMS] ffffffff8805ef80 ipv6 312832 (not loaded) [CONFIG_KALLSYMS] ffffffff8806e200 parport 47244 (not loaded) [CONFIG_KALLSYMS] ffffffff88073800 lp 17232 (not loaded) [CONFIG_KALLSYMS] ffffffff8807fd00 parport_pc 33896 (not loaded) [CONFIG_KALLSYMS] ffffffff8808ab00 usbserial 39280 (not loaded) [CONFIG_KALLSYMS] ffffffff8808e900 hw_random 7968 (not loaded) [CONFIG_KALLSYMS] ffffffff88098f80 uhci_hcd 38304 (not loaded) [CONFIG_KALLSYMS] ffffffff880a4600 ehci_hcd 39944 (not loaded) [CONFIG_KALLSYMS] ffffffff880acd80 i2c_core 29568 (not loaded) [CONFIG_KALLSYMS] ffffffff880b1700 i2c_i801 11540 (not loaded) [CONFIG_KALLSYMS] ffffffff880b6000 joydev 13952 (not loaded) [CONFIG_KALLSYMS] ffffffff880bb000 edd 13984 (not loaded) [CONFIG_KALLSYMS]
--- 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++; }