--- crash-4.0/xen_hyper.c.orig +++ crash-4.0/xen_hyper.c @@ -41,6 +41,12 @@ xen_hyper_init(void) 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 <address>\" 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/netdump.c.orig +++ crash-4.0/netdump.c @@ -874,6 +874,8 @@ netdump_memory_dump(FILE *fp) 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 @@ dump_Elf32_Nhdr(Elf32_Off offset, int st */ 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 @@ dump_Elf64_Nhdr(Elf64_Off offset, int st */ 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; @@ -2312,3 +2318,22 @@ is_sadump_xen(void) 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/x86_64.c.orig +++ crash-4.0/x86_64.c @@ -1386,6 +1386,10 @@ x86_64_kvtop(struct task_context *tc, ul 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/defs.h.orig +++ crash-4.0/defs.h @@ -2157,10 +2157,13 @@ struct load_module { #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; \ }\ } @@ -4076,6 +4079,8 @@ int kdump_memory_dump(FILE *); 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/xen_hyper_defs.h.orig +++ crash-4.0/xen_hyper_defs.h @@ -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/main.c.orig +++ crash-4.0/main.c @@ -48,6 +48,7 @@ static struct option long_options[] = { {"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 @@ main(int argc, char **argv) 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/lkcd_x86_trace.c.orig +++ crash-4.0/lkcd_x86_trace.c @@ -1423,6 +1423,7 @@ find_trace( 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 @@ find_trace( 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; @@ -2534,7 +2536,8 @@ eframe_label(char *funcname, ulong eip) efp->tracesys_exit = symbol_search("tracesys_exit"); } - if ((efp->sysenter = symbol_search("sysenter_entry"))) { + if ((efp->sysenter = symbol_search("sysenter_entry")) || + (efp->sysenter = symbol_search("ia32_sysenter_target"))) { if ((sp = symbol_search("sysexit_ret_end_marker"))) efp->sysenter_end = sp; else if ((sp = symbol_search("system_call"))) --- crash-4.0/x86.c.orig +++ crash-4.0/x86.c @@ -2805,7 +2805,10 @@ x86_kvtop_PAE(struct task_context *tc, u *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); @@ -4889,7 +4892,8 @@ x86_init_hyper(int when) 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/netdump.h.orig +++ crash-4.0/netdump.h @@ -109,6 +109,7 @@ struct xen_kdump_data { ulong accesses; int p2m_frames; ulong *p2m_mfn_frame_list; + ulong xen_phys_start; }; #define KDUMP_P2M_INIT (0x1)