X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=monitor.c;h=d9257ffb3337af585a713100da154d3fe8c2cdea;hb=502a53952d574717bdb626b651b16cadacab46f4;hp=4e6f6fabac6edf6694fe0cc9b631c0ae697c53f0;hpb=d24b15a8d8f59c79d9183e8d884867a64cb003bb;p=qemu diff --git a/monitor.c b/monitor.c index 4e6f6fa..d9257ff 100644 --- a/monitor.c +++ b/monitor.c @@ -64,6 +64,8 @@ static int term_outbuf_index; static void monitor_start_input(void); +CPUState *mon_cpu = NULL; + void term_flush(void) { if (term_outbuf_index > 0) { @@ -196,39 +198,82 @@ static void do_info_version(void) term_printf("%s\n", QEMU_VERSION); } -static void do_info_network(void) +static void do_info_block(void) { - int i, j; - NetDriverState *nd; - - for(i = 0; i < nb_nics; i++) { - nd = &nd_table[i]; - term_printf("%d: ifname=%s macaddr=", i, nd->ifname); - for(j = 0; j < 6; j++) { - if (j > 0) - term_printf(":"); - term_printf("%02x", nd->macaddr[j]); + bdrv_info(); +} + +/* get the current CPU defined by the user */ +int mon_set_cpu(int cpu_index) +{ + CPUState *env; + + for(env = first_cpu; env != NULL; env = env->next_cpu) { + if (env->cpu_index == cpu_index) { + mon_cpu = env; + return 0; } - term_printf("\n"); } + return -1; } - -static void do_info_block(void) + +CPUState *mon_get_cpu(void) { - bdrv_info(); + if (!mon_cpu) { + mon_set_cpu(0); + } + return mon_cpu; } static void do_info_registers(void) { + CPUState *env; + env = mon_get_cpu(); + if (!env) + return; #ifdef TARGET_I386 - cpu_dump_state(cpu_single_env, NULL, monitor_fprintf, + cpu_dump_state(env, NULL, monitor_fprintf, X86_DUMP_FPU); #else - cpu_dump_state(cpu_single_env, NULL, monitor_fprintf, + cpu_dump_state(env, NULL, monitor_fprintf, 0); #endif } +static void do_info_cpus(void) +{ + CPUState *env; + + /* just to set the default cpu if not already done */ + mon_get_cpu(); + + for(env = first_cpu; env != NULL; env = env->next_cpu) { + term_printf("%c CPU #%d:", + (env == mon_cpu) ? '*' : ' ', + env->cpu_index); +#if defined(TARGET_I386) + term_printf(" pc=0x" TARGET_FMT_lx, env->eip + env->segs[R_CS].base); + if (env->hflags & HF_HALTED_MASK) + term_printf(" (halted)"); +#elif defined(TARGET_PPC) + term_printf(" nip=0x" TARGET_FMT_lx, env->nip); + if (env->halted) + term_printf(" (halted)"); +#elif defined(TARGET_SPARC) + term_printf(" pc=0x" TARGET_FMT_lx " npc=0x" TARGET_FMT_lx, env->pc, env->npc); + if (env->halted) + term_printf(" (halted)"); +#endif + term_printf("\n"); + } +} + +static void do_cpu_set(int index) +{ + if (mon_set_cpu(index) < 0) + term_printf("Invalid CPU index\n"); +} + static void do_info_jit(void) { dump_exec_info(NULL, monitor_fprintf); @@ -311,7 +356,7 @@ static void do_change(const char *device, const char *filename) static void do_screen_dump(const char *filename) { - vga_screen_dump(filename); + vga_hw_screen_dump(filename); } static void do_log(const char *items) @@ -395,6 +440,7 @@ static void term_printc(int c) static void memory_dump(int count, int format, int wsize, target_ulong addr, int is_physical) { + CPUState *env; int nb_per_line, l, line_size, i, max_digits, len; uint8_t buf[16]; uint64_t v; @@ -402,6 +448,9 @@ static void memory_dump(int count, int format, int wsize, if (format == 'i') { int flags; flags = 0; + env = mon_get_cpu(); + if (!env && !is_physical) + return; #ifdef TARGET_I386 if (wsize == 2) { flags = 1; @@ -410,11 +459,19 @@ static void memory_dump(int count, int format, int wsize, } else { /* as default we use the current CS size */ flags = 0; - if (!(cpu_single_env->segs[R_CS].flags & DESC_B_MASK)) - flags = 1; + if (env) { +#ifdef TARGET_X86_64 + if ((env->efer & MSR_EFER_LMA) && + (env->segs[R_CS].flags & DESC_L_MASK)) + flags = 2; + else +#endif + if (!(env->segs[R_CS].flags & DESC_B_MASK)) + flags = 1; + } } #endif - monitor_disas(addr, count, is_physical, flags); + monitor_disas(env, addr, count, is_physical, flags); return; } @@ -451,7 +508,10 @@ static void memory_dump(int count, int format, int wsize, if (is_physical) { cpu_physical_memory_rw(addr, buf, l, 0); } else { - cpu_memory_rw_debug(cpu_single_env, addr, buf, l, 0); + env = mon_get_cpu(); + if (!env) + break; + cpu_memory_rw_debug(env, addr, buf, l, 0); } i = 0; while (i < l) { @@ -606,6 +666,8 @@ static const KeyDef key_defs[] = { { 0x09, "8" }, { 0x0a, "9" }, { 0x0b, "0" }, + { 0x0c, "minus" }, + { 0x0d, "equal" }, { 0x0e, "backspace" }, { 0x0f, "tab" }, @@ -655,6 +717,24 @@ static const KeyDef key_defs[] = { { 0x45, "num_lock" }, { 0x46, "scroll_lock" }, + { 0xb5, "kp_divide" }, + { 0x37, "kp_multiply" }, + { 0x4a, "kp_substract" }, + { 0x4e, "kp_add" }, + { 0x9c, "kp_enter" }, + { 0x53, "kp_decimal" }, + + { 0x52, "kp_0" }, + { 0x4f, "kp_1" }, + { 0x50, "kp_2" }, + { 0x51, "kp_3" }, + { 0x4b, "kp_4" }, + { 0x4c, "kp_5" }, + { 0x4d, "kp_6" }, + { 0x47, "kp_7" }, + { 0x48, "kp_8" }, + { 0x49, "kp_9" }, + { 0x56, "<" }, { 0x57, "f11" }, @@ -680,11 +760,18 @@ static const KeyDef key_defs[] = { static int get_keycode(const char *key) { const KeyDef *p; + char *endp; + int ret; for(p = key_defs; p->name != NULL; p++) { if (!strcmp(key, p->name)) return p->keycode; } + if (strstart(key, "0x", NULL)) { + ret = strtoul(key, &endp, 0); + if (*endp == '\0' && ret >= 0x01 && ret <= 0xff) + return ret; + } return -1; } @@ -790,10 +877,14 @@ static void print_pte(uint32_t addr, uint32_t pte, uint32_t mask) static void tlb_info(void) { - CPUState *env = cpu_single_env; + CPUState *env; int l1, l2; uint32_t pgd, pde, pte; + env = mon_get_cpu(); + if (!env) + return; + if (!(env->cr[0] & CR0_PG_MASK)) { term_printf("PG disabled\n"); return; @@ -844,10 +935,14 @@ static void mem_print(uint32_t *pstart, int *plast_prot, static void mem_info(void) { - CPUState *env = cpu_single_env; + CPUState *env; int l1, l2, prot, last_prot; uint32_t pgd, pde, pte, start, end; + env = mon_get_cpu(); + if (!env) + return; + if (!(env->cr[0] & CR0_PG_MASK)) { term_printf("PG disabled\n"); return; @@ -885,6 +980,81 @@ static void mem_info(void) } #endif +static void do_info_kqemu(void) +{ +#ifdef USE_KQEMU + CPUState *env; + int val; + val = 0; + env = mon_get_cpu(); + if (!env) { + term_printf("No cpu initialized yet"); + return; + } + val = env->kqemu_enabled; + term_printf("kqemu support: "); + switch(val) { + default: + case 0: + term_printf("disabled\n"); + break; + case 1: + term_printf("enabled for user code\n"); + break; + case 2: + term_printf("enabled for user and kernel code\n"); + break; + } +#else + term_printf("kqemu support: not compiled\n"); +#endif +} + +#ifdef CONFIG_PROFILER + +int64_t kqemu_time; +int64_t qemu_time; +int64_t kqemu_exec_count; +int64_t dev_time; +int64_t kqemu_ret_int_count; +int64_t kqemu_ret_excp_count; +int64_t kqemu_ret_intr_count; + +static void do_info_profile(void) +{ + int64_t total; + total = qemu_time; + if (total == 0) + total = 1; + term_printf("async time %lld (%0.3f)\n", + dev_time, dev_time / (double)ticks_per_sec); + term_printf("qemu time %lld (%0.3f)\n", + qemu_time, qemu_time / (double)ticks_per_sec); + term_printf("kqemu time %lld (%0.3f %0.1f%%) count=%lld int=%lld excp=%lld intr=%lld\n", + kqemu_time, kqemu_time / (double)ticks_per_sec, + kqemu_time / (double)total * 100.0, + kqemu_exec_count, + kqemu_ret_int_count, + kqemu_ret_excp_count, + kqemu_ret_intr_count); + qemu_time = 0; + kqemu_time = 0; + kqemu_exec_count = 0; + dev_time = 0; + kqemu_ret_int_count = 0; + kqemu_ret_excp_count = 0; + kqemu_ret_intr_count = 0; +#ifdef USE_KQEMU + kqemu_record_dump(); +#endif +} +#else +static void do_info_profile(void) +{ + term_printf("Internal profiler not compiled\n"); +} +#endif + static term_cmd_t term_cmds[] = { { "help|?", "s?", do_help, "[cmd]", "show the help" }, @@ -931,6 +1101,12 @@ static term_cmd_t term_cmds[] = { "", "send system power down event" }, { "sum", "ii", do_sum, "addr size", "compute the checksum of a memory region" }, + { "usb_add", "s", do_usb_add, + "device", "add USB device (e.g. 'host:bus.addr' or 'host:vendor_id:product_id')" }, + { "usb_del", "s", do_usb_del, + "device", "remove USB device 'bus.addr'" }, + { "cpu", "i", do_cpu_set, + "index", "set the default CPU" }, { NULL, NULL, }, }; @@ -943,6 +1119,8 @@ static term_cmd_t info_cmds[] = { "", "show the block devices" }, { "registers", "", do_info_registers, "", "show the cpu registers" }, + { "cpus", "", do_info_cpus, + "", "show infos for each CPU" }, { "history", "", do_info_history, "", "show the command line history", }, { "irq", "", irq_info, @@ -959,6 +1137,14 @@ static term_cmd_t info_cmds[] = { #endif { "jit", "", do_info_jit, "", "show dynamic compiler info", }, + { "kqemu", "", do_info_kqemu, + "", "show kqemu information", }, + { "usb", "", usb_info, + "", "show guest USB devices", }, + { "usbhost", "", usb_host_info, + "", "show host USB devices", }, + { "profile", "", do_info_profile, + "", "show profiling information", }, { NULL, NULL, }, }; @@ -980,75 +1166,105 @@ typedef struct MonitorDef { #if defined(TARGET_I386) static target_long monitor_get_pc (struct MonitorDef *md, int val) { - return cpu_single_env->eip + cpu_single_env->segs[R_CS].base; + CPUState *env = mon_get_cpu(); + if (!env) + return 0; + return env->eip + env->segs[R_CS].base; } #endif #if defined(TARGET_PPC) static target_long monitor_get_ccr (struct MonitorDef *md, int val) { + CPUState *env = mon_get_cpu(); unsigned int u; int i; + if (!env) + return 0; + u = 0; for (i = 0; i < 8; i++) - u |= cpu_single_env->crf[i] << (32 - (4 * i)); + u |= env->crf[i] << (32 - (4 * i)); return u; } static target_long monitor_get_msr (struct MonitorDef *md, int val) { - return (cpu_single_env->msr[MSR_POW] << MSR_POW) | - (cpu_single_env->msr[MSR_ILE] << MSR_ILE) | - (cpu_single_env->msr[MSR_EE] << MSR_EE) | - (cpu_single_env->msr[MSR_PR] << MSR_PR) | - (cpu_single_env->msr[MSR_FP] << MSR_FP) | - (cpu_single_env->msr[MSR_ME] << MSR_ME) | - (cpu_single_env->msr[MSR_FE0] << MSR_FE0) | - (cpu_single_env->msr[MSR_SE] << MSR_SE) | - (cpu_single_env->msr[MSR_BE] << MSR_BE) | - (cpu_single_env->msr[MSR_FE1] << MSR_FE1) | - (cpu_single_env->msr[MSR_IP] << MSR_IP) | - (cpu_single_env->msr[MSR_IR] << MSR_IR) | - (cpu_single_env->msr[MSR_DR] << MSR_DR) | - (cpu_single_env->msr[MSR_RI] << MSR_RI) | - (cpu_single_env->msr[MSR_LE] << MSR_LE); + CPUState *env = mon_get_cpu(); + if (!env) + return 0; + return (env->msr[MSR_POW] << MSR_POW) | + (env->msr[MSR_ILE] << MSR_ILE) | + (env->msr[MSR_EE] << MSR_EE) | + (env->msr[MSR_PR] << MSR_PR) | + (env->msr[MSR_FP] << MSR_FP) | + (env->msr[MSR_ME] << MSR_ME) | + (env->msr[MSR_FE0] << MSR_FE0) | + (env->msr[MSR_SE] << MSR_SE) | + (env->msr[MSR_BE] << MSR_BE) | + (env->msr[MSR_FE1] << MSR_FE1) | + (env->msr[MSR_IP] << MSR_IP) | + (env->msr[MSR_IR] << MSR_IR) | + (env->msr[MSR_DR] << MSR_DR) | + (env->msr[MSR_RI] << MSR_RI) | + (env->msr[MSR_LE] << MSR_LE); } static target_long monitor_get_xer (struct MonitorDef *md, int val) { - return (cpu_single_env->xer[XER_SO] << XER_SO) | - (cpu_single_env->xer[XER_OV] << XER_OV) | - (cpu_single_env->xer[XER_CA] << XER_CA) | - (cpu_single_env->xer[XER_BC] << XER_BC); + CPUState *env = mon_get_cpu(); + if (!env) + return 0; + return (env->xer[XER_SO] << XER_SO) | + (env->xer[XER_OV] << XER_OV) | + (env->xer[XER_CA] << XER_CA) | + (env->xer[XER_BC] << XER_BC); } static target_long monitor_get_decr (struct MonitorDef *md, int val) { - return cpu_ppc_load_decr(cpu_single_env); + CPUState *env = mon_get_cpu(); + if (!env) + return 0; + return cpu_ppc_load_decr(env); } static target_long monitor_get_tbu (struct MonitorDef *md, int val) { - return cpu_ppc_load_tbu(cpu_single_env); + CPUState *env = mon_get_cpu(); + if (!env) + return 0; + return cpu_ppc_load_tbu(env); } static target_long monitor_get_tbl (struct MonitorDef *md, int val) { - return cpu_ppc_load_tbl(cpu_single_env); + CPUState *env = mon_get_cpu(); + if (!env) + return 0; + return cpu_ppc_load_tbl(env); } #endif #if defined(TARGET_SPARC) +#ifndef TARGET_SPARC64 static target_long monitor_get_psr (struct MonitorDef *md, int val) { - return GET_PSR(cpu_single_env); + CPUState *env = mon_get_cpu(); + if (!env) + return 0; + return GET_PSR(env); } +#endif static target_long monitor_get_reg(struct MonitorDef *md, int val) { - return cpu_single_env->regwptr[val]; + CPUState *env = mon_get_cpu(); + if (!env) + return 0; + return env->regwptr[val]; } #endif @@ -1183,8 +1399,10 @@ static MonitorDef monitor_defs[] = { { "pc", offsetof(CPUState, pc) }, { "npc", offsetof(CPUState, npc) }, { "y", offsetof(CPUState, y) }, +#ifndef TARGET_SPARC64 { "psr", 0, &monitor_get_psr, }, { "wim", offsetof(CPUState, wim) }, +#endif { "tbr", offsetof(CPUState, tbr) }, { "fsr", offsetof(CPUState, fsr) }, { "f0", offsetof(CPUState, fpr[0]) }, @@ -1219,6 +1437,32 @@ static MonitorDef monitor_defs[] = { { "f29", offsetof(CPUState, fpr[29]) }, { "f30", offsetof(CPUState, fpr[30]) }, { "f31", offsetof(CPUState, fpr[31]) }, +#ifdef TARGET_SPARC64 + { "f32", offsetof(CPUState, fpr[32]) }, + { "f34", offsetof(CPUState, fpr[34]) }, + { "f36", offsetof(CPUState, fpr[36]) }, + { "f38", offsetof(CPUState, fpr[38]) }, + { "f40", offsetof(CPUState, fpr[40]) }, + { "f42", offsetof(CPUState, fpr[42]) }, + { "f44", offsetof(CPUState, fpr[44]) }, + { "f46", offsetof(CPUState, fpr[46]) }, + { "f48", offsetof(CPUState, fpr[48]) }, + { "f50", offsetof(CPUState, fpr[50]) }, + { "f52", offsetof(CPUState, fpr[52]) }, + { "f54", offsetof(CPUState, fpr[54]) }, + { "f56", offsetof(CPUState, fpr[56]) }, + { "f58", offsetof(CPUState, fpr[58]) }, + { "f60", offsetof(CPUState, fpr[60]) }, + { "f62", offsetof(CPUState, fpr[62]) }, + { "asi", offsetof(CPUState, asi) }, + { "pstate", offsetof(CPUState, pstate) }, + { "cansave", offsetof(CPUState, cansave) }, + { "canrestore", offsetof(CPUState, canrestore) }, + { "otherwin", offsetof(CPUState, otherwin) }, + { "wstate", offsetof(CPUState, wstate) }, + { "cleanwin", offsetof(CPUState, cleanwin) }, + { "fprs", offsetof(CPUState, fprs) }, +#endif #endif { NULL }, }; @@ -1230,6 +1474,7 @@ static void expr_error(const char *fmt) longjmp(expr_env, 1); } +/* return 0 if OK, -1 if not found, -2 if no CPU defined */ static int get_monitor_def(target_long *pval, const char *name) { MonitorDef *md; @@ -1240,7 +1485,10 @@ static int get_monitor_def(target_long *pval, const char *name) if (md->get_value) { *pval = md->get_value(md, md->offset); } else { - ptr = (uint8_t *)cpu_single_env + md->offset; + CPUState *env = mon_get_cpu(); + if (!env) + return -2; + ptr = (uint8_t *)env + md->offset; switch(md->type) { case MD_I32: *pval = *(int32_t *)ptr; @@ -1274,6 +1522,7 @@ static target_long expr_unary(void) { target_long n; char *p; + int ret; switch(*pch) { case '+': @@ -1323,8 +1572,11 @@ static target_long expr_unary(void) while (isspace(*pch)) pch++; *q = 0; - if (get_monitor_def(&n, buf)) + ret = get_monitor_def(&n, buf); + if (ret == -1) expr_error("unknown register"); + else if (ret == -2) + expr_error("no cpu defined"); } break; case '\0': @@ -1332,6 +1584,7 @@ static target_long expr_unary(void) n = 0; break; default: + /* XXX: 64 bit version */ n = strtoul(pch, &p, 0); if (pch == p) { expr_error("invalid char in expression"); @@ -1926,6 +2179,7 @@ void readline_find_completion(const char *cmdline) int nb_args, i, len; const char *ptype, *str; term_cmd_t *cmd; + const KeyDef *key; parse_cmdline(cmdline, &nb_args, args); #ifdef DEBUG_COMPLETION @@ -1987,6 +2241,11 @@ void readline_find_completion(const char *cmdline) for(cmd = info_cmds; cmd->name != NULL; cmd++) { cmd_completion(str, cmd->name); } + } else if (!strcmp(cmd->name, "sendkey")) { + completion_index = strlen(str); + for(key = key_defs; key->name != NULL; key++) { + cmd_completion(str, key->name); + } } break; default: