Hi Kevin, Worth, Kevin wrote: > My config file is attached. Kernel is 2.6.20 + Ubuntu patches. > It was built from http://packages.ubuntu.com/feisty/linux-source-2.6.20 > > Since it might be easy to see the parts I have changed from the defaults, > the diff between my config and the Ubuntu "generic" config is below. Thank you for your .config file. I could reproduce this problem. I created the patch, and it was merged into DEVEL tree. Could you get the DEVEL package by the following command and test it ? cvs -z3 -d:pserver:anonymous at makedumpfile.cvs.sourceforge.net:/cvsroot/makedumpfile co -r DEVEL -P makedumpfile If you cannot download it, please try the attached patch for makedumpfile-1.2.9. Thanks Ken'ichi Ohmichi ------------------------------- [PATCH] Add vtop_x86 support. On x86 machine, the existing makedumpfile translates a virtual address only by referring PT_LOAD header of /proc/vmcore. This feature is not enough for x86 machine, because some kernel data is located in vmalloc area. Then, this patch adds the translating feature for vmalloc address. Signed-off-by: Ken'ichi Ohmichi <oomichi at mxs.nes.nec.co.jp> --- diff -puN backup/makedumpfile-1.2.9/makedumpfile.c makedumpfile/makedumpfile.c --- backup/makedumpfile-1.2.9/makedumpfile.c 2008-09-04 16:31:58.000000000 +0900 +++ makedumpfile/makedumpfile.c 2008-09-24 14:56:02.000000000 +0900 @@ -1803,6 +1803,7 @@ get_symbol_info(void) SYMBOL_INIT(_stext, "_stext"); SYMBOL_INIT(swapper_pg_dir, "swapper_pg_dir"); SYMBOL_INIT(init_level4_pgt, "init_level4_pgt"); + SYMBOL_INIT(vmlist, "vmlist"); SYMBOL_INIT(phys_base, "phys_base"); SYMBOL_INIT(node_online_map, "node_online_map"); SYMBOL_INIT(node_states, "node_states"); @@ -1910,6 +1911,8 @@ get_structure_info(void) OFFSET_INIT(node_memblk_s.size, "node_memblk_s", "size"); OFFSET_INIT(node_memblk_s.nid, "node_memblk_s", "nid"); + OFFSET_INIT(vm_struct.addr, "vm_struct", "addr"); + ENUM_NUMBER_INIT(NR_FREE_PAGES, "NR_FREE_PAGES"); ENUM_NUMBER_INIT(N_ONLINE, "N_ONLINE"); @@ -2095,6 +2098,7 @@ generate_vmcoreinfo(void) WRITE_SYMBOL("_stext", _stext); WRITE_SYMBOL("swapper_pg_dir", swapper_pg_dir); WRITE_SYMBOL("init_level4_pgt", init_level4_pgt); + WRITE_SYMBOL("vmlist", vmlist); WRITE_SYMBOL("phys_base", phys_base); WRITE_SYMBOL("node_online_map", node_online_map); WRITE_SYMBOL("node_states", node_states); @@ -2142,6 +2146,7 @@ generate_vmcoreinfo(void) WRITE_MEMBER_OFFSET("node_memblk_s.start_paddr", node_memblk_s.start_paddr); WRITE_MEMBER_OFFSET("node_memblk_s.size", node_memblk_s.size); WRITE_MEMBER_OFFSET("node_memblk_s.nid", node_memblk_s.nid); + WRITE_MEMBER_OFFSET("vm_struct.addr", vm_struct.addr); if (SYMBOL(node_data) != NOT_FOUND_SYMBOL) WRITE_ARRAY_LENGTH("node_data", node_data); @@ -2339,6 +2344,7 @@ read_vmcoreinfo(void) READ_SYMBOL("_stext", _stext); READ_SYMBOL("swapper_pg_dir", swapper_pg_dir); READ_SYMBOL("init_level4_pgt", init_level4_pgt); + READ_SYMBOL("vmlist", vmlist); READ_SYMBOL("phys_base", phys_base); READ_SYMBOL("node_online_map", node_online_map); READ_SYMBOL("node_states", node_states); @@ -2379,6 +2385,7 @@ read_vmcoreinfo(void) READ_MEMBER_OFFSET("node_memblk_s.start_paddr", node_memblk_s.start_paddr); READ_MEMBER_OFFSET("node_memblk_s.size", node_memblk_s.size); READ_MEMBER_OFFSET("node_memblk_s.nid", node_memblk_s.nid); + READ_MEMBER_OFFSET("vm_struct.addr", vm_struct.addr); READ_ARRAY_LENGTH("node_data", node_data); READ_ARRAY_LENGTH("pgdat_list", pgdat_list); diff -puN backup/makedumpfile-1.2.9/makedumpfile.h makedumpfile/makedumpfile.h --- backup/makedumpfile-1.2.9/makedumpfile.h 2008-09-04 16:31:58.000000000 +0900 +++ makedumpfile/makedumpfile.h 2008-09-24 15:59:13.000000000 +0900 @@ -498,6 +498,24 @@ do { \ #define _SECTION_SIZE_BITS_PAE (30) #define _MAX_PHYSMEM_BITS (32) #define _MAX_PHYSMEM_BITS_PAE (36) + +#define PGDIR_SHIFT_3LEVEL (30) +#define PTRS_PER_PTE_3LEVEL (512) +#define PTRS_PER_PGD_3LEVEL (4) +#define PMD_SHIFT (21) /* only used by PAE translators */ +#define PTRS_PER_PMD (512) /* only used by PAE translators */ +#define PTE_SHIFT (12) /* only used by PAE translators */ +#define PTRS_PER_PTE (512) /* only used by PAE translators */ + +#define pgd_index_PAE(address) (((address) >> PGDIR_SHIFT_3LEVEL) & (PTRS_PER_PGD_3LEVEL - 1)) +#define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) +#define pte_index(address) (((address) >> PTE_SHIFT) & (PTRS_PER_PTE - 1)) + +#define _PAGE_PRESENT (0x001) +#define _PAGE_PSE (0x080) + +#define ENTRY_MASK (~0x8000000000000fffULL) + #endif /* x86 */ #ifdef __x86_64__ @@ -611,10 +629,11 @@ do { \ */ #ifdef __x86__ int get_machdep_info_x86(void); +unsigned long long vaddr_to_paddr_x86(unsigned long vaddr); #define get_phys_base() TRUE #define get_machdep_info() get_machdep_info_x86() #define get_versiondep_info() TRUE -#define vaddr_to_paddr(X) vaddr_to_paddr_general(X) +#define vaddr_to_paddr(X) vaddr_to_paddr_x86(X) #endif /* x86 */ #ifdef __x86_64__ @@ -840,6 +859,7 @@ struct symbol_table { unsigned long long _stext; unsigned long long swapper_pg_dir; unsigned long long init_level4_pgt; + unsigned long long vmlist; unsigned long long phys_base; unsigned long long node_online_map; unsigned long long node_states; @@ -919,6 +939,9 @@ struct offset_table { long size; long nid; } node_memblk_s; + struct vm_struct { + long addr; + } vm_struct; /* * for Xen extraction @@ -1051,19 +1074,6 @@ struct domain_list { #define is_direct(x) \ ((x) >= DIRECTMAP_VIRT_START && (x) < DIRECTMAP_VIRT_END) -#define PGDIR_SHIFT_3LEVEL (30) -#define PTRS_PER_PTE_3LEVEL (512) -#define PTRS_PER_PGD_3LEVEL (4) -#define PMD_SHIFT (21) /* only used by PAE translators */ -#define PTRS_PER_PMD (512) /* only used by PAE translators */ -#define PTE_SHIFT (12) /* only used by PAE translators */ -#define PTRS_PER_PTE (512) /* only used by PAE translators */ - -#define _PAGE_PRESENT 0x001 -#define _PAGE_PSE 0x080 - -#define ENTRY_MASK (~0x8000000000000fffULL) - unsigned long long kvtop_xen_x86(unsigned long kvaddr); #define kvtop_xen(X) kvtop_xen_x86(X) diff -puN backup/makedumpfile-1.2.9/x86.c makedumpfile/x86.c --- backup/makedumpfile-1.2.9/x86.c 2008-09-04 16:31:58.000000000 +0900 +++ makedumpfile/x86.c 2008-09-24 16:06:25.000000000 +0900 @@ -20,6 +20,8 @@ int get_machdep_info_x86(void) { + unsigned long vmlist, vmalloc_start; + /* PAE */ if ((vt.mem_flags & MEMORY_X86_PAE) || ((SYMBOL(pkmap_count) != NOT_FOUND_SYMBOL) @@ -28,6 +30,7 @@ get_machdep_info_x86(void) == 512)) { DEBUG_MSG("\n"); DEBUG_MSG("PAE : ON\n"); + vt.mem_flags |= MEMORY_X86_PAE; info->section_size_bits = _SECTION_SIZE_BITS_PAE; info->max_physmem_bits = _MAX_PHYSMEM_BITS_PAE; } else { @@ -38,9 +41,123 @@ get_machdep_info_x86(void) } info->page_offset = __PAGE_OFFSET; + if (SYMBOL(_stext) == NOT_FOUND_SYMBOL) { + ERRMSG("Can't get the symbol of _stext.\n"); + return FALSE; + } + info->kernel_start = SYMBOL(_stext) & ~KVBASE_MASK; + DEBUG_MSG("kernel_start : %lx\n", info->kernel_start); + + /* + * For the compatibility, makedumpfile should run without the symbol + * vmlist and the offset of vm_struct.addr if they are not necessary. + */ + if ((SYMBOL(vmlist) == NOT_FOUND_SYMBOL) + || (OFFSET(vm_struct.addr) == NOT_FOUND_STRUCTURE)) { + return TRUE; + } + if (!readmem(VADDR, SYMBOL(vmlist), &vmlist, sizeof(vmlist))) { + ERRMSG("Can't get vmlist.\n"); + return FALSE; + } + if (!readmem(VADDR, vmlist + OFFSET(vm_struct.addr), &vmalloc_start, + sizeof(vmalloc_start))) { + ERRMSG("Can't get vmalloc_start.\n"); + return FALSE; + } + info->vmalloc_start = vmalloc_start; + DEBUG_MSG("vmalloc_start: %lx\n", vmalloc_start); + return TRUE; } +unsigned long long +vtop_x86_PAE(unsigned long vaddr) +{ + unsigned long long page_dir, pgd_pte, pmd_paddr, pmd_pte; + unsigned long long pte_paddr, pte; + + if (SYMBOL(swapper_pg_dir) == NOT_FOUND_SYMBOL) { + ERRMSG("Can't get the symbol of swapper_pg_dir.\n"); + return NOT_PADDR; + } + + page_dir = SYMBOL(swapper_pg_dir); + page_dir += pgd_index_PAE(vaddr) * sizeof(unsigned long long); + if (!readmem(VADDR, page_dir, &pgd_pte, sizeof(pgd_pte))) { + ERRMSG("Can't get pgd_pte (page_dir:%llx).\n", page_dir); + return NOT_PADDR; + } + if (!(pgd_pte & _PAGE_PRESENT)) + return NOT_PADDR; + + if (info->vaddr_for_vtop == vaddr) + MSG(" PGD : %16llx => %16llx\n", page_dir, pgd_pte); + + pmd_paddr = pgd_pte & ENTRY_MASK; + pmd_paddr += pmd_index(vaddr) * sizeof(unsigned long long); + if (!readmem(PADDR, pmd_paddr, &pmd_pte, sizeof(pmd_pte))) { + ERRMSG("Can't get pmd_pte (pmd_paddr:%llx).\n", pmd_paddr); + return NOT_PADDR; + } + if (!(pmd_pte & _PAGE_PRESENT)) + return NOT_PADDR; + + if (info->vaddr_for_vtop == vaddr) + MSG(" PMD : %16llx => %16llx\n", pmd_paddr, pmd_pte); + + if (pmd_pte & _PAGE_PSE) + return (pmd_pte & ENTRY_MASK) + (vaddr & ((1UL << PMD_SHIFT) - 1)); + + pte_paddr = pmd_pte & ENTRY_MASK; + pte_paddr += pte_index(vaddr) * sizeof(unsigned long long); + if (!readmem(PADDR, pte_paddr, &pte, sizeof(pte))) + return NOT_PADDR; + + if (!(pte & _PAGE_PRESENT)) + return NOT_PADDR; + + if (info->vaddr_for_vtop == vaddr) + MSG(" PTE : %16llx => %16llx\n", pte_paddr, pte); + + return (pte & ENTRY_MASK) + (vaddr & ((1UL << PTE_SHIFT) - 1)); +} + +int +is_vmalloc_addr_x86(unsigned long vaddr) +{ + return (info->vmalloc_start && vaddr >= info->vmalloc_start); +} + +unsigned long long +vaddr_to_paddr_x86(unsigned long vaddr) +{ + unsigned long long paddr; + + if ((paddr = vaddr_to_paddr_general(vaddr)) != NOT_PADDR) + return paddr; + + if ((SYMBOL(vmlist) == NOT_FOUND_SYMBOL) + || (OFFSET(vm_struct.addr) == NOT_FOUND_STRUCTURE)) { + ERRMSG("Can't get necessary information for vmalloc translation.\n"); + return NOT_PADDR; + } + if (!is_vmalloc_addr_x86(vaddr)) + return (vaddr - info->kernel_start); + + if (vt.mem_flags & MEMORY_X86_PAE) { + paddr = vtop_x86_PAE(vaddr); + } else { + /* + * TODO: Support vmalloc translation of not-PAE kernel. + */ + ERRMSG("This makedumpfile does not support vmalloc "); + ERRMSG("translation of not-PAE kernel.\n"); + return NOT_PADDR; + } + return paddr; +} + /* * for Xen extraction */