--- crash-4.0-6.2/main.c 2008-04-29 11:56:26.000000000 -0400 +++ crash-4.0-6.3/main.c 2008-04-23 14:38:07.000000000 -0400 @@ -48,6 +48,7 @@ {"no_ikconfig", 0, 0, 0}, {"hyper", 0, 0, 0}, {"p2m_mfn", required_argument, 0, 0}, + {"xen_phys_start", required_argument, 0, 0}, {"zero_excluded", 0, 0, 0}, {"no_panic", 0, 0, 0}, {"more", 0, 0, 0}, @@ -155,6 +156,9 @@ else if (STREQ(long_options[option_index].name, "p2m_mfn")) xen_kdump_p2m_mfn(optarg); + else if (STREQ(long_options[option_index].name, "xen_phys_start")) + set_xen_phys_start(optarg); + else if (STREQ(long_options[option_index].name, "zero_excluded")) *diskdump_flags |= ZERO_EXCLUDED; --- crash-4.0-6.2/memory.c 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/memory.c 2008-04-03 15:19:08.000000000 -0400 @@ -133,7 +133,9 @@ static void search(ulong, ulong, ulong, int, ulong *, int); static int next_upage(struct task_context *, ulong, ulong *); static int next_kpage(ulong, ulong *); -static ulong next_vmlist_vaddr(struct meminfo *, ulong); +static ulong last_vmalloc_address(void); +static ulong next_vmlist_vaddr(ulong); +static int next_identity_mapping(ulong, ulong *); static int vm_area_page_dump(ulong, ulong, ulong, ulong, void *, struct reference *); static int dump_swap_info(ulong, ulong *, ulong *); @@ -11029,6 +11031,8 @@ meminfo.flags = (ADDRESS_SPECIFIED|GET_HIGHEST); dump_vmlist(&meminfo); end = meminfo.retval; + if (end < start) + end = (ulong)(-1); } break; } @@ -11196,10 +11200,12 @@ * that is equal to or comes after the passed-in address. */ static ulong -next_vmlist_vaddr(struct meminfo *mi, ulong vaddr) +next_vmlist_vaddr(ulong vaddr) { ulong i, count; + struct meminfo meminfo, *mi; + mi = &meminfo; BZERO(mi, sizeof(struct meminfo)); mi->flags = GET_VMLIST_COUNT; @@ -11230,17 +11236,12 @@ /* * Return the next kernel virtual address page that comes after - * the passed-in address. + * the passed-in, untranslatable, address. */ static int next_kpage(ulong vaddr, ulong *nextvaddr) { - int n; - ulong paddr, vaddr_orig, node_size; - struct node_table *nt; - ulonglong pstart, pend; - ulong vmalloc_limit; - struct meminfo meminfo; + ulong vaddr_orig; vaddr_orig = vaddr; vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE(); /* first possible page */ @@ -11248,16 +11249,11 @@ if (vaddr < vaddr_orig) /* wrapped back to zero? */ return FALSE; - meminfo.memtype = KVADDR; - meminfo.spec_addr = 0; - meminfo.flags = (ADDRESS_SPECIFIED|GET_HIGHEST); - dump_vmlist(&meminfo); - vmalloc_limit = meminfo.retval; - if (IS_VMALLOC_ADDR(vaddr_orig)) { - if (IS_VMALLOC_ADDR(vaddr) && (vaddr < vmalloc_limit)) { + if (IS_VMALLOC_ADDR(vaddr) && + (vaddr < last_vmalloc_address())) { if (machine_type("X86_64")) - vaddr = next_vmlist_vaddr(&meminfo, vaddr); + vaddr = next_vmlist_vaddr(vaddr); *nextvaddr = vaddr; return TRUE; } @@ -11270,26 +11266,8 @@ return FALSE; } - paddr = VTOP(vaddr); - - for (n = 0; n < vt->numnodes; n++) { - nt = &vt->node_table[n]; - if ((vt->flags & V_MEM_MAP) && (vt->numnodes == 1)) - node_size = vt->max_mapnr; - else - node_size = nt->size; - - pstart = nt->start_paddr; - pend = pstart + ((ulonglong)node_size * PAGESIZE()); - - if ((paddr < pstart) || (paddr >= pend)) - continue; - /* - * We're in the physical range. - */ - *nextvaddr = vaddr; + if (next_identity_mapping(vaddr, nextvaddr)) return TRUE; - } if (vt->vmalloc_start > vaddr) { *nextvaddr = vt->vmalloc_start; @@ -12385,6 +12363,77 @@ } /* + * Return the current vmalloc address limit, storing it + * if it's a dumpfile. + */ + +static ulong +last_vmalloc_address(void) +{ + struct meminfo meminfo; + static ulong vmalloc_limit = 0; + + if (!vmalloc_limit) { + BZERO(&meminfo, sizeof(struct meminfo)); + meminfo.memtype = KVADDR; + meminfo.spec_addr = 0; + meminfo.flags = (ADDRESS_SPECIFIED|GET_HIGHEST); + dump_vmlist(&meminfo); + vmalloc_limit = meminfo.retval; + } + + return vmalloc_limit; +} + +/* + * Determine whether an identity-mapped virtual address + * refers to an existant physical page, and if not bump + * it up to the next node. + */ +static int +next_identity_mapping(ulong vaddr, ulong *nextvaddr) +{ + int n; + struct node_table *nt; + ulonglong paddr, pstart, pend; + ulong node_size; + + paddr = VTOP(vaddr); + + for (n = 0; n < vt->numnodes; n++) { + nt = &vt->node_table[n]; + if ((vt->flags & V_MEM_MAP) && (vt->numnodes == 1)) + node_size = vt->max_mapnr; + else + node_size = nt->size; + + pstart = nt->start_paddr; + pend = pstart + ((ulonglong)node_size * PAGESIZE()); + + /* + * Check the next node. + */ + if (paddr >= pend) + continue; + /* + * Bump up to the next node. + */ + if (paddr < pstart) { + *nextvaddr = PTOV(paddr); + continue; + } + /* + * We're in the physical range. + */ + *nextvaddr = vaddr; + return TRUE; + } + + return FALSE; +} + + +/* * Return the L1 cache size in bytes, which can be found stored in the * cache_cache. */ --- crash-4.0-6.2/task.c 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/task.c 2008-04-04 09:58:25.000000000 -0400 @@ -208,6 +208,9 @@ MEMBER_OFFSET_INIT(task_struct_processor, "task_struct", "processor"); MEMBER_OFFSET_INIT(task_struct_p_pptr, "task_struct", "p_pptr"); MEMBER_OFFSET_INIT(task_struct_parent, "task_struct", "parent"); + if (INVALID_MEMBER(task_struct_parent)) + MEMBER_OFFSET_INIT(task_struct_parent, "task_struct", + "real_parent"); MEMBER_OFFSET_INIT(task_struct_has_cpu, "task_struct", "has_cpu"); MEMBER_OFFSET_INIT(task_struct_cpus_runnable, "task_struct", "cpus_runnable"); --- crash-4.0-6.2/kernel.c 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/kernel.c 2008-04-11 11:01:00.000000000 -0400 @@ -49,6 +49,7 @@ static void BUG_bytes_init(void); static int BUG_x86(void); static int BUG_x86_64(void); +static void cpu_maps_init(void); /* @@ -66,6 +67,8 @@ if (pc->flags & KERNEL_DEBUG_QUERY) return; + cpu_maps_init(); + kt->stext = symbol_value("_stext"); kt->etext = symbol_value("_etext"); get_text_init_space(); @@ -502,6 +505,104 @@ } /* + * If the cpu_present_map, cpu_online_map and cpu_possible_maps exist, + * set up the kt->cpu_flags[NR_CPUS] with their settings. + */ +static void +cpu_maps_init(void) +{ + int i, c, m, cpu, len; + char *buf; + ulong *maskptr; + struct mapinfo { + ulong cpu_flag; + char *name; + } mapinfo[] = { + { POSSIBLE, "cpu_possible_map" }, + { PRESENT, "cpu_present_map" }, + { ONLINE, "cpu_online_map" }, + }; + + if ((len = STRUCT_SIZE("cpumask_t")) < 0) + len = sizeof(ulong); + + buf = GETBUF(len); + + for (m = 0; m < sizeof(mapinfo)/sizeof(struct mapinfo); m++) { + if (!kernel_symbol_exists(mapinfo[m].name)) + continue; + + if (!readmem(symbol_value(mapinfo[m].name), KVADDR, buf, len, + mapinfo[m].name, RETURN_ON_ERROR)) { + error(WARNING, "cannot read %s\n", mapinfo[m].name); + continue; + } + + maskptr = (ulong *)buf; + for (i = 0; i < (len/sizeof(ulong)); i++, maskptr++) { + if (*maskptr == 0) + continue; + for (c = 0; c < BITS_PER_LONG; c++) + if (*maskptr & (0x1UL << c)) { + cpu = (i * BITS_PER_LONG) + c; + kt->cpu_flags[cpu] |= mapinfo[m].cpu_flag; + } + } + + if (CRASHDEBUG(1)) { + fprintf(fp, "%s: ", mapinfo[m].name); + for (i = 0; i < NR_CPUS; i++) { + if (kt->cpu_flags[i] & mapinfo[m].cpu_flag) + fprintf(fp, "%d ", i); + } + fprintf(fp, "\n"); + } + + } + + FREEBUF(buf); +} + +/* + * Determine whether a cpu is in one of the cpu masks. + */ +int +in_cpu_map(int map, int cpu) +{ + if (cpu >= (kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS)) { + error(INFO, "in_cpu_map: invalid cpu: %d\n", cpu); + return FALSE; + } + + switch (map) + { + case POSSIBLE: + if (!kernel_symbol_exists("cpu_possible_map")) { + error(INFO, "cpu_possible_map does not exist\n"); + return FALSE; + } + return (kt->cpu_flags[cpu] & POSSIBLE); + + case PRESENT: + if (!kernel_symbol_exists("cpu_present_map")) { + error(INFO, "cpu_present_map does not exist\n"); + return FALSE; + } + return (kt->cpu_flags[cpu] & PRESENT); + + case ONLINE: + if (!kernel_symbol_exists("cpu_online_map")) { + error(INFO, "cpu_online_map does not exist\n"); + return FALSE; + } + return (kt->cpu_flags[cpu] & ONLINE); + } + + return FALSE; +} + + +/* * For lack of a better manner of verifying that the namelist and dumpfile * (or live kernel) match up, verify that the Linux banner is where * the namelist says it is. Since this is common place to bail, extra @@ -3854,11 +3955,39 @@ for (i = 0; i < nr_cpus; i++) fprintf(fp, "%s%.*lx ", (i % 4) == 0 ? "\n " : "", LONG_PRLEN, kt->__per_cpu_offset[i]); - fprintf(fp, "\n cpu_flags[NR_CPUS]:"); + fprintf(fp, "\n cpu_flags[NR_CPUS]: "); for (i = 0; i < nr_cpus; i++) fprintf(fp, "%lx ", kt->cpu_flags[i]); + fprintf(fp, "\n"); + fprintf(fp, " cpu_possible_map: "); + if (kernel_symbol_exists("cpu_possible_map")) { + for (i = 0; i < nr_cpus; i++) { + if (kt->cpu_flags[i] & POSSIBLE) + fprintf(fp, "%d ", i); + } + fprintf(fp, "\n"); + } else + fprintf(fp, "(does not exist)\n"); + fprintf(fp, " cpu_present_map: "); + if (kernel_symbol_exists("cpu_present_map")) { + for (i = 0; i < nr_cpus; i++) { + if (kt->cpu_flags[i] & PRESENT) + fprintf(fp, "%d ", i); + } + fprintf(fp, "\n"); + } else + fprintf(fp, "(does not exist)\n"); + fprintf(fp, " cpu_online_map: "); + if (kernel_symbol_exists("cpu_online_map")) { + for (i = 0; i < nr_cpus; i++) { + if (kt->cpu_flags[i] & ONLINE) + fprintf(fp, "%d ", i); + } + fprintf(fp, "\n"); + } else + fprintf(fp, "(does not exist)\n"); others = 0; - fprintf(fp, "\n xen_flags: %lx (", kt->xen_flags); + fprintf(fp, " xen_flags: %lx (", kt->xen_flags); if (kt->xen_flags & WRITABLE_PAGE_TABLES) fprintf(fp, "%sWRITABLE_PAGE_TABLES", others++ ? "|" : ""); if (kt->xen_flags & SHADOW_PAGE_TABLES) @@ -5560,8 +5689,7 @@ } /* - * For kernels containing at least the cpu_online_map, use it - * to determine the cpu count. + * If it exists, return the number of cpus in the cpu_online_map. */ int get_cpus_online() @@ -5600,8 +5728,46 @@ } /* - * For kernels containing at least the cpu_possible_map, used - * to determine the cpu count (of online and offline cpus). + * If it exists, return the number of cpus in the cpu_present_map. + */ +int +get_cpus_present() +{ + int i, len, present; + struct gnu_request req; + char *buf; + ulong *maskptr; + + if (!symbol_exists("cpu_present_map")) + return 0; + + if (LKCD_KERNTYPES()) { + if ((len = STRUCT_SIZE("cpumask_t")) < 0) + error(FATAL, "cannot determine type cpumask_t\n"); + } else + len = get_symbol_type("cpu_present_map", NULL, &req) == + TYPE_CODE_UNDEF ? sizeof(ulong) : req.length; + buf = GETBUF(len); + + present = 0; + + if (readmem(symbol_value("cpu_present_map"), KVADDR, buf, len, + "cpu_present_map", RETURN_ON_ERROR)) { + + maskptr = (ulong *)buf; + for (i = 0; i < (len/sizeof(ulong)); i++, maskptr++) + present += count_bits_long(*maskptr); + + FREEBUF(buf); + if (CRASHDEBUG(1)) + error(INFO, "get_cpus_present: present: %d\n", present); + } + + return present; +} + +/* + * If it exists, return the number of cpus in the cpu_possible_map. */ int get_cpus_possible() --- crash-4.0-6.2/x86.c 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/x86.c 2008-04-23 13:56:05.000000000 -0400 @@ -2846,7 +2846,10 @@ *paddr = kvaddr - DIRECTMAP_VIRT_START; return TRUE; } - pgd = (ulonglong *)symbol_value("idle_pg_table_l3"); + if (symbol_exists("idle_pg_table_l3")) + pgd = (ulonglong *)symbol_value("idle_pg_table_l3"); + else + pgd = (ulonglong *)symbol_value("idle_pg_table"); } else { if (!vt->vmalloc_start) { *paddr = VTOP(kvaddr); @@ -4965,7 +4968,8 @@ break; case PRE_GDB: - if (symbol_exists("idle_pg_table_l3")) { + if (symbol_exists("create_pae_xen_mappings") || + symbol_exists("idle_pg_table_l3")) { machdep->flags |= PAE; PGDIR_SHIFT = PGDIR_SHIFT_3LEVEL; PTRS_PER_PTE = PTRS_PER_PTE_3LEVEL; --- crash-4.0-6.2/s390x.c 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/s390x.c 2008-04-11 11:26:36.000000000 -0400 @@ -337,6 +337,11 @@ level--; } + /* Check if this is a large page. */ + if (entry & 0x400ULL) + /* Add the 1MB page offset and return the final value. */ + return table + (vaddr & 0xfffffULL); + /* Get the page table entry */ entry = _kl_pg_table_deref_s390x(vaddr, entry & ~0x7ffULL); if (!entry) --- crash-4.0-6.2/ppc64.c 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/ppc64.c 2008-04-08 17:06:40.000000000 -0400 @@ -1,7 +1,7 @@ /* ppc64.c -- core analysis suite * - * Copyright (C) 2004, 2005, 2006 David Anderson - * Copyright (C) 2004, 2005, 2006 Red Hat, Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007, 2008 David Anderson + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (C) 2004, 2006 Haren Myneni, IBM Corporation * * This program is free software; you can redistribute it and/or modify @@ -2367,17 +2367,21 @@ static void ppc64_paca_init(void) { -#define BITS_FOR_LONG sizeof(ulong)*8 int i, cpus, nr_paca; char *cpu_paca_buf; ulong data_offset; - ulong cpu_online_map[NR_CPUS/BITS_FOR_LONG]; + int map; if (!symbol_exists("paca")) error(FATAL, "PPC64: Could not find 'paca' symbol\n"); - if (!symbol_exists("cpu_online_map")) - error(FATAL, "PPC64: Could not find 'cpu_online_map' symbol\n"); + if (symbol_exists("cpu_present_map")) + map = PRESENT; + else if (symbol_exists("cpu_online_map")) + map = ONLINE; + else + error(FATAL, + "PPC64: cannot find 'cpu_present_map' or 'cpu_online_map' symbols\n"); if (!MEMBER_EXISTS("paca_struct", "data_offset")) return; @@ -2397,15 +2401,11 @@ error(FATAL, "Recompile crash with larger NR_CPUS\n"); } - readmem(symbol_value("cpu_online_map"), KVADDR, &cpu_online_map[0], - nr_paca/8, "cpu_online_map", FAULT_ON_ERROR); - for (i = cpus = 0; i < nr_paca; i++) { - div_t val = div(i, BITS_FOR_LONG); /* - * CPU online? + * CPU present (or online)? */ - if (!(cpu_online_map[val.quot] & (0x1UL << val.rem))) + if (!in_cpu_map(map, i)) continue; readmem(symbol_value("paca") + (i * SIZE(ppc64_paca)), --- crash-4.0-6.2/x86_64.c 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/x86_64.c 2008-04-23 14:59:49.000000000 -0400 @@ -1401,6 +1401,10 @@ return FALSE; if (XEN_HYPER_MODE()) { + if (XEN_VIRT_ADDR(kvaddr)) { + *paddr = kvaddr - XEN_VIRT_START + xen_phys_start(); + return TRUE; + } if (DIRECTMAP_VIRT_ADDR(kvaddr)) { *paddr = kvaddr - DIRECTMAP_VIRT_START; return TRUE; --- crash-4.0-6.2/symbols.c 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/symbols.c 2008-04-14 13:49:19.000000000 -0400 @@ -2540,6 +2540,11 @@ goto bailout; break; + case EM_S390: + if (machine_type_mismatch(file, "S390", NULL, 0)) + goto bailout; + break; + default: if (machine_type_mismatch(file, "(unknown)", NULL, 0)) goto bailout; @@ -2573,6 +2578,11 @@ goto bailout; break; + case EM_S390: + if (machine_type_mismatch(file, "S390X", NULL, 0)) + goto bailout; + break; + default: if (machine_type_mismatch(file, "(unknown)", NULL, 0)) goto bailout; --- crash-4.0-6.2/lkcd_x86_trace.c 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/lkcd_x86_trace.c 2008-04-23 13:56:05.000000000 -0400 @@ -1423,6 +1423,7 @@ if (XEN_HYPER_MODE()) { func_name = kl_funcname(pc); if (STREQ(func_name, "idle_loop") || STREQ(func_name, "hypercall") + || STREQ(func_name, "tracing_off") || STREQ(func_name, "handle_exception")) { UPDATE_FRAME(func_name, pc, 0, sp, bp, asp, 0, 0, bp - sp, 0); return(trace->nframes); @@ -1682,6 +1683,7 @@ if (func_name && XEN_HYPER_MODE()) { if (STREQ(func_name, "continue_nmi") || STREQ(func_name, "vmx_asm_vmexit_handler") || + STREQ(func_name, "handle_nmi_mce") || STREQ(func_name, "deferred_nmi")) { /* Interrupt frame */ sp = curframe->fp + 4; --- crash-4.0-6.2/netdump.c 2008-04-29 11:56:26.000000000 -0400 +++ crash-4.0-6.3/netdump.c 2008-04-23 14:49:00.000000000 -0400 @@ -874,6 +874,8 @@ nd->xen_kdump_data->cache_hits * 100 / nd->xen_kdump_data->accesses); netdump_print("\n p2m_frames: %d\n", nd->xen_kdump_data->p2m_frames); + netdump_print(" xen_phys_start: %lx\n", + nd->xen_kdump_data->xen_phys_start); netdump_print(" p2m_mfn_frame_list: %lx\n", nd->xen_kdump_data->p2m_mfn_frame_list); for (i = 0; i < nd->xen_kdump_data->p2m_frames; i++) @@ -1521,6 +1523,8 @@ */ if (!nd->xen_kdump_data->p2m_mfn) nd->xen_kdump_data->p2m_mfn = *(uptr+(words-1)); + if (words > 9 && !nd->xen_kdump_data->xen_phys_start) + nd->xen_kdump_data->xen_phys_start = *(uptr+(words-2)); } } break; @@ -1724,6 +1728,8 @@ */ if (!nd->xen_kdump_data->p2m_mfn) nd->xen_kdump_data->p2m_mfn = *(up+(words-1)); + if (words > 9 && !nd->xen_kdump_data->xen_phys_start) + nd->xen_kdump_data->xen_phys_start = *(up+(words-2)); } } break; @@ -2090,10 +2096,16 @@ * panic task. Whereas in kdump, regs are captured for all * CPUs if they responded to an IPI. */ - if (nd->num_prstatus_notes > 1) + if (nd->num_prstatus_notes > 1) { + if (bt->tc->processor >= nd->num_prstatus_notes) + error(FATAL, + "cannot determine NT_PRSTATUS ELF note " + "for %s task: %lx\n", + (bt->task == tt->panic_task) ? + "panic" : "active", bt->task); note = (Elf64_Nhdr *) nd->nt_prstatus_percpu[bt->tc->processor]; - else + } else note = (Elf64_Nhdr *)nd->nt_prstatus; len = sizeof(Elf64_Nhdr); @@ -2312,3 +2324,22 @@ return FALSE; } + +void +set_xen_phys_start(char *arg) +{ + ulong value; + int errflag = 0; + + value = htol(arg, RETURN_ON_ERROR|QUIET, &errflag); + if (!errflag) + xen_kdump_data.xen_phys_start = value; + else + error(WARNING, "invalid xen_phys_start argument: %s\n", arg); +} + +ulong +xen_phys_start(void) +{ + return nd->xen_kdump_data->xen_phys_start; +} --- crash-4.0-6.2/xen_hyper.c 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/xen_hyper.c 2008-04-23 15:50:49.000000000 -0400 @@ -41,6 +41,12 @@ long member_offset; #endif + if (machine_type("X86_64") && + symbol_exists("xen_phys_start") && !xen_phys_start()) + error(WARNING, + "This hypervisor is relocatable; if initialization fails below, try\n" + " using the \"--xen_phys_start
\" command line option.\n\n"); + if (symbol_exists("crashing_cpu")) { get_symbol_data("crashing_cpu", sizeof(xht->crashing_cpu), &xht->crashing_cpu); --- crash-4.0-6.2/defs.h 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/defs.h 2008-04-23 14:49:44.000000000 -0400 @@ -509,8 +509,11 @@ long __cpu_idx[NR_CPUS]; long __per_cpu_offset[NR_CPUS]; ulong cpu_flags[NR_CPUS]; +#define POSSIBLE (0x1) +#define PRESENT (0x2) +#define ONLINE (0x4) +#define NMI (0x8) int BUG_bytes; -#define NMI 0x1 ulong xen_flags; #define WRITABLE_PAGE_TABLES (0x1) #define SHADOW_PAGE_TABLES (0x2) @@ -2162,10 +2165,13 @@ #define FILL_PML4_HYPER() { \ if (!machdep->machspec->last_pml4_read) { \ - readmem(symbol_value("idle_pg_table_4"), KVADDR, \ - machdep->machspec->pml4, PAGESIZE(), "idle_pg_table_4", \ + unsigned long idle_pg_table = \ + symbol_exists("idle_pg_table_4") ? symbol_value("idle_pg_table_4") : \ + symbol_value("idle_pg_table"); \ + readmem(idle_pg_table, KVADDR, \ + machdep->machspec->pml4, PAGESIZE(), "idle_pg_table", \ FAULT_ON_ERROR); \ - machdep->machspec->last_pml4_read = symbol_value("idle_pg_table_4"); \ + machdep->machspec->last_pml4_read = idle_pg_table; \ }\ } @@ -3597,7 +3603,9 @@ void clear_machdep_cache(void); struct stack_hook *gather_text_list(struct bt_info *); int get_cpus_online(void); +int get_cpus_present(void); int get_cpus_possible(void); +int in_cpu_map(int, int); void print_stack_text_syms(struct bt_info *, ulong, ulong); void back_trace(struct bt_info *); #define BT_RAW (0x1ULL) @@ -4081,6 +4089,8 @@ void get_kdump_regs(struct bt_info *, ulong *, ulong *); void xen_kdump_p2m_mfn(char *); int is_sadump_xen(void); +void set_xen_phys_start(char *); +ulong xen_phys_start(void); /* * diskdump.c --- crash-4.0-6.2/xen_hyper_defs.h 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/xen_hyper_defs.h 2008-04-23 14:45:42.000000000 -0400 @@ -64,6 +64,9 @@ #define DIRECTMAP_VIRT_START (0xffff830000000000) #define DIRECTMAP_VIRT_END (0xffff840000000000) #define PAGE_OFFSET_XEN_HYPER DIRECTMAP_VIRT_START +#define XEN_VIRT_START (0xffff828c80000000) +#define XEN_VIRT_ADDR(vaddr) \ + (((vaddr) >= XEN_VIRT_START) && ((vaddr) < DIRECTMAP_VIRT_START)) #endif #ifdef IA64 --- crash-4.0-6.2/netdump.h 2008-04-29 11:56:26.000000000 -0400 +++ crash-4.0-6.3/netdump.h 2008-04-23 14:39:05.000000000 -0400 @@ -109,6 +109,7 @@ ulong accesses; int p2m_frames; ulong *p2m_mfn_frame_list; + ulong xen_phys_start; }; #define KDUMP_P2M_INIT (0x1) --- crash-4.0-6.2/crash.8 2008-04-29 11:56:27.000000000 -0400 +++ crash-4.0-6.3/crash.8 2008-04-16 08:31:53.000000000 -0400 @@ -362,6 +362,7 @@ .I whatis displays the definition of structures, unions, typedefs or text/data symbols. +.TP .I wr modifies the contents of memory. When writing to memory on a live system, this command should obviously be used with great care.