Index: defs.h =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/defs.h,v retrieving revision 1.5 retrieving revision 1.5.2.1 diff -u -r1.5 -r1.5.2.1 --- defs.h 13 Feb 2007 06:37:55 -0000 1.5 +++ defs.h 15 Feb 2007 00:38:15 -0000 1.5.2.1 @@ -3765,6 +3765,7 @@ #define display_idt_table() \ error(FATAL, "-d option TBD on ia64 architecture\n"); int ia64_in_init_stack(ulong addr); +int ia64_in_mca_stack_hyper(ulong addr, struct bt_info *bt); #define OLD_UNWIND (0x1) /* CONFIG_IA64_NEW_UNWIND not turned on */ #define NEW_UNWIND (0x2) /* CONFIG_IA64_NEW_UNWIND turned on */ @@ -4331,7 +4332,7 @@ extern int have_partial_symbols(void); extern int have_full_symbols(void); -#if defined(X86) || defined(X86_64) +#if defined(X86) || defined(X86_64) || defined(IA64) #define XEN_HYPERVISOR_ARCH #endif Index: ia64.c =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/ia64.c,v retrieving revision 1.2 retrieving revision 1.2.8.2 diff -u -r1.2 -r1.2.8.2 --- ia64.c 21 Dec 2006 00:01:02 -0000 1.2 +++ ia64.c 15 Feb 2007 01:41:28 -0000 1.2.8.2 @@ -16,6 +16,7 @@ */ #ifdef IA64 #include "defs.h" +#include "xen_hyper_defs.h" #include static int ia64_verify_symbol(const char *, ulong, char); @@ -79,6 +80,7 @@ static ulong ia64_xendump_panic_task(struct xendump_data *); static void ia64_get_xendump_regs(struct xendump_data *, struct bt_info *, ulong *, ulong *); +static void ia64_init_hyper(int); struct machine_specific ia64_machine_specific = { 0 }; @@ -87,6 +89,11 @@ { struct syment *sp, *spn; + if (XEN_HYPER_MODE()) { + ia64_init_hyper(when); + return; + } + switch (when) { case SETUP_ENV: @@ -1154,9 +1161,15 @@ { ulong ksp; - readmem(task + OFFSET(task_struct_thread_ksp), KVADDR, - &ksp, sizeof(void *), - "thread_struct ksp", FAULT_ON_ERROR); + if (XEN_HYPER_MODE()) { + readmem(task + XEN_HYPER_OFFSET(vcpu_thread_ksp), KVADDR, + &ksp, sizeof(void *), + "vcpu thread ksp", FAULT_ON_ERROR); + } else { + readmem(task + OFFSET(task_struct_thread_ksp), KVADDR, + &ksp, sizeof(void *), + "thread_struct ksp", FAULT_ON_ERROR); + } return ksp; } @@ -1511,7 +1524,10 @@ BZERO(&eframe, sizeof(ulong) * NUM_PT_REGS); open_tmpfile(); - dump_struct("pt_regs", addr, RADIX(16)); + if (XEN_HYPER_MODE()) + dump_struct("cpu_user_regs", addr, RADIX(16)); + else + dump_struct("pt_regs", addr, RADIX(16)); rewind(pc->tmpfile); fval = 0; @@ -3951,5 +3967,248 @@ STREQ(closest_symbol(*rip), "schedule")) error(INFO, "xendump: switch_stack possibly not saved -- try \"bt -t\"\n"); +} + +/* for XEN Hypervisor analysis */ + +static int +ia64_is_kvaddr_hyper(ulong addr) +{ + return (addr >= HYPERVISOR_VIRT_START && addr < HYPERVISOR_VIRT_END); +} + +static int +ia64_kvtop_hyper(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbose) +{ + unsigned long virt_percpu_start, phys_percpu_start; + + if (!IS_KVADDR(kvaddr)) + return FALSE; + + if (PERCPU_VIRT_ADDR(kvaddr)) { + virt_percpu_start = symbol_value("__phys_per_cpu_start"); + phys_percpu_start = virt_percpu_start - DIRECTMAP_VIRT_START; + *paddr = kvaddr - PERCPU_ADDR + phys_percpu_start; + return TRUE; + } else if (DIRECTMAP_VIRT_ADDR(kvaddr)) { + *paddr = kvaddr - DIRECTMAP_VIRT_START; + return TRUE; + } + + return FALSE; +} + +static void +ia64_post_init_hyper(void) +{ + struct machine_specific *ms; + + ms = &ia64_machine_specific; + + if (symbol_exists("unw_init_frame_info")) { + machdep->flags |= NEW_UNWIND; + if (MEMBER_EXISTS("unw_frame_info", "pt")) { + if (MEMBER_EXISTS("pt_regs", "ar_csd")) { + machdep->flags |= NEW_UNW_V3; + ms->unwind_init = unwind_init_v3; + ms->unwind = unwind_v3; + ms->unwind_debug = unwind_debug_v3; + ms->dump_unwind_stats = dump_unwind_stats_v3; + } else { + machdep->flags |= NEW_UNW_V2; + ms->unwind_init = unwind_init_v2; + ms->unwind = unwind_v2; + ms->unwind_debug = unwind_debug_v2; + ms->dump_unwind_stats = dump_unwind_stats_v2; + } + } else { + machdep->flags |= NEW_UNW_V1; + ms->unwind_init = unwind_init_v1; + ms->unwind = unwind_v1; + ms->unwind_debug = unwind_debug_v1; + ms->dump_unwind_stats = dump_unwind_stats_v1; + } + } else { + machdep->flags |= OLD_UNWIND; + ms->unwind_init = ia64_old_unwind_init; + ms->unwind = ia64_old_unwind; + } + ms->unwind_init(); +} + +int +ia64_in_mca_stack_hyper(ulong addr, struct bt_info *bt) +{ + int plen, i; + ulong paddr, stackbase, stacktop; + ulong *__per_cpu_mca; + struct xen_hyper_vcpu_context *vcc; + + vcc = xen_hyper_vcpu_to_vcpu_context(bt->task); + if (!vcc) + return 0; + + if (!symbol_exists("__per_cpu_mca") || + !(plen = get_array_length("__per_cpu_mca", NULL, 0)) || + (plen < xht->pcpus)) + return 0; + + if (!machdep->kvtop(NULL, addr, &paddr, 0)) + return 0; + + __per_cpu_mca = (ulong *)GETBUF(sizeof(ulong) * xht->pcpus); + + if (!readmem(symbol_value("__per_cpu_mca"), KVADDR, __per_cpu_mca, + sizeof(ulong) * xht->pcpus, "__per_cpu_mca", RETURN_ON_ERROR|QUIET)) + return 0; + + if (CRASHDEBUG(1)) { + for (i = 0; i < xht->pcpus; i++) { + fprintf(fp, "__per_cpu_mca[%d]: %lx\n", + i, __per_cpu_mca[i]); + } + } + + stackbase = __per_cpu_mca[vcc->processor]; + stacktop = stackbase + (STACKSIZE() * 2); + FREEBUF(__per_cpu_mca); + + if ((paddr >= stackbase) && (paddr < stacktop)) + return 1; + else + return 0; +} + +static void +ia64_init_hyper(int when) +{ + struct syment *sp; + + switch (when) + { + case SETUP_ENV: +#if defined(PR_SET_FPEMU) && defined(PR_FPEMU_NOPRINT) + prctl(PR_SET_FPEMU, PR_FPEMU_NOPRINT, 0, 0, 0); +#endif +#if defined(PR_SET_UNALIGN) && defined(PR_UNALIGN_NOPRINT) + prctl(PR_SET_UNALIGN, PR_UNALIGN_NOPRINT, 0, 0, 0); +#endif + break; + + case PRE_SYMTAB: + machdep->verify_symbol = ia64_verify_symbol; + machdep->machspec = &ia64_machine_specific; + if (pc->flags & KERNEL_DEBUG_QUERY) + return; + machdep->pagesize = memory_page_size(); + machdep->pageshift = ffs(machdep->pagesize) - 1; + machdep->pageoffset = machdep->pagesize - 1; + machdep->pagemask = ~(machdep->pageoffset); + switch (machdep->pagesize) + { + case 4096: + machdep->stacksize = (power(2, 3) * PAGESIZE()); + break; + case 8192: + machdep->stacksize = (power(2, 2) * PAGESIZE()); + break; + case 16384: + machdep->stacksize = (power(2, 1) * PAGESIZE()); + break; + case 65536: + machdep->stacksize = (power(2, 0) * PAGESIZE()); + break; + default: + machdep->stacksize = 32*1024; + break; + } + if ((machdep->pgd = (char *)malloc(PAGESIZE())) == NULL) + error(FATAL, "cannot malloc pgd space."); + if ((machdep->pud = (char *)malloc(PAGESIZE())) == NULL) + error(FATAL, "cannot malloc pud space."); + if ((machdep->pmd = (char *)malloc(PAGESIZE())) == NULL) + error(FATAL, "cannot malloc pmd space."); + if ((machdep->ptbl = (char *)malloc(PAGESIZE())) == NULL) + error(FATAL, "cannot malloc ptbl space."); + machdep->last_pgd_read = 0; + machdep->last_pud_read = 0; + machdep->last_pmd_read = 0; + machdep->last_ptbl_read = 0; + machdep->verify_paddr = ia64_verify_paddr; + machdep->ptrs_per_pgd = PTRS_PER_PGD; + machdep->machspec->phys_start = UNKNOWN_PHYS_START; + /* ODA: if need make hyper version + if (machdep->cmdline_arg) + parse_cmdline_arg(); */ + break; + + case PRE_GDB: + + if (pc->flags & KERNEL_DEBUG_QUERY) + return; + + machdep->kvbase = HYPERVISOR_VIRT_START; + machdep->identity_map_base = HYPERVISOR_VIRT_START; + machdep->is_kvaddr = ia64_is_kvaddr_hyper; + machdep->is_uvaddr = generic_is_uvaddr; + machdep->eframe_search = ia64_eframe_search; + machdep->back_trace = ia64_back_trace_cmd; + machdep->processor_speed = xen_hyper_ia64_processor_speed; + machdep->uvtop = ia64_uvtop; + machdep->kvtop = ia64_kvtop_hyper; + machdep->get_stack_frame = ia64_get_stack_frame; + machdep->get_stackbase = ia64_get_stackbase; + machdep->get_stacktop = ia64_get_stacktop; + machdep->translate_pte = ia64_translate_pte; + machdep->memory_size = xen_hyper_ia64_memory_size; + machdep->dis_filter = ia64_dis_filter; + machdep->cmd_mach = ia64_cmd_mach; + machdep->get_smp_cpus = xen_hyper_ia64_get_smp_cpus; + machdep->line_number_hooks = ia64_line_number_hooks; + machdep->value_to_symbol = generic_machdep_value_to_symbol; + machdep->init_kernel_pgd = NULL; + + if ((sp = symbol_search("_stext"))) { + machdep->machspec->kernel_region = + VADDR_REGION(sp->value); + machdep->machspec->kernel_start = sp->value; + } else { +// machdep->machspec->kernel_region = KERNEL_CACHED_REGION; +// machdep->machspec->kernel_start = KERNEL_CACHED_BASE; + } + + /* machdep table for Xen Hypervisor */ + xhmachdep->pcpu_init = xen_hyper_ia64_pcpu_init; + break; + + case POST_GDB: + STRUCT_SIZE_INIT(switch_stack, "switch_stack"); + MEMBER_OFFSET_INIT(thread_struct_fph, "thread_struct", "fph"); + MEMBER_OFFSET_INIT(switch_stack_b0, "switch_stack", "b0"); + MEMBER_OFFSET_INIT(switch_stack_ar_bspstore, + "switch_stack", "ar_bspstore"); + MEMBER_OFFSET_INIT(switch_stack_ar_pfs, + "switch_stack", "ar_pfs"); + MEMBER_OFFSET_INIT(switch_stack_ar_rnat, + "switch_stack", "ar_rnat"); + MEMBER_OFFSET_INIT(switch_stack_pr, + "switch_stack", "pr"); + + XEN_HYPER_STRUCT_SIZE_INIT(cpuinfo_ia64, "cpuinfo_ia64"); + XEN_HYPER_MEMBER_OFFSET_INIT(cpuinfo_ia64_proc_freq, "cpuinfo_ia64", "proc_freq"); + XEN_HYPER_MEMBER_OFFSET_INIT(cpuinfo_ia64_vendor, "cpuinfo_ia64", "vendor"); + if (symbol_exists("per_cpu__cpu_info")) { + xht->cpu_data_address = symbol_value("per_cpu__cpu_info"); + } + /* kakuma Can this be calculated? */ + if (!machdep->hz) { + machdep->hz = XEN_HYPER_HZ; + } + break; + + case POST_INIT: + ia64_post_init_hyper(); + break; + } } #endif Index: kernel.c =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/kernel.c,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -u -r1.4 -r1.4.2.1 --- kernel.c 13 Feb 2007 06:37:55 -0000 1.4 +++ kernel.c 15 Feb 2007 00:38:15 -0000 1.4.2.1 @@ -1426,24 +1426,25 @@ if (XEN_HYPER_MODE()) { #ifdef XEN_HYPERVISOR_ARCH - /* "task" means physical cpu id */ + /* "task" means vcpu for xen hypervisor */ if (active) { for (c = 0; c < XEN_HYPER_MAX_CPUS(); c++) { if (!xen_hyper_test_pcpu_id(c)) continue; - fake_tc.task = c; + fake_tc.task = xen_hyper_pcpu_to_active_vcpu(c); BT_SETUP(&fake_tc); - print_pcpu_header_hyper(fp, c, subsequent++); + xen_hyper_print_bt_header(fp, fake_tc.task, subsequent++); back_trace(bt); } } else { if (args[optind]) { - fake_tc.task = atoi(args[optind]); + fake_tc.task = xen_hyper_pcpu_to_active_vcpu( + convert(args[optind], 0, NULL, NUM_DEC | NUM_HEX)); } else { - fake_tc.task = 0; /* ODA: set current */ + fake_tc.task = XEN_HYPER_VCPU_LAST_CONTEXT()->vcpu; } BT_SETUP(&fake_tc); - print_pcpu_header_hyper(fp, fake_tc.task, 0); + xen_hyper_print_bt_header(fp, fake_tc.task, 0); back_trace(bt); } return; Index: main.c =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/main.c,v retrieving revision 1.5 retrieving revision 1.5.2.2 diff -u -r1.5 -r1.5.2.2 --- main.c 13 Feb 2007 06:37:55 -0000 1.5 +++ main.c 15 Feb 2007 00:52:26 -0000 1.5.2.2 @@ -425,10 +425,7 @@ #ifdef XEN_HYPERVISOR_ARCH machdep_init(POST_GDB); xen_hyper_init(); - xhmachdep->pcpu_init(); - xen_hyper_domain_init(); - xen_hyper_vcpu_init(); - xen_hyper_post_init(); + machdep_init(POST_INIT); #else error(FATAL, XEN_HYPERVISOR_NOT_SUPPORTED); #endif @@ -455,8 +452,8 @@ if (!(pc->flags & SILENT) && !(pc->flags & RUNTIME)) { if (XEN_HYPER_MODE()) { #ifdef XEN_HYPERVISOR_ARCH - display_xen_hyper_sys_stats(); - show_xen_hyper_vcpu_context(XEN_HYPER_VCPU_LAST_CONTEXT()); + xen_hyper_display_sys_stats(); + xen_hyper_show_vcpu_context(XEN_HYPER_VCPU_LAST_CONTEXT()); #else error(FATAL, XEN_HYPERVISOR_NOT_SUPPORTED); #endif Index: task.c =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/task.c,v retrieving revision 1.4 retrieving revision 1.4.2.1 diff -u -r1.4 -r1.4.2.1 --- task.c 13 Feb 2007 06:37:55 -0000 1.4 +++ task.c 15 Feb 2007 00:38:15 -0000 1.4.2.1 @@ -1906,6 +1906,9 @@ bt->stackbase); } + if (XEN_HYPER_MODE()) + return; + if (!IS_LAST_TASK_READ(bt->task)) { if (bt->stackbase == bt->task) { BCOPY(bt->stackbuf, tt->task_struct, SIZE(task_struct)); Index: unwind.c =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/unwind.c,v retrieving revision 1.1 retrieving revision 1.1.12.1 diff -u -r1.1 -r1.1.12.1 --- unwind.c 4 Dec 2006 06:53:00 -0000 1.1 +++ unwind.c 15 Feb 2007 00:38:15 -0000 1.1.12.1 @@ -36,6 +36,7 @@ /* #include can't include this -- it's changing over time! */ #include "defs.h" +#include "xen_hyper_defs.h" typedef unsigned char u8; typedef unsigned long long u64; @@ -1876,8 +1877,13 @@ ulong sw; sw = SWITCH_STACK_ADDR(bt->task); - if (!INSTACK(sw, bt) && !ia64_in_init_stack(sw)) - return FALSE; + if (XEN_HYPER_MODE()) { + if (!INSTACK(sw, bt) && !ia64_in_mca_stack_hyper(sw, bt)) + return FALSE; + } else { + if (!INSTACK(sw, bt) && !ia64_in_init_stack(sw)) + return FALSE; + } unw_init_frame_info(info, bt, sw); return TRUE; Index: x86.c =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/x86.c,v retrieving revision 1.5 retrieving revision 1.5.2.1 diff -u -r1.5 -r1.5.2.1 --- x86.c 13 Feb 2007 06:37:55 -0000 1.5 +++ x86.c 15 Feb 2007 00:38:15 -0000 1.5.2.1 @@ -4727,17 +4727,24 @@ static ulong x86_get_stackbase_hyper(ulong task) { + struct xen_hyper_vcpu_context *vcc; + int pcpu; ulong init_tss; ulong esp, base; char *buf; - /* task means pcpu here */ - if (!xen_hyper_test_pcpu_id(task)) { + /* task means vcpu here */ + vcc = xen_hyper_vcpu_to_vcpu_context(task); + if (!vcc) + error(FATAL, "invalid vcpu\n"); + + pcpu = vcc->processor; + if (!xen_hyper_test_pcpu_id(pcpu)) { error(FATAL, "invalid pcpu number\n"); } init_tss = symbol_value("init_tss"); buf = GETBUF(XEN_HYPER_SIZE(tss_struct)); - init_tss += XEN_HYPER_SIZE(tss_struct) * task; + init_tss += XEN_HYPER_SIZE(tss_struct) * pcpu; if (!readmem(init_tss, KVADDR, buf, XEN_HYPER_SIZE(tss_struct), "init_tss", RETURN_ON_ERROR)) { error(FATAL, "cannot read init_tss.\n"); @@ -4758,19 +4765,24 @@ static void x86_get_stack_frame_hyper(struct bt_info *bt, ulong *pcp, ulong *spp) { + struct xen_hyper_vcpu_context *vcc; int pcpu; ulong *regs; ulong esp, eip; - /* task means pcpu here */ - pcpu = bt->task; + /* task means vcpu here */ + vcc = xen_hyper_vcpu_to_vcpu_context(bt->task); + if (!vcc) + error(FATAL, "invalid vcpu\n"); + + pcpu = vcc->processor; if (!xen_hyper_test_pcpu_id(pcpu)) { error(FATAL, "invalid pcpu number\n"); } if (bt->flags & BT_TEXT_SYMBOLS_ALL) { if (spp) - *spp = x86_get_stackbase_hyper(pcpu); + *spp = x86_get_stackbase_hyper(bt->task); if (pcp) *pcp = 0; bt->flags &= ~BT_TEXT_SYMBOLS_ALL; @@ -4782,9 +4794,9 @@ eip = XEN_HYPER_X86_NOTE_EIP(regs); if (spp) { - if (esp < x86_get_stackbase_hyper(pcpu) || - esp >= x86_get_stacktop_hyper(pcpu)) - *spp = x86_get_stackbase_hyper(pcpu); + if (esp < x86_get_stackbase_hyper(bt->task) || + esp >= x86_get_stacktop_hyper(bt->task)) + *spp = x86_get_stackbase_hyper(bt->task); else *spp = esp; } @@ -4850,17 +4862,17 @@ machdep->get_stackbase = x86_get_stackbase_hyper; machdep->get_stacktop = x86_get_stacktop_hyper; machdep->translate_pte = x86_translate_pte; - machdep->memory_size = x86_memory_size_hyper; + machdep->memory_size = xen_hyper_x86_memory_size; machdep->dis_filter = x86_dis_filter; // machdep->cmd_mach = x86_cmd_mach; /* ODA: check */ - machdep->get_smp_cpus = x86_get_smp_cpus_hyper; + machdep->get_smp_cpus = xen_hyper_x86_get_smp_cpus; // machdep->line_number_hooks = x86_line_number_hooks; /* ODA: check */ machdep->flags |= FRAMESIZE_DEBUG; /* ODA: check */ machdep->value_to_symbol = generic_machdep_value_to_symbol; machdep->clear_machdep_cache = x86_clear_machdep_cache; /* machdep table for Xen Hypervisor */ - xhmachdep->pcpu_init = x86_xen_hyper_pcpu_init; + xhmachdep->pcpu_init = xen_hyper_x86_pcpu_init; break; case POST_GDB: @@ -4877,6 +4889,9 @@ XEN_HYPER_MEMBER_OFFSET_INIT(cpu_time_stime_master_stamp, "cpu_time", "stime_master_stamp"); XEN_HYPER_MEMBER_OFFSET_INIT(cpu_time_tsc_scale, "cpu_time", "tsc_scale"); XEN_HYPER_MEMBER_OFFSET_INIT(cpu_time_calibration_timer, "cpu_time", "calibration_timer"); + if (symbol_exists("cpu_data")) { + xht->cpu_data_address = symbol_value("cpu_data"); + } /* KAK Can this be calculated? */ if (!machdep->hz) { machdep->hz = XEN_HYPER_HZ; Index: x86_64.c =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/x86_64.c,v retrieving revision 1.5 retrieving revision 1.5.2.1 diff -u -r1.5 -r1.5.2.1 --- x86_64.c 13 Feb 2007 06:37:55 -0000 1.5 +++ x86_64.c 15 Feb 2007 00:38:15 -0000 1.5.2.1 @@ -4868,23 +4868,20 @@ static ulong x86_64_get_stackbase_hyper(ulong task) { - ulong init_tss, rsp0, base; - char *buf; + struct xen_hyper_vcpu_context *vcc; + struct xen_hyper_pcpu_context *pcc; + ulong rsp0, base; + + /* task means vcpu here */ + vcc = xen_hyper_vcpu_to_vcpu_context(task); + if (!vcc) + error(FATAL, "invalid vcpu\n"); - /* task means pcpu here */ - if (!xen_hyper_test_pcpu_id(task)) { + pcc = xen_hyper_id_to_pcpu_context(vcc->processor); + if (!pcc) error(FATAL, "invalid pcpu number\n"); - } - init_tss = symbol_value("init_tss"); - buf = GETBUF(XEN_HYPER_SIZE(tss_struct)); - init_tss += XEN_HYPER_SIZE(tss_struct) * task; - if (!readmem(init_tss, KVADDR, buf, - XEN_HYPER_SIZE(tss_struct), "init_tss", RETURN_ON_ERROR)) { - error(FATAL, "cannot read init_tss.\n"); - } - rsp0 = ULONG(buf + XEN_HYPER_OFFSET(tss_struct_rsp0)); - FREEBUF(buf); + rsp0 = pcc->sp.rsp0; base = rsp0 & (~(STACKSIZE() - 1)); return base; } @@ -4895,22 +4892,58 @@ return x86_64_get_stackbase_hyper(task) + STACKSIZE(); } +#define EXCEPTION_STACKSIZE_HYPER (1024UL) + +static ulong +x86_64_in_exception_stack_hyper(ulong vcpu, ulong rsp) +{ + struct xen_hyper_vcpu_context *vcc; + struct xen_hyper_pcpu_context *pcc; + int i; + ulong stackbase; + + vcc = xen_hyper_vcpu_to_vcpu_context(vcpu); + if (!vcc) + error(FATAL, "invalid vcpu\n"); + + pcc = xen_hyper_id_to_pcpu_context(vcc->processor); + if (!pcc) + error(FATAL, "invalid pcpu number\n"); + + for (i = 0; i < XEN_HYPER_TSS_IST_MAX; i++) { + if (pcc->ist[i] == 0) { + continue; + } + stackbase = pcc->ist[i] - EXCEPTION_STACKSIZE_HYPER; + if ((rsp & ~(EXCEPTION_STACKSIZE_HYPER - 1)) == stackbase) { + return stackbase; + } + } + + return 0; +} + static void x86_64_get_stack_frame_hyper(struct bt_info *bt, ulong *pcp, ulong *spp) { + struct xen_hyper_vcpu_context *vcc; int pcpu; ulong *regs; ulong rsp, rip; - /* task means pcpu here */ - pcpu = bt->task; + /* task means vcpu here */ + vcc = xen_hyper_vcpu_to_vcpu_context(bt->task); + if (!vcc) + error(FATAL, "invalid vcpu\n"); + + pcpu = vcc->processor; if (!xen_hyper_test_pcpu_id(pcpu)) { error(FATAL, "invalid pcpu number\n"); } if (bt->flags & BT_TEXT_SYMBOLS_ALL) { if (spp) - *spp = x86_64_get_stackbase_hyper(pcpu); + *spp = x86_64_get_stackbase_hyper(bt->task); if (pcp) *pcp = 0; bt->flags &= ~BT_TEXT_SYMBOLS_ALL; @@ -4922,9 +4955,11 @@ rip = XEN_HYPER_X86_64_NOTE_RIP(regs); if (spp) { - if (rsp < x86_64_get_stackbase_hyper(pcpu) || - rsp >= x86_64_get_stacktop_hyper(pcpu)) - *spp = x86_64_get_stackbase_hyper(pcpu); + if (x86_64_in_exception_stack_hyper(bt->task, rsp)) + *spp = rsp; + else if (rsp < x86_64_get_stackbase_hyper(bt->task) || + rsp >= x86_64_get_stacktop_hyper(bt->task)) + *spp = x86_64_get_stackbase_hyper(bt->task); else *spp = rsp; } @@ -4981,18 +5016,58 @@ return result; } +static void +x86_64_print_eframe_regs_hyper(struct bt_info *bt) +{ + ulong *up; + ulong offset; + struct syment *sp; + + + up = (ulong *)(&bt->stackbuf[bt->stacktop - bt->stackbase]); + up -= 21; + + fprintf(fp, " [exception RIP: "); + if ((sp = value_search(up[16], &offset))) { + fprintf(fp, "%s", sp->name); + if (offset) + fprintf(fp, (output_radix == 16) ? + "+0x%lx" : "+%ld", offset); + } else + fprintf(fp, "unknown or invalid address"); + fprintf(fp, "]\n"); + + fprintf(fp, " RIP: %016lx RSP: %016lx RFLAGS: %08lx\n", + up[16], up[19], up[18]); + fprintf(fp, " RAX: %016lx RBX: %016lx RCX: %016lx\n", + up[10], up[5], up[11]); + fprintf(fp, " RDX: %016lx RSI: %016lx RDI: %016lx\n", + up[11], up[13], up[14]); + fprintf(fp, " RBP: %016lx R8: %016lx R9: %016lx\n", + up[4], up[9], up[8]); + fprintf(fp, " R10: %016lx R11: %016lx R12: %016lx\n", + up[7], up[6], up[3]); + fprintf(fp, " R13: %016lx R14: %016lx R15: %016lx\n", + up[2], up[1], up[0]); + fprintf(fp, " ORIG_RAX: %016lx CS: %04lx SS: %04lx\n", + up[15], up[17], up[20]); + + fprintf(fp, "--- ---\n"); +} + /* * simple back tracer for xen hypervisor - * irq stack and exception stack does not exist. so relative easy. + * irq stack does not exist. so relative easy. */ static void x86_64_simple_back_trace_cmd_hyper(struct bt_info *bt_in) { int i, level, done; - ulong rsp; + ulong rsp, estack, stacktop; ulong *up; FILE *ofp; struct bt_info bt_local, *bt; + char ebuf[EXCEPTION_STACKSIZE_HYPER]; bt = &bt_local; BCOPY(bt_in, bt, sizeof(struct bt_info)); @@ -5015,6 +5090,60 @@ else ofp = fp; + while ((estack = x86_64_in_exception_stack_hyper(bt->task, rsp))) { + bt->flags |= BT_EXCEPTION_STACK; + bt->stackbase = estack; + bt->stacktop = estack + EXCEPTION_STACKSIZE_HYPER; + bt->stackbuf = ebuf; + + if (!readmem(bt->stackbase, KVADDR, bt->stackbuf, + bt->stacktop - bt->stackbase, "exception stack contents", + RETURN_ON_ERROR)) + error(FATAL, "read of exception stack at %lx failed\n", + bt->stackbase); + + stacktop = bt->stacktop - 168; + + for (i = (rsp - bt->stackbase)/sizeof(ulong); + !done && (rsp < stacktop); i++, rsp += sizeof(ulong)) { + + up = (ulong *)(&bt->stackbuf[i*sizeof(ulong)]); + + if (!is_kernel_text(*up)) + continue; + + switch (x86_64_print_stack_entry_hyper(bt, ofp, level, i,*up)) + { + case BACKTRACE_ENTRY_DISPLAYED: + level++; + break; + case BACKTRACE_ENTRY_IGNORED: + break; + case BACKTRACE_COMPLETE: + done = TRUE; + break; + } + } + + if (!BT_REFERENCE_CHECK(bt)) + x86_64_print_eframe_regs_hyper(bt); + + up = (ulong *)(&bt->stackbuf[bt->stacktop - bt->stackbase]); + up -= 2; + rsp = bt->stkptr = *up; + up -= 3; + bt->instptr = *up; + done = FALSE; + bt->frameptr = 0; + } + + if (bt->flags & BT_EXCEPTION_STACK) { + bt->flags &= ~BT_EXCEPTION_STACK; + bt->stackbase = bt_in->stackbase; + bt->stacktop = bt_in->stacktop; + bt->stackbuf = bt_in->stackbuf; + } + for (i = (rsp - bt->stackbase)/sizeof(ulong); !done && (rsp < bt->stacktop); i++, rsp += sizeof(ulong)) { @@ -5089,24 +5218,28 @@ machdep->get_stackbase = x86_64_get_stackbase_hyper; machdep->get_stacktop = x86_64_get_stacktop_hyper; machdep->translate_pte = x86_64_translate_pte; - machdep->memory_size = x86_memory_size_hyper; /* KAK add */ + machdep->memory_size = xen_hyper_x86_memory_size; /* KAK add */ machdep->is_task_addr = x86_64_is_task_addr; machdep->dis_filter = x86_64_dis_filter; machdep->cmd_mach = x86_64_cmd_mach; - machdep->get_smp_cpus = x86_get_smp_cpus_hyper; /* KAK add */ + machdep->get_smp_cpus = xen_hyper_x86_get_smp_cpus; /* KAK add */ machdep->line_number_hooks = x86_64_line_number_hooks; machdep->value_to_symbol = generic_machdep_value_to_symbol; machdep->init_kernel_pgd = x86_64_init_kernel_pgd; machdep->clear_machdep_cache = x86_64_clear_machdep_cache; /* machdep table for Xen Hypervisor */ - xhmachdep->pcpu_init = x86_xen_hyper_pcpu_init; + xhmachdep->pcpu_init = xen_hyper_x86_pcpu_init; break; case POST_GDB: XEN_HYPER_STRUCT_SIZE_INIT(cpuinfo_x86, "cpuinfo_x86"); XEN_HYPER_STRUCT_SIZE_INIT(tss_struct, "tss_struct"); XEN_HYPER_MEMBER_OFFSET_INIT(tss_struct_rsp0, "tss_struct", "rsp0"); + XEN_HYPER_MEMBER_OFFSET_INIT(tss_struct_ist, "tss_struct", "ist"); + if (symbol_exists("cpu_data")) { + xht->cpu_data_address = symbol_value("cpu_data"); + } /* KAK Can this be calculated? */ if (!machdep->hz) { machdep->hz = XEN_HYPER_HZ; Index: xen_hyper.c =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/xen_hyper.c,v retrieving revision 1.2 retrieving revision 1.2.8.3 diff -u -r1.2 -r1.2.8.3 --- xen_hyper.c 21 Dec 2006 00:01:02 -0000 1.2 +++ xen_hyper.c 15 Feb 2007 01:41:28 -0000 1.2.8.3 @@ -1,8 +1,11 @@ /* * xen_hyper.c * - * Portions Copyright (C) 2006 Fujitsu Limited - * Portions Copyright (C) 2006 VA Linux Systems Japan K.K. + * Portions Copyright (C) 2006-2007 Fujitsu Limited + * Portions Copyright (C) 2006-2007 VA Linux Systems Japan K.K. + * + * Authors: Itsuro Oda + * Fumihiko Kakuma * * This file is part of Xencrash. * @@ -25,6 +28,8 @@ #ifdef XEN_HYPERVISOR_ARCH #include "xen_hyper_defs.h" +static void xen_hyper_schedule_init(void); + /* * Do initialization for Xen Hyper system here. */ @@ -32,22 +37,54 @@ xen_hyper_init(void) { char *buf; +#if defined(X86) || defined(X86_64) long member_offset; +#endif - get_symbol_data("crashing_cpu", sizeof(xht->crashing_cpu), - &xht->crashing_cpu); + if (symbol_exists("crashing_cpu")) { + get_symbol_data("crashing_cpu", sizeof(xht->crashing_cpu), + &xht->crashing_cpu); + } else { + xht->crashing_cpu = XEN_HYPER_PCPU_ID_INVALID; + } machdep->get_smp_cpus(); machdep->memory_size(); - if (machine_type("X86") || machine_type("X86_64")) { - member_offset = MEMBER_OFFSET("cpuinfo_x86", "x86_model_id"); - buf = GETBUF(XEN_HYPER_SIZE(cpuinfo_x86)); - xen_hyper_fill_cpu_data_x86(xht->crashing_cpu, buf); - strncpy(xht->utsname.machine, (char *)(buf + member_offset), - sizeof(xht->utsname.machine)-1); - FREEBUF(buf); +#ifdef IA64 + if((xht->__per_cpu_offset = malloc(sizeof(ulong) * XEN_HYPER_MAX_CPUS())) == NULL) { + error(FATAL, "cannot malloc __per_cpu_offset space.\n"); + } + if (!readmem(symbol_value("__per_cpu_offset"), KVADDR, + xht->__per_cpu_offset, sizeof(ulong) * XEN_HYPER_MAX_CPUS(), + "__per_cpu_offset", RETURN_ON_ERROR)) { + error(FATAL, "cannot read __per_cpu_offset.\n"); + } +#endif + +#if defined(X86) || defined(X86_64) + member_offset = MEMBER_OFFSET("cpuinfo_x86", "x86_model_id"); + buf = GETBUF(XEN_HYPER_SIZE(cpuinfo_x86)); + if (xen_hyper_test_pcpu_id(XEN_HYPER_CRASHING_CPU())) { + xen_hyper_x86_fill_cpu_data(XEN_HYPER_CRASHING_CPU(), buf); + } else { + xen_hyper_x86_fill_cpu_data(xht->cpu_idxs[0], buf); } + strncpy(xht->utsname.machine, (char *)(buf + member_offset), + sizeof(xht->utsname.machine)-1); + FREEBUF(buf); +#elif defined(IA64) + buf = GETBUF(XEN_HYPER_SIZE(cpuinfo_ia64)); + if (xen_hyper_test_pcpu_id(XEN_HYPER_CRASHING_CPU())) { + xen_hyper_ia64_fill_cpu_data(XEN_HYPER_CRASHING_CPU(), buf); + } else { + xen_hyper_ia64_fill_cpu_data(xht->cpu_idxs[0], buf); + } + strncpy(xht->utsname.machine, (char *)(buf + XEN_HYPER_OFFSET(cpuinfo_ia64_vendor)), + sizeof(xht->utsname.machine)-1); + FREEBUF(buf); +#endif +#ifndef IA64 XEN_HYPER_STRUCT_SIZE_INIT(note_buf_t, "note_buf_t"); XEN_HYPER_STRUCT_SIZE_INIT(crash_note_t, "crash_note_t"); XEN_HYPER_MEMBER_OFFSET_INIT(crash_note_t_core, "crash_note_t", "core"); @@ -92,12 +129,29 @@ XEN_HYPER_STRUCT_SIZE_INIT(ELF_Signifo,"ELF_Signifo"); XEN_HYPER_STRUCT_SIZE_INIT(ELF_Gregset,"ELF_Gregset"); XEN_HYPER_STRUCT_SIZE_INIT(ELF_Timeval,"ELF_Timeval"); +#endif XEN_HYPER_STRUCT_SIZE_INIT(domain, "domain"); XEN_HYPER_STRUCT_SIZE_INIT(vcpu, "vcpu"); +#ifndef IA64 XEN_HYPER_STRUCT_SIZE_INIT(cpu_info, "cpu_info"); +#endif XEN_HYPER_STRUCT_SIZE_INIT(cpu_user_regs, "cpu_user_regs"); + /* + * Do some initialization. + */ +#ifndef IA64 xen_hyper_dumpinfo_init(); +#endif + xhmachdep->pcpu_init(); + xen_hyper_domain_init(); + xen_hyper_vcpu_init(); + xen_hyper_misc_init(); + /* + * xen_hyper_post_init() have to be called after all initialize + * functions finished. + */ + xen_hyper_post_init(); } /* @@ -165,6 +219,12 @@ XEN_HYPER_MEMBER_OFFSET_INIT(vcpu_vcpu_dirty_cpumask, "vcpu", "vcpu_dirty_cpumask"); XEN_HYPER_MEMBER_OFFSET_INIT(vcpu_arch, "vcpu", "arch"); +#ifdef IA64 + XEN_HYPER_ASSIGN_OFFSET(vcpu_thread_ksp) = + MEMBER_OFFSET("vcpu", "arch") + MEMBER_OFFSET("arch_vcpu", "_thread") + + MEMBER_OFFSET("thread_struct", "ksp"); +#endif + if((xhvct->vcpu_struct = malloc(XEN_HYPER_SIZE(vcpu))) == NULL) { error(FATAL, "cannot malloc vcpu struct space.\n"); } @@ -180,12 +240,13 @@ /* * Do initialization for pcpu of Xen Hyper system here. */ +#if defined(X86) || defined(X86_64) void -x86_xen_hyper_pcpu_init(void) +xen_hyper_x86_pcpu_init(void) { ulong cpu_info; ulong init_tss_base, init_tss; - long sp; + ulong sp; struct xen_hyper_pcpu_context *pcc; char *buf, *bp; int i, cpuid; @@ -223,6 +284,176 @@ } pcc = &xhpct->context_array[cpuid]; xen_hyper_store_pcpu_context(pcc, cpu_info, bp); + xen_hyper_store_pcpu_context_tss(pcc, init_tss, buf); + } + FREEBUF(buf); +} + +#elif defined(IA64) +void +xen_hyper_ia64_pcpu_init(void) +{ + struct xen_hyper_pcpu_context *pcc; + int i, cpuid; + + /* get physical cpu context */ + xen_hyper_alloc_pcpu_context_space(XEN_HYPER_MAX_CPUS()); + for_cpu_indexes(i, cpuid) + { + pcc = &xhpct->context_array[cpuid]; + pcc->processor_id = cpuid; + } +} +#endif + +/* + * Do initialization for some miscellaneous thing + * of Xen Hyper system here. + */ +void +xen_hyper_misc_init(void) +{ + XEN_HYPER_STRUCT_SIZE_INIT(schedule_data, "schedule_data"); + XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_schedule_lock, "schedule_data", "schedule_lock"); + XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_curr, "schedule_data", "curr"); + XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_idle, "schedule_data", "idle"); + XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_sched_priv, "schedule_data", "sched_priv"); + XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_s_timer, "schedule_data", "s_timer"); + XEN_HYPER_MEMBER_OFFSET_INIT(schedule_data_tick, "schedule_data", "tick"); + + XEN_HYPER_STRUCT_SIZE_INIT(scheduler, "scheduler"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_name, "scheduler", "name"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_opt_name, "scheduler", "opt_name"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_sched_id, "scheduler", "sched_id"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_init, "scheduler", "init"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_tick, "scheduler", "tick"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_init_vcpu, "scheduler", "init_vcpu"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_destroy_domain, "scheduler", "destroy_domain"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_sleep, "scheduler", "sleep"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_wake, "scheduler", "wake"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_set_affinity, "scheduler", "set_affinity"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_do_schedule, "scheduler", "do_schedule"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_adjust, "scheduler", "adjust"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_dump_settings, "scheduler", "dump_settings"); + XEN_HYPER_MEMBER_OFFSET_INIT(scheduler_dump_cpu_state, "scheduler", "dump_cpu_state"); + + xen_hyper_schedule_init(); +} + +/* + * Do initialization for scheduler of Xen Hyper system here. + */ +#define XEN_HYPER_SCHEDULERS_ARRAY_CNT 10 +#define XEN_HYPER_SCHEDULER_NAME 1024 + +static void +xen_hyper_schedule_init(void) +{ + ulong addr, opt_sched, schedulers, opt_name; + long scheduler_opt_name; + long schedulers_buf[XEN_HYPER_SCHEDULERS_ARRAY_CNT]; + struct xen_hyper_sched_context *schc; + char *buf; + char opt_name_buf[XEN_HYPER_OPT_SCHED_SIZE]; + int i, cpuid, flag; + + /* get scheduler information */ + if((xhscht->scheduler_struct = + malloc(XEN_HYPER_SIZE(scheduler))) == NULL) { + error(FATAL, "cannot malloc scheduler struct space.\n"); + } + buf = GETBUF(XEN_HYPER_SCHEDULER_NAME); + opt_sched = symbol_value("opt_sched"); + if (!readmem(opt_sched, KVADDR, xhscht->opt_sched, + XEN_HYPER_OPT_SCHED_SIZE, "opt_sched,", RETURN_ON_ERROR)) { + error(FATAL, "cannot read opt_sched,.\n"); + } + schedulers = symbol_value("schedulers"); + scheduler_opt_name = XEN_HYPER_OFFSET(scheduler_opt_name); + addr = schedulers; + while (xhscht->name == NULL) { + if (!readmem(addr, KVADDR, schedulers_buf, + sizeof(long) * XEN_HYPER_SCHEDULERS_ARRAY_CNT, + "schedulers", RETURN_ON_ERROR)) { + error(FATAL, "cannot read schedulers.\n"); + } + for (i = 0; i < XEN_HYPER_SCHEDULERS_ARRAY_CNT; i++) { + if (schedulers_buf[i] == 0) { + error(FATAL, "schedule data not found.\n"); + } + if (!readmem(schedulers_buf[i], KVADDR, + xhscht->scheduler_struct, XEN_HYPER_SIZE(scheduler), + "scheduler", RETURN_ON_ERROR)) { + error(FATAL, "cannot read scheduler.\n"); + } + opt_name = ULONG(xhscht->scheduler_struct + + scheduler_opt_name); + if (!readmem(opt_name, KVADDR, opt_name_buf, + XEN_HYPER_OPT_SCHED_SIZE, "opt_name", RETURN_ON_ERROR)) { + error(FATAL, "cannot read opt_name.\n"); + } + if (strncmp(xhscht->opt_sched, opt_name_buf, + XEN_HYPER_OPT_SCHED_SIZE)) + continue; + xhscht->scheduler = schedulers_buf[i]; + xhscht->sched_id = INT(xhscht->scheduler_struct + + XEN_HYPER_OFFSET(scheduler_sched_id)); + addr = ULONG(xhscht->scheduler_struct + + XEN_HYPER_OFFSET(scheduler_name)); + if (!readmem(addr, KVADDR, buf, XEN_HYPER_SCHEDULER_NAME, + "scheduler_name", RETURN_ON_ERROR)) { + error(FATAL, "cannot read scheduler_name.\n"); + } + if (strlen(buf) >= XEN_HYPER_SCHEDULER_NAME) { + error(FATAL, "cannot read scheduler_name.\n"); + } + if((xhscht->name = malloc(strlen(buf) + 1)) == NULL) { + error(FATAL, "cannot malloc scheduler_name space.\n"); + } + BZERO(xhscht->name, strlen(buf) + 1); + strncpy(xhscht->name, buf, strlen(buf)); + break; + } + addr += sizeof(long) * XEN_HYPER_SCHEDULERS_ARRAY_CNT; + } + FREEBUF(buf); + + /* get schedule_data information */ + if((xhscht->sched_context_array = + malloc(sizeof(struct xen_hyper_sched_context) * XEN_HYPER_MAX_CPUS())) == NULL) { + error(FATAL, "cannot malloc xen_hyper_sched_context struct space.\n"); + } + BZERO(xhscht->sched_context_array, + sizeof(struct xen_hyper_sched_context) * XEN_HYPER_MAX_CPUS()); + buf = GETBUF(XEN_HYPER_SIZE(schedule_data)); + if (symbol_exists("per_cpu__schedule_data")) { + addr = symbol_value("per_cpu__schedule_data"); + flag = TRUE; + } else { + addr = symbol_value("schedule_data"); + flag = FALSE; + } + for_cpu_indexes(i, cpuid) + { + schc = &xhscht->sched_context_array[cpuid]; + if (flag) { + schc->schedule_data = + xen_hyper_per_cpu(addr, i); + } else { + schc->schedule_data = addr + + XEN_HYPER_SIZE(schedule_data) * i; + } + if (!readmem(schc->schedule_data, + KVADDR, buf, XEN_HYPER_SIZE(schedule_data), + "schedule_data", RETURN_ON_ERROR)) { + error(FATAL, "cannot read schedule_data.\n"); + } + schc->cpu_id = cpuid; + schc->curr = ULONG(buf + XEN_HYPER_OFFSET(schedule_data_curr)); + schc->idle = ULONG(buf + XEN_HYPER_OFFSET(schedule_data_idle)); + schc->sched_priv = + ULONG(buf + XEN_HYPER_OFFSET(schedule_data_sched_priv)); + schc->tick = ULONG(buf + XEN_HYPER_OFFSET(schedule_data_tick)); } FREEBUF(buf); } @@ -233,9 +464,22 @@ void xen_hyper_post_init(void) { + struct xen_hyper_pcpu_context *pcc; + int i, cpuid; + + /* set current vcpu to pcpu context */ + for_cpu_indexes(i, cpuid) + { + pcc = &xhpct->context_array[cpuid]; + if (!pcc->current_vcpu) { + pcc->current_vcpu = + xen_hyper_get_active_vcpu_from_pcpuid(cpuid); + } + } + /* set pcpu last */ if (!(xhpct->last = - xen_hyper_id_to_pcpu_context(xht->crashing_cpu))) { + xen_hyper_id_to_pcpu_context(XEN_HYPER_CRASHING_CPU()))) { xhpct->last = &xhpct->context_array[xht->cpu_idxs[0]]; } @@ -261,7 +505,7 @@ } /* - * Do initialization for dump information header here. + * Do initialization for dump information here. */ void xen_hyper_dumpinfo_init(void) @@ -273,7 +517,7 @@ int i, cpuid; /* - * kakuma NOTE: It is not clear that what ikind of + * NOTE kakuma: It is not clear that what kind of * a elf note format each one of the xen uses. * So, we decide it confirming whether a symbol exists. */ @@ -287,6 +531,10 @@ error(WARNING, "unsupported elf note format.\n"); return; } + if (!xen_hyper_test_pcpu_id(XEN_HYPER_CRASHING_CPU())) { + error(WARNING, "crashing_cpu not found.\n"); + return; + } size = sizeof(struct xen_hyper_dumpinfo_context) * XEN_HYPER_MAX_CPUS(); if((xhdit->context_array = malloc(size)) == NULL) { @@ -306,7 +554,7 @@ /* read a sample note */ buf = GETBUF(xhdit->note_size); - if (!xen_hyper_fill_elf_notes(xhdit->context_array[xht->crashing_cpu].note, + if (!xen_hyper_fill_elf_notes(xhdit->context_array[XEN_HYPER_CRASHING_CPU()].note, buf, XEN_HYPER_ELF_NOTE_FILL_T_NOTE)) { error(FATAL, "cannot read per_cpu__crash_notes.\n"); } @@ -343,9 +591,9 @@ memcpy(xhdit->crash_note_xen_info_ptr, bp + xhdit->core_size, xhdit->xen_info_size); xhdit->context_xen_info.note = - xhdit->context_array[xht->crashing_cpu].note + + xhdit->context_array[XEN_HYPER_CRASHING_CPU()].note + xhdit->core_size; - xhdit->context_xen_info.pcpu_id = xht->crashing_cpu; + xhdit->context_xen_info.pcpu_id = XEN_HYPER_CRASHING_CPU(); xhdit->context_xen_info.crash_xen_info_ptr = xhdit->crash_note_xen_info_ptr + xhdit->xen_info_offset; break; @@ -364,9 +612,9 @@ memcpy(xhdit->crash_note_xen_core_ptr, bp + xhdit->core_size, xhdit->xen_core_size); xhdit->context_xen_core.note = - xhdit->context_array[xht->crashing_cpu].note + + xhdit->context_array[XEN_HYPER_CRASHING_CPU()].note + xhdit->core_size; - xhdit->context_xen_core.pcpu_id = xht->crashing_cpu; + xhdit->context_xen_core.pcpu_id = XEN_HYPER_CRASHING_CPU(); xhdit->context_xen_core.crash_xen_core_ptr = xhdit->crash_note_xen_core_ptr + xhdit->xen_core_offset; /* xen info */ @@ -381,9 +629,9 @@ bp + xhdit->core_size + xhdit->xen_core_size, xhdit->xen_info_size); xhdit->context_xen_info.note = - xhdit->context_array[xht->crashing_cpu].note + + xhdit->context_array[XEN_HYPER_CRASHING_CPU()].note + xhdit->core_size + xhdit->xen_core_size; - xhdit->context_xen_info.pcpu_id = xht->crashing_cpu; + xhdit->context_xen_info.pcpu_id = XEN_HYPER_CRASHING_CPU(); xhdit->context_xen_info.crash_xen_info_ptr = xhdit->crash_note_xen_info_ptr + xhdit->xen_info_offset; break; @@ -391,7 +639,7 @@ error(FATAL, "logic error in cheking elf note format occurs.\n"); } - size = xhdit->core_size * XEN_HYPER_MAX_PCPUS(); + size = xhdit->core_size * XEN_HYPER_NR_PCPUS(); if(!(xhdit->crash_note_core_array = malloc(size))) { error(FATAL, "cannot malloc note_buf_t struct space.\n"); } @@ -421,6 +669,8 @@ struct xen_hyper_dumpinfo_context * xen_hyper_id_to_dumpinfo_context(uint id) { + if (!xen_hyper_test_pcpu_id(id)) + return NULL; return &xhdit->context_array[id]; } @@ -509,9 +759,9 @@ return; } - XEN_HYPER_RUNNING_DOMAINS() = XEN_HYPER_MAX_DOMAINS() = + XEN_HYPER_RUNNING_DOMAINS() = XEN_HYPER_NR_DOMAINS() = xen_hyper_get_domains(); - xen_hyper_alloc_domain_context_space(XEN_HYPER_MAX_DOMAINS()); + xen_hyper_alloc_domain_context_space(XEN_HYPER_NR_DOMAINS()); dc = xhdt->context_array; /* restore an idle domain context. */ @@ -624,7 +874,7 @@ xen_hyper_read_domain(*next)) == NULL) { error(FATAL, "cannot get next domain from domain context array.\n"); } - if (idx > XEN_HYPER_MAX_DOMAINS()) { + if (idx > XEN_HYPER_NR_DOMAINS()) { *next = 0; } else { dc = xhdt->context_array; @@ -707,7 +957,7 @@ if (!domain) { return NULL; } - for (i = 0, dc = xhdt->context_array; i < XEN_HYPER_MAX_DOMAINS(); + for (i = 0, dc = xhdt->context_array; i < XEN_HYPER_NR_DOMAINS(); i++, dc++) { if (domain == dc->domain) { return dc; @@ -732,7 +982,7 @@ if (id == XEN_HYPER_DOMAIN_ID_INVALID) { return NULL; } - for (i = 0, dc = xhdt->context_array; i < XEN_HYPER_MAX_DOMAINS(); + for (i = 0, dc = xhdt->context_array; i < XEN_HYPER_NR_DOMAINS(); i++, dc++) { if (id == dc->domain_id) { return dc; @@ -763,7 +1013,7 @@ dc->evtchn = ULONG(dp + XEN_HYPER_OFFSET(domain_evtchn)); for (i = 0; i < XEN_HYPER_MAX_VIRT_CPUS; i++) { dc->vcpu[i] = ULONG(dp + XEN_HYPER_OFFSET(domain_vcpu) + i*sizeof(void *)); - if (dc->vcpu[i]) XEN_HYPER_MAX_VCPUS(dc)++; + if (dc->vcpu[i]) XEN_HYPER_NR_VCPUS_IN_DOM(dc)++; } return dc; @@ -868,15 +1118,15 @@ return; } - xen_hyper_alloc_vcpu_context_arrays_space(XEN_HYPER_MAX_DOMAINS()); + xen_hyper_alloc_vcpu_context_arrays_space(XEN_HYPER_NR_DOMAINS()); for (i = 0, xht->vcpus = 0, dc = xhdt->context_array, vcca = xhvct->vcpu_context_arrays; - i < XEN_HYPER_MAX_DOMAINS(); i++, dc++, vcca++) { + i < XEN_HYPER_NR_DOMAINS(); i++, dc++, vcca++) { dc->vcpu_context_array = vcca; xen_hyper_alloc_vcpu_context_space(vcca, - XEN_HYPER_MAX_VCPUS(dc)); + XEN_HYPER_NR_VCPUS_IN_DOM(dc)); for (j = 0, vcc = vcca->context_array; - j < XEN_HYPER_MAX_VCPUS(dc); j++, vcc++) { + j < XEN_HYPER_NR_VCPUS_IN_DOM(dc); j++, vcc++) { xen_hyper_read_vcpu(dc->vcpu[j]); xen_hyper_store_vcpu_context(vcc, dc->vcpu[j], xhvct->vcpu_struct); @@ -1152,6 +1402,29 @@ } /* + * Store init_tss contents. + */ +struct xen_hyper_pcpu_context * +xen_hyper_store_pcpu_context_tss(struct xen_hyper_pcpu_context *pcc, + ulong init_tss, char *tss) +{ + int i; + uint64_t *ist_p; + + pcc->init_tss = init_tss; + if (machine_type("X86")) { + pcc->sp.esp0 = ULONG(tss + XEN_HYPER_OFFSET(tss_struct_esp0)); + } else if (machine_type("X86_64")) { + pcc->sp.rsp0 = ULONG(tss + XEN_HYPER_OFFSET(tss_struct_rsp0)); + ist_p = (uint64_t *)(tss + XEN_HYPER_OFFSET(tss_struct_ist)); + for (i = 0; i < XEN_HYPER_TSS_IST_MAX; i++, ist_p++) { + pcc->ist[i] = ULONG(ist_p); + } + } + return pcc; +} + +/* * Read pcpu struct. */ char * @@ -1195,15 +1468,15 @@ /* * Fill cpu_data. - * ia64 has difference cpu_data format. */ char * -xen_hyper_fill_cpu_data_x86(int idx, char *cpuinfo_x86) +xen_hyper_x86_fill_cpu_data(int idx, char *cpuinfo_x86) { - ulong cpu_data_base, cpu_data; + ulong cpu_data; - cpu_data_base = symbol_value("cpu_data"); - cpu_data = cpu_data_base + XEN_HYPER_SIZE(cpuinfo_x86) *idx; + if (!xen_hyper_test_pcpu_id(idx) || !xht->cpu_data_address) + return NULL; + cpu_data = xht->cpu_data_address + XEN_HYPER_SIZE(cpuinfo_x86) * idx; if (!readmem(cpu_data, KVADDR, cpuinfo_x86, XEN_HYPER_SIZE(cpuinfo_x86), "cpu_data", RETURN_ON_ERROR)) { error(WARNING, "cannot read cpu_data.\n"); @@ -1212,11 +1485,27 @@ return cpuinfo_x86; } +char * +xen_hyper_ia64_fill_cpu_data(int idx, char *cpuinfo_ia64) +{ + ulong cpu_data; + + if (!xen_hyper_test_pcpu_id(idx) || !xht->cpu_data_address) + return NULL; + cpu_data = xen_hyper_per_cpu(xht->cpu_data_address, idx); + if (!readmem(cpu_data, KVADDR, cpuinfo_ia64, XEN_HYPER_SIZE(cpuinfo_ia64), + "cpu_data", RETURN_ON_ERROR)) { + error(WARNING, "cannot read cpu_data.\n"); + return NULL; + } + return cpuinfo_ia64; +} + /* * Return whether vcpu is crashing. */ int -is_xen_hyper_vcpu_crash(struct xen_hyper_vcpu_context *vcc) +xen_hyper_is_vcpu_crash(struct xen_hyper_vcpu_context *vcc) { if (vcc == xht->crashing_vcc) return TRUE; @@ -1232,7 +1521,8 @@ ulong *cpumask = xht->cpumask; uint i, j; - if (pcpu_id > XEN_HYPER_MAX_CPUS()) { + if (pcpu_id == XEN_HYPER_PCPU_ID_INVALID || + pcpu_id > XEN_HYPER_MAX_CPUS()) { return FALSE; } @@ -1309,9 +1599,11 @@ if (xht->cpu_idxs) { free(xht->cpu_idxs); } - if((xht->cpu_idxs = malloc(sizeof(uint) * XEN_HYPER_MAX_PCPUS())) == NULL) { + if((xht->cpu_idxs = malloc(sizeof(uint) * XEN_HYPER_MAX_CPUS())) == NULL) { error(FATAL, "cannot malloc cpu_idxs space.\n"); } + memset(xht->cpu_idxs, 0xff, sizeof(uint) * XEN_HYPER_MAX_CPUS()); + for (i = cpus = 0, cpumask = xht->cpumask, cpu_idx = xht->cpu_idxs; i < (XEN_HYPER_SIZE(cpumask_t)/sizeof(ulong)); i++, cpumask++) { for (j = 0; j < sizeof(ulong) * 8; j++) { @@ -1328,7 +1620,7 @@ * Calculate the number of physical cpu for x86. */ int -x86_get_smp_cpus_hyper(void) +xen_hyper_x86_get_smp_cpus(void) { if (xht->pcpus) { return xht->pcpus; @@ -1338,26 +1630,73 @@ } /* - * Calculate used memory size. + * Calculate used memory size for x86. */ uint64_t -x86_memory_size_hyper(void) +xen_hyper_x86_memory_size(void) { ulong vaddr; if (machdep->memsize) { return machdep->memsize; } - vaddr = symbol_value("max_page"); - if (!readmem(vaddr, KVADDR, &xht->max_page, sizeof(xht->max_page), - "max_page", RETURN_ON_ERROR)) { - error(WARNING, "cannot read max_page.\n"); + vaddr = symbol_value("total_pages"); + if (!readmem(vaddr, KVADDR, &xht->total_pages, sizeof(xht->total_pages), + "total_pages", RETURN_ON_ERROR)) { + error(WARNING, "cannot read total_pages.\n"); } - machdep->memsize = (uint64_t)(xht->max_page) * (uint64_t)(machdep->pagesize); + machdep->memsize = (uint64_t)(xht->total_pages) * (uint64_t)(machdep->pagesize); return machdep->memsize; } +/* + * Calculate the number of physical cpu for ia64. + */ +int +xen_hyper_ia64_get_smp_cpus(void) +{ + return xen_hyper_x86_get_smp_cpus(); +} + +/* + * Calculate used memory size for ia64. + */ +uint64_t +xen_hyper_ia64_memory_size(void) +{ + return xen_hyper_x86_memory_size(); +} + +/* + * Calculate and return the speed of the processor. + */ +ulong +xen_hyper_ia64_processor_speed(void) +{ + ulong mhz, proc_freq; + + if (machdep->mhz) + return(machdep->mhz); + + mhz = 0; + + if (!xht->cpu_data_address || + !XEN_HYPER_VALID_STRUCT(cpuinfo_ia64) || + !XEN_HYPER_VALID_MEMBER(cpuinfo_ia64_proc_freq)) + return (machdep->mhz = mhz); + + readmem(xen_hyper_per_cpu(xht->cpu_data_address, xht->cpu_idxs[0]) + + XEN_HYPER_OFFSET(cpuinfo_ia64_proc_freq), + KVADDR, &proc_freq, sizeof(ulong), + "cpuinfo_ia64 proc_freq", FAULT_ON_ERROR); + + mhz = proc_freq/1000000; + + return (machdep->mhz = mhz); +} + + /* * Print an aligned string with specified length. @@ -1395,11 +1734,61 @@ } } +ulong +xen_hyper_get_active_vcpu_from_pcpuid(ulong pcpuid) +{ + struct xen_hyper_pcpu_context *pcc; + struct xen_hyper_vcpu_context_array *vcca; + struct xen_hyper_vcpu_context *vcc; + int i, j; + + if (!xen_hyper_test_pcpu_id(pcpuid)) + return 0; + + pcc = &xhpct->context_array[pcpuid]; + if (pcc->current_vcpu) + return pcc->current_vcpu; + + for (i = 0, vcca = xhvct->vcpu_context_arrays; + i < xhvct->vcpu_context_arrays_cnt; i++, vcca++) { + for (j = 0, vcc = vcca->context_array; + j < vcca->context_array_cnt; j++, vcc++) { + if (vcc->processor == pcpuid && + vcc->state == XEN_HYPER_RUNSTATE_running) { + return vcc->vcpu; + } + } + } + + return 0; +} + +ulong +xen_hyper_pcpu_to_active_vcpu(ulong pcpu) +{ + ulong vcpu; + + /* if pcpu is vcpu address, return it. */ + if (pcpu & (~(PAGESIZE() - 1))) { + return pcpu; + } + + if(!(vcpu = XEN_HYPER_CURR_VCPU(pcpu))) + error(FATAL, "invalid pcpu id\n"); + return vcpu; +} + void -print_pcpu_header_hyper(FILE *out, int pcpu, int newline) +xen_hyper_print_bt_header(FILE *out, ulong vcpu, int newline) { + struct xen_hyper_vcpu_context *vcc; + if (newline) fprintf(out, "\n"); - fprintf(out, "PCPU: %2d\n", pcpu); + + vcc = xen_hyper_vcpu_to_vcpu_context(vcpu); + if (!vcc) + error(FATAL, "invalid vcpu\n"); + fprintf(out, "PCPU: %2d VCPU: %lx\n", vcc->processor, vcpu); } #endif Index: xen_hyper_command.c =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/xen_hyper_command.c,v retrieving revision 1.3 retrieving revision 1.3.2.1 diff -u -r1.3 -r1.3.2.1 --- xen_hyper_command.c 13 Feb 2007 06:37:55 -0000 1.3 +++ xen_hyper_command.c 15 Feb 2007 00:38:15 -0000 1.3.2.1 @@ -1,8 +1,11 @@ /* * xen_hyper_command.c * - * Portions Copyright (C) 2006 Fujitsu Limited - * Portions Copyright (C) 2006 VA Linux Systems Japan K.K. + * Portions Copyright (C) 2006-2007 Fujitsu Limited + * Portions Copyright (C) 2006-2007 VA Linux Systems Japan K.K. + * + * Authors: Itsuro Oda + * Fumihiko Kakuma * * This file is part of Xencrash. * @@ -42,23 +45,32 @@ }; #endif -static void do_xen_hyper_domain(struct domain_args *da); -static void do_xen_hyper_doms(struct domain_args *da); -static void show_xen_hyper_doms(struct xen_hyper_domain_context *dc); -static void do_xen_hyper_dumpinfo(ulong flag, struct dumpinfo_args *ena); -static void show_xen_hyper_dumpinfo(ulong flag, - struct xen_hyper_dumpinfo_context *enc); -static void do_xen_hyper_pcpus(ulong flag, struct pcpu_args *pca); -static void show_xen_hyper_pcpus(ulong flag, struct xen_hyper_pcpu_context *pcc); -static void do_xen_hyper_vcpu(struct vcpu_args *vca); -static void do_xen_hyper_vcpus(struct vcpu_args *vca); -static void show_xen_hyper_vcpus(struct xen_hyper_vcpu_context *vcc); +#ifdef IA64 +char *xhregt[] = { + "aaa", "bbb", + NULL +}; +#endif + +static void xen_hyper_do_domain(struct xen_hyper_cmd_args *da); +static void xen_hyper_do_doms(struct xen_hyper_cmd_args *da); +static void xen_hyper_show_doms(struct xen_hyper_domain_context *dc); +static void xen_hyper_do_dumpinfo(ulong flag, struct xen_hyper_cmd_args *dia); +static void xen_hyper_show_dumpinfo(ulong flag, + struct xen_hyper_dumpinfo_context *dic); +static void xen_hyper_do_pcpus(ulong flag, struct xen_hyper_cmd_args *pca); +static void xen_hyper_show_pcpus(ulong flag, struct xen_hyper_pcpu_context *pcc); +static void xen_hyper_do_sched(ulong flag, struct xen_hyper_cmd_args *scha); +static void xen_hyper_show_sched(ulong flag, struct xen_hyper_sched_context *schc); +static void xen_hyper_do_vcpu(struct xen_hyper_cmd_args *vca); +static void xen_hyper_do_vcpus(struct xen_hyper_cmd_args *vca); +static void xen_hyper_show_vcpus(struct xen_hyper_vcpu_context *vcc); static char *xen_hyper_domain_to_type(ulong domain, int *type, char *buf, int verbose); static char *xen_hyper_domain_context_to_type( struct xen_hyper_domain_context *dc, int *type, char *buf, int verbose); static int xen_hyper_str_to_domain_context(char *string, ulong *value, struct xen_hyper_domain_context **dcp); -static int xen_hyper_str_to_dumpinfo_context(char *string, ulong *value, struct xen_hyper_dumpinfo_context **encp); +static int xen_hyper_str_to_dumpinfo_context(char *string, ulong *value, struct xen_hyper_dumpinfo_context **dicp); static int xen_hyper_strvcpu_to_vcpu_context(char *string, ulong *value, struct xen_hyper_vcpu_context **vccp); static int @@ -71,14 +83,14 @@ * Display domain struct. */ void -cmd_xen_hyper_domain(void) +xen_hyper_cmd_domain(void) { + struct xen_hyper_cmd_args da; struct xen_hyper_domain_context *dc; - struct domain_args da; ulong val; int c, cnt, type, bogus; - BZERO(&da, sizeof(struct domain_args)); + BZERO(&da, sizeof(struct xen_hyper_cmd_args)); while ((c = getopt(argcnt, args, "")) != EOF) { switch(c) { @@ -100,8 +112,8 @@ case XEN_HYPER_STR_DOMAIN: da.value[cnt] = val; da.type[cnt] = type; - da.domain[cnt] = dc->domain; - da.dc[cnt] = dc; + da.addr[cnt] = dc->domain; + da.context[cnt] = dc; cnt++; break; case XEN_HYPER_STR_INVALID: @@ -120,23 +132,23 @@ return; } - do_xen_hyper_domain(&da); + xen_hyper_do_domain(&da); } /* - * Do the work requested by cmd_xen_hyper_dom(). + * Do the work requested by xen_hyper_cmd_dom(). */ static void -do_xen_hyper_domain(struct domain_args *da) +xen_hyper_do_domain(struct xen_hyper_cmd_args *da) { int i; if (da->cnt) { if (da->cnt == 1) { - xhdt->last = da->dc[0]; + xhdt->last = da->context[0]; } for (i = 0; i < da->cnt; i++) { - dump_struct("domain", da->domain[i], 0); + dump_struct("domain", da->addr[i], 0); } } else { dump_struct("domain", xhdt->last->domain, 0); @@ -147,14 +159,14 @@ * Display domain status. */ void -cmd_xen_hyper_doms(void) +xen_hyper_cmd_doms(void) { + struct xen_hyper_cmd_args da; struct xen_hyper_domain_context *dc; - struct domain_args da; ulong val; int c, cnt, type, bogus; - BZERO(&da, sizeof(struct domain_args)); + BZERO(&da, sizeof(struct xen_hyper_cmd_args)); while ((c = getopt(argcnt, args, "")) != EOF) { switch(c) { @@ -176,8 +188,8 @@ case XEN_HYPER_STR_DOMAIN: da.value[cnt] = val; da.type[cnt] = type; - da.domain[cnt] = dc->domain; - da.dc[cnt] = dc; + da.addr[cnt] = dc->domain; + da.context[cnt] = dc; cnt++; break; case XEN_HYPER_STR_INVALID: @@ -196,14 +208,14 @@ return; } - do_xen_hyper_doms(&da); + xen_hyper_do_doms(&da); } /* - * Do the work requested by cmd_xen_hyper_doms(). + * Do the work requested by xen_hyper_cmd_doms(). */ static void -do_xen_hyper_doms(struct domain_args *da) +xen_hyper_do_doms(struct xen_hyper_cmd_args *da) { struct xen_hyper_domain_context *dca; char buf1[XEN_HYPER_CMD_BUFSIZE]; @@ -214,18 +226,18 @@ mkstring(buf1, VADDR_PRLEN, CENTER|RJUST, "DOMAIN")); if (da->cnt) { for (i = 0; i < da->cnt; i++) { - show_xen_hyper_doms(da->dc[i]); + xen_hyper_show_doms(da->context[i]); } } else { - for (i = 0, dca=xhdt->context_array; i < XEN_HYPER_MAX_DOMAINS(); + for (i = 0, dca=xhdt->context_array; i < XEN_HYPER_NR_DOMAINS(); i++, dca++) { - show_xen_hyper_doms(dca); + xen_hyper_show_doms(dca); } } } static void -show_xen_hyper_doms(struct xen_hyper_domain_context *dc) +xen_hyper_show_doms(struct xen_hyper_domain_context *dc) { double mmem, tmem; char *act, *crash; @@ -287,15 +299,15 @@ * Display ELF Notes information. */ void -cmd_xen_hyper_dumpinfo(void) +xen_hyper_cmd_dumpinfo(void) { - struct dumpinfo_args ena; + struct xen_hyper_cmd_args dia; ulong flag; ulong val; - struct xen_hyper_dumpinfo_context *enc; + struct xen_hyper_dumpinfo_context *dic; int c, cnt, type, bogus; - BZERO(&ena, sizeof(struct cmd_args)); + BZERO(&dia, sizeof(struct xen_hyper_cmd_args)); flag= 0; while ((c = getopt(argcnt, args, "rt")) != EOF) { switch(c) @@ -318,14 +330,14 @@ cnt = bogus = 0; while (args[optind]) { if (IS_A_NUMBER(args[optind])) { - type = xen_hyper_str_to_dumpinfo_context(args[optind], &val, &enc); + type = xen_hyper_str_to_dumpinfo_context(args[optind], &val, &dic); switch (type) { case XEN_HYPER_STR_PCID: case XEN_HYPER_STR_ADDR: - ena.value[cnt] = val; - ena.type[cnt] = type; - ena.enc[cnt] = enc; + dia.value[cnt] = val; + dia.type[cnt] = type; + dia.context[cnt] = dic; cnt++; break; @@ -341,28 +353,28 @@ } optind++; } - ena.cnt = cnt; + dia.cnt = cnt; if (!cnt && bogus) { return; } - do_xen_hyper_dumpinfo(flag, &ena); + xen_hyper_do_dumpinfo(flag, &dia); } /* - * Do the work requested by cmd_xen_hyper_dumpinfo(). + * Do the work requested by xen_hyper_cmd_dumpinfo(). */ static void -do_xen_hyper_dumpinfo(ulong flag, struct dumpinfo_args *ena) +xen_hyper_do_dumpinfo(ulong flag, struct xen_hyper_cmd_args *dia) { - struct xen_hyper_dumpinfo_context *enc; + struct xen_hyper_dumpinfo_context *dic; char buf[XEN_HYPER_CMD_BUFSIZE]; int i, cnt; - if (ena->cnt) { - cnt = ena->cnt; + if (dia->cnt) { + cnt = dia->cnt; } else { - cnt = XEN_HYPER_MAX_PCPUS(); + cnt = XEN_HYPER_NR_PCPUS(); } for (i = 0; i < cnt; i++) { if (i == 0 || flag & XEN_HYPER_DUMPINFO_REGS || @@ -375,17 +387,17 @@ sprintf(&buf[strlen(buf)], " PID PPID PGRP SID"); fprintf(fp, "%s\n", buf); } - if (ena->cnt) { - enc = ena->enc[i]; + if (dia->cnt) { + dic = dia->context[i]; } else { - enc = xen_hyper_id_to_dumpinfo_context(xht->cpu_idxs[i]); + dic = xen_hyper_id_to_dumpinfo_context(xht->cpu_idxs[i]); } - show_xen_hyper_dumpinfo(flag, enc); + xen_hyper_show_dumpinfo(flag, dic); } } static void -show_xen_hyper_dumpinfo(ulong flag, struct xen_hyper_dumpinfo_context *enc) +xen_hyper_show_dumpinfo(ulong flag, struct xen_hyper_dumpinfo_context *dic) { char buf[XEN_HYPER_CMD_BUFSIZE]; char *note_buf; @@ -394,14 +406,14 @@ long tv_sec, tv_usec; int pid, i, regcnt; - if (!enc->note) { + if (!dic || !dic->note) { return; } - note_buf = enc->ELF_Prstatus_ptr; - sprintf(buf, "%5d ", enc->pcpu_id); + note_buf = dic->ELF_Prstatus_ptr; + sprintf(buf, "%5d ", dic->pcpu_id); mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, - (char *)(enc->note)); + (char *)(dic->note)); pid = INT(note_buf + XEN_HYPER_OFFSET(ELF_Prstatus_pr_pid)); sprintf(&buf[strlen(buf)], " %5d ", pid); @@ -423,7 +435,7 @@ addr = (ulong)note_buf + XEN_HYPER_OFFSET(ELF_Prstatus_pr_utime); - for (i = 0; i < 4; i++, addr+=XEN_HYPER_SIZE(ELF_Timeval)) { + for (i = 0; i < 4; i++, addr += XEN_HYPER_SIZE(ELF_Timeval)) { switch (i) { case 0: @@ -448,7 +460,7 @@ (char *)(tv_sec)); strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, - (char *)(tv_sec)); + (char *)(tv_usec)); fprintf(fp, "%s\n", buf); } } @@ -474,7 +486,7 @@ * Dump the Xen conring in chronological order. */ void -cmd_xen_hyper_log(void) +xen_hyper_cmd_log(void) { int c; @@ -490,11 +502,11 @@ if (argerrs) cmd_usage(pc->curcmd, SYNOPSIS); - dump_xen_hyper_log(); + xen_hyper_dump_log(); } void -dump_xen_hyper_log(void) +xen_hyper_dump_log(void) { uint conringc, conringp; uint warp, start, len, idx, i; @@ -543,22 +555,25 @@ * Display physical cpu information. */ void -cmd_xen_hyper_pcpus(void) +xen_hyper_cmd_pcpus(void) { + struct xen_hyper_cmd_args pca; struct xen_hyper_pcpu_context *pcc; - struct pcpu_args pca; ulong flag; ulong val; int c, cnt, type, bogus; - BZERO(&pca, sizeof(struct pcpu_args)); + BZERO(&pca, sizeof(struct xen_hyper_cmd_args)); flag= 0; - while ((c = getopt(argcnt, args, "r")) != EOF) { + while ((c = getopt(argcnt, args, "rt")) != EOF) { switch(c) { case 'r': flag |= XEN_HYPER_PCPUS_REGS; break; + case 't': + flag |= XEN_HYPER_PCPUS_TSS; + break; default: argerrs++; break; @@ -577,8 +592,8 @@ case XEN_HYPER_STR_PCPU: pca.value[cnt] = val; pca.type[cnt] = type; - pca.pcpu[cnt] = pcc->pcpu; - pca.pcc[cnt] = pcc; + pca.addr[cnt] = pcc->pcpu; + pca.context[cnt] = pcc; cnt++; break; case XEN_HYPER_STR_INVALID: @@ -597,14 +612,14 @@ return; } - do_xen_hyper_pcpus(flag, &pca); + xen_hyper_do_pcpus(flag, &pca); } /* - * Do the work requested by cmd_xen_hyper_pcpu(). + * Do the work requested by xen_hyper_cmd_pcpu(). */ static void -do_xen_hyper_pcpus(ulong flag, struct pcpu_args *pca) +xen_hyper_do_pcpus(ulong flag, struct xen_hyper_cmd_args *pca) { struct xen_hyper_pcpu_context *pcc; uint cpuid; @@ -612,21 +627,21 @@ if (pca->cnt) { for (i = 0; i < pca->cnt; i++) { - show_xen_hyper_pcpus(flag, pca->pcc[i]); + xen_hyper_show_pcpus(flag, pca->context[i]); flag |= XEN_HYPER_PCPUS_1STCALL; } } else { for_cpu_indexes(i, cpuid) { pcc = xen_hyper_id_to_pcpu_context(cpuid); - show_xen_hyper_pcpus(flag, pcc); + xen_hyper_show_pcpus(flag, pcc); flag |= XEN_HYPER_PCPUS_1STCALL; } } } static void -show_xen_hyper_pcpus(ulong flag, struct xen_hyper_pcpu_context *pcc) +xen_hyper_show_pcpus(ulong flag, struct xen_hyper_pcpu_context *pcc) { char *act = " "; char buf[XEN_HYPER_CMD_BUFSIZE]; @@ -634,18 +649,21 @@ if (!(pcc->pcpu)) { return; } - if (xht->crashing_cpu == pcc->processor_id) { + if (XEN_HYPER_CRASHING_CPU() == pcc->processor_id) { act = " *"; } - if ((flag & XEN_HYPER_PCPUS_REGS) || - (!(flag & XEN_HYPER_PCPUS_REGS) && !(flag & XEN_HYPER_PCPUS_1STCALL))) { - if ((flag & XEN_HYPER_PCPUS_REGS) && (flag & XEN_HYPER_PCPUS_1STCALL)) { + if ((flag & XEN_HYPER_PCPUS_REGS) || (flag & XEN_HYPER_PCPUS_TSS) || + !(flag & XEN_HYPER_PCPUS_1STCALL)) { + if (((flag & XEN_HYPER_PCPUS_REGS) || (flag & XEN_HYPER_PCPUS_TSS)) && + (flag & XEN_HYPER_PCPUS_1STCALL)) { fprintf(fp, "\n"); } sprintf(buf, " PCID "); mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|RJUST, "PCPU"); strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|RJUST, "CUR-VCPU"); + strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|RJUST, "TSS"); fprintf(fp, "%s\n", buf); } @@ -654,18 +672,161 @@ strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, (char *)(pcc->current_vcpu)); + strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, + (char *)(pcc->init_tss)); fprintf(fp, "%s\n", buf); if (flag & XEN_HYPER_PCPUS_REGS) { fprintf(fp, "Register information:\n"); dump_struct("cpu_user_regs", pcc->guest_cpu_user_regs, 0); } + if (flag & XEN_HYPER_PCPUS_TSS) { + fprintf(fp, "init_tss information:\n"); + dump_struct("tss_struct", pcc->init_tss, 0); + } +} + +/* + * Display schedule info. + */ +void +xen_hyper_cmd_sched(void) +{ + struct xen_hyper_cmd_args scha; + struct xen_hyper_pcpu_context *pcc; + ulong flag; + ulong val; + int c, cnt, type, bogus; + + BZERO(&scha, sizeof(struct xen_hyper_cmd_args)); + flag = 0; + while ((c = getopt(argcnt, args, "v")) != EOF) { + switch(c) + { + case 'v': + flag |= XEN_HYPER_SCHED_VERBOSE; + break; + + default: + argerrs++; + break; + } + } + + if (argerrs) + cmd_usage(pc->curcmd, SYNOPSIS); + + cnt = bogus = 0; + while (args[optind]) { + if (IS_A_NUMBER(args[optind])) { + type = xen_hyper_str_to_pcpu_context(args[optind], &val, &pcc); + switch (type) { + case XEN_HYPER_STR_PCID: + scha.value[cnt] = val; + scha.type[cnt] = type; + scha.context[cnt] = &xhscht->sched_context_array[val]; + cnt++; + break; + case XEN_HYPER_STR_PCPU: + case XEN_HYPER_STR_INVALID: + error(INFO, "invalid pcpu id value: %s\n\n", + args[optind]); + bogus++; + } + } else { + error(FATAL, "invalid address: %s\n", + args[optind]); + } + optind++; + } + scha.cnt = cnt; + if (bogus && !cnt) { + return; + } + + xen_hyper_do_sched(flag, &scha); +} + +/* + * Do the work requested by xen_hyper_cmd_pcpu(). + */ +static void +xen_hyper_do_sched(ulong flag, struct xen_hyper_cmd_args *scha) +{ + struct xen_hyper_sched_context *schc; + uint cpuid; + int i; + + fprintf(fp, "Scheduler name : %s\n\n", xhscht->name); + + if (scha->cnt) { + for (i = 0; i < scha->cnt; i++) { + xen_hyper_show_sched(flag, scha->context[i]); + flag |= XEN_HYPER_SCHED_1STCALL; + } + } else { + for_cpu_indexes(i, cpuid) + { + schc = &xhscht->sched_context_array[cpuid]; + xen_hyper_show_sched(flag, schc); + flag |= XEN_HYPER_SCHED_1STCALL; + } + } +} + +static void +xen_hyper_show_sched(ulong flag, struct xen_hyper_sched_context *schc) +{ + char buf[XEN_HYPER_CMD_BUFSIZE]; + + if (!(schc->schedule_data)) { + return; + } + if ((flag & XEN_HYPER_SCHED_VERBOSE) || + !(flag & XEN_HYPER_SCHED_1STCALL)) { + if ((flag & XEN_HYPER_SCHED_1STCALL) && + (flag & XEN_HYPER_SCHED_VERBOSE)) { + fprintf(fp, "\n"); + } + sprintf(buf, " CPU "); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|RJUST, "SCH-DATA"); + strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|RJUST, "SCH-PRIV"); + strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|RJUST, "CUR-VCPU"); + strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|RJUST, "IDL-VCPU"); + strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|RJUST, "TICK"); + fprintf(fp, "%s\n", buf); + } + + sprintf(buf, "%5d ", schc->cpu_id); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, + (char *)(schc->schedule_data)); + strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, + (char *)(schc->sched_priv)); + strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, + (char *)(schc->curr)); + strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, + (char *)(schc->idle)); + strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, + (char *)(schc->tick)); + fprintf(fp, "%s\n", buf); + if (flag & XEN_HYPER_SCHED_VERBOSE) { + ; + } } /* * Display general system info. */ void -cmd_xen_hyper_sys(void) +xen_hyper_cmd_sys(void) { int c; ulong sflag; @@ -693,7 +854,7 @@ fprintf(fp, "No support argument\n"); /* display config info here. */ else - display_xen_hyper_sys_stats(); + xen_hyper_display_sys_stats(); return; } } @@ -702,7 +863,7 @@ * Display system stats at init-time or for the sys command. */ void -display_xen_hyper_sys_stats(void) +xen_hyper_display_sys_stats(void) { struct new_utsname *uts; char buf1[XEN_HYPER_CMD_BUFSIZE]; @@ -777,18 +938,18 @@ } XEN_HYPER_PRI(fp, len, "CPUS: ", buf1, flag, - (buf1, "%d\n", XEN_HYPER_MAX_PCPUS())); + (buf1, "%d\n", XEN_HYPER_NR_PCPUS())); XEN_HYPER_PRI(fp, len, "DOMAINS: ", buf1, flag, - (buf1, "%d\n", XEN_HYPER_MAX_DOMAINS())); + (buf1, "%d\n", XEN_HYPER_NR_DOMAINS())); /* !!!Display a date here if it can be found. */ XEN_HYPER_PRI(fp, len, "UPTIME: ", buf1, flag, (buf1, "%s\n", convert_time(get_uptime_hyper(), buf2))); /* !!!Display a version here if it can be found. */ - if (uts->machine) { - XEN_HYPER_PRI(fp, len, "MACHINE: ", buf1, flag, - (buf1, "%s ", uts->machine)); + XEN_HYPER_PRI_CONST(fp, len, "MACHINE: ", flag); + if (strlen(uts->machine)) { + fprintf(fp, "%s ", uts->machine); } else { - XEN_HYPER_PRI_CONST(fp, len, "MACHINE: unknown ", flag); + fprintf(fp, "unknown "); } if ((mhz = machdep->processor_speed())) fprintf(fp, "(%ld Mhz)\n", mhz); @@ -804,15 +965,15 @@ * Display vcpu struct. */ void -cmd_xen_hyper_vcpu(void) +xen_hyper_cmd_vcpu(void) { - struct vcpu_args vca; + struct xen_hyper_cmd_args vca; struct xen_hyper_vcpu_context *vcc; ulong flag; ulong valvc, valdom; int c, cnt, type, bogus; - BZERO(&vca, sizeof(struct vcpu_args)); + BZERO(&vca, sizeof(struct xen_hyper_cmd_args)); flag = 0; while ((c = getopt(argcnt, args, "i")) != EOF) { switch(c) @@ -845,8 +1006,8 @@ case XEN_HYPER_STR_VCPU: vca.value[cnt] = valvc; vca.type[cnt] = type; - vca.vcpu[cnt] = vcc->vcpu; - vca.vcc[cnt] = vcc; + vca.addr[cnt] = vcc->vcpu; + vca.context[cnt] = vcc; cnt++; break; case XEN_HYPER_STR_INVALID: @@ -866,23 +1027,23 @@ return; } - do_xen_hyper_vcpu(&vca); + xen_hyper_do_vcpu(&vca); } /* - * Do the work requested by cmd_xen_hyper_vcpu(). + * Do the work requested by xen_hyper_cmd_vcpu(). */ static void -do_xen_hyper_vcpu(struct vcpu_args *vca) +xen_hyper_do_vcpu(struct xen_hyper_cmd_args *vca) { int i; if (vca->cnt) { if (vca->cnt == 1) { - xhvct->last = vca->vcc[0]; + xhvct->last = vca->context[0]; } for (i = 0; i < vca->cnt; i++) { - dump_struct("vcpu", vca->vcpu[i], 0); + dump_struct("vcpu", vca->addr[i], 0); } } else { dump_struct("vcpu", xhvct->last->vcpu, 0); @@ -893,15 +1054,15 @@ * Display vcpu status. */ void -cmd_xen_hyper_vcpus(void) +xen_hyper_cmd_vcpus(void) { - struct vcpu_args vca; + struct xen_hyper_cmd_args vca; struct xen_hyper_vcpu_context *vcc; ulong flag; ulong valvc, valdom; int c, cnt, type, bogus; - BZERO(&vca, sizeof(struct vcpu_args)); + BZERO(&vca, sizeof(struct xen_hyper_cmd_args)); flag = 0; while ((c = getopt(argcnt, args, "i")) != EOF) { switch(c) @@ -934,8 +1095,8 @@ case XEN_HYPER_STR_VCPU: vca.value[cnt] = valvc; vca.type[cnt] = type; - vca.vcpu[cnt] = vcc->vcpu; - vca.vcc[cnt] = vcc; + vca.addr[cnt] = vcc->vcpu; + vca.context[cnt] = vcc; cnt++; break; case XEN_HYPER_STR_INVALID: @@ -954,14 +1115,14 @@ return; } - do_xen_hyper_vcpus(&vca); + xen_hyper_do_vcpus(&vca); } /* - * Do the work requested by cmd_xen_hyper_vcpus(). + * Do the work requested by xen_hyper_cmd_vcpus(). */ static void -do_xen_hyper_vcpus(struct vcpu_args *vca) +xen_hyper_do_vcpus(struct xen_hyper_cmd_args *vca) { struct xen_hyper_vcpu_context_array *vcca; struct xen_hyper_vcpu_context *vcc; @@ -974,21 +1135,21 @@ mkstring(buf2, VADDR_PRLEN, CENTER|RJUST, "DOMAIN")); if (vca->cnt) { for (i = 0; i < vca->cnt; i++) { - show_xen_hyper_vcpus(vca->vcc[i]); + xen_hyper_show_vcpus(vca->context[i]); } } else { for (i = 0, vcca = xhvct->vcpu_context_arrays; - i < XEN_HYPER_MAX_DOMAINS(); i++, vcca++) { + i < XEN_HYPER_NR_DOMAINS(); i++, vcca++) { for (j = 0, vcc = vcca->context_array; j < vcca->context_array_valid; j++, vcc++) { - show_xen_hyper_vcpus(vcc); + xen_hyper_show_vcpus(vcc); } } } } static void -show_xen_hyper_vcpus(struct xen_hyper_vcpu_context *vcc) +xen_hyper_show_vcpus(struct xen_hyper_vcpu_context *vcc) { int type; char *act, *crash; @@ -1223,7 +1384,7 @@ * Display a vcpu context. */ void -show_xen_hyper_vcpu_context(struct xen_hyper_vcpu_context *vcc) +xen_hyper_show_vcpu_context(struct xen_hyper_vcpu_context *vcc) { char buf[XEN_HYPER_CMD_BUFSIZE]; struct xen_hyper_pcpu_context *pcc; @@ -1261,7 +1422,7 @@ fprintf(fp, "HARDWARE RESET"); } else if (machdep->flags & INIT) { fprintf(fp, "INIT"); - } else if (is_xen_hyper_vcpu_crash(vcc)) { + } else if (xen_hyper_is_vcpu_crash(vcc)) { fprintf(fp, "CRASH"); } else { fprintf(fp, "ACTIVE"); @@ -1275,7 +1436,7 @@ */ static int xen_hyper_str_to_dumpinfo_context(char *string, ulong *value, - struct xen_hyper_dumpinfo_context **encp) + struct xen_hyper_dumpinfo_context **dicp) { ulong dvalue, hvalue; struct xen_hyper_dumpinfo_context *note_did, *note_hid; @@ -1326,32 +1487,32 @@ case 2: if (note_did && note_hid) { *value = dvalue; - *encp = note_did; + *dicp = note_did; type = XEN_HYPER_STR_PCID; } break; case 1: if (note_did) { *value = dvalue; - *encp = note_did; + *dicp = note_did; type = XEN_HYPER_STR_PCID; } if (note_hid) { *value = hvalue; - *encp = note_hid; + *dicp = note_hid; type = XEN_HYPER_STR_PCID; } if (note_dad) { *value = dvalue; - *encp = note_dad; + *dicp = note_dad; type = XEN_HYPER_STR_ADDR; } if (note_had) { *value = hvalue; - *encp = note_had; + *dicp = note_had; type = XEN_HYPER_STR_ADDR; } break; Index: xen_hyper_defs.h =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/xen_hyper_defs.h,v retrieving revision 1.2 retrieving revision 1.2.8.1 diff -u -r1.2 -r1.2.8.1 --- xen_hyper_defs.h 21 Dec 2006 00:01:02 -0000 1.2 +++ xen_hyper_defs.h 15 Feb 2007 00:38:15 -0000 1.2.8.1 @@ -1,8 +1,11 @@ /* * xen_hyper_defs.h * - * Portions Copyright (C) 2006 Fujitsu Limited - * Portions Copyright (C) 2006 VA Linux Systems Japan K.K. + * Portions Copyright (C) 2006-2007 Fujitsu Limited + * Portions Copyright (C) 2006-2007 VA Linux Systems Japan K.K. + * + * Authors: Itsuro Oda + * Fumihiko Kakuma * * This file is part of Xencrash. * @@ -63,15 +66,32 @@ #define PAGE_OFFSET_XEN_HYPER DIRECTMAP_VIRT_START #endif +#ifdef IA64 +#define HYPERVISOR_VIRT_START (0xe800000000000000) +#define HYPERVISOR_VIRT_END (0xf800000000000000) +#define DEFAULT_SHAREDINFO_ADDR (0xf100000000000000) +#define PERCPU_PAGE_SIZE 65536 +#define PERCPU_ADDR (DEFAULT_SHAREDINFO_ADDR - PERCPU_PAGE_SIZE) +#define DIRECTMAP_VIRT_START (0xf000000000000000) +#define DIRECTMAP_VIRT_END PERCPU_ADDR + +#define PERCPU_VIRT_ADDR(vaddr) \ + (((vaddr) >= PERCPU_ADDR) && ((vaddr) < PERCPU_ADDR + PERCPU_PAGE_SIZE)) + +#undef IA64_RBS_OFFSET +#define IA64_RBS_OFFSET ((XEN_HYPER_SIZE(vcpu) + 15) & ~15) + +#endif /* IA64 */ + #define DIRECTMAP_VIRT_ADDR(vaddr) \ (((vaddr) >= DIRECTMAP_VIRT_START) && ((vaddr) < DIRECTMAP_VIRT_END)) typedef uint16_t domid_t; typedef uint32_t Elf_Word; -/* NOTE kakuma: - * The following defines are temporary version for elf note format - * which is used only in crash. +/* + * NOTE kakuma: The following defines are temporary version for + * elf note format which is used only in crash. */ #define XEN_HYPER_ELF_NOTE_V1 1 #define XEN_HYPER_ELF_NOTE_V2 2 @@ -98,10 +118,16 @@ #define XEN_HYPER_MAX_VIRT_CPUS (1) #endif +#if defined(X86) || defined(X86_64) #define XEN_HYPER_PERCPU_SHIFT 12 #define xen_hyper_per_cpu(var, cpu) \ - ((ulong)var + (((ulong)(cpu))<__per_cpu_offset[cpu])) +#endif +#if defined(X86) || defined(X86_64) #define XEN_HYPER_STACK_ORDER 2 #if 0 #define XEN_HYPER_STACK_SIZE (machdep->pagesize << XEN_HYPER_STACK_ORDER) @@ -109,6 +135,7 @@ #define XEN_HYPER_GET_CPU_INFO(sp) \ ((sp & ~(STACKSIZE()-1)) | \ (STACKSIZE() - XEN_HYPER_SIZE(cpu_info))) +#endif #define XEN_HYPER_CONRING_SIZE 16384 @@ -202,7 +229,20 @@ #define XEN_HYPER_RUNSTATE_ERROR ((int)(-1)) /* - * Programs constant + * PCPU + */ +#define XEN_HYPER_TSS_IST_MAX 7 + +/* + * Scheduler + */ +#define XEN_SCHEDULER_SEDF 4 +#define XEN_SCHEDULER_CREDIT 5 + +#define XEN_HYPER_OPT_SCHED_SIZE 10 + +/* + * Constants for function */ #define XEN_HYPER_CMD_BUFSIZE (1024) @@ -238,43 +278,29 @@ #define XEN_HYPER_ELF_NOTE_FILL_T_XEN_REGS (4) /* - * command interface structs + * Command interface structs */ #define XEN_HYPER_MAX_ARGS 100 -struct cmd_args { +struct xen_hyper_cmd_args { int cnt; ulong value[XEN_HYPER_MAX_ARGS]; int type[XEN_HYPER_MAX_ARGS]; ulong addr[XEN_HYPER_MAX_ARGS]; + void *context[XEN_HYPER_MAX_ARGS]; }; /* - * Domain command + * dump information command */ -#define XEN_HYPER_MAX_DOMS_ARGS XEN_HYPER_MAX_ARGS - -struct domain_args { - int cnt; - ulong value[XEN_HYPER_MAX_DOMS_ARGS]; - int type[XEN_HYPER_MAX_DOMS_ARGS]; - ulong domain[XEN_HYPER_MAX_DOMS_ARGS]; - struct xen_hyper_domain_context *dc[XEN_HYPER_MAX_DOMS_ARGS]; -}; +/* options */ +#define XEN_HYPER_DUMPINFO_TIME (0x1) +#define XEN_HYPER_DUMPINFO_REGS (0x2) /* - * Virtual cpu command + * Domain command */ -#define XEN_HYPER_MAX_VCPUS_ARGS XEN_HYPER_MAX_ARGS -#define XEN_HYPER_VCPUS_ID (0x1) - -struct vcpu_args { - int cnt; - ulong value[XEN_HYPER_MAX_VCPUS_ARGS]; - ulong type[XEN_HYPER_MAX_VCPUS_ARGS]; - ulong vcpu[XEN_HYPER_MAX_VCPUS_ARGS]; - struct xen_hyper_vcpu_context *vcc[XEN_HYPER_MAX_VCPUS_ARGS]; -}; +#define XEN_HYPER_MAX_DOMS_ARGS XEN_HYPER_MAX_ARGS /* * Physical cpu command @@ -282,28 +308,21 @@ #define XEN_HYPER_MAX_PCPUS_ARGS XEN_HYPER_MAX_ARGS #define XEN_HYPER_PCPUS_1STCALL (0x1) #define XEN_HYPER_PCPUS_REGS (0x2) +#define XEN_HYPER_PCPUS_TSS (0x4) -struct pcpu_args { - int cnt; - ulong value[XEN_HYPER_MAX_PCPUS_ARGS]; - int type[XEN_HYPER_MAX_PCPUS_ARGS]; - ulong pcpu[XEN_HYPER_MAX_PCPUS_ARGS]; - struct xen_hyper_pcpu_context *pcc[XEN_HYPER_MAX_PCPUS_ARGS]; -}; +/* + * Schedule command + */ +#define XEN_HYPER_MAX_SCHED_ARGS XEN_HYPER_MAX_ARGS +#define XEN_HYPER_SCHED_1STCALL (0x1) +#define XEN_HYPER_SCHED_VERBOSE (0x2) /* - * dump information command + * Virtual cpu command */ -/* options */ -#define XEN_HYPER_DUMPINFO_TIME (0x1) -#define XEN_HYPER_DUMPINFO_REGS (0x2) +#define XEN_HYPER_MAX_VCPUS_ARGS XEN_HYPER_MAX_ARGS +#define XEN_HYPER_VCPUS_ID (0x1) -struct dumpinfo_args { - int cnt; - ulong value[XEN_HYPER_MAX_ARGS]; - int type[XEN_HYPER_MAX_ARGS]; - struct xen_hyper_dumpinfo_context *enc[XEN_HYPER_MAX_ARGS]; -}; /* * table structs @@ -316,9 +335,10 @@ ulong flags; ulong stext; ulong etext; + ulong cpu_data_address; struct new_utsname utsname; uint cpu_curr; - uint max_cpus; /* max cpu in system max */ + uint max_cpus; /* max cpu in system */ int cores; /* number of cpu core */ int pcpus; /* number of physical cpu */ int vcpus; /* number of virtual cpu */ @@ -326,8 +346,10 @@ int crashing_cpu; struct xen_hyper_vcpu_context *crashing_vcc; ulong max_page; + ulong total_pages; ulong *cpumask; uint *cpu_idxs; + ulong *__per_cpu_offset; }; struct xen_hyper_dumpinfo_context { @@ -431,10 +453,18 @@ /* pcpu */ struct xen_hyper_pcpu_context { + /* pcpu info */ ulong pcpu; /* pcpu address */ uint processor_id; ulong guest_cpu_user_regs; ulong current_vcpu; + /* tss_struct info */ + ulong init_tss; + union { + uint32_t esp0; + uint64_t rsp0; + } sp; + uint64_t ist[XEN_HYPER_TSS_IST_MAX]; /* This is valid on x86_64 */ }; struct xen_hyper_pcpu_table { @@ -444,9 +474,22 @@ }; /* scheduler */ +struct xen_hyper_sched_context { + uint cpu_id; + ulong schedule_data; + ulong curr; + ulong idle; + ulong sched_priv; + ulong tick; +}; + struct xen_hyper_sched_table { - int type; - char opt_sched[10]; + char *name; + char opt_sched[XEN_HYPER_OPT_SCHED_SIZE]; + uint sched_id; + ulong scheduler; + char *scheduler_struct; + struct xen_hyper_sched_context *sched_context_array; }; struct syment; @@ -464,6 +507,7 @@ long cpu_time; long cpu_user_regs; long cpumask_t; + long cpuinfo_ia64; long cpuinfo_x86; long crash_note_t; /* elf note v2, v3 */ long crash_note_core_t; /* elf note v2, v3 */ @@ -474,6 +518,7 @@ long crash_xen_info_t; /* elf note v3 */ long domain; long note_buf_t; /* elf note v1 */ + long schedule_data; long scheduler; long timer; long tss_struct; @@ -510,6 +555,9 @@ long cpu_time_stime_master_stamp; long cpu_time_tsc_scale; long cpu_time_calibration_timer; + /* cpuinfo_ia64 */ + long cpuinfo_ia64_proc_freq; + long cpuinfo_ia64_vendor; /* crash_note_t */ long crash_note_t_core; /* elf note v2, v3 */ long crash_note_t_xen; /* elf note v2 */ @@ -540,6 +588,28 @@ long domain_domain_flags; long domain_evtchn; long domain_vcpu; + /* schedule_data */ + long schedule_data_schedule_lock; + long schedule_data_curr; + long schedule_data_idle; + long schedule_data_sched_priv; + long schedule_data_s_timer; + long schedule_data_tick; + /* scheduler */ + long scheduler_name; + long scheduler_opt_name; + long scheduler_sched_id; + long scheduler_init; + long scheduler_tick; + long scheduler_init_vcpu; + long scheduler_destroy_domain; + long scheduler_sleep; + long scheduler_wake; + long scheduler_set_affinity; + long scheduler_do_schedule; + long scheduler_adjust; + long scheduler_dump_settings; + long scheduler_dump_cpu_state; /* timer */ long timer_expires; long timer_cpu; @@ -550,6 +620,7 @@ /* tss */ long tss_struct_rsp0; long tss_struct_esp0; + long tss_struct_ist; /* vcpu */ long vcpu_vcpu_id; long vcpu_processor; @@ -569,6 +640,9 @@ long vcpu_nmi_addr; long vcpu_vcpu_dirty_cpumask; long vcpu_arch; +#ifdef IA64 + long vcpu_thread_ksp; +#endif /* vcpu_runstate_info */ long vcpu_runstate_info_state; long vcpu_runstate_info_state_entry_time; @@ -597,6 +671,7 @@ * System */ #define XEN_HYPER_MAX_CPUS() (xht->max_cpus) +#define XEN_HYPER_CRASHING_CPU() (xht->crashing_cpu) /* * Dump information @@ -611,24 +686,26 @@ */ #define XEN_HYPER_DOMAIN_F_INIT 0x1 -#define XEN_HYPER_MAX_DOMAINS() (xht->domains) +#define XEN_HYPER_NR_DOMAINS() (xht->domains) #define XEN_HYPER_RUNNING_DOMAINS() (xhdt->running_domains) /* * Phisycal CPU */ -#define XEN_HYPER_MAX_PCPUS() (xht->pcpus) +#define XEN_HYPER_NR_PCPUS() (xht->pcpus) #define for_cpu_indexes(i, cpuid) \ for (i = 0, cpuid = xht->cpu_idxs[i]; \ - i < XEN_HYPER_MAX_PCPUS(); \ + i < XEN_HYPER_NR_PCPUS(); \ cpuid = xht->cpu_idxs[++i]) +#define XEN_HYPER_CURR_VCPU(pcpuid) \ + (xen_hyper_get_active_vcpu_from_pcpuid(pcpuid)) /* * VCPU */ #define XEN_HYPER_VCPU_F_INIT 0x1 -#define XEN_HYPER_MAX_VCPUS(domain_context) (domain_context->vcpu_cnt) +#define XEN_HYPER_NR_VCPUS_IN_DOM(domain_context) (domain_context->vcpu_cnt) #define XEN_HYPER_VCPU_LAST_CONTEXT() (xhvct->last) /* @@ -665,14 +742,15 @@ /* * Xen Hyper command help */ -extern char *help_xen_hyper_domain[]; -extern char *help_xen_hyper_doms[]; -extern char *help_xen_hyper_dumpinfo[]; -extern char *help_xen_hyper_log[]; -extern char *help_xen_hyper_pcpus[]; -extern char *help_xen_hyper_sys[]; -extern char *help_xen_hyper_vcpu[]; -extern char *help_xen_hyper_vcpus[]; +extern char *xen_hyper_help_domain[]; +extern char *xen_hyper_help_doms[]; +extern char *xen_hyper_help_dumpinfo[]; +extern char *xen_hyper_help_log[]; +extern char *xen_hyper_help_pcpus[]; +extern char *xen_hyper_help_sched[]; +extern char *xen_hyper_help_sys[]; +extern char *xen_hyper_help_vcpu[]; +extern char *xen_hyper_help_vcpus[]; /* * Prototype @@ -682,8 +760,15 @@ /* * x86 */ -int x86_get_smp_cpus_hyper(void); -uint64_t x86_memory_size_hyper(void); +int xen_hyper_x86_get_smp_cpus(void); +uint64_t xen_hyper_x86_memory_size(void); + +/* + * IA64 + */ +int xen_hyper_ia64_get_smp_cpus(void); +uint64_t xen_hyper_ia64_memory_size(void); +ulong xen_hyper_ia64_processor_speed(void); /* * Xen Hyper @@ -692,6 +777,7 @@ void xen_hyper_domain_init(void); void xen_hyper_vcpu_init(void); void xen_hyper_dumpinfo_init(void); +void xen_hyper_misc_init(void); void xen_hyper_post_init(void); struct xen_hyper_dumpinfo_context *xen_hyper_id_to_dumpinfo_context(uint id); struct xen_hyper_dumpinfo_context *xen_hyper_note_to_dumpinfo_context(ulong note); @@ -740,38 +826,48 @@ int xen_hyper_vcpu_state(struct xen_hyper_vcpu_context *vcc); /* pcpu */ -void x86_xen_hyper_pcpu_init(void); +#if defined(X86) || defined(X86_64) +void xen_hyper_x86_pcpu_init(void); +#elif defined(IA64) +void xen_hyper_ia64_pcpu_init(void); +#endif struct xen_hyper_pcpu_context *xen_hyper_id_to_pcpu_context(uint id); struct xen_hyper_pcpu_context *xen_hyper_pcpu_to_pcpu_context(ulong pcpu); struct xen_hyper_pcpu_context *xen_hyper_store_pcpu_context(struct xen_hyper_pcpu_context *pcc, ulong pcpu, char *pcp); +struct xen_hyper_pcpu_context *xen_hyper_store_pcpu_context_tss(struct xen_hyper_pcpu_context *pcc, + ulong init_tss, char *tss); char *xen_hyper_read_pcpu(ulong pcpu); char *xen_hyper_fill_pcpu_struct(ulong pcpu, char *pcpu_struct); void xen_hyper_alloc_pcpu_context_space(int pcpus); /* others */ -char *xen_hyper_fill_cpu_data_x86(int idx, char *cpuinfo_x86); -int is_xen_hyper_vcpu_crash(struct xen_hyper_vcpu_context *vcc); -void print_pcpu_header_hyper(FILE *out, int pcpu, int newline); +char *xen_hyper_x86_fill_cpu_data(int idx, char *cpuinfo_x86); +char *xen_hyper_ia64_fill_cpu_data(int idx, char *cpuinfo_ia64); +int xen_hyper_is_vcpu_crash(struct xen_hyper_vcpu_context *vcc); +void xen_hyper_print_bt_header(FILE *out, ulong pcpu, int newline); +ulong xen_hyper_get_active_vcpu_from_pcpuid(ulong pcpu); +ulong xen_hyper_pcpu_to_active_vcpu(ulong pcpu); void xen_hyper_get_cpu_info(void); int xen_hyper_test_pcpu_id(uint pcpu_id); /* * Xen Hyper command */ -void cmd_xen_hyper_help(void); -void cmd_xen_hyper_domain(void); -void cmd_xen_hyper_doms(void); -void cmd_xen_hyper_dumpinfo(void); -void cmd_xen_hyper_log(void); -void dump_xen_hyper_log(void); -void cmd_xen_hyper_pcpus(void); -void cmd_xen_hyper_sys(void); -void cmd_xen_hyper_vcpu(void); -void cmd_xen_hyper_vcpus(void); -void display_xen_hyper_sys_stats(void); +void xen_hyper_cmd_help(void); +void xen_hyper_cmd_domain(void); +void xen_hyper_cmd_doms(void); +void xen_hyper_cmd_dumpinfo(void); +void xen_hyper_cmd_log(void); +void xen_hyper_dump_log(void); +void xen_hyper_cmd_pcpus(void); +void xen_hyper_cmd_sched(void); +void xen_hyper_cmd_sys(void); +void xen_hyper_cmd_vcpu(void); +void xen_hyper_cmd_vcpus(void); +void xen_hyper_display_sys_stats(void); -void show_xen_hyper_vcpu_context(struct xen_hyper_vcpu_context *vcc); +void xen_hyper_show_vcpu_context(struct xen_hyper_vcpu_context *vcc); char *xen_hyper_domain_state_string(struct xen_hyper_domain_context *dc, char *buf, int verbose); char *xen_hyper_vcpu_state_string(struct xen_hyper_vcpu_context *vcc, Index: xen_hyper_dump_tables.c =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/xen_hyper_dump_tables.c,v retrieving revision 1.2 retrieving revision 1.2.8.2 diff -u -r1.2 -r1.2.8.2 --- xen_hyper_dump_tables.c 21 Dec 2006 00:01:02 -0000 1.2 +++ xen_hyper_dump_tables.c 15 Feb 2007 01:41:28 -0000 1.2.8.2 @@ -1,8 +1,11 @@ /* * xen_hyper_dump_tables.c * - * Portions Copyright (C) 2006 Fujitsu Limited - * Portions Copyright (C) 2006 VA Linux Systems Japan K.K. + * Portions Copyright (C) 2006-2007 Fujitsu Limited + * Portions Copyright (C) 2006-2007 VA Linux Systems Japan K.K. + * + * Authors: Itsuro Oda + * Fumihiko Kakuma * * This file is part of Xencrash. * @@ -25,20 +28,23 @@ #ifdef XEN_HYPERVISOR_ARCH #include "xen_hyper_defs.h" -static void dump_xen_hyper_table(int verbose); -static void dump_xen_hyper_dumpinfo_table(int verbose); -static void dump_xen_hyper_domain_table(int verbose); -static void dump_xen_hyper_vcpu_table(int verbose); -static void dump_xen_hyper_pcpu_table(int verbose); -static void dump_xen_hyper_size_table(char *spec, ulong makestruct); -static void dump_xen_hyper_offset_table(char *spec, ulong makestruct); +static void xen_hyper_dump_xen_hyper_table(int verbose); +static void xen_hyper_dump_xen_hyper_dumpinfo_table(int verbose); +static void xen_hyper_dump_xen_hyper_domain_table(int verbose); +static void xen_hyper_dump_xen_hyper_vcpu_table(int verbose); +static void xen_hyper_dump_xen_hyper_pcpu_table(int verbose); +static void xen_hyper_dump_xen_hyper_sched_table(int verbose); +static void xen_hyper_dump_xen_hyper_size_table(char *spec, ulong makestruct); +static void xen_hyper_dump_xen_hyper_offset_table(char *spec, ulong makestruct); + +static void xen_hyper_dump_mem(void *mem, ulong len, int dsz); /* * Get help for a command, to dump an internal table, or the GNU public * license copying/warranty information. */ void -cmd_xen_hyper_help(void) +xen_hyper_cmd_help(void) { int c; int oflag; @@ -46,7 +52,7 @@ oflag = 0; while ((c = getopt(argcnt, args, - "aBbcDgHhMmnOopszX:")) != EOF) { + "aBbcDgHhM:mnOopszX:")) != EOF) { switch(c) { case 'a': @@ -98,29 +104,37 @@ break; } if (!strncmp("Xen", optarg, strlen(optarg))) - dump_xen_hyper_table(VERBOSE); + xen_hyper_dump_xen_hyper_table(VERBOSE); else if (!strncmp("xen", optarg, strlen(optarg))) - dump_xen_hyper_table(!VERBOSE); + xen_hyper_dump_xen_hyper_table(!VERBOSE); else if (!strncmp("Dmp", optarg, strlen(optarg))) - dump_xen_hyper_dumpinfo_table(VERBOSE); + xen_hyper_dump_xen_hyper_dumpinfo_table(VERBOSE); else if (!strncmp("dmp", optarg, strlen(optarg))) - dump_xen_hyper_dumpinfo_table(!VERBOSE); + xen_hyper_dump_xen_hyper_dumpinfo_table(!VERBOSE); else if (!strncmp("Dom", optarg, strlen(optarg))) - dump_xen_hyper_domain_table(VERBOSE); + xen_hyper_dump_xen_hyper_domain_table(VERBOSE); else if (!strncmp("dom", optarg, strlen(optarg))) - dump_xen_hyper_domain_table(!VERBOSE); + xen_hyper_dump_xen_hyper_domain_table(!VERBOSE); else if (!strncmp("Vcp", optarg, strlen(optarg))) - dump_xen_hyper_vcpu_table(VERBOSE); + xen_hyper_dump_xen_hyper_vcpu_table(VERBOSE); else if (!strncmp("vcp", optarg, strlen(optarg))) - dump_xen_hyper_vcpu_table(!VERBOSE); + xen_hyper_dump_xen_hyper_vcpu_table(!VERBOSE); else if (!strncmp("Pcp", optarg, strlen(optarg))) - dump_xen_hyper_pcpu_table(!VERBOSE); + xen_hyper_dump_xen_hyper_pcpu_table(VERBOSE); else if (!strncmp("pcp", optarg, strlen(optarg))) - dump_xen_hyper_pcpu_table(VERBOSE); + xen_hyper_dump_xen_hyper_pcpu_table(!VERBOSE); + else if (!strncmp("Sch", optarg, strlen(optarg))) + xen_hyper_dump_xen_hyper_sched_table(VERBOSE); + else if (!strncmp("sch", optarg, strlen(optarg))) + xen_hyper_dump_xen_hyper_sched_table(!VERBOSE); else if (!strncmp("siz", optarg, strlen(optarg))) - dump_xen_hyper_size_table(NULL, TRUE); + xen_hyper_dump_xen_hyper_size_table(NULL, TRUE); else if (!strncmp("ofs", optarg, strlen(optarg))) - dump_xen_hyper_offset_table(NULL, TRUE); + xen_hyper_dump_xen_hyper_offset_table(NULL, TRUE); + else { + argerrs++; + break; + } return; case 'z': fprintf(fp, "help options:\n"); @@ -145,6 +159,8 @@ fprintf(fp, " -X vcp - vcpu table data\n"); fprintf(fp, " -X Pcp - pcpu table data (verbose)\n"); fprintf(fp, " -X pcp - pcpu table data\n"); + fprintf(fp, " -X Sch - schedule table data (verbose)\n"); + fprintf(fp, " -X sch - schedule table data\n"); fprintf(fp, " -X siz - size table data\n"); fprintf(fp, " -X ofs - offset table data\n"); return; @@ -178,7 +194,7 @@ * "help -x xen" output */ static void -dump_xen_hyper_table(int verbose) +xen_hyper_dump_xen_hyper_table(int verbose) { char buf[XEN_HYPER_CMD_BUFSIZE]; uint cpuid; @@ -187,6 +203,8 @@ len = 14; flag = XEN_HYPER_PRI_R; + XEN_HYPER_PRI(fp, len, "cpu_data_address: ", buf, flag, + (buf, "%lu\n", xht->cpu_data_address)); XEN_HYPER_PRI(fp, len, "cpu_curr: ", buf, flag, (buf, "%u\n", xht->cpu_curr)); XEN_HYPER_PRI(fp, len, "max_cpus: ", buf, flag, @@ -207,6 +225,10 @@ (buf, "%lu\n", xht->max_page)); XEN_HYPER_PRI(fp, len, "cpumask: ", buf, flag, (buf, "%p\n", xht->cpumask)); + if (verbose && xht->cpumask) { + xen_hyper_dump_mem(xht->cpumask, + XEN_HYPER_SIZE(cpumask_t), sizeof(long)); + } XEN_HYPER_PRI(fp, len, "cpu_idxs: ", buf, flag, (buf, "%p\n", xht->cpu_idxs)); if (verbose) { @@ -219,18 +241,23 @@ * "help -x dmp" output */ static void -dump_xen_hyper_dumpinfo_table(int verbose) +xen_hyper_dump_xen_hyper_dumpinfo_table(int verbose) { char buf[XEN_HYPER_CMD_BUFSIZE]; int len, flag; - len = 24; + len = 25; flag = XEN_HYPER_PRI_R; XEN_HYPER_PRI(fp, len, "note_ver: ", buf, flag, (buf, "%u\n", xhdit->note_ver)); XEN_HYPER_PRI(fp, len, "context_array: ", buf, flag, (buf, "%p\n", xhdit->context_array)); + if (verbose && xhdit->context_array) { + xen_hyper_dump_mem((long *)xhdit->context_array, + sizeof(struct xen_hyper_dumpinfo_context) * + XEN_HYPER_MAX_CPUS(), sizeof(long)); + } XEN_HYPER_PRI_CONST(fp, len, "context_xen_core: ", flag|XEN_HYPER_PRI_LF); XEN_HYPER_PRI(fp, len, "note: ", buf, flag, (buf, "%lx\n", xhdit->context_xen_core.note)); @@ -247,10 +274,25 @@ (buf, "%p\n", xhdit->context_xen_info.crash_xen_info_ptr)); XEN_HYPER_PRI(fp, len, "crash_note_core_array: ", buf, flag, (buf, "%p\n", xhdit->crash_note_core_array)); + if (verbose && xhdit->crash_note_core_array) { + xen_hyper_dump_mem((long *)xhdit->crash_note_core_array, + xhdit->core_size * XEN_HYPER_NR_PCPUS(), + sizeof(long)); + } XEN_HYPER_PRI(fp, len, "crash_note_xen_core_ptr: ", buf, flag, (buf, "%p\n", xhdit->crash_note_xen_core_ptr)); + if (verbose && xhdit->crash_note_xen_core_ptr) { + xen_hyper_dump_mem( + xhdit->crash_note_xen_core_ptr, + xhdit->xen_core_size, sizeof(long)); + } XEN_HYPER_PRI(fp, len, "crash_note_xen_info_ptr: ", buf, flag, (buf, "%p\n", xhdit->crash_note_xen_info_ptr)); + if (verbose && xhdit->crash_note_xen_info_ptr) { + xen_hyper_dump_mem( + xhdit->crash_note_xen_info_ptr, + xhdit->xen_info_size, sizeof(long)); + } XEN_HYPER_PRI(fp, len, "note_size: ", buf, flag, (buf, "%u\n", xhdit->note_size)); XEN_HYPER_PRI(fp, len, "core_offset: ", buf, flag, @@ -271,7 +313,7 @@ * "help -x dom" output */ static void -dump_xen_hyper_domain_table(int verbose) +xen_hyper_dump_xen_hyper_domain_table(int verbose) { char buf[XEN_HYPER_CMD_BUFSIZE]; int len, flag; @@ -303,7 +345,7 @@ * "help -x vcp" output */ static void -dump_xen_hyper_vcpu_table(int verbose) +xen_hyper_dump_xen_hyper_vcpu_table(int verbose) { char buf[XEN_HYPER_CMD_BUFSIZE]; int len, flag; @@ -331,16 +373,51 @@ * "help -x pcp" output */ static void -dump_xen_hyper_pcpu_table(int verbose) +xen_hyper_dump_xen_hyper_pcpu_table(int verbose) { char buf[XEN_HYPER_CMD_BUFSIZE]; - int len, flag; + struct xen_hyper_pcpu_context *pcca; + int len, flag, i; +#ifdef X86_64 + uint64_t *ist_p; + int j; +#endif - len = 15; + len = 21; flag = XEN_HYPER_PRI_R; XEN_HYPER_PRI(fp, len, "context_array: ", buf, flag, (buf, "%p\n", xhpct->context_array)); + if (verbose) { + for (i = 0, pcca = xhpct->context_array; + i < XEN_HYPER_MAX_CPUS(); i++, pcca++) { + snprintf(buf, XEN_HYPER_CMD_BUFSIZE, "context_array %d: ", i); + XEN_HYPER_PRI_CONST(fp, len, buf, flag|XEN_HYPER_PRI_LF); + XEN_HYPER_PRI(fp, len, "pcpu: ", buf, flag, + (buf, "%lx\n", pcca->pcpu)); + XEN_HYPER_PRI(fp, len, "processor_id: ", buf, flag, + (buf, "%u\n", pcca->processor_id)); + XEN_HYPER_PRI(fp, len, "guest_cpu_user_regs: ", buf, flag, + (buf, "%lx\n", pcca->guest_cpu_user_regs)); + XEN_HYPER_PRI(fp, len, "current_vcpu: ", buf, flag, + (buf, "%lx\n", pcca->current_vcpu)); + XEN_HYPER_PRI(fp, len, "init_tss: ", buf, flag, + (buf, "%lx\n", pcca->init_tss)); +#ifdef X86 + XEN_HYPER_PRI(fp, len, "sp.esp0: ", buf, flag, + (buf, "%x\n", pcca->sp.esp0)); +#endif +#ifdef X86_64 + XEN_HYPER_PRI(fp, len, "sp.rsp0: ", buf, flag, + (buf, "%lx\n", pcca->sp.rsp0)); + for (j = 0, ist_p = pcca->ist; + j < XEN_HYPER_TSS_IST_MAX; j++, ist_p++) { + XEN_HYPER_PRI(fp, len, "ist: ", buf, flag, + (buf, "%lx\n", *ist_p)); + } +#endif + } + } XEN_HYPER_PRI(fp, len, "last: ", buf, flag, (buf, "%p\n", xhpct->last)); XEN_HYPER_PRI(fp, len, "pcpu_struct: ", buf, flag, @@ -348,15 +425,59 @@ } /* + * "help -x sch" output + */ +static void +xen_hyper_dump_xen_hyper_sched_table(int verbose) +{ + struct xen_hyper_sched_context *schc; + char buf[XEN_HYPER_CMD_BUFSIZE]; + int len, flag, i; + + len = 21; + flag = XEN_HYPER_PRI_R; + + XEN_HYPER_PRI(fp, len, "name: ", buf, flag, + (buf, "%s\n", xhscht->name)); + XEN_HYPER_PRI(fp, len, "opt_sched: ", buf, flag, + (buf, "%s\n", xhscht->opt_sched)); + XEN_HYPER_PRI(fp, len, "sched_id: ", buf, flag, + (buf, "%d\n", xhscht->sched_id)); + XEN_HYPER_PRI(fp, len, "scheduler: ", buf, flag, + (buf, "%lx\n", xhscht->scheduler)); + XEN_HYPER_PRI(fp, len, "scheduler_struct: ", buf, flag, + (buf, "%p\n", xhscht->scheduler_struct)); + XEN_HYPER_PRI(fp, len, "sched_context_array: ", buf, flag, + (buf, "%p\n", xhscht->sched_context_array)); + if (verbose) { + for (i = 0, schc = xhscht->sched_context_array; + i < xht->pcpus; i++, schc++) { + XEN_HYPER_PRI(fp, len, "sched_context_array[", buf, + flag, (buf, "%d]\n", i)); + XEN_HYPER_PRI(fp, len, "schedule_data: ", buf, flag, + (buf, "%lx\n", schc->schedule_data)); + XEN_HYPER_PRI(fp, len, "curr: ", buf, flag, + (buf, "%lx\n", schc->curr)); + XEN_HYPER_PRI(fp, len, "idle: ", buf, flag, + (buf, "%lx\n", schc->idle)); + XEN_HYPER_PRI(fp, len, "sched_priv: ", buf, flag, + (buf, "%lx\n", schc->sched_priv)); + XEN_HYPER_PRI(fp, len, "tick: ", buf, flag, + (buf, "%lx\n", schc->tick)); + } + } +} + +/* * "help -x siz" output */ static void -dump_xen_hyper_size_table(char *spec, ulong makestruct) +xen_hyper_dump_xen_hyper_size_table(char *spec, ulong makestruct) { char buf[XEN_HYPER_CMD_BUFSIZE]; int len, flag; - len = 20; + len = 23; flag = XEN_HYPER_PRI_R; XEN_HYPER_PRI(fp, len, "ELF_Prstatus: ", buf, flag, @@ -375,6 +496,8 @@ (buf, "%ld\n", xen_hyper_size_table.cpu_user_regs)); XEN_HYPER_PRI(fp, len, "cpumask_t: ", buf, flag, (buf, "%ld\n", xen_hyper_size_table.cpumask_t)); + XEN_HYPER_PRI(fp, len, "cpuinfo_ia64: ", buf, flag, + (buf, "%ld\n", xen_hyper_size_table.cpuinfo_ia64)); XEN_HYPER_PRI(fp, len, "cpuinfo_x86: ", buf, flag, (buf, "%ld\n", xen_hyper_size_table.cpuinfo_x86)); XEN_HYPER_PRI(fp, len, "crash_note_t: ", buf, flag, @@ -395,6 +518,8 @@ (buf, "%ld\n", xen_hyper_size_table.domain)); XEN_HYPER_PRI(fp, len, "note_buf_t: ", buf, flag, (buf, "%ld\n", xen_hyper_size_table.note_buf_t)); + XEN_HYPER_PRI(fp, len, "schedule_data: ", buf, flag, + (buf, "%ld\n", xen_hyper_size_table.schedule_data)); XEN_HYPER_PRI(fp, len, "scheduler: ", buf, flag, (buf, "%ld\n", xen_hyper_size_table.scheduler)); XEN_HYPER_PRI(fp, len, "timer: ", buf, flag, @@ -413,7 +538,7 @@ * "help -x ofs" output */ static void -dump_xen_hyper_offset_table(char *spec, ulong makestruct) +xen_hyper_dump_xen_hyper_offset_table(char *spec, ulong makestruct) { char buf[XEN_HYPER_CMD_BUFSIZE]; int len, flag; @@ -451,12 +576,14 @@ (buf, "%ld\n", xen_hyper_offset_table.ELF_Timeval_tv_sec)); XEN_HYPER_PRI(fp, len, "ELF_Timeval_tv_usec: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.ELF_Timeval_tv_usec)); + XEN_HYPER_PRI(fp, len, "cpu_info_guest_cpu_user_regs: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.cpu_info_guest_cpu_user_regs)); XEN_HYPER_PRI(fp, len, "cpu_info_processor_id: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.cpu_info_processor_id)); XEN_HYPER_PRI(fp, len, "cpu_info_current_vcpu: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.cpu_info_current_vcpu)); + XEN_HYPER_PRI(fp, len, "cpu_time_local_tsc_stamp: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.cpu_time_local_tsc_stamp)); XEN_HYPER_PRI(fp, len, "cpu_time_stime_local_stamp: ", buf, flag, @@ -521,6 +648,49 @@ (buf, "%ld\n", xen_hyper_offset_table.domain_evtchn)); XEN_HYPER_PRI(fp, len, "domain_vcpu: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.domain_vcpu)); + + XEN_HYPER_PRI(fp, len, "schedule_data_schedule_lock: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.schedule_data_schedule_lock)); + XEN_HYPER_PRI(fp, len, "schedule_data_curr: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.schedule_data_curr)); + XEN_HYPER_PRI(fp, len, "schedule_data_idle: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.schedule_data_idle)); + XEN_HYPER_PRI(fp, len, "schedule_data_sched_priv: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.schedule_data_sched_priv)); + XEN_HYPER_PRI(fp, len, "schedule_data_s_timer: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.schedule_data_s_timer)); + XEN_HYPER_PRI(fp, len, "schedule_data_tick: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.schedule_data_tick)); + + XEN_HYPER_PRI(fp, len, "scheduler_name: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_name)); + XEN_HYPER_PRI(fp, len, "scheduler_opt_name: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_opt_name)); + XEN_HYPER_PRI(fp, len, "scheduler_sched_id: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_sched_id)); + XEN_HYPER_PRI(fp, len, "scheduler_init: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_init)); + XEN_HYPER_PRI(fp, len, "scheduler_tick: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_tick)); + XEN_HYPER_PRI(fp, len, "scheduler_init_vcpu: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_init_vcpu)); + XEN_HYPER_PRI(fp, len, "scheduler_destroy_domain: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_destroy_domain)); + XEN_HYPER_PRI(fp, len, "scheduler_sleep: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_sleep)); + XEN_HYPER_PRI(fp, len, "scheduler_wake: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_wake)); + XEN_HYPER_PRI(fp, len, "scheduler_set_affinity: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_set_affinity)); + XEN_HYPER_PRI(fp, len, "scheduler_do_schedule: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_do_schedule)); + XEN_HYPER_PRI(fp, len, "scheduler_adjust: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_adjust)); + XEN_HYPER_PRI(fp, len, "scheduler_dump_settings: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_dump_settings)); + XEN_HYPER_PRI(fp, len, "scheduler_dump_cpu_state: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.scheduler_dump_cpu_state)); + XEN_HYPER_PRI(fp, len, "timer_expires: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.timer_expires)); XEN_HYPER_PRI(fp, len, "timer_cpu: ", buf, flag, @@ -533,10 +703,12 @@ (buf, "%ld\n", xen_hyper_offset_table.timer_heap_offset)); XEN_HYPER_PRI(fp, len, "timer_killed: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.timer_killed)); + XEN_HYPER_PRI(fp, len, "tss_struct_rsp0: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.tss_struct_rsp0)); XEN_HYPER_PRI(fp, len, "tss_struct_esp0: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.tss_struct_esp0)); + XEN_HYPER_PRI(fp, len, "vcpu_vcpu_id: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.vcpu_vcpu_id)); XEN_HYPER_PRI(fp, len, "vcpu_processor: ", buf, flag, @@ -579,5 +751,43 @@ (buf, "%ld\n", xen_hyper_offset_table.vcpu_runstate_info_state_entry_time)); XEN_HYPER_PRI(fp, len, "vcpu_runstate_info_time: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.vcpu_runstate_info_time)); +#ifdef IA64 + XEN_HYPER_PRI(fp, len, "vcpu_thread_ksp: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.vcpu_thread_ksp)); +#endif +} + +/* + * dump specified memory with specified size. + */ +#define DSP_BYTE_SIZE 16 + +static void +xen_hyper_dump_mem(void *mem, ulong len, int dsz) +{ + long i, max; + void *mem_w = mem; + + if (!len || + (dsz != SIZEOF_8BIT && dsz != SIZEOF_16BIT && + dsz != SIZEOF_32BIT && dsz != SIZEOF_64BIT)) + return; + max = len / dsz + (len % dsz ? 1 : 0); + for (i = 0; i < max; i++) { + if (i != 0 && !(i % (DSP_BYTE_SIZE / dsz))) + fprintf(fp, "\n"); + if (i == 0 || !(i % (DSP_BYTE_SIZE / dsz))) + fprintf(fp, "%p : ", mem_w); + if (dsz == SIZEOF_8BIT) + fprintf(fp, "%02x ", *(uint8_t *)mem_w); + else if (dsz == SIZEOF_16BIT) + fprintf(fp, "%04x ", *(uint16_t *)mem_w); + else if (dsz == SIZEOF_32BIT) + fprintf(fp, "%08x ", *(uint32_t *)mem_w); + else if (dsz == SIZEOF_64BIT) + fprintf(fp, "%016llx ", *(unsigned long long *)mem_w); + mem_w = (char *)mem_w + dsz; + } + fprintf(fp, "\n"); } #endif Index: xen_hyper_global_data.c =================================================================== RCS file: /cvsroot/xen_ia64/people/xencrash/src/crash/xen_hyper_global_data.c,v retrieving revision 1.1 retrieving revision 1.1.12.1 diff -u -r1.1 -r1.1.12.1 --- xen_hyper_global_data.c 5 Dec 2006 01:06:38 -0000 1.1 +++ xen_hyper_global_data.c 15 Feb 2007 00:38:15 -0000 1.1.12.1 @@ -1,8 +1,11 @@ /* * xen_hyper_global_data.c * - * Portions Copyright (C) 2006 Fujitsu Limited - * Portions Copyright (C) 2006 VA Linux Systems Japan K.K. + * Portions Copyright (C) 2006-2007 Fujitsu Limited + * Portions Copyright (C) 2006-2007 VA Linux Systems Japan K.K. + * + * Authors: Itsuro Oda + * Fumihiko Kakuma * * This file is part of Xencrash. * @@ -63,32 +66,35 @@ {"ascii", cmd_ascii, help_ascii, 0}, {"bt", cmd_bt, help_bt, 0}, {"dis", cmd_dis, help_dis, 0}, - {"domain", cmd_xen_hyper_domain, help_xen_hyper_domain, REFRESH_TASK_TABLE}, - {"doms", cmd_xen_hyper_doms, help_xen_hyper_doms, REFRESH_TASK_TABLE}, - {"dumpinfo",cmd_xen_hyper_dumpinfo, help_xen_hyper_dumpinfo,0}, + {"domain", xen_hyper_cmd_domain, xen_hyper_help_domain, REFRESH_TASK_TABLE}, + {"doms", xen_hyper_cmd_doms, xen_hyper_help_doms, REFRESH_TASK_TABLE}, +#if defined(X86) || defined(X86_64) + {"dumpinfo",xen_hyper_cmd_dumpinfo, xen_hyper_help_dumpinfo,0}, +#endif {"eval", cmd_eval, help_eval, 0}, {"exit", cmd_quit, help_exit, 0}, {"extend", cmd_extend, help_extend, 0}, {"foreach", cmd_foreach, help_foreach, 0}, {"gdb", cmd_gdb, help_gdb, 0}, - {"help", cmd_xen_hyper_help, help_help, 0}, + {"help", xen_hyper_cmd_help, help_help, 0}, {"list", cmd_list, help__list, 0}, - {"log", cmd_xen_hyper_log, help_xen_hyper_log, 0}, + {"log", xen_hyper_cmd_log, xen_hyper_help_log, 0}, {"p", cmd_p, help_p, 0}, - {"pcpus", cmd_xen_hyper_pcpus, help_xen_hyper_pcpus, 0}, + {"pcpus", xen_hyper_cmd_pcpus, xen_hyper_help_pcpus, 0}, {"pte", cmd_pte, help_pte, 0}, {"q", cmd_quit, help_quit, 0}, {"rd", cmd_rd, help_rd, 0}, {"repeat", cmd_repeat, help_repeat, 0}, + {"sched", xen_hyper_cmd_sched, xen_hyper_help_sched, 0}, {"search", cmd_search, help_search, 0}, {"set", cmd_set, help_set, 0}, {"struct", cmd_struct, help_struct, 0}, {"sym", cmd_sym, help_sym, 0}, - {"sys", cmd_xen_hyper_sys, help_xen_hyper_sys, 0}, + {"sys", xen_hyper_cmd_sys, xen_hyper_help_sys, 0}, {"test", cmd_test, NULL, HIDDEN_COMMAND}, {"union", cmd_union, help_union, 0}, - {"vcpu", cmd_xen_hyper_vcpu, help_xen_hyper_vcpu, REFRESH_TASK_TABLE}, - {"vcpus", cmd_xen_hyper_vcpus, help_xen_hyper_vcpus, REFRESH_TASK_TABLE}, + {"vcpu", xen_hyper_cmd_vcpu, xen_hyper_help_vcpu, REFRESH_TASK_TABLE}, + {"vcpus", xen_hyper_cmd_vcpus, xen_hyper_help_vcpus, REFRESH_TASK_TABLE}, {"whatis", cmd_whatis, help_whatis, 0}, {"wr", cmd_wr, help_wr, 0}, {(char *)NULL} @@ -104,7 +110,7 @@ * help data */ -char *help_xen_hyper_domain[] = { +char *xen_hyper_help_domain[] = { "domain", "display contents of domain struct", "[domain-id | domainp] ...", @@ -114,7 +120,7 @@ NULL }; -char *help_xen_hyper_doms[] = { +char *xen_hyper_help_doms[] = { "doms", "display domain status information", "[domain-id | domainp] ...", @@ -148,7 +154,7 @@ NULL }; -char *help_xen_hyper_dumpinfo[] = { +char *xen_hyper_help_dumpinfo[] = { "dumpinfo", "display Xen dump information", "[-t | -r] [pcpu-id | enotep] ...", @@ -160,22 +166,23 @@ NULL }; -char *help_xen_hyper_log[] = { +char *xen_hyper_help_log[] = { "log", "dump system message buffer", " This command dumps the xen conring contents in chronological order." , NULL }; -char *help_xen_hyper_pcpus[] = { +char *xen_hyper_help_pcpus[] = { "pcpus", "display physical cpu information", -"[-r] [pcpu-id | pcpup] ...", +"[-r][-t] [pcpu-id | pcpup] ...", " This command displays physical cpu information for selected, or all, cpus" , " pcpu-id a physical cpu id.", " pcpup a physical cpu pointer.", " cur-vcpu a current virtual cpu pointer.", " -r display register information.", +" -t display init_tss information.", " ", " The crashing physical cpu will be highlighted by an aster ", " (\"*\") preceding its information.", @@ -186,10 +193,101 @@ " 0 ff1a3fb4 ffbf9080", " * 1 ff1dbfb4 ffbf8080", " %s>", +" ", +" Show the physical cpu status of all with register information:\n", +" %s> pcpus -r", +" PCID PCPU CUR-VCPU", +" * 0 ff1b7fb4 ffbef080", +" Register information:", +" struct cpu_user_regs {", +" ebx = 0x0,", +" ecx = 0xdcf4bed8,", +" edx = 0xc0326887,", +" esi = 0x63,", +" edi = 0x0,", +" ebp = 0xdcf4bee0,", +" eax = 0x25,", +" error_code = 0x6,", +" entry_vector = 0xe,", +" eip = 0xc01014a7,", +" cs = 0x61,", +" saved_upcall_mask = 0x0,", +" _pad0 = 0x0,", +" eflags = 0x202,", +" esp = 0xdcf4bed0,", +" ss = 0x69,", +" _pad1 = 0x0,", +" es = 0x7b,", +" _pad2 = 0x0,", +" ds = 0x7b,", +" _pad3 = 0x0,", +" fs = 0x0,", +" _pad4 = 0x0,", +" gs = 0x0,", +" _pad5 = 0x0", +" }", +" ", +" Show the physical cpu status of all with init_tss information:\n", +" %s> pcpus -t", +" PCID PCPU CUR-VCPU", +" * 0 ff1b7fb4 ffbef080", +" init_tss information:", +" struct tss_struct {", +" back_link = 0x0,", +" __blh = 0x0,", +" esp0 = 0xff1b7fe8,", +" ss0 = 0xe010,", +" __ss0h = 0x0,", +" esp1 = 0xdcf4bff8,", +" ss1 = 0x69,", +" __ss1h = 0x0,", +" esp2 = 0x0,", +" ss2 = 0x0,", +" __ss2h = 0x0,", +" __cr3 = 0x0,", +" eip = 0x0,", +" eflags = 0x0,", +" eax = 0x0,", +" ecx = 0x0,", +" edx = 0x0,", +" ebx = 0x0,", +" esp = 0x0,", +" ebp = 0x0,", +" esi = 0x0,", +" edi = 0x0,", +" es = 0x0,", +" __esh = 0x0,", +" cs = 0x0,", +" __csh = 0x0,", +" ss = 0x0,", +" __ssh = 0x0,", +" ds = 0x0,", +" __dsh = 0x0,", +" fs = 0x0,", +" __fsh = 0x0,", +" gs = 0x0,", +" __gsh = 0x0,", +" ldt = 0x0,", +" __ldth = 0x0,", +" trace = 0x0,", +" bitmap = 0x8000,", +" __cacheline_filler = \"\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\"", +" }", +NULL +}; + +char *xen_hyper_help_sched[] = { +"pcpus", +"display scheduler information", +"[-r][-t] [pcpu-id] ...", +" This command displays scheduler information for selected, or all, cpus" , +" pcpu-id a physical cpu id.", +" -v display verbosely scheduler information.", +" ", NULL }; -char *help_xen_hyper_sys[] = { +char *xen_hyper_help_sys[] = { "sys", "system data", "[-c [name|number]] config", @@ -208,7 +306,7 @@ NULL }; -char *help_xen_hyper_vcpu[] = { +char *xen_hyper_help_vcpu[] = { "vcpu", "display contents of vcpu struct", "[vcpup] ...", @@ -218,7 +316,7 @@ NULL }; -char *help_xen_hyper_vcpus[] = { +char *xen_hyper_help_vcpus[] = { "vcpus", "display vcpu status information", "[-i domain-id vcpu-id | vcpup] ...",