--- crash-4.0-4.8/memory.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/memory.c 2007-11-15 11:55:55.000000000 -0500 @@ -277,7 +277,16 @@ MEMBER_OFFSET_INIT(page_count, "page", "_count"); MEMBER_OFFSET_INIT(page_flags, "page", "flags"); MEMBER_OFFSET_INIT(page_mapping, "page", "mapping"); + if (INVALID_MEMBER(page_mapping)) + ANON_MEMBER_OFFSET_INIT(page_mapping, "page", "mapping"); + if (INVALID_MEMBER(page_mapping) && + (THIS_KERNEL_VERSION < LINUX(2,6,17)) && + MEMBER_EXISTS("page", "_mapcount")) + ASSIGN_OFFSET(page_mapping) = MEMBER_OFFSET("page", "_mapcount") + + STRUCT_SIZE("atomic_t") + sizeof(ulong); MEMBER_OFFSET_INIT(page_index, "page", "index"); + if (INVALID_MEMBER(page_index)) + ANON_MEMBER_OFFSET_INIT(page_mapping, "page", "index"); MEMBER_OFFSET_INIT(page_buffers, "page", "buffers"); MEMBER_OFFSET_INIT(page_lru, "page", "lru"); MEMBER_OFFSET_INIT(page_pte, "page", "pte"); @@ -555,12 +564,12 @@ get_symbol_data("high_memory", sizeof(ulong), &vt->high_memory); - if (kernel_symbol_exists("mem_map")) { + if (kernel_symbol_exists("mem_section")) + vt->flags |= SPARSEMEM; + else if (kernel_symbol_exists("mem_map")) { get_symbol_data("mem_map", sizeof(char *), &vt->mem_map); vt->flags |= FLATMEM; - } else if (kernel_symbol_exists("mem_section")) - vt->flags |= SPARSEMEM; - else + } else vt->flags |= DISCONTIGMEM; sparse_mem_init(); @@ -4004,7 +4013,7 @@ pp = section_mem_map_addr(section); pp = sparse_decode_mem_map(pp, section_nr); - phys = section_nr * PAGES_PER_SECTION() * PAGESIZE(); + phys = (physaddr_t) section_nr * PAGES_PER_SECTION() * PAGESIZE(); section_size = PAGES_PER_SECTION(); for (i = 0; i < section_size; @@ -6915,13 +6924,14 @@ if (!read_string(name, kbuf, BUFSIZE-1)) { if (vt->flags & (PERCPU_KMALLOC_V1|PERCPU_KMALLOC_V2)) - error(FATAL, + error(WARNING, "cannot read kmem_cache_s.name string at %lx\n", name); else - error(FATAL, + error(WARNING, "cannot read kmem_cache_s.c_name string at %lx\n", name); + sprintf(kbuf, "(unknown)"); } } FREEBUF(cache_buf); @@ -6982,13 +6992,14 @@ if (!read_string(name, buf, BUFSIZE-1)) { if (vt->flags & (PERCPU_KMALLOC_V1|PERCPU_KMALLOC_V2)) - error(FATAL, + error(WARNING, "cannot read kmem_cache_s.name string at %lx\n", name); else - error(FATAL, + error(WARNING, "cannot read kmem_cache_s.c_name string at %lx\n", name); + sprintf(buf, "(unknown)"); } } @@ -7566,10 +7577,12 @@ } else { name = ULONG(si->cache_buf + OFFSET(kmem_cache_s_c_name)); - if (!read_string(name, buf, BUFSIZE-1)) - error(FATAL, + if (!read_string(name, buf, BUFSIZE-1)) { + error(WARNING, "cannot read kmem_cache_s.c_name string at %lx\n", name); + sprintf(buf, "(unknown)"); + } } if (reqname && !STREQ(reqname, buf)) @@ -7764,10 +7777,12 @@ readmem(si->cache+OFFSET(kmem_cache_s_name), KVADDR, &name, sizeof(ulong), "name", FAULT_ON_ERROR); - if (!read_string(name, buf, BUFSIZE-1)) - error(FATAL, + if (!read_string(name, buf, BUFSIZE-1)) { + error(WARNING, "cannot read kmem_cache_s.name string at %lx\n", name); + sprintf(buf, "(unknown)"); + } } if (reqname && !STREQ(reqname, buf)) @@ -7984,10 +7999,12 @@ readmem(si->cache+OFFSET(kmem_cache_s_name), KVADDR, &name, sizeof(ulong), "name", FAULT_ON_ERROR); - if (!read_string(name, buf, BUFSIZE-1)) - error(FATAL, + if (!read_string(name, buf, BUFSIZE-1)) { + error(WARNING, "cannot read kmem_cache_s.name string at %lx\n", name); + sprintf(buf, "(unknown)"); + } } if (reqname && !STREQ(reqname, buf)) @@ -12229,7 +12246,9 @@ addr = mem_sec[SECTION_NR_TO_ROOT(nr)] + (nr & SECTION_ROOT_MASK()) * SIZE(mem_section); else - addr = mem_sec[0] + (nr & SECTION_ROOT_MASK()) * SIZE(mem_section); + addr = symbol_value("mem_section") + + (SECTIONS_PER_ROOT() * SECTION_NR_TO_ROOT(nr) + + (nr & SECTION_ROOT_MASK())) * SIZE(mem_section); if (!IS_KVADDR(addr)) return 0; @@ -12708,6 +12727,12 @@ static void kmem_cache_init_slub(void) { + if (CRASHDEBUG(1) && + !(vt->flags & CONFIG_NUMA) && (vt->numnodes > 1)) + error(WARNING, + "kmem_cache_init_slub: numnodes: %d without CONFIG_NUMA\n", + vt->numnodes); + vt->flags |= KMEM_CACHE_INIT; } @@ -12826,6 +12851,12 @@ continue; fprintf(fp, kmem_cache_hdr); } + if (ignore_cache(si, buf)) { + fprintf(fp, "%lx %-18s [IGNORED]\n", + si->cache_list[i], buf); + goto next_cache; + } + objsize = UINT(si->cache_buf + OFFSET(kmem_cache_objsize)); size = UINT(si->cache_buf + OFFSET(kmem_cache_size)); objects = UINT(si->cache_buf + OFFSET(kmem_cache_objects)); @@ -12961,6 +12992,9 @@ total_slabs += full_slabs; break; } + + if (!(vt->flags & CONFIG_NUMA)) + break; } switch (cmd) @@ -13038,6 +13072,9 @@ n, node_nr_slabs, node_nr_partial, per_cpu[n]); do_node_lists_slub(si, node_ptr, n); + + if (!(vt->flags & CONFIG_NUMA)) + break; } fprintf(fp, "\n"); --- crash-4.0-4.8/kernel.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/kernel.c 2007-11-06 13:32:23.000000000 -0500 @@ -390,8 +390,12 @@ STRUCT_SIZE_INIT(__wait_queue, "__wait_queue"); if (VALID_STRUCT(__wait_queue)) { - MEMBER_OFFSET_INIT(__wait_queue_task, - "__wait_queue", "task"); + if (MEMBER_EXISTS("__wait_queue", "task")) + MEMBER_OFFSET_INIT(__wait_queue_task, + "__wait_queue", "task"); + else + MEMBER_OFFSET_INIT(__wait_queue_task, + "__wait_queue", "private"); MEMBER_OFFSET_INIT(__wait_queue_head_task_list, "__wait_queue_head", "task_list"); MEMBER_OFFSET_INIT(__wait_queue_task_list, @@ -3017,6 +3021,18 @@ retbuf = search_directory_tree(dir, file); if (!retbuf) { + sprintf(dir, "/lib/modules/%s/updates", kt->utsname.release); + if (!(retbuf = search_directory_tree(dir, file))) { + switch (kt->flags & (KMOD_V1|KMOD_V2)) + { + case KMOD_V2: + sprintf(file, "%s.ko", modref); + retbuf = search_directory_tree(dir, file); + } + } + } + + if (!retbuf) { sprintf(dir, "/lib/modules/%s", kt->utsname.release); if (!(retbuf = search_directory_tree(dir, file))) { switch (kt->flags & (KMOD_V1|KMOD_V2)) --- crash-4.0-4.8/ia64.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/ia64.c 2007-11-15 10:41:51.000000000 -0500 @@ -3810,7 +3810,16 @@ phys_start); } return; - } + } else if (LKCD_DUMPFILE()) { + + if (lkcd_get_kernel_start(&phys_start)) { + machdep->machspec->phys_start = phys_start; + if (CRASHDEBUG(1)) + fprintf(fp, + "LKCD dump: phys_start: %lx\n", + phys_start); + } + } if ((vd = get_kdump_vmcore_data())) { /* --- crash-4.0-4.8/s390.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/s390.c 2007-11-15 13:36:08.000000000 -0500 @@ -21,17 +21,6 @@ #define S390_WORD_SIZE 4 #define S390_ADDR_MASK 0x7fffffff -#define S390_PAGE_SHIFT 12 -#define S390_PAGE_SIZE (1UL << S390_PAGE_SHIFT) -#define S390_PAGE_MASK (~(S390_PAGE_SIZE-1)) - -#define S390_PGDIR_SHIFT 20 -#define S390_PGDIR_SIZE (1UL << S390_PGDIR_SHIFT) -#define S390_PGDIR_MASK (~(S390_PGDIR_SIZE-1)) - -#define S390_PTRS_PER_PGD 2048 -#define S390_PTRS_PER_PTE 256 - #define S390_PMD_BASE_MASK (~((1UL<<6)-1)) #define S390_PT_BASE_MASK S390_PMD_BASE_MASK #define S390_PAGE_BASE_MASK (~((1UL<<12)-1)) @@ -44,26 +33,10 @@ #define S390_PAGE_INVALID 0x400 /* HW invalid */ #define S390_PAGE_INVALID_MASK 0x601ULL /* for linux 2.6 */ #define S390_PAGE_INVALID_NONE 0x401ULL /* for linux 2.6 */ -#define S390_PAGE_TABLE_LEN 0xf /* only full page-tables */ -#define S390_PAGE_TABLE_INV 0x20 /* invalid page-table */ #define S390_PTE_INVALID_MASK 0x80000900 #define S390_PTE_INVALID(x) ((x) & S390_PTE_INVALID_MASK) -#define S390_PMD_INVALID_MASK 0x80000000 -#define S390_PMD_INVALID(x) ((x) & S390_PMD_INVALID_MASK) - -/* pgd/pmd/pte query macros */ -#define s390_pmd_none(x) ((x) & S390_PAGE_TABLE_INV) -#define s390_pmd_bad(x) (((x) & (~S390_PMD_BASE_MASK & \ - ~S390_PAGE_TABLE_INV)) != \ - S390_PAGE_TABLE_LEN) - -#define s390_pte_none(x) (((x) & (S390_PAGE_INVALID | S390_RO_S390 | \ - S390_PAGE_PRESENT)) == \ - S390_PAGE_INVALID) - - #define ASYNC_STACK_SIZE STACKSIZE() // can be 4096 or 8192 #define KERNEL_STACK_SIZE STACKSIZE() // can be 4096 or 8192 @@ -73,8 +46,6 @@ * declarations of static functions */ static void s390_print_lowcore(char*, struct bt_info*,int); -static unsigned long s390_pgd_offset(unsigned long, unsigned long); -static unsigned long s390_pte_offset(unsigned long, unsigned long); static int s390_kvtop(struct task_context *, ulong, physaddr_t *, int); static int s390_uvtop(struct task_context *, ulong, physaddr_t *, int); static int s390_vtop(unsigned long, ulong, physaddr_t*, int); @@ -292,60 +263,87 @@ /* * page table traversal functions */ -static unsigned long -s390_pgd_offset(unsigned long pgd_base, unsigned long vaddr) -{ - unsigned long pgd_off, pmd_base; - pgd_off = ((vaddr >> S390_PGDIR_SHIFT) & (S390_PTRS_PER_PGD - 1)) - * S390_WORD_SIZE; - readmem(pgd_base + pgd_off, PHYSADDR, &pmd_base,sizeof(long), - "pgd_base",FAULT_ON_ERROR); - return pmd_base; -} - -unsigned long s390_pte_offset(unsigned long pte_base, unsigned long vaddr) +/* Segment table traversal function */ +static ulong _kl_sg_table_deref_s390(ulong vaddr, ulong table, int len) { - unsigned pte_off, pte_val; + ulong offset, entry; + + offset = ((vaddr >> 20) & 0x7ffUL) * 4; + if (offset >= (len + 1)*64) + /* Offset is over the table limit. */ + return 0; + readmem(table + offset, KVADDR, &entry, sizeof(entry), "entry", + FAULT_ON_ERROR); - pte_off = ((vaddr >> S390_PAGE_SHIFT) & (S390_PTRS_PER_PTE - 1)) - * S390_WORD_SIZE; - readmem(pte_base + pte_off, PHYSADDR, &pte_val, sizeof(long), - "pte_val",FAULT_ON_ERROR); - return pte_val; + /* + * Check if the segment table entry could be read and doesn't have + * any of the reserved bits set. + */ + if (entry & 0x80000000UL) + return 0; + /* Check if the segment table entry has the invalid bit set. */ + if (entry & 0x40UL) + return 0; + /* Segment table entry is valid and well formed. */ + return entry; +} + +/* Page table traversal function */ +static ulong _kl_pg_table_deref_s390(ulong vaddr, ulong table, int len) +{ + ulong offset, entry; + + offset = ((vaddr >> 12) & 0xffUL) * 4; + if (offset >= (len + 1)*64) + /* Offset is over the table limit. */ + return 0; + readmem(table + offset, KVADDR, &entry, sizeof(entry), "entry", + FAULT_ON_ERROR); + /* + * Check if the page table entry could be read and doesn't have + * any of the reserved bits set. + */ + if (entry & 0x80000900UL) + return 0; + /* Check if the page table entry has the invalid bit set. */ + if (entry & 0x400UL) + return 0; + /* Page table entry is valid and well formed. */ + return entry; } -/* - * Generic vtop function for user and kernel addresses - */ +/* lookup virtual address in page tables */ static int -s390_vtop(unsigned long pgd_base, ulong kvaddr, physaddr_t *paddr, int verbose) +s390_vtop(unsigned long table, ulong vaddr, physaddr_t *phys_addr, int verbose) { - unsigned pte_base, pte_val; + ulong entry, paddr; + int len; - /* get the pgd entry */ - pte_base = s390_pgd_offset(pgd_base,kvaddr); - if(S390_PMD_INVALID(pte_base) || - s390_pmd_bad(pte_base) || - s390_pmd_none(pte_base)) { - *paddr = 0; - return FALSE; - } - /* get the pte */ - pte_base = pte_base & S390_PT_BASE_MASK; - pte_val = s390_pte_offset(pte_base,kvaddr); - if(S390_PTE_INVALID(pte_val) || - s390_pte_none(pte_val)){ - *paddr = 0; + /* + * Get the segment table entry. + * We assume that the segment table length field in the asce + * is set to the maximum value of 127 (which translates to + * a segment table with 2048 entries) and that the addressing + * mode is 31 bit. + */ + entry = _kl_sg_table_deref_s390(vaddr, table, 127); + if (!entry) return FALSE; - } - if(!s390_pte_present(pte_val)){ - /* swapped out */ - *paddr = pte_val; + table = entry & 0x7ffffc00UL; + len = entry & 0xfUL; + + /* Get the page table entry */ + entry = _kl_pg_table_deref_s390(vaddr, table, len); + if (!entry) return FALSE; - } - *paddr = (pte_val & S390_PAGE_BASE_MASK) | - (kvaddr & (~(S390_PAGE_MASK))); + + /* Isolate the page origin from the page table entry. */ + paddr = entry & 0x7ffff000UL; + + /* Add the page offset and return the final value. */ + *phys_addr = paddr + (vaddr & 0xfffUL); + return TRUE; } --- crash-4.0-4.8/s390x.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/s390x.c 2007-11-15 13:36:08.000000000 -0500 @@ -20,24 +20,6 @@ #define S390X_WORD_SIZE 8 -#define S390X_PAGE_SHIFT 12 -#define S390X_PAGE_SIZE (1ULL << S390X_PAGE_SHIFT) -#define S390X_PAGE_MASK (~(S390X_PAGE_SIZE-1)) - -#define S390X_PGDIR_SHIFT 31 -#define S390X_PGDIR_SIZE (1ULL << S390X_PGDIR_SHIFT) -#define S390X_PGDIR_MASK (~(S390X_PGDIR_SIZE-1)) - -#define S390X_PMD_SHIFT 20 -#define S390X_PMD_SIZE (1ULL << S390X_PMD_SHIFT) -#define S390X_PMD_MASK (~(S390X_PMD_SIZE-1)) - -#define S390X_PTRS_PER_PGD 2048 -#define S390X_PTRS_PER_PMD 2048 -#define S390X_PTRS_PER_PTE 256 - -#define S390X_PMD_BASE_MASK (~((1ULL<<12)-1)) -#define S390X_PT_BASE_MASK (~((1ULL<<11)-1)) #define S390X_PAGE_BASE_MASK (~((1ULL<<12)-1)) /* Flags used in entries of page dirs and page tables. @@ -48,37 +30,11 @@ #define S390X_PAGE_INVALID 0x400ULL /* HW invalid */ #define S390X_PAGE_INVALID_MASK 0x601ULL /* for linux 2.6 */ #define S390X_PAGE_INVALID_NONE 0x401ULL /* for linux 2.6 */ -#define S390X_PMD_ENTRY_INV 0x20ULL /* invalid segment table entry */ -#define S390X_PGD_ENTRY_INV 0x20ULL /* invalid region table entry */ -#define S390X_PMD_ENTRY 0x00 -#define S390X_PGD_ENTRY_FIRST 0x05 /* first part of pmd is valid */ -#define S390X_PGD_ENTRY_SECOND 0xc7 /* second part of pmd is valid */ -#define S390X_PGD_ENTRY_FULL 0x07 /* complete pmd is valid */ /* bits 52, 55 must contain zeroes in a pte */ #define S390X_PTE_INVALID_MASK 0x900ULL #define S390X_PTE_INVALID(x) ((x) & S390X_PTE_INVALID_MASK) -/* pgd/pmd/pte query macros */ -#define s390x_pgd_none(x) ((x) & S390X_PGD_ENTRY_INV) -#define s390x_pgd_bad(x) !( (((x) & S390X_PGD_ENTRY_FIRST) == \ - S390X_PGD_ENTRY_FIRST) || \ - (((x) & S390X_PGD_ENTRY_SECOND) == \ - S390X_PGD_ENTRY_SECOND) || \ - (((x) & S390X_PGD_ENTRY_FULL) == \ - S390X_PGD_ENTRY_FULL)) - -#define s390x_pmd_none(x) ((x) & S390X_PMD_ENTRY_INV) -#define s390x_pmd_bad(x) (((x) & (~S390X_PT_BASE_MASK & \ - ~S390X_PMD_ENTRY_INV)) != \ - S390X_PMD_ENTRY) - -#define s390x_pte_none(x) (((x) & (S390X_PAGE_INVALID | \ - S390X_PAGE_RO | \ - S390X_PAGE_PRESENT)) == \ - S390X_PAGE_INVALID) - - #define ASYNC_STACK_SIZE STACKSIZE() // can be 8192 or 16384 #define KERNEL_STACK_SIZE STACKSIZE() // can be 8192 or 16384 @@ -88,9 +44,6 @@ * declarations of static functions */ static void s390x_print_lowcore(char*, struct bt_info*,int); -static unsigned long s390x_pgd_offset(unsigned long, unsigned long); -static unsigned long s390x_pmd_offset(unsigned long, unsigned long); -static unsigned long s390x_pte_offset(unsigned long, unsigned long); static int s390x_kvtop(struct task_context *, ulong, physaddr_t *, int); static int s390x_uvtop(struct task_context *, ulong, physaddr_t *, int); static int s390x_vtop(unsigned long, ulong, physaddr_t*, int); @@ -304,81 +257,97 @@ } } -/* +/* * page table traversal functions */ -unsigned long s390x_pgd_offset(unsigned long pgd_base, unsigned long vaddr) -{ - unsigned long pgd_off, pmd_base; - - pgd_off = ((vaddr >> S390X_PGDIR_SHIFT) & - (S390X_PTRS_PER_PGD - 1)) * 8; - readmem(pgd_base + pgd_off, PHYSADDR, &pmd_base, sizeof(long), - "pmd_base",FAULT_ON_ERROR); - - return pmd_base; -} -unsigned long s390x_pmd_offset(unsigned long pmd_base, unsigned long vaddr) -{ - unsigned long pmd_off, pte_base; - - pmd_off = ((vaddr >> S390X_PMD_SHIFT) & (S390X_PTRS_PER_PMD - 1)) - * 8; - readmem(pmd_base + pmd_off, PHYSADDR, &pte_base, sizeof(long), - "pte_base",FAULT_ON_ERROR); - return pte_base; -} - -unsigned long s390x_pte_offset(unsigned long pte_base, unsigned long vaddr) -{ - unsigned long pte_off, pte_val; - - pte_off = ((vaddr >> S390X_PAGE_SHIFT) & (S390X_PTRS_PER_PTE - 1)) - * 8; - readmem(pte_base + pte_off, PHYSADDR, &pte_val, sizeof(long), - "pte_val",FAULT_ON_ERROR); - return pte_val; +/* Region or segment table traversal function */ +static ulong _kl_rsg_table_deref_s390x(ulong vaddr, ulong table, + int len, int level) +{ + ulong offset, entry; + + offset = ((vaddr >> (11*level + 20)) & 0x7ffULL) * 8; + if (offset >= (len + 1)*4096) + /* Offset is over the table limit. */ + return 0; + readmem(table + offset, KVADDR, &entry, sizeof(entry), "entry", + FAULT_ON_ERROR); + /* + * Check if the segment table entry could be read and doesn't have + * any of the reserved bits set. + */ + if ((entry & 0xcULL) != (level << 2)) + return 0; + /* Check if the region table entry has the invalid bit set. */ + if (entry & 0x40ULL) + return 0; + /* Region table entry is valid and well formed. */ + return entry; } -/* - * Generic vtop function for user and kernel addresses - */ -static int -s390x_vtop(unsigned long pgd_base, ulong kvaddr, physaddr_t *paddr, int verbose) +/* Page table traversal function */ +static ulong _kl_pg_table_deref_s390x(ulong vaddr, ulong table) { - unsigned long pmd_base, pte_base, pte_val; + ulong offset, entry; - /* get the pgd entry */ - pmd_base = s390x_pgd_offset(pgd_base,kvaddr); - if(s390x_pgd_bad(pmd_base) || - s390x_pgd_none(pmd_base)){ - *paddr = 0; + offset = ((vaddr >> 12) & 0xffULL) * 8; + readmem(table + offset, KVADDR, &entry, sizeof(entry), "entry", + FAULT_ON_ERROR); + /* + * Check if the page table entry could be read and doesn't have + * any of the reserved bits set. + */ + if (entry & 0x900ULL) + return 0; + /* Check if the page table entry has the invalid bit set. */ + if (entry & 0x400ULL) + return 0; + /* Page table entry is valid and well formed. */ + return entry; +} + +/* lookup virtual address in page tables */ +int s390x_vtop(ulong table, ulong vaddr, physaddr_t *phys_addr, int verbose) +{ + ulong entry, paddr; + int level, len; + + /* + * Walk the region and segment tables. + * We assume that the table length field in the asce is set to the + * maximum value of 3 (which translates to a region first, region + * second, region third or segment table with 2048 entries) and that + * the addressing mode is 64 bit. + */ + len = 3; + /* Read the first entry to find the number of page table levels. */ + readmem(table, KVADDR, &entry, sizeof(entry), "entry", FAULT_ON_ERROR); + level = (entry & 0xcULL) >> 2; + if ((vaddr >> (31 + 11*level)) != 0ULL) { + /* Address too big for the number of page table levels. */ return FALSE; } - /* get the pmd */ - pmd_base = pmd_base & S390X_PMD_BASE_MASK; - pte_base = s390x_pmd_offset(pmd_base,kvaddr); - if(s390x_pmd_bad(pte_base) || - s390x_pmd_none(pte_base)) { - *paddr = 0; - return FALSE; + while (level >= 0) { + entry = _kl_rsg_table_deref_s390x(vaddr, table, len, level); + if (!entry) + return 0; + table = entry & ~0xfffULL; + len = entry & 0x3ULL; + level--; } - /* get the pte */ - pte_base = pte_base & S390X_PT_BASE_MASK; - pte_val = s390x_pte_offset(pte_base,kvaddr); - if (S390X_PTE_INVALID(pte_val) || - s390x_pte_none(pte_val)){ - *paddr = 0; - return FALSE; - } - if(!s390x_pte_present(pte_val)){ - /* swapped out */ - *paddr = pte_val; + + /* Get the page table entry */ + entry = _kl_pg_table_deref_s390x(vaddr, entry & ~0x7ffULL); + if (!entry) return FALSE; - } - *paddr = (pte_val & S390X_PAGE_BASE_MASK) | - (kvaddr & (~(S390X_PAGE_MASK))); + + /* Isolate the page origin from the page table entry. */ + paddr = entry & ~0xfffULL; + + /* Add the page offset and return the final value. */ + *phys_addr = paddr + (vaddr & 0xfffULL); + return TRUE; } --- crash-4.0-4.8/ppc64.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/ppc64.c 2007-11-13 14:24:01.000000000 -0500 @@ -160,7 +160,8 @@ m->l2_index_size = PMD_INDEX_SIZE_L4_64K; m->l3_index_size = PUD_INDEX_SIZE_L4_64K; m->l4_index_size = PGD_INDEX_SIZE_L4_64K; - m->pte_shift = PTE_SHIFT_L4_64K; + m->pte_shift = symbol_exists("demote_segment_4k") ? + PTE_SHIFT_L4_64K_V2 : PTE_SHIFT_L4_64K_V1; m->l2_masked_bits = PMD_MASKED_BITS_64K; } else { /* 4K pagesize */ @@ -305,7 +306,7 @@ void ppc64_dump_machdep_table(ulong arg) { - int others; + int i, c, others; others = 0; fprintf(fp, " flags: %lx (", machdep->flags); @@ -368,10 +369,41 @@ fprintf(fp, " max_physmem_bits: %ld\n", machdep->max_physmem_bits); fprintf(fp, " sections_per_root: %ld\n", machdep->sections_per_root); fprintf(fp, " machspec: %lx\n", (ulong)machdep->machspec); - fprintf(fp, " pgd_index_size: %d\n", machdep->machspec->l4_index_size); - fprintf(fp, " pud_index_size: %d\n", machdep->machspec->l3_index_size); - fprintf(fp, " pmd_index_size: %d\n", machdep->machspec->l2_index_size); - fprintf(fp, " pte_index_size: %d\n", machdep->machspec->l1_index_size); + fprintf(fp, " hwintrstack[%d]: ", NR_CPUS); + for (c = 0; c < NR_CPUS; c++) { + for (others = 0, i = c; i < NR_CPUS; i++) { + if (machdep->machspec->hwintrstack[i]) + others++; + } + if (!others) { + fprintf(fp, "%s%s", + c && ((c % 4) == 0) ? "\n " : "", + c ? "(remainder unused)" : "(unused)"); + break; + } + + fprintf(fp, "%s%016lx ", + ((c % 4) == 0) ? "\n " : "", + machdep->machspec->hwintrstack[c]); + } + fprintf(fp, "\n"); + fprintf(fp, " hwstackbuf: %lx\n", (ulong)machdep->machspec->hwstackbuf); + fprintf(fp, " hwstacksize: %d\n", machdep->machspec->hwstacksize); + fprintf(fp, " level4: %lx\n", (ulong)machdep->machspec->level4); + fprintf(fp, " last_level4_read: %lx\n", (ulong)machdep->machspec->last_level4_read); + fprintf(fp, " l4_index_size: %d\n", machdep->machspec->l4_index_size); + fprintf(fp, " l3_index_size: %d\n", machdep->machspec->l3_index_size); + fprintf(fp, " l2_index_size: %d\n", machdep->machspec->l2_index_size); + fprintf(fp, " l1_index_size: %d\n", machdep->machspec->l1_index_size); + fprintf(fp, " ptrs_per_l3: %d\n", machdep->machspec->ptrs_per_l3); + fprintf(fp, " ptrs_per_l2: %d\n", machdep->machspec->ptrs_per_l2); + fprintf(fp, " ptrs_per_l1: %d\n", machdep->machspec->ptrs_per_l1); + fprintf(fp, " l4_shift: %d\n", machdep->machspec->l4_shift); + fprintf(fp, " l3_shift: %d\n", machdep->machspec->l3_shift); + fprintf(fp, " l2_shift: %d\n", machdep->machspec->l2_shift); + fprintf(fp, " l1_shift: %d\n", machdep->machspec->l1_shift); + fprintf(fp, " pte_shift: %d\n", machdep->machspec->pte_shift); + fprintf(fp, " l2_masked_bits: %x\n", machdep->machspec->l2_masked_bits); } /* --- crash-4.0-4.8/symbols.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/symbols.c 2007-11-09 17:23:35.000000000 -0500 @@ -7516,6 +7516,9 @@ char *secname; int i; + if ((store = bfd_make_empty_symbol(bfd)) == NULL) + error(FATAL, "bfd_make_empty_symbol() failed\n"); + s1 = lm->mod_symtable; s2 = lm->mod_symend; while (s1 < s2) { --- crash-4.0-4.8/cmdline.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/cmdline.c 2007-10-31 14:18:48.000000000 -0500 @@ -400,6 +400,8 @@ CRASHPAGER_argv[i]); } break; + default: + return NULL; } return buf; --- crash-4.0-4.8/lkcd_common.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/lkcd_common.c 2007-11-16 15:18:05.000000000 -0500 @@ -708,14 +708,15 @@ if (lkcd->zones[ii].start == zone) { if (lkcd->zones[ii].pages[page].offset != 0) { if (lkcd->zones[ii].pages[page].offset != off) { - error(INFO, "conflicting page: zone %lld, " + if (CRASHDEBUG(1)) + error(INFO, "LKCD: conflicting page: zone %lld, " "page %lld: %lld, %lld != %lld\n", (unsigned long long)zone, (unsigned long long)page, (unsigned long long)paddr, (unsigned long long)off, (unsigned long long)lkcd->zones[ii].pages[page].offset); - abort(); + return -1; } ret = 0; } else { @@ -787,6 +788,27 @@ } +#ifdef IA64 + +int +lkcd_get_kernel_start(ulong *addr) +{ + if (!addr) + return 0; + + switch (lkcd->version) + { + case LKCD_DUMP_V8: + case LKCD_DUMP_V9: + return lkcd_get_kernel_start_v8(addr); + + default: + return 0; + } +} + +#endif + int lkcd_lseek(physaddr_t paddr) @@ -1244,7 +1266,7 @@ unsigned char *source, ulong sourcelen) { ulong retlen = destlen; - int rc; + int rc = FALSE; switch (uncompress(dest, &retlen, source, sourcelen)) { --- crash-4.0-4.8/lkcd_v8.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/lkcd_v8.c 2007-11-09 17:23:35.000000000 -0500 @@ -71,7 +71,7 @@ int get_lkcd_regs_for_cpu_v8(struct bt_info *bt, ulong *eip, ulong *esp) { - int cpu; + int cpu = bt->tc->processor; if (!bt || !bt->tc) { fprintf(stderr, "get_lkcd_regs_for_cpu_v8: invalid tc " @@ -79,8 +79,6 @@ return -EINVAL; } - cpu = bt->tc->processor; - if (cpu >= NR_CPUS) { fprintf(stderr, "get_lkcd_regs_for_cpu_v8, cpu (%d) too high\n", cpu); return -EINVAL; --- crash-4.0-4.8/lkcd_fix_mem.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/lkcd_fix_mem.c 2007-11-15 10:41:51.000000000 -0500 @@ -97,4 +97,14 @@ return 0; } +int lkcd_get_kernel_start_v8(ulong *addr) +{ + if (!addr) + return 0; + + *addr = ((dump_header_asm_t *)lkcd->dump_header_asm)->dha_kernel_addr; + + return 1; +} + #endif // IA64 --- crash-4.0-4.8/defs.h 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/defs.h 2007-11-15 12:09:43.000000000 -0500 @@ -2526,7 +2526,8 @@ #define PMD_INDEX_SIZE_L4_64K 12 #define PUD_INDEX_SIZE_L4_64K 0 #define PGD_INDEX_SIZE_L4_64K 4 -#define PTE_SHIFT_L4_64K 32 +#define PTE_SHIFT_L4_64K_V1 32 +#define PTE_SHIFT_L4_64K_V2 30 #define PMD_MASKED_BITS_64K 0x1ff #define L4_OFFSET(vaddr) ((vaddr >> (machdep->machspec->l4_shift)) & 0x1ff) @@ -3874,6 +3875,7 @@ int lkcd_dump_init_v8_arch(struct _dump_header_s *dh); int fix_addr_v7(int); int get_lkcd_regs_for_cpu_arch(int cpu, ulong *eip, ulong *esp); +int lkcd_get_kernel_start_v8(ulong *addr); /* * lkcd_v8.c @@ -4144,6 +4146,7 @@ void lkcd_dumpfile_complaint(uint32_t, uint32_t, int); int set_mb_benchmark(ulong); ulonglong fix_lkcd_address(ulonglong); +int lkcd_get_kernel_start(ulong *addr); int get_lkcd_regs_for_cpu(struct bt_info *bt, ulong *eip, ulong *esp); /* --- crash-4.0-4.8/extensions/echo.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/extensions/echo.c 2007-11-09 16:53:29.000000000 -0500 @@ -17,25 +17,34 @@ #include "defs.h" /* From the crash source top-level directory */ -void cmd_echo(); /* Declare the commands and their help data. */ +int _init(void); +int _fini(void); + +void cmd_echo(void); /* Declare the commands and their help data. */ char *help_echo[]; static struct command_table_entry command_table[] = { - "echo", cmd_echo, help_echo, 0, /* One or more commands, */ - NULL, /* terminated by NULL, */ + { "echo", cmd_echo, help_echo, 0 }, /* One or more commands, */ + { NULL } /* terminated by NULL, */ }; -_init() /* Register the command set. */ +int +_init(void) /* Register the command set. */ { register_extension(command_table); + return 1; } /* * The _fini() function is called if the shared object is unloaded. * If desired, perform any cleanups here. */ -_fini() { } +int +_fini(void) +{ + return 1; +} /* @@ -45,7 +54,7 @@ * to accomplish what your task. */ void -cmd_echo() +cmd_echo(void) { int c; --- crash-4.0-4.8/extensions/dminfo.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/extensions/dminfo.c 2007-11-09 16:53:29.000000000 -0500 @@ -16,6 +16,9 @@ #include "defs.h" /* From the crash source top-level directory */ +int _init(void); +int _fini(void); + /* * Indices of size-offset array (Used by GET_xxx macros) * @@ -1508,7 +1511,7 @@ {NULL, NULL, NULL, 0}, }; -int _init() +int _init(void) { register_extension(command_table); @@ -1525,7 +1528,7 @@ return 0; } -int _fini() +int _fini(void) { return 0; } --- crash-4.0-4.8/extensions/libsial/sial_op.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/extensions/libsial/sial_op.c 2007-11-09 15:44:42.000000000 -0500 @@ -28,15 +28,15 @@ #define V3 (v3?v3:(v3=NODE_EXE(P3))) #define V4 (v4?v4:(v4=NODE_EXE(P4))) -#define L1 (unival(v1?v1:V1)) -#define L2 (unival(v2?v2:V2)) -#define L3 (unival(v3?v3:V3)) -#define L4 (unival(v4?v4:V4)) - -#define S1 ((v1?v1:V1)->v.data) -#define S2 ((v2?v2:V2)->v.data) -#define S3 ((v3?v3:V3)->v.data) -#define S4 ((v4?v4:V4)->v.data) +#define L1 (unival(V1)) +#define L2 (unival(V2)) +#define L3 (unival(V3)) +#define L4 (unival(V4)) + +#define S1 ((V1)->v.data) +#define S2 ((V2)->v.data) +#define S3 ((V3)->v.data) +#define S4 ((V4)->v.data) void sial_do_deref(int n, value_t *v, value_t *ref); ul @@ -545,39 +545,53 @@ case ADD: { /* expr + expr */ /* adding two pointers ? */ if(V2->type.type == V_REF) goto inval; - sial_transfer(v=sial_newval(), V1, L1 + L2*size); + + V1; + sial_transfer(v=sial_newval(), v1, + unival(v1) + L2 * size); } break; case SUB: { /* expr - expr */ - /* different results if mixed types. if both are pointers then result is a V_BASE */ if(V2->type.type == V_REF) v=sial_makebtype(L1 - L2); - else sial_transfer(v=sial_newval(), V1, L1 - L2*size); + else { + V1; + sial_transfer(v=sial_newval(), v1, + unival(v1) - L2 * size); + } } break; case PREDECR: { /* pre is easy */ - sial_transfer(v=sial_newval(), V1, L1-size); - sial_setval(V1, v); + V1; + sial_transfer(v=sial_newval(), v1, + unival(v1) - size); + sial_setval(v1, v); } break; case PREINCR: { - sial_transfer(v=sial_newval(), V1, L1+size); - sial_setval(V1, v); + V1; + sial_transfer(v=sial_newval(), v1, + unival(v1) + size); + sial_setval(v1, v); } break; case POSTINCR: { - sial_transfer(v=sial_newval(), V1, L1+size); - sial_setval(V1, v); - sial_transfer(v, V1, L1); + V1; + sial_transfer(v=sial_newval(), v1, + unival(v1) + size); + sial_setval(v1, v); + sial_transfer(v, v1, unival(v1)); } break; case POSTDECR: { - sial_transfer(v=sial_newval(), V1, L1-size); - sial_setval(V1, v); - sial_transfer(v, V1, L1); + V1; + sial_transfer(v=sial_newval(), v1, + unival(v1) - size); + sial_setval(v1, v); + sial_transfer(v, v1, unival(v1)); } break; default: @@ -625,26 +639,33 @@ } break; case PREDECR: { /* pre is easy */ - sial_transfer(v=sial_newval(), V1, L1-1); - sial_setval(V1, v); + V1; + sial_transfer(v=sial_newval(), v1, + unival(v1) - 1); + sial_setval(v1, v); } break; case PREINCR: { V1; - sial_transfer(v=sial_newval(), V1, L1+1); - sial_setval(V1, v); + sial_transfer(v=sial_newval(), v1, + unival(v1) + 1); + sial_setval(v1, v); } break; case POSTINCR: { - sial_transfer(v=sial_newval(), V1, L1+1); - sial_setval(V1, v); - sial_transfer(v, V1, L1); + V1; + sial_transfer(v=sial_newval(), v1, + unival(v1) + 1); + sial_setval(v1, v); + sial_transfer(v, v1, unival(v1)); } break; case POSTDECR: { - sial_transfer(v=sial_newval(), V1, L1-1); - sial_setval(V1, v); - sial_transfer(v, V1, L1); + V1; + sial_transfer(v=sial_newval(), v1, + unival(v1) - 1); + sial_setval(v1, v); + sial_transfer(v, v1, unival(v1)); } break; default: sial_rerror(&P1->pos, "Oops ops ! [%d]", top); @@ -682,12 +703,14 @@ else { /* if it's a Me-op then v is already set */ - if(top != o->op) { sial_setval(V1, v); } - else { - - sial_setval(V1, V2); + V1; + if(top != o->op) { + sial_setval(v1, v); + } else { + sial_setval(v1, V2); v=sial_cloneval(V2); } + } } /* the result of a assignment if not an Lvalue_t */ --- crash-4.0-4.8/extensions/sial.c 2007-11-19 16:10:47.000000000 -0500 +++ crash-4.0-4.9/extensions/sial.c 2007-11-13 16:03:15.000000000 -0500 @@ -1,5 +1,5 @@ /* - * $Id: sial.c,v 1.3 2007/10/30 15:50:57 anderson Exp $ + * $Id: sial.c,v 1.5 2007/11/13 21:03:15 anderson Exp $ * * This file is part of lcrash, an analysis tool for Linux memory dumps. * @@ -638,7 +638,17 @@ run_callback(void) { extern char *crash_global_cmd(); +FILE *ofp = NULL; + + if (fp) { + ofp = sial_getofile(); + sial_setofile(fp); + } + sial_cmd(crash_global_cmd(), args, argcnt); + + if (ofp) + sial_setofile(ofp); }