--- crash-4.0-3.22/help.c 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/help.c 2007-04-25 09:17:38.000000000 -0400 @@ -1235,13 +1235,17 @@ " stacks (x86_64) for possible exception frames; all other arguments", " will be ignored since this is not a context-sensitive operation.", " -f display all stack data contained in a frame; this option can be", -" used to determine the arguments passed to each function (x86 only);", -" on IA64, the argument register contents are dumped.", -" -o use old backtrace method, permissable only on kernels that were", -" compiled without the -fomit-frame_pointer (x86 only).", -" -O use old backtrace method by default, permissable only on kernels", -" that were compiled without the -fomit-frame_pointer; subsequent", -" usage of this option toggles the backtrace method (x86 only).", +" used to determine the arguments passed to each function; on ia64,", +" the argument register contents are dumped.", +" -o x86: use old backtrace method, permissable only on kernels that were", +" compiled without the -fomit-frame_pointer.", +" x86_64: use old backtrace method, which dumps potentially stale", +" kernel text return addresses found on the stack.", +" -O x86: use old backtrace method by default, permissable only on kernels", +" that were compiled without the -fomit-frame_pointer; subsequent usage", +" of this option toggles the backtrace method.", +" x86_64: use old backtrace method by default; subsequent usage of this", +" option toggles the backtrace method.", #if !defined(GDB_6_0) && !defined(GDB_6_1) " -g use gdb stack trace code. (alpha only)", #endif @@ -1256,11 +1260,8 @@ " Note that all examples below are for x86 only. The output format will differ", " for other architectures. x86 backtraces from kernels that were compiled", " with the --fomit-frame-pointer CFLAG occasionally will drop stack frames,", -" or display a stale frame reference. x86_64 backtraces are only slightly", -" more intelligent than those generated from kernel oops messages; text return", -" addresses shown in the back trace may include stale references. When in", -" doubt as to the accuracy of a backtrace, the -t option may help fill in", -" the blanks.\n", +" or display a stale frame reference. When in doubt as to the accuracy of a", +" backtrace, the -t or -T options may help fill in the blanks.\n", "EXAMPLES", " Display the stack trace of the active task(s) when the kernel panicked:\n", " %s> bt -a", --- crash-4.0-3.22/task.c 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/task.c 2007-04-25 09:18:51.000000000 -0400 @@ -4745,7 +4745,7 @@ fd = &foreach_data; fd->keys = 1; fd->keyword_array[0] = FOREACH_BT; - fd->flags |= FOREACH_t_FLAG; + fd->flags |= (FOREACH_t_FLAG|FOREACH_o_FLAG); dietask = lasttask = NO_TASK; --- crash-4.0-3.22/kernel.c 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/kernel.c 2007-04-25 09:19:18.000000000 -0400 @@ -1393,7 +1393,8 @@ } #define FRAMESIZE_DEBUG_MESSAGE \ -"usage: bt -F [size|clear|dump|seek|noseek|validate|novalidate] [-I eip]\n If eip: set its associated framesize to size.\n \"validate/novalidate\" will turn on/off V bit for this eip entry.\n If !eip: \"clear\" will clear the framesize cache and RA seek/noseek flags.\n \"dump\" will dump the current framesize cache entries.\n \"seek/noseek\" turns on/off RA seeking.\n \"validate/novalidate\" turns on/off V bit for all current entries.\n" +"\nx86 usage: bt -F [size|clear|dump|seek|noseek|validate|novalidate] [-I eip]\n If eip: set its associated framesize to size.\n \"validate/novalidate\" will turn on/off V bit for this eip entry.\n If !eip: \"clear\" will clear the framesize cache and RA seek/noseek flags.\n \"dump\" will dump the current framesize cache entries.\n \"seek/noseek\" turns on/off RA seeking.\n \"validate/novalidate\" turns on/off V bit for all current entries.\n\nx86_64 usage: bt -F [clear|dump|validate] [-I rip]\n If rip: \"validate\" will verbosely recalculate the framesize.\n If !rip: \"clear\" will clear the framesize cache.\n \"dump\" will dump the current framesize cache entries.\n" + /* * Display a kernel stack backtrace. Arguments may be any number pid or task @@ -1461,7 +1462,7 @@ break; case 'O': - if (!machine_type("X86")) + if (!(machine_type("X86") || machine_type("X86_64"))) option_not_supported(c); else if (kt->flags & USE_OLD_BT) { /* --- crash-4.0-3.22/ia64.c 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/ia64.c 2007-04-26 08:31:45.000000000 -0400 @@ -3981,7 +3981,8 @@ static int ia64_kvtop_hyper(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbose) { - unsigned long virt_percpu_start, phys_percpu_start; + ulong virt_percpu_start, phys_percpu_start; + ulong addr, dirp, entry; if (!IS_KVADDR(kvaddr)) return FALSE; @@ -3994,9 +3995,37 @@ } else if (DIRECTMAP_VIRT_ADDR(kvaddr)) { *paddr = kvaddr - DIRECTMAP_VIRT_START; return TRUE; + } else if (!FRAME_TABLE_VIRT_ADDR(kvaddr)) { + return FALSE; } - return FALSE; + /* frametable virtual address */ + addr = kvaddr - VIRT_FRAME_TABLE_ADDR; + + dirp = symbol_value("frametable_pg_dir"); + dirp += ((addr >> PGDIR_SHIFT_3L) & (PTRS_PER_PGD - 1)) * sizeof(ulong); + readmem(dirp, KVADDR, &entry, sizeof(ulong), + "frametable_pg_dir", FAULT_ON_ERROR); + + dirp = entry & _PFN_MASK; + if (!dirp) + return FALSE; + dirp += ((addr >> PMD_SHIFT) & (PTRS_PER_PMD - 1)) * sizeof(ulong); + readmem(dirp, PHYSADDR, &entry, sizeof(ulong), + "frametable pmd", FAULT_ON_ERROR); + + dirp = entry & _PFN_MASK; + if (!dirp) + return FALSE; + dirp += ((addr >> PAGESHIFT()) & (PTRS_PER_PTE - 1)) * sizeof(ulong); + readmem(dirp, PHYSADDR, &entry, sizeof(ulong), + "frametable pte", FAULT_ON_ERROR); + + if (!(entry & _PAGE_P)) + return FALSE; + + *paddr = (entry & _PFN_MASK) + (kvaddr & (PAGESIZE() - 1)); + return TRUE; } static void --- crash-4.0-3.22/s390.c 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/s390.c 2007-04-25 08:58:52.000000000 -0400 @@ -538,10 +538,11 @@ /* Linux 2.6 */ unsigned long runqueue_addr, runqueue_offset; unsigned long cpu_offset, per_cpu_offset_addr, running_task; - char runqueue[4096]; + char *runqueue; int cpu; cpu = s390_cpu_of_task(task); + runqueue = GETBUF(SIZE(runqueue)); runqueue_offset=symbol_value("per_cpu__runqueues"); per_cpu_offset_addr=symbol_value("__per_cpu_offset"); @@ -549,10 +550,10 @@ &cpu_offset, sizeof(long),"per_cpu_offset", FAULT_ON_ERROR); runqueue_addr=runqueue_offset + cpu_offset; - readmem(runqueue_addr,KVADDR,&runqueue,sizeof(runqueue), + readmem(runqueue_addr,KVADDR,runqueue,SIZE(runqueue), "runqueue", FAULT_ON_ERROR); - running_task = *((unsigned long*)&runqueue[MEMBER_OFFSET( - "runqueue", "curr")]); + running_task = ULONG(runqueue + OFFSET(runqueue_curr)); + FREEBUF(runqueue); if(running_task == task) return TRUE; else --- crash-4.0-3.22/s390x.c 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/s390x.c 2007-04-25 08:58:52.000000000 -0400 @@ -572,10 +572,11 @@ /* Linux 2.6 */ unsigned long runqueue_addr, runqueue_offset; unsigned long cpu_offset, per_cpu_offset_addr, running_task; - char runqueue[4096]; + char *runqueue; int cpu; cpu = s390x_cpu_of_task(task); + runqueue = GETBUF(SIZE(runqueue)); runqueue_offset=symbol_value("per_cpu__runqueues"); per_cpu_offset_addr=symbol_value("__per_cpu_offset"); @@ -583,10 +584,10 @@ &cpu_offset, sizeof(long),"per_cpu_offset", FAULT_ON_ERROR); runqueue_addr=runqueue_offset + cpu_offset; - readmem(runqueue_addr,KVADDR,&runqueue,sizeof(runqueue), + readmem(runqueue_addr,KVADDR,runqueue,SIZE(runqueue), "runqueue", FAULT_ON_ERROR); - running_task = *((unsigned long*)&runqueue[MEMBER_OFFSET( - "runqueue", "curr")]); + running_task = ULONG(runqueue + OFFSET(runqueue_curr)); + FREEBUF(runqueue); if(running_task == task) return TRUE; else --- crash-4.0-3.22/x86_64.c 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/x86_64.c 2007-04-25 16:30:03.000000000 -0400 @@ -47,6 +47,7 @@ static struct syment *x86_64_function_called_by(ulong); static int is_direct_call_target(struct bt_info *); static void get_x86_64_frame(struct bt_info *, ulong *, ulong *); +static ulong text_lock_function(char *, struct bt_info *, ulong); static int x86_64_print_stack_entry(struct bt_info *, FILE *, int, int, ulong); static void x86_64_display_full_frame(struct bt_info *, ulong, FILE *); static void x86_64_do_bt_reference_check(struct bt_info *, ulong,char *); @@ -87,6 +88,10 @@ static void x86_64_init_hyper(int); static ulong x86_64_get_stackbase_hyper(ulong); static ulong x86_64_get_stacktop_hyper(ulong); +static int x86_64_framesize_cache_resize(void); +static int x86_64_framesize_cache_func(int, ulong, int *); +static int x86_64_get_framesize(struct bt_info *, ulong); +static void x86_64_framesize_debug(struct bt_info *); struct machine_specific x86_64_machine_specific = { 0 }; @@ -1910,6 +1915,74 @@ } /* + * Determine the function containing a .text.lock. reference. + */ +static ulong +text_lock_function(char *name, struct bt_info *bt, ulong locktext) +{ + int c, reterror, instr, arg; + char buf[BUFSIZE]; + char *arglist[MAXARGS]; + char *p1; + ulong locking_func; + + instr = arg = -1; + locking_func = 0; + + open_tmpfile2(); + + if (STREQ(name, ".text.lock.spinlock")) + sprintf(buf, "x/4i 0x%lx", locktext); + else + sprintf(buf, "x/1i 0x%lx", locktext); + + if (!gdb_pass_through(buf, pc->tmpfile2, GNU_RETURN_ON_ERROR)) { + close_tmpfile2(); + bt->flags |= BT_FRAMESIZE_DISABLE; + return 0; + } + + rewind(pc->tmpfile2); + while (fgets(buf, BUFSIZE, pc->tmpfile2)) { + c = parse_line(buf, arglist); + + if (instr == -1) { + /* + * Check whether are + * in the output string. + */ + if (LASTCHAR(arglist[0]) == ':') { + instr = 1; + arg = 2; + } else { + instr = 2; + arg = 3; + } + } + + if (c < (arg+1)) + break; + + if (STREQ(arglist[instr], "jmpq") || STREQ(arglist[instr], "jmp")) { + p1 = arglist[arg]; + reterror = 0; + locking_func = htol(p1, RETURN_ON_ERROR, &reterror); + if (reterror) + locking_func = 0; + break; + } + } + close_tmpfile2(); + + if (!locking_func) + bt->flags |= BT_FRAMESIZE_DISABLE; + + return locking_func; + +} + + +/* * print one entry of a stack trace */ #define BACKTRACE_COMPLETE (1) @@ -1921,8 +1994,8 @@ x86_64_print_stack_entry(struct bt_info *bt, FILE *ofp, int level, int stkindex, ulong text) { - ulong rsp, offset; - struct syment *sp; + ulong rsp, offset, locking_func; + struct syment *sp, *spl; char *name; int result; long eframe_check; @@ -1997,9 +2070,22 @@ bt->frameptr = rsp + sizeof(ulong); } - fprintf(ofp, "%s#%d [%8lx] %s at %lx\n", level < 10 ? " " : "", level, + fprintf(ofp, "%s#%d [%8lx] %s at %lx", level < 10 ? " " : "", level, rsp, name, text); + if (STREQ(name, "tracesys")) + fprintf(ofp, " (via system_call)"); + else if (STRNEQ(name, ".text.lock.")) { + if ((locking_func = text_lock_function(name, bt, text)) && + (spl = value_search(locking_func, &offset))) + fprintf(ofp, " (via %s)", spl->name); + } + + if (bt->flags & BT_FRAMESIZE_DISABLE) + fprintf(ofp, " *"); + + fprintf(ofp, "\n"); + if (bt->flags & BT_LINE_NUMBERS) { get_line_number(text, buf, FALSE); if (strlen(buf)) @@ -2131,7 +2217,7 @@ static void x86_64_low_budget_back_trace_cmd(struct bt_info *bt_in) { - int i, level, done; + int i, level, done, framesize; ulong rsp, offset, stacktop; ulong *up; long cs; @@ -2157,7 +2243,7 @@ BCOPY(bt_in, bt, sizeof(struct bt_info)); if (bt->flags & BT_FRAMESIZE_DEBUG) { - dwarf_debug(bt); + x86_64_framesize_debug(bt); return; } @@ -2235,6 +2321,8 @@ stacktop = bt->stacktop - SIZE(pt_regs); + bt->flags &= ~BT_FRAMESIZE_DISABLE; + for (i = (rsp - bt->stackbase)/sizeof(ulong); !done && (rsp < stacktop); i++, rsp += sizeof(ulong)) { @@ -2250,6 +2338,10 @@ i += SIZE(pt_regs)/sizeof(ulong); case BACKTRACE_ENTRY_DISPLAYED: level++; + if ((framesize = x86_64_get_framesize(bt, *up)) >= 0) { + rsp += framesize; + i += framesize/sizeof(ulong); + } break; case BACKTRACE_ENTRY_IGNORED: break; @@ -2287,8 +2379,10 @@ bt->flags |= BT_START; x86_64_print_stack_entry(bt, ofp, level, 0, bt->instptr); - bt->flags &= ~BT_START; + bt->flags &= ~(BT_START|BT_FRAMESIZE_DISABLE); level++; + if ((framesize = x86_64_get_framesize(bt, bt->instptr)) >= 0) + rsp += framesize; } } @@ -2317,6 +2411,8 @@ stacktop = bt->stacktop - 64; /* from kernel code */ + bt->flags &= ~BT_FRAMESIZE_DISABLE; + for (i = (rsp - bt->stackbase)/sizeof(ulong); !done && (rsp < stacktop); i++, rsp += sizeof(ulong)) { @@ -2332,6 +2428,10 @@ i += SIZE(pt_regs)/sizeof(ulong); case BACKTRACE_ENTRY_DISPLAYED: level++; + if ((framesize = x86_64_get_framesize(bt, *up)) >= 0) { + rsp += framesize; + i += framesize/sizeof(ulong); + } break; case BACKTRACE_ENTRY_IGNORED: break; @@ -2445,6 +2545,9 @@ /* * Walk the process stack. */ + + bt->flags &= ~BT_FRAMESIZE_DISABLE; + for (i = (rsp - bt->stackbase)/sizeof(ulong); !done && (rsp < bt->stacktop); i++, rsp += sizeof(ulong)) { @@ -2459,6 +2562,9 @@ * lets us know if it's a real text return address. */ spt = value_search(*up, &offset); + if (!offset && !(bt->flags & BT_FRAMESIZE_DISABLE)) + continue; + /* * sp gets the syment of the function that the text * routine above called before leaving its return @@ -2509,6 +2615,10 @@ i += SIZE(pt_regs)/sizeof(ulong); case BACKTRACE_ENTRY_DISPLAYED: level++; + if ((framesize = x86_64_get_framesize(bt, *up)) >= 0) { + rsp += framesize; + i += framesize/sizeof(ulong); + } break; case BACKTRACE_ENTRY_IGNORED: break; @@ -2896,6 +3006,18 @@ if (value) sp = value_search(value, &offset); + /* + * Functions that jmp to schedule() or schedule_timeout(). + */ + if (sp) { + if ((STREQ(sp->name, "schedule_timeout_interruptible") || + STREQ(sp->name, "schedule_timeout_uninterruptible"))) + sp = symbol_search("schedule_timeout"); + + if (STREQ(sp->name, "__cond_resched")) + sp = symbol_search("schedule"); + } + return sp; } @@ -3248,12 +3370,14 @@ char *user_regs; ulong ur_rip, ur_rsp; ulong halt_rip, halt_rsp; + ulong crash_kexec_rip, crash_kexec_rsp; bt = &bt_local; BCOPY(bt_in, bt, sizeof(struct bt_info)); ms = machdep->machspec; ur_rip = ur_rsp = 0; halt_rip = halt_rsp = 0; + crash_kexec_rip = crash_kexec_rsp = 0; stage = 0; estack = -1; @@ -3290,7 +3414,6 @@ for (i = 0, up = (ulong *)bt->stackbuf; i < (bt->stacktop - bt->stackbase)/sizeof(ulong); i++, up++) { sym = closest_symbol(*up); - if (XEN_CORE_DUMPFILE()) { if (STREQ(sym, "xen_machine_kexec")) { *rip = *up; @@ -3302,7 +3425,17 @@ STREQ(sym, "start_disk_dump") || STREQ(sym, "disk_dump") || STREQ(sym, "crash_kexec") || + STREQ(sym, "machine_kexec") || STREQ(sym, "try_crashdump")) { + /* + * Use second instance of crash_kexec if it exists. + */ + if (!(bt->flags & BT_TEXT_SYMBOLS) && + STREQ(sym, "crash_kexec") && !crash_kexec_rip) { + crash_kexec_rip = *up; + crash_kexec_rsp = bt->stackbase + ((char *)(up) - bt->stackbuf); + continue; + } *rip = *up; *rsp = bt->stackbase + ((char *)(up) - bt->stackbuf); return; @@ -3388,6 +3521,12 @@ if (panic) return; + if (crash_kexec_rip) { + *rip = crash_kexec_rip; + *rsp = crash_kexec_rsp; + return; + } + skip_stage: switch (stage) { @@ -5273,4 +5412,307 @@ break; } } + + +struct framesize_cache { + ulong textaddr; + int framesize; +}; + +static struct framesize_cache *x86_64_framesize_cache = NULL; +static int framesize_cache_entries = 0; + +#define FRAMESIZE_QUERY (1) +#define FRAMESIZE_ENTER (2) +#define FRAMESIZE_DUMP (3) + +#define FRAMESIZE_CACHE_INCR (50) + +static int +x86_64_framesize_cache_resize(void) +{ + int i; + struct framesize_cache *new_fc, *fc; + + if ((new_fc = realloc(x86_64_framesize_cache, + (framesize_cache_entries+FRAMESIZE_CACHE_INCR) * + sizeof(struct framesize_cache))) == NULL) { + error(INFO, "cannot realloc x86_64_framesize_cache space!\n"); + return FALSE; + } + + fc = new_fc + framesize_cache_entries; + for (i = framesize_cache_entries; + i < (framesize_cache_entries+FRAMESIZE_CACHE_INCR); + fc++, i++) { + fc->textaddr = 0; + fc->framesize = 0; + } + + x86_64_framesize_cache = new_fc; + framesize_cache_entries += FRAMESIZE_CACHE_INCR; + + return TRUE; +} + +static int +x86_64_framesize_cache_func(int cmd, ulong textaddr, int *framesize) +{ + int i; + struct framesize_cache *fc; + char buf[BUFSIZE]; + + if (!x86_64_framesize_cache) { + framesize_cache_entries = FRAMESIZE_CACHE_INCR; + if ((x86_64_framesize_cache = calloc(framesize_cache_entries, + sizeof(struct framesize_cache))) == NULL) + error(FATAL, + "cannot calloc x86_64_framesize_cache space!\n"); + } + + switch (cmd) + { + case FRAMESIZE_QUERY: + fc = &x86_64_framesize_cache[0]; + for (i = 0; i < framesize_cache_entries; i++, fc++) { + if (fc->textaddr == textaddr) { + *framesize = fc->framesize; + return TRUE; + } + } + return FALSE; + + case FRAMESIZE_ENTER: +retry: + fc = &x86_64_framesize_cache[0]; + for (i = 0; i < framesize_cache_entries; i++, fc++) { + if ((fc->textaddr == 0) || + (fc->textaddr == textaddr)) { + fc->textaddr = textaddr; + fc->framesize = *framesize; + return fc->framesize; + } + } + + if (x86_64_framesize_cache_resize()) + goto retry; + + return *framesize; + + case FRAMESIZE_DUMP: + fc = &x86_64_framesize_cache[0]; + for (i = 0; i < framesize_cache_entries; i++, fc++) { + if (fc->textaddr == 0) { + if (i < (framesize_cache_entries-1)) { + fprintf(fp, "[%d-%d]: (unused)\n", + i, framesize_cache_entries-1); + } + break; + } + + fprintf(fp, "[%3d]: %lx %3d (%s)\n", i, + fc->textaddr, fc->framesize, + value_to_symstr(fc->textaddr, buf, 0)); + } + break; + } + + return TRUE; +} + +#define BT_FRAMESIZE_IGNORE_MASK \ + (BT_OLD_BACK_TRACE|BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_ALL|BT_FRAMESIZE_DISABLE) + +static int +x86_64_get_framesize(struct bt_info *bt, ulong textaddr) +{ + int c, framesize, instr, arg; + struct syment *sp; + long max_instructions; + ulong offset; + char buf[BUFSIZE]; + char buf2[BUFSIZE]; + char *arglist[MAXARGS]; + ulong locking_func, textaddr_save, current; + char *p1, *p2; + int reterror; + + if (!(bt->flags & BT_FRAMESIZE_DEBUG)) { + if ((bt->flags & BT_FRAMESIZE_IGNORE_MASK) || + (kt->flags & USE_OLD_BT)) + return 0; + } + + if (!(sp = value_search(textaddr, &offset))) { + if (!(bt->flags & BT_FRAMESIZE_DEBUG)) + bt->flags |= BT_FRAMESIZE_DISABLE; + return 0; + } + + if (!(bt->flags & BT_FRAMESIZE_DEBUG) && + x86_64_framesize_cache_func(FRAMESIZE_QUERY, textaddr, &framesize)) { + if (framesize == -1) + bt->flags |= BT_FRAMESIZE_DISABLE; + return framesize; + } + + /* + * Bait and switch an incoming .text.lock address + * with the containing function's address. + */ + if (STRNEQ(sp->name, ".text.lock.") && + (locking_func = text_lock_function(sp->name, bt, textaddr))) { + if (!(sp = value_search(locking_func, &offset))) { + bt->flags |= BT_FRAMESIZE_DISABLE; + return 0; + } + textaddr_save = textaddr; + textaddr = locking_func; + } else + textaddr_save = 0; + + framesize = 0; + max_instructions = textaddr - sp->value; + instr = arg = -1; + + open_tmpfile2(); + + sprintf(buf, "x/%ldi 0x%lx", + max_instructions, sp->value); + + if (!gdb_pass_through(buf, pc->tmpfile2, GNU_RETURN_ON_ERROR)) { + close_tmpfile2(); + bt->flags |= BT_FRAMESIZE_DISABLE; + return 0; + } + + rewind(pc->tmpfile2); + while (fgets(buf, BUFSIZE, pc->tmpfile2)) { + strcpy(buf2, buf); + + if (CRASHDEBUG(3)) + fprintf(pc->saved_fp, buf2); + + c = parse_line(buf, arglist); + + if (instr == -1) { + /* + * Check whether are + * in the output string. + */ + if (LASTCHAR(arglist[0]) == ':') { + instr = 1; + arg = 2; + } else { + instr = 2; + arg = 3; + } + } + + if (c < (arg+1)) + continue; + + reterror = 0; + current = htol(strip_ending_char(arglist[0], ':'), + RETURN_ON_ERROR, &reterror); + if (reterror) + continue; + if (current >= textaddr) + break; + + if (STRNEQ(arglist[instr], "push")) { + framesize += 8; + if (CRASHDEBUG(2) || (bt->flags & BT_FRAMESIZE_DEBUG)) + fprintf(pc->saved_fp, "%s\t[framesize: %d]\n", + strip_linefeeds(buf2), framesize); + } else if (STRNEQ(arglist[instr], "pop")) { + framesize -= 8; + if (CRASHDEBUG(2) || (bt->flags & BT_FRAMESIZE_DEBUG)) + fprintf(pc->saved_fp, "%s\t[framesize: %d]\n", + strip_linefeeds(buf2), framesize); + } else if (STRNEQ(arglist[instr], "add") && + (p1 = strstr(arglist[arg], ",%rsp"))) { + *p1 = NULLCHAR; + p2 = arglist[arg]; + reterror = 0; + offset = htol(p2+1, RETURN_ON_ERROR, &reterror); + if (reterror) + continue; + framesize -= offset; + if (CRASHDEBUG(2) || (bt->flags & BT_FRAMESIZE_DEBUG)) + fprintf(pc->saved_fp, "%s\t[framesize: %d]\n", + strip_linefeeds(buf2), framesize); + } else if (STRNEQ(arglist[instr], "sub") && + (p1 = strstr(arglist[arg], ",%rsp"))) { + *p1 = NULLCHAR; + p2 = arglist[arg]; + reterror = 0; + offset = htol(p2+1, RETURN_ON_ERROR, &reterror); + if (reterror) + continue; + framesize += offset; + if (CRASHDEBUG(2) || (bt->flags & BT_FRAMESIZE_DEBUG)) + fprintf(pc->saved_fp, "%s\t[framesize: %d]\n", + strip_linefeeds(buf2), framesize); + } else if (STRNEQ(arglist[instr], "retq")) { + bt->flags |= BT_FRAMESIZE_DISABLE; + framesize = -1; + if (CRASHDEBUG(2) || (bt->flags & BT_FRAMESIZE_DEBUG)) + fprintf(pc->saved_fp, "%s\t[framesize: DISABLED]\n", + strip_linefeeds(buf2)); + break; + } + } + close_tmpfile2(); + + if (textaddr_save) + textaddr = textaddr_save; + + return (x86_64_framesize_cache_func(FRAMESIZE_ENTER, textaddr, &framesize)); +} + +static void +x86_64_framesize_debug(struct bt_info *bt) +{ + int framesize; + + switch (bt->hp->esp) + { + case 1: /* "dump" */ + if (bt->hp->eip) { + framesize = 1; + x86_64_framesize_cache_func(FRAMESIZE_ENTER, bt->hp->eip, + &framesize); + } else + x86_64_framesize_cache_func(FRAMESIZE_DUMP, 0, NULL); + break; + + case 0: + if (bt->hp->eip) { + framesize = 0; + x86_64_framesize_cache_func(FRAMESIZE_ENTER, bt->hp->eip, + &framesize); + } else /* "clear" */ + BZERO(&x86_64_framesize_cache[0], + sizeof(struct framesize_cache)*framesize_cache_entries); + break; + + case -1: + if (!bt->hp->eip) + error(INFO, "x86_64_framesize_debug: ignoring command\n"); + else + x86_64_get_framesize(bt, bt->hp->eip); + break; + + default: + if (bt->hp->esp > 1) { + framesize = bt->hp->esp; + if (bt->hp->eip) + x86_64_framesize_cache_func(FRAMESIZE_ENTER, bt->hp->eip, + &framesize); + } else + error(INFO, "x86_64_framesize_debug: ignoring command\n"); + break; + } +} #endif /* X86_64 */ --- crash-4.0-3.22/xen_hyper.c 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/xen_hyper.c 2007-04-26 08:31:45.000000000 -0400 @@ -170,6 +170,26 @@ XEN_HYPER_MEMBER_OFFSET_INIT(domain_domain_flags, "domain", "domain_flags"); XEN_HYPER_MEMBER_OFFSET_INIT(domain_evtchn, "domain", "evtchn"); XEN_HYPER_MEMBER_OFFSET_INIT(domain_vcpu, "domain", "vcpu"); + XEN_HYPER_MEMBER_OFFSET_INIT(domain_arch, "domain", "arch"); + + XEN_HYPER_STRUCT_SIZE_INIT(arch_shared_info, "arch_shared_info"); + XEN_HYPER_MEMBER_OFFSET_INIT(arch_shared_info_max_pfn, "arch_shared_info", "max_pfn"); + XEN_HYPER_MEMBER_OFFSET_INIT(arch_shared_info_pfn_to_mfn_frame_list_list, "arch_shared_info", "pfn_to_mfn_frame_list_list"); + XEN_HYPER_MEMBER_OFFSET_INIT(arch_shared_info_nmi_reason, "arch_shared_info", "nmi_reason"); + + XEN_HYPER_STRUCT_SIZE_INIT(shared_info, "shared_info"); + XEN_HYPER_MEMBER_OFFSET_INIT(shared_info_vcpu_info, "shared_info", "vcpu_info"); + XEN_HYPER_MEMBER_OFFSET_INIT(shared_info_evtchn_pending, "shared_info", "evtchn_pending"); + XEN_HYPER_MEMBER_OFFSET_INIT(shared_info_evtchn_mask, "shared_info", "evtchn_mask"); + XEN_HYPER_MEMBER_OFFSET_INIT(shared_info_arch, "shared_info", "arch"); + + XEN_HYPER_STRUCT_SIZE_INIT(arch_domain, "arch_domain"); +#ifdef IA64 + XEN_HYPER_MEMBER_OFFSET_INIT(arch_domain_mm, "arch_domain", "mm"); + + XEN_HYPER_STRUCT_SIZE_INIT(mm_struct, "mm_struct"); + XEN_HYPER_MEMBER_OFFSET_INIT(mm_struct_pgd, "mm_struct", "pgd"); +#endif if((xhdt->domain_struct = malloc(XEN_HYPER_SIZE(domain))) == NULL) { error(FATAL, "cannot malloc domain struct space.\n"); @@ -453,7 +473,8 @@ 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)); + if (XEN_HYPER_VALID_MEMBER(schedule_data_tick)) + schc->tick = ULONG(buf + XEN_HYPER_OFFSET(schedule_data_tick)); } FREEBUF(buf); } @@ -751,7 +772,7 @@ xen_hyper_refresh_domain_context_space(void) { char *domain_struct; - ulong domain, next, idle_vcpu; + ulong domain, next, dom_xen, dom_io, idle_vcpu; struct xen_hyper_domain_context *dc; struct xen_hyper_domain_context *dom0; @@ -764,6 +785,25 @@ xen_hyper_alloc_domain_context_space(XEN_HYPER_NR_DOMAINS()); dc = xhdt->context_array; + + /* restore an dom_io context. */ + get_symbol_data("dom_io", sizeof(dom_io), &dom_io); + if ((domain_struct = xen_hyper_read_domain(dom_io)) == NULL) { + error(FATAL, "cannot read dom_io.\n"); + } + xen_hyper_store_domain_context(dc, dom_io, domain_struct); + xhdt->dom_io = dc; + dc++; + + /* restore an dom_xen context. */ + get_symbol_data("dom_xen", sizeof(dom_xen), &dom_xen); + if ((domain_struct = xen_hyper_read_domain(dom_xen)) == NULL) { + error(FATAL, "cannot read dom_xen.\n"); + } + xen_hyper_store_domain_context(dc, dom_xen, domain_struct); + xhdt->dom_xen = dc; + dc++; + /* restore an idle domain context. */ get_symbol_data("idle_vcpu", sizeof(idle_vcpu), &idle_vcpu); if (!readmem(idle_vcpu + MEMBER_OFFSET("vcpu", "domain"), @@ -814,7 +854,7 @@ error(FATAL, "cannot read domain.next_in_list.\n"); } } - i++; /* for idle domain */ + i += 3; /* for dom_io, dom_xen and idle domain */ return i; } @@ -1009,7 +1049,10 @@ dc->shared_info = ULONG(dp + XEN_HYPER_OFFSET(domain_shared_info)); dc->sched_priv = ULONG(dp + XEN_HYPER_OFFSET(domain_sched_priv)); dc->next_in_list = ULONG(dp + XEN_HYPER_OFFSET(domain_next_in_list)); - dc->domain_flags = ULONG(dp + XEN_HYPER_OFFSET(domain_domain_flags)); + if (XEN_HYPER_VALID_MEMBER(domain_domain_flags)) + dc->domain_flags = ULONG(dp + XEN_HYPER_OFFSET(domain_domain_flags)); + else + dc->domain_flags = XEN_HYPER_DOMF_ERROR; 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 *)); @@ -1231,7 +1274,8 @@ vcc->vcpu_info = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_vcpu_info)); vcc->domain = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_domain)); vcc->next_in_list = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_next_in_list)); - vcc->sleep_tick = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_sleep_tick)); + if (XEN_HYPER_VALID_MEMBER(vcpu_sleep_tick)) + vcc->sleep_tick = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_sleep_tick)); vcc->sched_priv = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_sched_priv)); vcc->state = INT(vcp + XEN_HYPER_OFFSET(vcpu_runstate) + XEN_HYPER_OFFSET(vcpu_runstate_info_state)); @@ -1239,7 +1283,10 @@ XEN_HYPER_OFFSET(vcpu_runstate) + XEN_HYPER_OFFSET(vcpu_runstate_info_state_entry_time)); vcc->runstate_guest = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_runstate_guest)); - vcc->vcpu_flags = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_vcpu_flags)); + if (XEN_HYPER_VALID_MEMBER(vcpu_vcpu_flags)) + vcc->vcpu_flags = ULONG(vcp + XEN_HYPER_OFFSET(vcpu_vcpu_flags)); + else + vcc->vcpu_flags = XEN_HYPER_VCPUF_ERROR; return vcc; } @@ -1299,8 +1346,8 @@ error(FATAL, "cannot malloc context arrays (%d domains).", domains); } - xhvct->vcpu_context_arrays_cnt = domains; BZERO(xhvct->vcpu_context_arrays, domains * sizeof(struct xen_hyper_vcpu_context_array)); + xhvct->vcpu_context_arrays_cnt = domains; } else if (domains > xhvct->vcpu_context_arrays_cnt) { if (!(xhvct->vcpu_context_arrays = realloc(xhvct->vcpu_context_arrays, @@ -1321,7 +1368,13 @@ void xen_hyper_alloc_vcpu_context_space(struct xen_hyper_vcpu_context_array *vcca, int vcpus) { - if (vcca->context_array == NULL) { + if (!vcpus) { + if (vcca->context_array != NULL) { + free(vcca->context_array); + vcca->context_array = NULL; + } + vcca->context_array_cnt = vcpus; + } else if (vcca->context_array == NULL) { if (!(vcca->context_array = malloc(vcpus * sizeof(struct xen_hyper_vcpu_context)))) { error(FATAL, "cannot malloc context array (%d vcpus).", @@ -1542,7 +1595,7 @@ * Calculate and return the uptime. */ ulonglong -get_uptime_hyper(void) +xen_hyper_get_uptime_hyper(void) { ulong jiffies, tmp1, tmp2; ulonglong jiffies_64, wrapped; @@ -1645,7 +1698,8 @@ "total_pages", RETURN_ON_ERROR)) { error(WARNING, "cannot read total_pages.\n"); } - machdep->memsize = (uint64_t)(xht->total_pages) * (uint64_t)(machdep->pagesize); + xht->sys_pages = xht->total_pages; + machdep->memsize = (uint64_t)(xht->sys_pages) * (uint64_t)(machdep->pagesize); return machdep->memsize; } @@ -1683,7 +1737,7 @@ if (!xht->cpu_data_address || !XEN_HYPER_VALID_STRUCT(cpuinfo_ia64) || - !XEN_HYPER_VALID_MEMBER(cpuinfo_ia64_proc_freq)) + XEN_HYPER_INVALID_MEMBER(cpuinfo_ia64_proc_freq)) return (machdep->mhz = mhz); readmem(xen_hyper_per_cpu(xht->cpu_data_address, xht->cpu_idxs[0]) + --- crash-4.0-3.22/xen_hyper_command.c 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/xen_hyper_command.c 2007-04-26 08:31:45.000000000 -0400 @@ -219,11 +219,19 @@ { struct xen_hyper_domain_context *dca; char buf1[XEN_HYPER_CMD_BUFSIZE]; + char buf2[XEN_HYPER_CMD_BUFSIZE]; int i; - fprintf(fp, - " DID %s ST T %%MMEM %%TMEM VCPU\n", - mkstring(buf1, VADDR_PRLEN, CENTER|RJUST, "DOMAIN")); + sprintf(buf1, " DID %s ST T ", + mkstring(buf2, VADDR_PRLEN, CENTER|RJUST, "DOMAIN")); + mkstring(&buf1[strlen(buf1)], INT_PRLEN, CENTER|RJUST, "MAXPAGE"); + strncat(buf1, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf1)-1); + mkstring(&buf1[strlen(buf1)], INT_PRLEN, CENTER|RJUST, "TOTPAGE"); + strncat(buf1, " VCPU ", XEN_HYPER_CMD_BUFSIZE-strlen(buf1)-1); + mkstring(&buf1[strlen(buf1)], VADDR_PRLEN, CENTER|RJUST, "SHARED_I"); + strncat(buf1, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf1)-1); + mkstring(&buf1[strlen(buf1)], LONG_PRLEN, CENTER|RJUST, "P2M_MFN"); + fprintf(fp, "%s\n", buf1); if (da->cnt) { for (i = 0; i < da->cnt; i++) { xen_hyper_show_doms(da->context[i]); @@ -239,11 +247,16 @@ static void xen_hyper_show_doms(struct xen_hyper_domain_context *dc) { - double mmem, tmem; char *act, *crash; uint cpuid; int type, i, j; struct xen_hyper_pcpu_context *pcc; +#if defined(X86) || defined(X86_64) + char *shared_info; +#elif defined(IA64) + char *domain_struct; + ulong pgd; +#endif char buf1[XEN_HYPER_CMD_BUFSIZE]; char buf2[XEN_HYPER_CMD_BUFSIZE]; @@ -251,6 +264,21 @@ return; } +#if defined(X86) || defined(X86_64) + shared_info = GETBUF(XEN_HYPER_SIZE(shared_info)); + if (dc->shared_info) { + if (!readmem(dc->shared_info, KVADDR, shared_info, + XEN_HYPER_SIZE(shared_info), "fill_shared_info_struct", + ACTIVE() ? (RETURN_ON_ERROR|QUIET) : RETURN_ON_ERROR)) { + error(WARNING, "cannot fill shared_info struct.\n"); + BZERO(shared_info, XEN_HYPER_SIZE(shared_info)); + } + } +#elif defined(IA64) + if ((domain_struct = xen_hyper_read_domain(dc->domain)) == NULL) { + error(FATAL, "cannot read domain.\n"); + } +#endif act = NULL; for_cpu_indexes(i, cpuid) { @@ -269,14 +297,6 @@ } else { crash = " "; } - if (dc->max_pages == -1) { - mmem = 100; - } else { - mmem = (double)(dc->max_pages) / - (double)(xht->max_page) * (double)100; - } - tmem = (double)(dc->tot_pages) / - (double)(xht->max_page) * (double)100; sprintf(buf1, "%s%s%5d ", act, crash, dc->domain_id); mkstring(&buf1[strlen(buf1)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, (char *)(dc->domain)); strncat(buf1, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf1)-1); @@ -284,15 +304,40 @@ xen_hyper_domain_state_string(dc, buf2, !VERBOSE)); sprintf(&buf1[strlen(buf1)], "%s ", xen_hyper_domain_context_to_type(dc, &type, buf2, !VERBOSE)); - - sprintf(buf2, "%3.1f", mmem); - mkstring(&buf1[strlen(buf1)], 5, RJUST, buf2); + mkstring(&buf1[strlen(buf1)], INT_PRLEN, CENTER|INT_HEX|RJUST, + MKSTR((long)(dc->max_pages))); strncat(buf1, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf1)-1); + mkstring(&buf1[strlen(buf1)], INT_PRLEN, CENTER|INT_HEX|RJUST, + MKSTR((long)(dc->tot_pages))); + sprintf(&buf1[strlen(buf1)], " %3d ", dc->vcpu_cnt); + mkstring(&buf1[strlen(buf1)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, + MKSTR(dc->shared_info)); + strncat(buf1, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf1)-1); +#if defined(X86) || defined(X86_64) + if (dc->shared_info) { + mkstring(&buf1[strlen(buf1)], LONG_PRLEN, CENTER|LONG_HEX|RJUST, + MKSTR(ULONG(shared_info + + XEN_HYPER_OFFSET(shared_info_arch) + + XEN_HYPER_OFFSET(arch_shared_info_pfn_to_mfn_frame_list_list))) + ); + } else { + mkstring(&buf1[strlen(buf1)], LONG_PRLEN, CENTER|RJUST, "----"); + } + FREEBUF(shared_info); +#elif defined(IA64) + pgd = ULONG(domain_struct + XEN_HYPER_OFFSET(domain_arch) + + XEN_HYPER_OFFSET(arch_domain_mm) + + XEN_HYPER_OFFSET(mm_struct_pgd)); + if (pgd) { + mkstring(&buf1[strlen(buf1)], LONG_PRLEN, + CENTER|LONG_HEX|RJUST, + MKSTR((pgd - DIRECTMAP_VIRT_START) >> machdep->pageshift)); + } else { + mkstring(&buf1[strlen(buf1)], LONG_PRLEN, CENTER|RJUST, "----"); + } +#endif - sprintf(buf2, "%3.1f", tmem); - mkstring(&buf1[strlen(buf1)], 5, RJUST, buf2); - - fprintf(fp, "%s %3d\n", buf1, dc->vcpu_cnt); + fprintf(fp, "%s\n", buf1); } /* @@ -413,7 +458,7 @@ note_buf = dic->ELF_Prstatus_ptr; sprintf(buf, "%5d ", dic->pcpu_id); mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, - (char *)(dic->note)); + MKSTR(dic->note)); pid = INT(note_buf + XEN_HYPER_OFFSET(ELF_Prstatus_pr_pid)); sprintf(&buf[strlen(buf)], " %5d ", pid); @@ -456,11 +501,11 @@ tv_usec = LONG(addr + XEN_HYPER_OFFSET(ELF_Timeval_tv_sec) + XEN_HYPER_OFFSET(ELF_Timeval_tv_usec)); - mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, - (char *)(tv_sec)); + mkstring(&buf[strlen(buf)], LONG_PRLEN, CENTER|LONG_HEX|RJUST, + MKSTR(tv_sec)); strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); - mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, - (char *)(tv_usec)); + mkstring(&buf[strlen(buf)], LONG_PRLEN, CENTER|LONG_HEX|RJUST, + MKSTR(tv_usec)); fprintf(fp, "%s\n", buf); } } @@ -477,7 +522,7 @@ } fprintf(fp, " %s = ", xhregt[i]); fprintf(fp, "0x%s\n", - mkstring(buf, VADDR_PRLEN, LONG_HEX|LJUST, (char *)(*regs))); + mkstring(buf, LONG_PRLEN, LONG_HEX|LJUST, MKSTR(*regs))); } } } @@ -668,13 +713,13 @@ } sprintf(buf, "%s%5d ", act, pcc->processor_id); - mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, (char *)(pcc->pcpu)); + mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, MKSTR(pcc->pcpu)); strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, - (char *)(pcc->current_vcpu)); + MKSTR(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)); + MKSTR(pcc->init_tss)); fprintf(fp, "%s\n", buf); if (flag & XEN_HYPER_PCPUS_REGS) { fprintf(fp, "Register information:\n"); @@ -796,26 +841,30 @@ 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"); + if (XEN_HYPER_VALID_MEMBER(schedule_data_tick)) { + strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); + mkstring(&buf[strlen(buf)], LONG_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)); + MKSTR(schc->schedule_data)); strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, - (char *)(schc->curr)); + MKSTR(schc->sched_priv)); strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, - (char *)(schc->idle)); + MKSTR(schc->curr)); strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, - (char *)(schc->tick)); + MKSTR(schc->idle)); + if (XEN_HYPER_VALID_MEMBER(schedule_data_tick)) { + strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); + mkstring(&buf[strlen(buf)], LONG_PRLEN, CENTER|LONG_HEX|RJUST, + MKSTR(schc->tick)); + } fprintf(fp, "%s\n", buf); if (flag & XEN_HYPER_SCHED_VERBOSE) { ; @@ -943,7 +992,7 @@ (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))); + (buf1, "%s\n", convert_time(xen_hyper_get_uptime_hyper(), buf2))); /* !!!Display a version here if it can be found. */ XEN_HYPER_PRI_CONST(fp, len, "MACHINE: ", flag); if (strlen(uts->machine)) { @@ -1176,7 +1225,7 @@ } sprintf(buf, "%s%s%5d %5d ", act, crash, vcc->vcpu_id, vcc->processor); mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, - (char *)(vcc->vcpu)); + MKSTR(vcc->vcpu)); strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); xen_hyper_vcpu_state_string(vcc, &buf[strlen(buf)], !VERBOSE); strncat(buf, " ", XEN_HYPER_CMD_BUFSIZE-strlen(buf)-1); @@ -1187,7 +1236,7 @@ sprintf(&buf[strlen(buf)], " %5d ", domid); } mkstring(&buf[strlen(buf)], VADDR_PRLEN, CENTER|LONG_HEX|RJUST, - (char *)(vcc->domain)); + MKSTR(vcc->domain)); fprintf(fp, "%s\n", buf); } @@ -1277,6 +1326,12 @@ if (!dc) { *type = XEN_HYPER_DOMAIN_TYPE_INVALID; return NULL; + } else if (dc->domain_id == XEN_HYPER_DOMID_IO) { + *type = XEN_HYPER_DOMAIN_TYPE_IO; + sprintf(buf, verbose ? "dom_io" : "O"); + } else if (dc->domain_id == XEN_HYPER_DOMID_XEN) { + *type = XEN_HYPER_DOMAIN_TYPE_XEN; + sprintf(buf, verbose ? "dom_xen" : "X"); } else if (dc == xhdt->idle_domain) { *type = XEN_HYPER_DOMAIN_TYPE_IDLE; sprintf(buf, verbose ? "idle domain" : "I"); @@ -1285,7 +1340,7 @@ sprintf(buf, verbose ? "domain 0" : "0"); } else { *type = XEN_HYPER_DOMAIN_TYPE_GUEST; - sprintf(buf, verbose ? "guest domain" : "G"); + sprintf(buf, verbose ? "domain U" : "U"); } return buf; } --- crash-4.0-3.22/xen_hyper_global_data.c 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/xen_hyper_global_data.c 2007-04-26 08:31:45.000000000 -0400 @@ -131,12 +131,14 @@ " 1. the DOMAIN-ID.", " 2. the struct domain pointer.", " 3. the domain state (SH, DY, CP, PO, PA, RU).", -" 4. the TYPE of domain(I, 0, G).", -" 5. displays percentage of page of max_pages member of domain", -" for max_page of system.", -" 6. displays percentage of page of tot_pages member of domain" , -" for max_page of system." , +" 4. the TYPE of domain.", +" (O:dom_io, X:dom_xen, I:idle domain, 0:domain 0, U:domain U).", +" 5. displays max_pages member of domain.", +" 6. displays tot_pages member of domain.", " 7. a number of vcpu that domain is assigned.", +" 8. the shared_info pointer of domain.", +" 9. frame containing list of mfns containing list of mfns" , +" containing p2m.", " ", " The active domain on each CPU will be highlighted by an angle ", " bracket (\">\") preceding its information.", @@ -145,11 +147,13 @@ "\nEXAMPLES", " Show the domain status of all:\n", " %s> doms", -" DID DOMAIN ST T %MMEM %TMEM VCPU", -" 32767 ffbfc080 RU I 0.0 0.0 2", -" >* 0 ff198080 RU 0 100.0 79.0 2", -" 4 ffbee080 RU G 6.3 6.3 2", -" 5 ff186080 RU G 6.3 6.3 2", +" DID DOMAIN ST T MAXPAGE TOTPAGE VCPU SHARED_I P2M_MFN", +" 32753 ffbf8080 RU O 0 0 0 0 ----", +" 32754 ffbfa080 RU X 0 0 0 0 ----", +" 32767 ffbfc080 RU I 0 0 2 0 ----", +" >* 0 ff198080 RU 0 ffffffff 32900 2 ff194000 18d0", +" 4 ffbee080 RU U 4000 4000 2 ff18d000 3eb92", +" 5 ff186080 RU U 4000 4000 2 ff184000 298d3", " %s>", NULL }; @@ -313,7 +317,7 @@ char *xen_hyper_help_sched[] = { "pcpus", "display scheduler information", -"[-r][-t] [pcpu-id] ...", +"[-v] [pcpu-id] ...", " This command displays scheduler information for selected, or all, cpus" , " pcpu-id a physical cpu id.", " -v display verbosely scheduler information.", --- crash-4.0-3.22/xen_hyper_dump_tables.c 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/xen_hyper_dump_tables.c 2007-04-26 08:31:45.000000000 -0400 @@ -217,12 +217,16 @@ (buf, "%d\n", xht->vcpus)); XEN_HYPER_PRI(fp, len, "domains: ", buf, flag, (buf, "%d\n", xht->domains)); + XEN_HYPER_PRI(fp, len, "sys_pages: ", buf, flag, + (buf, "%lu\n", xht->sys_pages)); XEN_HYPER_PRI(fp, len, "crashing_cpu: ", buf, flag, (buf, "%d\n", xht->crashing_cpu)); XEN_HYPER_PRI(fp, len, "crashing_vcc: ", buf, flag, (buf, "%p\n", xht->crashing_vcc)); XEN_HYPER_PRI(fp, len, "max_page: ", buf, flag, (buf, "%lu\n", xht->max_page)); + XEN_HYPER_PRI(fp, len, "total_pages: ", buf, flag, + (buf, "%lu\n", xht->total_pages)); XEN_HYPER_PRI(fp, len, "cpumask: ", buf, flag, (buf, "%p\n", xht->cpumask)); if (verbose && xht->cpumask) { @@ -327,6 +331,10 @@ (buf, "%d\n", xhdt->context_array_cnt)); XEN_HYPER_PRI(fp, len, "running_domains: ", buf, flag, (buf, "%lu\n", xhdt->running_domains)); + XEN_HYPER_PRI(fp, len, "dom_io: ", buf, flag, + (buf, "%p\n", xhdt->dom_io)); + XEN_HYPER_PRI(fp, len, "dom_xen: ", buf, flag, + (buf, "%p\n", xhdt->dom_xen)); XEN_HYPER_PRI(fp, len, "dom0: ", buf, flag, (buf, "%p\n", xhdt->dom0)); XEN_HYPER_PRI(fp, len, "idle_domain: ", buf, flag, @@ -488,6 +496,10 @@ (buf, "%ld\n", xen_hyper_size_table.ELF_Gregset)); XEN_HYPER_PRI(fp, len, "ELF_Timeval: ", buf, flag, (buf, "%ld\n", xen_hyper_size_table.ELF_Timeval)); + XEN_HYPER_PRI(fp, len, "arch_domain: ", buf, flag, + (buf, "%ld\n", xen_hyper_size_table.arch_domain)); + XEN_HYPER_PRI(fp, len, "arch_shared_info: ", buf, flag, + (buf, "%ld\n", xen_hyper_size_table.arch_shared_info)); XEN_HYPER_PRI(fp, len, "cpu_info: ", buf, flag, (buf, "%ld\n", xen_hyper_size_table.cpu_info)); XEN_HYPER_PRI(fp, len, "cpu_time: ", buf, flag, @@ -516,12 +528,18 @@ (buf, "%ld\n", xen_hyper_size_table.crash_xen_info_t)); XEN_HYPER_PRI(fp, len, "domain: ", buf, flag, (buf, "%ld\n", xen_hyper_size_table.domain)); +#ifdef IA64 + XEN_HYPER_PRI(fp, len, "mm_struct: ", buf, flag, + (buf, "%ld\n", xen_hyper_size_table.mm_struct)); +#endif 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, "shared_info: ", buf, flag, + (buf, "%ld\n", xen_hyper_size_table.shared_info)); XEN_HYPER_PRI(fp, len, "timer: ", buf, flag, (buf, "%ld\n", xen_hyper_size_table.timer)); XEN_HYPER_PRI(fp, len, "tss_struct: ", buf, flag, @@ -543,7 +561,7 @@ char buf[XEN_HYPER_CMD_BUFSIZE]; int len, flag; - len = 37; + len = 45; flag = XEN_HYPER_PRI_R; XEN_HYPER_PRI(fp, len, "ELF_Prstatus_pr_info: ", buf, flag, @@ -577,6 +595,18 @@ XEN_HYPER_PRI(fp, len, "ELF_Timeval_tv_usec: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.ELF_Timeval_tv_usec)); +#ifdef IA64 + XEN_HYPER_PRI(fp, len, "arch_domain_mm: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.arch_domain_mm)); +#endif + + XEN_HYPER_PRI(fp, len, "arch_shared_info_max_pfn: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.arch_shared_info_max_pfn)); + XEN_HYPER_PRI(fp, len, "arch_shared_info_pfn_to_mfn_frame_list_list: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.arch_shared_info_pfn_to_mfn_frame_list_list)); + XEN_HYPER_PRI(fp, len, "arch_shared_info_nmi_reason: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.arch_shared_info_nmi_reason)); + 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, @@ -649,6 +679,11 @@ XEN_HYPER_PRI(fp, len, "domain_vcpu: ", buf, flag, (buf, "%ld\n", xen_hyper_offset_table.domain_vcpu)); +#ifdef IA64 + XEN_HYPER_PRI(fp, len, "mm_struct_pgd: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.mm_struct_pgd)); +#endif + 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, @@ -691,6 +726,15 @@ 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, "shared_info_vcpu_info: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.shared_info_vcpu_info)); + XEN_HYPER_PRI(fp, len, "shared_info_evtchn_pending: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.shared_info_evtchn_pending)); + XEN_HYPER_PRI(fp, len, "shared_info_evtchn_mask: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.shared_info_evtchn_mask)); + XEN_HYPER_PRI(fp, len, "shared_info_arch: ", buf, flag, + (buf, "%ld\n", xen_hyper_offset_table.shared_info_arch)); + 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, --- crash-4.0-3.22/defs.h 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/defs.h 2007-04-25 09:33:34.000000000 -0400 @@ -3489,6 +3489,7 @@ #define BT_FROM_CALLFRAME (0x1000ULL) #define BT_EFRAME_SEARCH (0x2000ULL) #define BT_SPECULATE (0x4000ULL) +#define BT_FRAMESIZE_DISABLE (BT_SPECULATE) #define BT_RESCHEDULE (0x8000ULL) #define BT_SCHEDULE (BT_RESCHEDULE) #define BT_RET_FROM_SMP_FORK (0x10000ULL) --- crash-4.0-3.22/xen_hyper_defs.h 2007-04-26 16:56:43.000000000 -0400 +++ crash-4.0-4.1/xen_hyper_defs.h 2007-04-26 08:31:45.000000000 -0400 @@ -74,10 +74,15 @@ #define PERCPU_ADDR (DEFAULT_SHAREDINFO_ADDR - PERCPU_PAGE_SIZE) #define DIRECTMAP_VIRT_START (0xf000000000000000) #define DIRECTMAP_VIRT_END PERCPU_ADDR +#define VIRT_FRAME_TABLE_ADDR (0xf300000000000000) +#define VIRT_FRAME_TABLE_END (0xf400000000000000) #define PERCPU_VIRT_ADDR(vaddr) \ (((vaddr) >= PERCPU_ADDR) && ((vaddr) < PERCPU_ADDR + PERCPU_PAGE_SIZE)) +#define FRAME_TABLE_VIRT_ADDR(vaddr) \ + ((vaddr) >= VIRT_FRAME_TABLE_ADDR && (vaddr) < VIRT_FRAME_TABLE_END) + #undef IA64_RBS_OFFSET #define IA64_RBS_OFFSET ((XEN_HYPER_SIZE(vcpu) + 15) & ~15) @@ -147,6 +152,9 @@ /* * Domain */ +/* Prepared domain ID. */ +#define XEN_HYPER_DOMID_IO (0x7FF1U) +#define XEN_HYPER_DOMID_XEN (0x7FF2U) /* Domain flags (domain_flags). */ /* Is this domain privileged? */ #define XEN_HYPER__DOMF_privileged 0 @@ -266,9 +274,11 @@ #define XEN_HYPER_STR_PCPU (0x32) #define XEN_HYPER_STR_INVALID (-1) -#define XEN_HYPER_DOMAIN_TYPE_IDLE (0x0) -#define XEN_HYPER_DOMAIN_TYPE_DOM0 (0x1) -#define XEN_HYPER_DOMAIN_TYPE_GUEST (0x2) +#define XEN_HYPER_DOMAIN_TYPE_IO (0x0) +#define XEN_HYPER_DOMAIN_TYPE_XEN (0x1) +#define XEN_HYPER_DOMAIN_TYPE_IDLE (0x2) +#define XEN_HYPER_DOMAIN_TYPE_DOM0 (0x3) +#define XEN_HYPER_DOMAIN_TYPE_GUEST (0x4) #define XEN_HYPER_DOMAIN_TYPE_INVALID (-1) #define XEN_HYPER_ELF_NOTE_FILL_T_NOTE (0) @@ -343,6 +353,7 @@ int pcpus; /* number of physical cpu */ int vcpus; /* number of virtual cpu */ int domains; /* number of domain */ + ulong sys_pages; int crashing_cpu; struct xen_hyper_vcpu_context *crashing_vcc; ulong max_page; @@ -410,6 +421,8 @@ struct xen_hyper_domain_context *context_array; int context_array_cnt; ulong running_domains; + struct xen_hyper_domain_context *dom_io; + struct xen_hyper_domain_context *dom_xen; struct xen_hyper_domain_context *dom0; struct xen_hyper_domain_context *idle_domain; struct xen_hyper_domain_context *curr_domain; @@ -503,6 +516,8 @@ long ELF_Signifo; long ELF_Gregset; long ELF_Timeval; + long arch_domain; + long arch_shared_info; long cpu_info; long cpu_time; long cpu_user_regs; @@ -517,9 +532,13 @@ long crash_xen_core_t; /* elf note v3 */ long crash_xen_info_t; /* elf note v3 */ long domain; +#ifdef IA64 + long mm_struct; +#endif long note_buf_t; /* elf note v1 */ long schedule_data; long scheduler; + long shared_info; long timer; long tss_struct; long vcpu; @@ -545,6 +564,14 @@ long ELF_Prstatus_pr_fpvalid; long ELF_Timeval_tv_sec; long ELF_Timeval_tv_usec; + /* arch_domain */ +#ifdef IA64 + long arch_domain_mm; +#endif + /* arch_shared_info */ + long arch_shared_info_max_pfn; + long arch_shared_info_pfn_to_mfn_frame_list_list; + long arch_shared_info_nmi_reason; /* cpu_info */ long cpu_info_guest_cpu_user_regs; long cpu_info_processor_id; @@ -588,6 +615,11 @@ long domain_domain_flags; long domain_evtchn; long domain_vcpu; + long domain_arch; +#ifdef IA64 + /* mm_struct */ + long mm_struct_pgd; +#endif /* schedule_data */ long schedule_data_schedule_lock; long schedule_data_curr; @@ -610,6 +642,11 @@ long scheduler_adjust; long scheduler_dump_settings; long scheduler_dump_cpu_state; + /* shared_info */ + long shared_info_vcpu_info; + long shared_info_evtchn_pending; + long shared_info_evtchn_mask; + long shared_info_arch; /* timer */ long timer_expires; long timer_cpu; @@ -755,7 +792,7 @@ /* * Prototype */ -ulonglong get_uptime_hyper(void); +ulonglong xen_hyper_get_uptime_hyper(void); /* * x86