--- crash-4.0-4.11/memory.c 2007-12-12 13:51:52.000000000 -0500 +++ crash-4.0-4.12/memory.c 2007-12-11 16:09:56.000000000 -0500 @@ -96,6 +96,7 @@ static void dump_kmem_cache_slub(struct meminfo *); static void dump_kmem_cache_info_v2(struct meminfo *); static void kmem_cache_list_slub(void); +static ulong get_cpu_slab_ptr(struct meminfo *, int); static char *vaddr_to_kmem_cache(ulong, char *); static ulong vaddr_to_slab(ulong); static void do_slab_chain(int, struct meminfo *); @@ -453,10 +454,11 @@ MEMBER_OFFSET_INIT(kmem_cache_cpu_slab, "kmem_cache", "cpu_slab"); MEMBER_OFFSET_INIT(kmem_cache_list, "kmem_cache", "list"); MEMBER_OFFSET_INIT(kmem_cache_name, "kmem_cache", "name"); + MEMBER_OFFSET_INIT(kmem_cache_cpu_freelist, "kmem_cache_cpu", "freelist"); + MEMBER_OFFSET_INIT(kmem_cache_cpu_page, "kmem_cache_cpu", "page"); + MEMBER_OFFSET_INIT(kmem_cache_cpu_node, "kmem_cache_cpu", "node"); ANON_MEMBER_OFFSET_INIT(page_inuse, "page", "inuse"); ANON_MEMBER_OFFSET_INIT(page_offset, "page", "offset"); - ANON_MEMBER_OFFSET_INIT(page_lockless_freelist, "page", - "lockless_freelist"); ANON_MEMBER_OFFSET_INIT(page_slab, "page", "slab"); ANON_MEMBER_OFFSET_INIT(page_first_page, "page", "first_page"); ANON_MEMBER_OFFSET_INIT(page_freelist, "page", "freelist"); @@ -467,6 +469,7 @@ ARRAY_LENGTH_INIT(len, NULL, "kmem_cache.cpu_slab", NULL, 0); STRUCT_SIZE_INIT(kmem_cache_node, "kmem_cache_node"); + STRUCT_SIZE_INIT(kmem_cache_cpu, "kmem_cache_cpu"); MEMBER_OFFSET_INIT(kmem_cache_node_nr_partial, "kmem_cache_node", "nr_partial"); MEMBER_OFFSET_INIT(kmem_cache_node_nr_slabs, @@ -3390,6 +3393,7 @@ #define SLAB_DATA_NOSAVE (ADDRESS_SPECIFIED << 18) #define GET_SLUB_SLABS (ADDRESS_SPECIFIED << 19) #define GET_SLUB_OBJECTS (ADDRESS_SPECIFIED << 20) +#define VMLIST_VERIFY (ADDRESS_SPECIFIED << 21) #define GET_ALL \ (GET_SHARED_PAGES|GET_TOTALRAM_PAGES|GET_BUFFERS_PAGES|GET_SLAB_PAGES) @@ -6024,8 +6028,8 @@ PAGEOFFSET(fi->spec_addr) ? "in " : ""); break; } - fprintf(fp, "%s of %ld pages) ", - ordinal(offset+1, buf), power(2, order)); + fprintf(fp, "%s of %ld pages)", + ordinal(offset+1, buf), chunk_size/PAGESIZE()); } fi->retval = TRUE; @@ -6137,23 +6141,36 @@ static int dump_zone_free_area(ulong free_area, int num, ulong verbose) { - int i; + int i, j; long chunk_size; int flen, total_free, cnt; char buf[BUFSIZE]; ulong free_area_buf[3]; + char *free_area_buf2; + char *free_list_buf; + ulong free_list; struct list_data list_data, *ld; + int list_count; + ulong *free_ptr; if (VALID_STRUCT(free_area_struct)) { if (SIZE(free_area_struct) != (3 * sizeof(ulong))) error(FATAL, "unrecognized free_area_struct size: %ld\n", SIZE(free_area_struct)); + list_count = 1; } else if (VALID_STRUCT(free_area)) { - if (SIZE(free_area) != (3 * sizeof(ulong))) - error(FATAL, - "unrecognized free_area struct size: %ld\n", - SIZE(free_area)); + if (SIZE(free_area) == (3 * sizeof(ulong))) + list_count = 1; + else { + list_count = MEMBER_SIZE("free_area", + "free_list")/SIZE(list_head); + free_area_buf2 = GETBUF(SIZE(free_area)); + free_list_buf = GETBUF(SIZE(list_head)); + readmem(free_area, KVADDR, free_area_buf2, + SIZE(free_area), "free_area struct", + FAULT_ON_ERROR); + } } else error(FATAL, "neither free_area_struct or free_area structures exist\n"); @@ -6165,6 +6182,9 @@ total_free = 0; flen = MAX(VADDR_PRLEN, strlen("FREE_AREA_STRUCT")); + if (list_count > 1) + goto multiple_lists; + for (i = 0; i < num; i++, free_area += SIZE_OPTION(free_area_struct, free_area)) { if (verbose) @@ -6216,6 +6236,65 @@ } return total_free; + +multiple_lists: + + for (i = 0; i < num; i++, + free_area += SIZE_OPTION(free_area_struct, free_area)) { + + readmem(free_area, KVADDR, free_area_buf2, + SIZE(free_area), "free_area struct", FAULT_ON_ERROR); + + for (j = 0, free_list = free_area; j < list_count; + j++, free_list += SIZE(list_head)) { + + if (verbose) + fprintf(fp, free_area_hdr3); + + fprintf(fp, "%3d ", i); + chunk_size = power(2, i); + sprintf(buf, "%ldk", (chunk_size * PAGESIZE())/1024); + fprintf(fp, " %7s ", buf); + + readmem(free_list, KVADDR, free_list_buf, + SIZE(list_head), "free_area free_list", + FAULT_ON_ERROR); + fprintf(fp, "%s ", + mkstring(buf, flen, CENTER|LONG_HEX, MKSTR(free_list))); + + free_ptr = (ulong *)free_list_buf; + + if (*free_ptr == free_list) { + if (verbose) + fprintf(fp, "\n"); + else + fprintf(fp, "%6d %6d\n", 0, 0); + continue; + } + + BZERO(ld, sizeof(struct list_data)); + ld->flags = verbose | RETURN_ON_DUPLICATE; + ld->start = *free_ptr; + ld->end = free_list; + ld->list_head_offset = OFFSET(page_lru) + + OFFSET(list_head_next); + + cnt = do_list(ld); + if (cnt < 0) + error(FATAL, + "corrupted free list %d from free_area struct: %lx\n", + j, free_area); + + if (!verbose) + fprintf(fp, "%6d %6ld\n", cnt, cnt*chunk_size); + + total_free += (cnt * chunk_size); + } + } + + FREEBUF(free_area_buf2); + FREEBUF(free_list_buf); + return total_free; } /* @@ -6531,17 +6610,17 @@ char buf1[BUFSIZE]; char buf2[BUFSIZE]; ulong vmlist; - ulong addr, size, next, pcheck, count; + ulong addr, size, next, pcheck, count, verified; physaddr_t paddr; get_symbol_data("vmlist", sizeof(void *), &vmlist); next = vmlist; - count = 0; + count = verified = 0; while (next) { if (!(pc->curcmd_flags & HEADER_PRINTED) && (next == vmlist) && !(vi->flags & (GET_HIGHEST|GET_PHYS_TO_VMALLOC| - GET_VMLIST_COUNT|GET_VMLIST))) { + GET_VMLIST_COUNT|GET_VMLIST|VMLIST_VERIFY))) { fprintf(fp, "%s ", mkstring(buf, MAX(strlen("VM_STRUCT"), VADDR_PRLEN), CENTER|LJUST, "VM_STRUCT")); @@ -6574,7 +6653,11 @@ if (!(vi->flags & ADDRESS_SPECIFIED) || ((vi->memtype == KVADDR) && - ((vi->spec_addr >= addr) && (vi->spec_addr < (addr+size))))) + ((vi->spec_addr >= addr) && (vi->spec_addr < (addr+size))))) { + if (vi->flags & VMLIST_VERIFY) { + verified++; + break; + } fprintf(fp, "%s%s %s - %s %6ld\n", mkstring(buf,VADDR_PRLEN, LONG_HEX|CENTER|LJUST, MKSTR(next)), space(MINSPACE-1), @@ -6583,6 +6666,7 @@ mkstring(buf2, VADDR_PRLEN, LONG_HEX|LJUST, MKSTR(addr+size)), size); + } if ((vi->flags & ADDRESS_SPECIFIED) && (vi->memtype == PHYSADDR)) { @@ -6623,6 +6707,9 @@ if (vi->flags & GET_VMLIST_COUNT) vi->retval = count; + + if (vi->flags & VMLIST_VERIFY) + vi->retval = verified; } /* @@ -10076,6 +10163,8 @@ ulong task; struct task_context *tc; + pc->curcmd_flags &= ~HEADER_PRINTED; + switch (mi->memtype) { case KVADDR: @@ -10108,18 +10197,22 @@ */ if ((mi->memtype == KVADDR) && IS_VMALLOC_ADDR(mi->spec_addr)) { if (kvtop(NULL, mi->spec_addr, &paddr, 0)) { - mi->flags = orig_flags; + mi->flags = orig_flags | VMLIST_VERIFY; dump_vmlist(mi); - fprintf(fp, "\n"); - mi->spec_addr = paddr; - mi->memtype = PHYSADDR; + if (mi->retval) { + mi->flags = orig_flags; + dump_vmlist(mi); + fprintf(fp, "\n"); + mi->spec_addr = paddr; + mi->memtype = PHYSADDR; + goto mem_map; + } } - goto mem_map; } + /* * If the address is physical, check whether it's in vmalloc space. */ - if (mi->memtype == PHYSADDR) { mi->flags = orig_flags; mi->flags |= GET_PHYS_TO_VMALLOC; @@ -10200,8 +10293,8 @@ dump_mem_map(mi); if (!mi->retval) - fprintf(fp, "%llx: address not found\n", mi->spec_addr); - + fprintf(fp, "%llx: %s address not found in mem map\n", + mi->spec_addr, memtype_string(mi->memtype, 0)); } /* @@ -10520,6 +10613,7 @@ fprintf(fp, " slab_data: %lx\n", (ulong)vt->slab_data); if (verbose) dump_saved_slab_data(); + fprintf(fp, " cpu_slab_type: %d\n", vt->cpu_slab_type); fprintf(fp, " nr_swapfiles: %d\n", vt->nr_swapfiles); fprintf(fp, " last_swap_read: %lx\n", vt->last_swap_read); fprintf(fp, " swap_info_struct: %lx\n", (ulong)vt->swap_info_struct); @@ -11514,6 +11608,7 @@ } if (initialize) { + pgdat = UNINITIALIZED; /* * This order may have to change based upon architecture... */ @@ -11537,6 +11632,11 @@ } else pgdat = vt->node_table[0].pgdat; + if (initialize && (pgdat == UNINITIALIZED)) { + error(WARNING, "cannot initialize pgdat list\n\n"); + return; + } + for (n = 0, badaddr = FALSE; pgdat; n++) { if (n >= vt->numnodes) error(FATAL, "numnodes out of sync with pgdat_list?\n"); @@ -12405,8 +12505,8 @@ } /* - * For kernels containing the node_online_map, return - * the number of node bits set. + * For kernels containing the node_online_map or node_states[], + * return the number of online node bits set. */ static int get_nodes_online(void) @@ -12414,24 +12514,37 @@ int i, len, online; struct gnu_request req; ulong *maskptr; + long N_ONLINE; + ulong mapaddr; - if (!symbol_exists("node_online_map")) + if (!symbol_exists("node_online_map") && + !symbol_exists("node_states")) return 0; if (LKCD_KERNTYPES()) { if ((len = STRUCT_SIZE("nodemask_t")) < 0) error(FATAL, "cannot determine type nodemask_t\n"); - } else + mapaddr = symbol_value("node_online_map"); + } else if (symbol_exists("node_online_map")) { len = get_symbol_type("node_online_map", NULL, &req) == TYPE_CODE_UNDEF ? sizeof(ulong) : req.length; + mapaddr = symbol_value("node_online_map"); + } else if (symbol_exists("node_states")) { + if ((get_symbol_type("node_states", NULL, &req) != TYPE_CODE_ARRAY) || + !(len = get_array_length("node_states", NULL, 0)) || + !enumerator_value("N_ONLINE", &N_ONLINE)) + return 0; + len = req.length / len; + mapaddr = symbol_value("node_states") + (N_ONLINE * len); + } if (!(vt->node_online_map = (ulong *)malloc(len))) error(FATAL, "cannot malloc node_online_map\n"); - if (!readmem(symbol_value("node_online_map"), KVADDR, + if (!readmem(mapaddr, KVADDR, (void *)&vt->node_online_map[0], len, "node_online_map", QUIET|RETURN_ON_ERROR)) - error(FATAL, "cannot read node_online_map\n"); + error(FATAL, "cannot read node_online_map/node_states\n"); vt->node_online_map_len = len/sizeof(ulong); @@ -12736,6 +12849,8 @@ "kmem_cache_init_slub: numnodes: %d without CONFIG_NUMA\n", vt->numnodes); + vt->cpu_slab_type = MEMBER_TYPE("kmem_cache", "cpu_slab"); + vt->flags |= KMEM_CACHE_INIT; } @@ -12926,8 +13041,8 @@ total_slabs = total_objects = 0; for (i = 0; i < kt->cpus; i++) { - cpu_slab_ptr = ULONG(si->cache_buf + - OFFSET(kmem_cache_cpu_slab) + (sizeof(void *)*i)); + cpu_slab_ptr = get_cpu_slab_ptr(si, i); + if (!cpu_slab_ptr) continue; @@ -13031,8 +13146,7 @@ per_cpu = (ulong *)GETBUF(sizeof(ulong) * vt->numnodes); for (i = 0; i < kt->cpus; i++) { - cpu_slab_ptr = ULONG(si->cache_buf + - OFFSET(kmem_cache_cpu_slab) + (sizeof(void *)*i)); + cpu_slab_ptr = get_cpu_slab_ptr(si, i); fprintf(fp, "CPU %d SLAB:\n%s", i, cpu_slab_ptr ? "" : " (empty)\n"); @@ -13100,7 +13214,7 @@ physaddr_t paddr; ulong vaddr; ushort inuse; - ulong freelist, lockless_freelist, cpu_slab_ptr; + ulong freelist, cpu_slab_ptr; int i, cpu_slab, is_free, node; ulong p, q; @@ -13116,6 +13230,7 @@ si->slab); return; } + node = page_to_nid(si->slab); vaddr = PTOV(paddr); @@ -13129,10 +13244,6 @@ if (!readmem(si->slab + OFFSET(page_freelist), KVADDR, &freelist, sizeof(void *), "page.freelist", RETURN_ON_ERROR)) return; - if (!readmem(si->slab + OFFSET(page_lockless_freelist), KVADDR, - &lockless_freelist, sizeof(void *), "page.lockless_freelist", - RETURN_ON_ERROR)) - return; DUMP_SLAB_INFO_SLUB(); @@ -13140,8 +13251,8 @@ return; for (i = 0, cpu_slab = -1; i < kt->cpus; i++) { - cpu_slab_ptr = ULONG(si->cache_buf + - OFFSET(kmem_cache_cpu_slab) + (sizeof(void *)*i)); + cpu_slab_ptr = get_cpu_slab_ptr(si, i); + if (!cpu_slab_ptr) continue; if (cpu_slab_ptr == si->slab) { @@ -13450,6 +13561,45 @@ return retval; } +/* + * Figure out which of the kmem_cache.cpu_slab declarations + * is used by this kernel, and return a pointer to the slab + * page being used. + */ +static ulong +get_cpu_slab_ptr(struct meminfo *si, int cpu) +{ + ulong cpu_slab_ptr, page; + + switch (vt->cpu_slab_type) + { + case TYPE_CODE_STRUCT: + cpu_slab_ptr = ULONG(si->cache_buf + + OFFSET(kmem_cache_cpu_slab) + + OFFSET(kmem_cache_cpu_page)); + break; + + case TYPE_CODE_ARRAY: + cpu_slab_ptr = ULONG(si->cache_buf + + OFFSET(kmem_cache_cpu_slab) + (sizeof(void *)*cpu)); + + if (cpu_slab_ptr && VALID_MEMBER(kmem_cache_cpu_page)) { + if (!readmem(cpu_slab_ptr + OFFSET(kmem_cache_cpu_page), + KVADDR, &page, sizeof(void *), + "kmem_cache_cpu.page", RETURN_ON_ERROR)) + cpu_slab_ptr = 0; + else + cpu_slab_ptr = page; + } + break; + + default: + error(FATAL, "cannot determine location of kmem_cache.cpu_slab page\n"); + } + + return cpu_slab_ptr; +} + #ifdef NOT_USED ulong slab_to_kmem_cache_node(struct meminfo *si, ulong slab_page) --- crash-4.0-4.11/task.c 2007-12-12 13:51:52.000000000 -0500 +++ crash-4.0-4.12/task.c 2007-12-12 11:58:30.000000000 -0500 @@ -6396,15 +6396,16 @@ dump_CFS_runqueues(void) { int cpu; - ulong runq; - char *runqbuf; + ulong runq, cfs_rq; + char *runqbuf, *cfs_rq_buf; ulong leftmost, tasks_timeline; struct task_context *tc; long nr_running, cfs_rq_nr_running; struct rb_root *root; struct rb_node *node; - if (INVALID_MEMBER(rq_rt)) { + if (!VALID_STRUCT(cfs_rq)) { + STRUCT_SIZE_INIT(cfs_rq, "cfs_rq"); MEMBER_OFFSET_INIT(rq_rt, "rq", "rt"); MEMBER_OFFSET_INIT(rq_nr_running, "rq", "nr_running"); MEMBER_OFFSET_INIT(task_struct_se, "task_struct", "se"); @@ -6425,31 +6426,56 @@ runq = symbol_value("per_cpu__runqueues"); runqbuf = GETBUF(SIZE(runqueue)); + cfs_rq_buf = symbol_exists("per_cpu__init_cfs_rq") ? + GETBUF(SIZE(cfs_rq)) : NULL; for (cpu = 0; cpu < kt->cpus; cpu++) { if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { runq = symbol_value("per_cpu__runqueues") + - kt->__per_cpu_offset[cpu]; + kt->__per_cpu_offset[cpu]; } else runq = symbol_value("per_cpu__runqueues"); fprintf(fp, "RUNQUEUES[%d]: %lx\n", cpu, runq); - readmem(runq, KVADDR, runqbuf, SIZE(runqueue), "per-cpu rq", FAULT_ON_ERROR); - leftmost = ULONG(runqbuf + OFFSET(rq_cfs) + - OFFSET(cfs_rq_rb_leftmost)); - tasks_timeline = ULONG(runqbuf + OFFSET(rq_cfs) + - OFFSET(cfs_rq_tasks_timeline)); - nr_running = LONG(runqbuf + OFFSET(rq_nr_running)); - cfs_rq_nr_running = ULONG(runqbuf + OFFSET(rq_cfs) + - OFFSET(cfs_rq_nr_running)); + + if (cfs_rq_buf) { + /* + * Use default task group's cfs_rq on each cpu. + */ + if ((kt->flags & SMP) && (kt->flags & PER_CPU_OFF)) { + cfs_rq = symbol_value("per_cpu__init_cfs_rq") + + kt->__per_cpu_offset[cpu]; + } else + cfs_rq = symbol_value("per_cpu__init_cfs_rq"); + + readmem(cfs_rq, KVADDR, cfs_rq_buf, SIZE(cfs_rq), + "per-cpu cfs_rq", FAULT_ON_ERROR); + leftmost = ULONG(cfs_rq_buf + OFFSET(cfs_rq_rb_leftmost)); + tasks_timeline = ULONG(cfs_rq_buf + + OFFSET(cfs_rq_tasks_timeline)); + nr_running = LONG(cfs_rq_buf + OFFSET(rq_nr_running)); + cfs_rq_nr_running = ULONG(cfs_rq_buf + + OFFSET(cfs_rq_nr_running)); + root = (struct rb_root *)(cfs_rq + + OFFSET(cfs_rq_tasks_timeline)); + } else { + leftmost = ULONG(runqbuf + OFFSET(rq_cfs) + + OFFSET(cfs_rq_rb_leftmost)); + tasks_timeline = ULONG(runqbuf + OFFSET(rq_cfs) + + OFFSET(cfs_rq_tasks_timeline)); + nr_running = LONG(runqbuf + OFFSET(rq_nr_running)); + cfs_rq_nr_running = ULONG(runqbuf + OFFSET(rq_cfs) + + OFFSET(cfs_rq_nr_running)); + root = (struct rb_root *)(runq + OFFSET(rq_cfs) + + OFFSET(cfs_rq_tasks_timeline)); + } dump_RT_prio_array(nr_running != cfs_rq_nr_running, runq + OFFSET(rq_rt) + OFFSET(rt_rq_active), &runqbuf[OFFSET(rq_rt) + OFFSET(rt_rq_active)]); - root = (struct rb_root *)(runq + OFFSET(rq_cfs) + OFFSET(cfs_rq_tasks_timeline)); fprintf(fp, " CFS RB_ROOT: %lx\n", (ulong)root); if (!leftmost) @@ -6464,6 +6490,10 @@ print_task_header(fp, tc, FALSE); } } + + FREEBUF(runqbuf); + if (cfs_rq_buf) + FREEBUF(cfs_rq_buf); } static void --- crash-4.0-4.11/dev.c 2007-12-12 13:51:52.000000000 -0500 +++ crash-4.0-4.12/dev.c 2007-12-11 14:53:08.000000000 -0500 @@ -141,6 +141,8 @@ char *char_device_struct_buf; ulong next, savenext, name, fops; int major; + int name_typecode; + size_t name_size; if (!symbol_exists("chrdevs")) error(FATAL, "chrdevs: symbol does not exist\n"); @@ -188,6 +190,8 @@ char_device_struct_buf = GETBUF(SIZE(char_device_struct)); cdp = (ulong *)&chrdevs[0]; + name_typecode = MEMBER_TYPE("char_device_struct", "name"); + name_size = (size_t)MEMBER_SIZE("char_device_struct", "name"); for (i = 0; i < MAX_DEV; i++, cdp++) { if (!(*cdp)) @@ -201,11 +205,18 @@ OFFSET(char_device_struct_next)); name = ULONG(char_device_struct_buf + OFFSET(char_device_struct_name)); - if (name) { - if (!read_string(name, buf, BUFSIZE-1)) - sprintf(buf, "(unknown)"); - } else - sprintf(buf, "(unknown)"); + switch (name_typecode) + { + case TYPE_CODE_ARRAY: + snprintf(buf, name_size, char_device_struct_buf + + OFFSET(char_device_struct_name)); + break; + case TYPE_CODE_PTR: + default: + if (!name || !read_string(name, buf, BUFSIZE-1)) + break; + } + fops = ULONG(char_device_struct_buf + OFFSET(char_device_struct_fops)); major = INT(char_device_struct_buf + @@ -243,11 +254,19 @@ OFFSET(char_device_struct_next)); name = ULONG(char_device_struct_buf + OFFSET(char_device_struct_name)); - if (name) { - if (!read_string(name, buf, BUFSIZE-1)) - sprintf(buf, "(unknown)"); - } else - sprintf(buf, "(unknown)"); + switch (name_typecode) + { + case TYPE_CODE_ARRAY: + snprintf(buf, name_size, char_device_struct_buf + + OFFSET(char_device_struct_name)); + break; + case TYPE_CODE_PTR: + default: + if (!name || !read_string(name, buf, BUFSIZE-1)) + sprintf(buf, "(unknown)"); + break; + } + fops = ULONG(char_device_struct_buf + OFFSET(char_device_struct_fops)); major = INT(char_device_struct_buf + --- crash-4.0-4.11/x86_64.c 2007-12-12 13:51:52.000000000 -0500 +++ crash-4.0-4.12/x86_64.c 2007-12-10 11:47:28.000000000 -0500 @@ -184,6 +184,12 @@ machdep->machspec->modules_vaddr = MODULES_VADDR_2_6_11; machdep->machspec->modules_end = MODULES_END_2_6_11; + /* 2.6.24 layout */ + machdep->machspec->vmemmap_vaddr = VMEMMAP_VADDR_2_6_24; + machdep->machspec->vmemmap_end = VMEMMAP_END_2_6_24; + if (symbol_exists("vmemmap_populate")) + machdep->flags |= VMEMMAP; + machdep->uvtop = x86_64_uvtop_level4; break; @@ -342,6 +348,8 @@ fprintf(fp, "%sVM_XEN", others++ ? "|" : ""); if (machdep->flags & VM_XEN_RHEL4) fprintf(fp, "%sVM_XEN_RHEL4", others++ ? "|" : ""); + if (machdep->flags & VMEMMAP) + fprintf(fp, "%sVMEMMAP", others++ ? "|" : ""); if (machdep->flags & NO_TSS) fprintf(fp, "%sNO_TSS", others++ ? "|" : ""); if (machdep->flags & SCHED_TEXT) @@ -438,6 +446,10 @@ fprintf(fp, " vmalloc_end: %016lx\n", (ulong)ms->vmalloc_end); fprintf(fp, " modules_vaddr: %016lx\n", (ulong)ms->modules_vaddr); fprintf(fp, " modules_end: %016lx\n", (ulong)ms->modules_end); + fprintf(fp, " vmemmap_vaddr: %016lx %s\n", (ulong)ms->vmemmap_vaddr, + machdep->flags & VMEMMAP ? "" : "(unused)"); + fprintf(fp, " vmemmap_end: %016lx %s\n", (ulong)ms->vmemmap_end, + machdep->flags & VMEMMAP ? "" : "(unused)"); fprintf(fp, " phys_base: %lx\n", (ulong)ms->phys_base); fprintf(fp, " pml4: %lx\n", (ulong)ms->pml4); fprintf(fp, " last_pml4_read: %lx\n", (ulong)ms->last_pml4_read); @@ -827,6 +839,8 @@ x86_64_IS_VMALLOC_ADDR(ulong vaddr) { return ((vaddr >= VMALLOC_START && vaddr <= VMALLOC_END) || + ((machdep->flags & VMEMMAP) && + (vaddr >= VMEMMAP_VADDR && vaddr <= VMEMMAP_END)) || (vaddr >= MODULES_VADDR && vaddr <= MODULES_END)); } @@ -3952,6 +3966,8 @@ // fprintf(fp, " L1 CACHE SIZE: %d\n", l1_cache_size()); fprintf(fp, "KERNEL VIRTUAL BASE: %lx\n", machdep->kvbase); fprintf(fp, "KERNEL VMALLOC BASE: %lx\n", vt->vmalloc_start); + if (machdep->flags & VMEMMAP) + fprintf(fp, "KERNEL VMEMMAP BASE: %lx\n", machdep->machspec->vmemmap_vaddr); fprintf(fp, " KERNEL START MAP: %lx\n", __START_KERNEL_map); fprintf(fp, "KERNEL MODULES BASE: %lx\n", MODULES_VADDR); fprintf(fp, " KERNEL STACK SIZE: %ld\n", STACKSIZE()); --- crash-4.0-4.11/symbols.c 2007-12-12 13:51:52.000000000 -0500 +++ crash-4.0-4.12/symbols.c 2007-12-12 11:55:52.000000000 -0500 @@ -3795,6 +3795,7 @@ * #define STRUCT_EXISTS(X) (datatype_info((X), NULL, NULL) >= 0) * #define MEMBER_EXISTS(X,Y) (datatype_info((X), (Y), NULL) >= 0) * #define MEMBER_SIZE(X,Y) datatype_info((X), (Y), MEMBER_SIZE_REQUEST) + * #define MEMBER_TYPE(X,Y) datatype_info((X), (Y), MEMBER_TYPE_REQUEST) * #define ANON_MEMBER_OFFSET(X,Y) datatype_info((X), (Y), ANON_MEMBER_OFFSET_REQUEST) * * to determine structure or union sizes, or member offsets. @@ -3934,7 +3935,7 @@ FREEBUF(req); - if (dm && (dm != MEMBER_SIZE_REQUEST)) { + if (dm && (dm != MEMBER_SIZE_REQUEST) && (dm != MEMBER_TYPE_REQUEST)) { dm->type = type_found; dm->size = size; dm->member_size = member_size; @@ -3954,7 +3955,9 @@ if (dm == MEMBER_SIZE_REQUEST) return member_size; - else if (member) + else if (dm == MEMBER_TYPE_REQUEST) + return member_typecode; + else if (member) return offset; else return size; @@ -6143,8 +6146,6 @@ fprintf(fp, " page_inuse: %ld\n", OFFSET(page_inuse)); - fprintf(fp, " page_lockless_freelist: %ld\n", - OFFSET(page_lockless_freelist)); fprintf(fp, " page_slab: %ld\n", OFFSET(page_slab)); fprintf(fp, " page_first_page: %ld\n", @@ -6515,6 +6516,13 @@ fprintf(fp, " kmem_cache_node_full: %ld\n", OFFSET(kmem_cache_node_full)); + fprintf(fp, " kmem_cache_cpu_freelist: %ld\n", + OFFSET(kmem_cache_cpu_freelist)); + fprintf(fp, " kmem_cache_cpu_page: %ld\n", + OFFSET(kmem_cache_cpu_page)); + fprintf(fp, " kmem_cache_cpu_node: %ld\n", + OFFSET(kmem_cache_cpu_node)); + fprintf(fp, " net_device_next: %ld\n", OFFSET(net_device_next)); fprintf(fp, " net_device_name: %ld\n", @@ -6899,6 +6907,7 @@ SIZE(kmem_bufctl_t)); fprintf(fp, " kmem_cache: %ld\n", SIZE(kmem_cache)); fprintf(fp, " kmem_cache_node: %ld\n", SIZE(kmem_cache_node)); + fprintf(fp, " kmem_cache_cpu: %ld\n", SIZE(kmem_cache_cpu)); fprintf(fp, " swap_info_struct: %ld\n", SIZE(swap_info_struct)); @@ -7032,6 +7041,8 @@ SIZE(unwind_table)); fprintf(fp, " rlimit: %ld\n", SIZE(rlimit)); + fprintf(fp, " cfs_rq: %ld\n", + SIZE(cfs_rq)); fprintf(fp, "\n array_table:\n"); /* --- crash-4.0-4.11/defs.h 2007-12-12 13:51:52.000000000 -0500 +++ crash-4.0-4.12/defs.h 2007-12-12 11:59:07.000000000 -0500 @@ -1414,7 +1414,6 @@ long kmem_cache_cpu_slab; long page_inuse; /* long page_offset; use "old" page->offset */ - long page_lockless_freelist; long page_slab; long page_first_page; long page_freelist; @@ -1427,6 +1426,9 @@ long upid_ns; long upid_pid_chain; long pid_tasks; + long kmem_cache_cpu_freelist; + long kmem_cache_cpu_page; + long kmem_cache_cpu_node; }; struct size_table { /* stash of commonly-used sizes */ @@ -1528,6 +1530,8 @@ long kmem_cache; long kmem_cache_node; long upid; + long kmem_cache_cpu; + long cfs_rq; }; struct array_table { @@ -1572,7 +1576,9 @@ #define MEMBER_OFFSET(X,Y) datatype_info((X), (Y), NULL) #define MEMBER_EXISTS(X,Y) (datatype_info((X), (Y), NULL) >= 0) #define MEMBER_SIZE_REQUEST ((struct datatype_member *)(-1)) +#define MEMBER_TYPE_REQUEST ((struct datatype_member *)(-3)) #define MEMBER_SIZE(X,Y) datatype_info((X), (Y), MEMBER_SIZE_REQUEST) +#define MEMBER_TYPE(X,Y) datatype_info((X), (Y), MEMBER_TYPE_REQUEST) #define ANON_MEMBER_OFFSET_REQUEST ((struct datatype_member *)(-2)) #define ANON_MEMBER_OFFSET(X,Y) datatype_info((X), (Y), ANON_MEMBER_OFFSET_REQUEST) @@ -1687,6 +1693,7 @@ int node_online_map_len; int nr_vm_stat_items; char **vm_stat_items; + int cpu_slab_type; }; #define NODES (0x1) @@ -2064,6 +2071,8 @@ #define PAGE_OFFSET (machdep->machspec->page_offset) #define VMALLOC_START (machdep->machspec->vmalloc_start_addr) #define VMALLOC_END (machdep->machspec->vmalloc_end) +#define VMEMMAP_VADDR (machdep->machspec->vmemmap_vaddr) +#define VMEMMAP_END (machdep->machspec->vmemmap_end) #define MODULES_VADDR (machdep->machspec->modules_vaddr) #define MODULES_END (machdep->machspec->modules_end) @@ -2084,6 +2093,9 @@ #define MODULES_VADDR_2_6_11 0xffffffff88000000 #define MODULES_END_2_6_11 0xfffffffffff00000 +#define VMEMMAP_VADDR_2_6_24 0xffffe20000000000 +#define VMEMMAP_END_2_6_24 0xffffe2ffffffffff + #define USERSPACE_TOP_XEN 0x0000800000000000 #define PAGE_OFFSET_XEN 0xffff880000000000 #define VMALLOC_START_ADDR_XEN 0xffffc20000000000 @@ -3746,6 +3758,8 @@ ulong page_offset; ulong vmalloc_start_addr; ulong vmalloc_end; + ulong vmemmap_vaddr; + ulong vmemmap_end; ulong modules_vaddr; ulong modules_end; ulong phys_base; @@ -3768,6 +3782,7 @@ #define SCHED_TEXT (0x40) #define PHYS_BASE (0x80) #define VM_XEN_RHEL4 (0x100) +#define VMEMMAP (0x200) #define VM_FLAGS (VM_ORIG|VM_2_6_11|VM_XEN|VM_XEN_RHEL4)