X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=monitor.c;h=7620bdebfe8623e5ab14a892ea138d6c2e2e83f3;hb=2313086addaf609c5f64636591818eebc213fd53;hp=d03de4f1d5612f3fa437e8051d3ecaaddfe9a506;hpb=2724b1806a63d66148cea62e1fe1cae3b417bc7e;p=qemu diff --git a/monitor.c b/monitor.c index d03de4f..7620bde 100644 --- a/monitor.c +++ b/monitor.c @@ -21,11 +21,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#include #include "hw/hw.h" +#include "hw/qdev.h" #include "hw/usb.h" #include "hw/pcmcia.h" #include "hw/pc.h" #include "hw/pci.h" +#include "hw/watchdog.h" #include "gdbstub.h" #include "net.h" #include "qemu-char.h" @@ -37,10 +40,10 @@ #include "audio/audio.h" #include "disas.h" #include "balloon.h" -#include #include "qemu-timer.h" #include "migration.h" #include "kvm.h" +#include "acl.h" //#define DEBUG //#define DEBUG_COMPLETION @@ -97,11 +100,17 @@ static void monitor_read_command(Monitor *mon, int show_prompt) readline_show_prompt(mon->rs); } -static void monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, - void *opaque) +static int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func, + void *opaque) { - readline_start(mon->rs, "Password: ", 1, readline_func, opaque); - /* prompt is printed on return from the command handler */ + if (mon->rs) { + readline_start(mon->rs, "Password: ", 1, readline_func, opaque); + /* prompt is printed on return from the command handler */ + return 0; + } else { + monitor_printf(mon, "terminal does not support password prompting\n"); + return -ENOTTY; + } } void monitor_flush(Monitor *mon) @@ -153,25 +162,25 @@ void monitor_print_filename(Monitor *mon, const char *filename) int i; for (i = 0; filename[i]; i++) { - switch (filename[i]) { - case ' ': - case '"': - case '\\': - monitor_printf(mon, "\\%c", filename[i]); - break; - case '\t': - monitor_printf(mon, "\\t"); - break; - case '\r': - monitor_printf(mon, "\\r"); - break; - case '\n': - monitor_printf(mon, "\\n"); - break; - default: - monitor_printf(mon, "%c", filename[i]); - break; - } + switch (filename[i]) { + case ' ': + case '"': + case '\\': + monitor_printf(mon, "\\%c", filename[i]); + break; + case '\t': + monitor_printf(mon, "\\t"); + break; + case '\r': + monitor_printf(mon, "\\r"); + break; + case '\n': + monitor_printf(mon, "\\n"); + break; + default: + monitor_printf(mon, "%c", filename[i]); + break; + } } } @@ -266,7 +275,7 @@ static void do_info(Monitor *mon, const char *item) static void do_info_version(Monitor *mon) { - monitor_printf(mon, "%s\n", QEMU_VERSION); + monitor_printf(mon, "%s\n", QEMU_VERSION QEMU_PKGVERSION); } static void do_info_name(Monitor *mon) @@ -311,6 +320,7 @@ static CPUState *mon_get_cpu(void) if (!cur_mon->mon_cpu) { mon_set_cpu(0); } + cpu_synchronize_state(cur_mon->mon_cpu, 0); return cur_mon->mon_cpu; } @@ -337,6 +347,7 @@ static void do_info_cpus(Monitor *mon) mon_get_cpu(); for(env = first_cpu; env != NULL; env = env->next_cpu) { + cpu_synchronize_state(env, 0); monitor_printf(mon, "%c CPU #%d:", (env == mon->mon_cpu) ? '*' : ' ', env->cpu_index); @@ -373,6 +384,8 @@ static void do_info_history(Monitor *mon) int i; const char *str; + if (!mon->rs) + return; i = 0; for(;;) { str = readline_get_history(mon->rs, i); @@ -465,17 +478,17 @@ static void change_vnc_password_cb(Monitor *mon, const char *password, static void do_change_vnc(Monitor *mon, const char *target, const char *arg) { if (strcmp(target, "passwd") == 0 || - strcmp(target, "password") == 0) { - if (arg) { + strcmp(target, "password") == 0) { + if (arg) { char password[9]; - strncpy(password, arg, sizeof(password)); - password[sizeof(password) - 1] = '\0'; + strncpy(password, arg, sizeof(password)); + password[sizeof(password) - 1] = '\0'; change_vnc_password_cb(mon, password, NULL); } else { monitor_read_password(mon, change_vnc_password_cb, NULL); } } else { - if (vnc_display_open(NULL, target) < 0) + if (vnc_display_open(NULL, target) < 0) monitor_printf(mon, "could not start VNC server on %s\n", target); } } @@ -484,9 +497,9 @@ static void do_change(Monitor *mon, const char *device, const char *target, const char *arg) { if (strcmp(device, "vnc") == 0) { - do_change_vnc(mon, target, arg); + do_change_vnc(mon, target, arg); } else { - do_change_block(mon, device, target, arg); + do_change_block(mon, device, target, arg); } } @@ -516,6 +529,17 @@ static void do_log(Monitor *mon, const char *items) cpu_set_log(mask); } +static void do_singlestep(Monitor *mon, const char *option) +{ + if (!option || !strcmp(option, "on")) { + singlestep = 1; + } else if (!strcmp(option, "off")) { + singlestep = 0; + } else { + monitor_printf(mon, "unexpected option %s\n", option); + } +} + static void do_stop(Monitor *mon) { vm_stop(EXCP_INTERRUPT); @@ -558,19 +582,27 @@ static void encrypted_bdrv_it(void *opaque, BlockDriverState *bs) } } -#ifdef CONFIG_GDBSTUB -static void do_gdbserver(Monitor *mon, const char *port) +static void do_gdbserver(Monitor *mon, const char *device) { - if (!port) - port = DEFAULT_GDBSTUB_PORT; - if (gdbserver_start(port) < 0) { - monitor_printf(mon, "Could not open gdbserver socket on port '%s'\n", - port); + if (!device) + device = "tcp::" DEFAULT_GDBSTUB_PORT; + if (gdbserver_start(device) < 0) { + monitor_printf(mon, "Could not open gdbserver on device '%s'\n", + device); + } else if (strcmp(device, "none") == 0) { + monitor_printf(mon, "Disabled gdbserver\n"); } else { - monitor_printf(mon, "Waiting gdb connection on port '%s'\n", port); + monitor_printf(mon, "Waiting for gdb connection on device '%s'\n", + device); + } +} + +static void do_watchdog_action(Monitor *mon, const char *action) +{ + if (select_watchdog_action(action) == -1) { + monitor_printf(mon, "Unknown watchdog action '%s'\n", action); } } -#endif static void monitor_printc(Monitor *mon, int c) { @@ -1343,7 +1375,7 @@ static void tlb_info(Monitor *mon) static void do_info_kqemu(Monitor *mon) { -#ifdef USE_KQEMU +#ifdef CONFIG_KQEMU CPUState *env; int val; val = 0; @@ -1384,6 +1416,25 @@ static void do_info_kvm(Monitor *mon) #endif } +static void do_info_numa(Monitor *mon) +{ + int i; + CPUState *env; + + monitor_printf(mon, "%d nodes\n", nb_numa_nodes); + for (i = 0; i < nb_numa_nodes; i++) { + monitor_printf(mon, "node %d cpus:", i); + for (env = first_cpu; env != NULL; env = env->next_cpu) { + if (env->numa_node == i) { + monitor_printf(mon, " %d", env->cpu_index); + } + } + monitor_printf(mon, "\n"); + monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i, + node_mem[i] >> 20); + } +} + #ifdef CONFIG_PROFILER int64_t kqemu_time; @@ -1420,7 +1471,7 @@ static void do_info_profile(Monitor *mon) kqemu_ret_int_count = 0; kqemu_ret_excp_count = 0; kqemu_ret_intr_count = 0; -#ifdef USE_KQEMU +#ifdef CONFIG_KQEMU kqemu_record_dump(); #endif } @@ -1445,6 +1496,7 @@ static void do_info_capture(Monitor *mon) } } +#ifdef HAS_AUDIO static void do_stop_capture(Monitor *mon, int n) { int i; @@ -1460,7 +1512,6 @@ static void do_stop_capture(Monitor *mon, int n) } } -#ifdef HAS_AUDIO static void do_wav_capture(Monitor *mon, const char *path, int has_freq, int freq, int has_bits, int bits, @@ -1497,9 +1548,13 @@ static void do_inject_nmi(Monitor *mon, int cpu_index) static void do_info_status(Monitor *mon) { - if (vm_running) - monitor_printf(mon, "VM status: running\n"); - else + if (vm_running) { + if (singlestep) { + monitor_printf(mon, "VM status: running (single step mode)\n"); + } else { + monitor_printf(mon, "VM status: running\n"); + } + } else monitor_printf(mon, "VM status: paused\n"); } @@ -1524,114 +1579,92 @@ static void do_info_balloon(Monitor *mon) monitor_printf(mon, "balloon: actual=%d\n", (int)(actual >> 20)); } -/* Please update qemu-doc.texi when adding or changing commands */ +static void do_acl(Monitor *mon, + const char *command, + const char *aclname, + const char *match, + int has_index, + int index) +{ + qemu_acl *acl; + + acl = qemu_acl_find(aclname); + if (!acl) { + monitor_printf(mon, "acl: unknown list '%s'\n", aclname); + return; + } + + if (strcmp(command, "show") == 0) { + int i = 0; + qemu_acl_entry *entry; + monitor_printf(mon, "policy: %s\n", + acl->defaultDeny ? "deny" : "allow"); + TAILQ_FOREACH(entry, &acl->entries, next) { + i++; + monitor_printf(mon, "%d: %s %s\n", i, + entry->deny ? "deny" : "allow", + entry->match); + } + } else if (strcmp(command, "reset") == 0) { + qemu_acl_reset(acl); + monitor_printf(mon, "acl: removed all rules\n"); + } else if (strcmp(command, "policy") == 0) { + if (!match) { + monitor_printf(mon, "acl: missing policy parameter\n"); + return; + } + + if (strcmp(match, "allow") == 0) { + acl->defaultDeny = 0; + monitor_printf(mon, "acl: policy set to 'allow'\n"); + } else if (strcmp(match, "deny") == 0) { + acl->defaultDeny = 1; + monitor_printf(mon, "acl: policy set to 'deny'\n"); + } else { + monitor_printf(mon, "acl: unknown policy '%s', expected 'deny' or 'allow'\n", match); + } + } else if ((strcmp(command, "allow") == 0) || + (strcmp(command, "deny") == 0)) { + int deny = strcmp(command, "deny") == 0 ? 1 : 0; + int ret; + + if (!match) { + monitor_printf(mon, "acl: missing match parameter\n"); + return; + } + + if (has_index) + ret = qemu_acl_insert(acl, deny, match, index); + else + ret = qemu_acl_append(acl, deny, match); + if (ret < 0) + monitor_printf(mon, "acl: unable to add acl entry\n"); + else + monitor_printf(mon, "acl: added rule at position %d\n", ret); + } else if (strcmp(command, "remove") == 0) { + int ret; + + if (!match) { + monitor_printf(mon, "acl: missing match parameter\n"); + return; + } + + ret = qemu_acl_remove(acl, match); + if (ret < 0) + monitor_printf(mon, "acl: no matching acl entry\n"); + else + monitor_printf(mon, "acl: removed rule at position %d\n", ret); + } else { + monitor_printf(mon, "acl: unknown command '%s'\n", command); + } +} + static const mon_cmd_t mon_cmds[] = { - { "help|?", "s?", help_cmd, - "[cmd]", "show the help" }, - { "commit", "s", do_commit, - "device|all", "commit changes to the disk images (if -snapshot is used) or backing files" }, - { "info", "s?", do_info, - "subcommand", "show various information about the system state" }, - { "q|quit", "", do_quit, - "", "quit the emulator" }, - { "eject", "-fB", do_eject, - "[-f] device", "eject a removable medium (use -f to force it)" }, - { "change", "BFs?", do_change, - "device filename [format]", "change a removable medium, optional format" }, - { "screendump", "F", do_screen_dump, - "filename", "save screen into PPM image 'filename'" }, - { "logfile", "F", do_logfile, - "filename", "output logs to 'filename'" }, - { "log", "s", do_log, - "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" }, - { "savevm", "s?", do_savevm, - "tag|id", "save a VM snapshot. If no tag or id are provided, a new snapshot is created" }, - { "loadvm", "s", do_loadvm, - "tag|id", "restore a VM snapshot from its tag or id" }, - { "delvm", "s", do_delvm, - "tag|id", "delete a VM snapshot from its tag or id" }, - { "stop", "", do_stop, - "", "stop emulation", }, - { "c|cont", "", do_cont, - "", "resume emulation", }, -#ifdef CONFIG_GDBSTUB - { "gdbserver", "s?", do_gdbserver, - "[port]", "start gdbserver session (default port=1234)", }, -#endif - { "x", "/l", do_memory_dump, - "/fmt addr", "virtual memory dump starting at 'addr'", }, - { "xp", "/l", do_physical_memory_dump, - "/fmt addr", "physical memory dump starting at 'addr'", }, - { "p|print", "/l", do_print, - "/fmt expr", "print expression value (use $reg for CPU register access)", }, - { "i", "/ii.", do_ioport_read, - "/fmt addr", "I/O port read" }, - - { "sendkey", "si?", do_sendkey, - "keys [hold_ms]", "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)" }, - { "system_reset", "", do_system_reset, - "", "reset the system" }, - { "system_powerdown", "", do_system_powerdown, - "", "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" }, - { "mouse_move", "sss?", do_mouse_move, - "dx dy [dz]", "send mouse move events" }, - { "mouse_button", "i", do_mouse_button, - "state", "change mouse button state (1=L, 2=M, 4=R)" }, - { "mouse_set", "i", do_mouse_set, - "index", "set which mouse device receives events" }, -#ifdef HAS_AUDIO - { "wavcapture", "si?i?i?", do_wav_capture, - "path [frequency bits channels]", - "capture audio to a wave file (default frequency=44100 bits=16 channels=2)" }, -#endif - { "stopcapture", "i", do_stop_capture, - "capture index", "stop capture" }, - { "memsave", "lis", do_memory_save, - "addr size file", "save to disk virtual memory dump starting at 'addr' of size 'size'", }, - { "pmemsave", "lis", do_physical_memory_save, - "addr size file", "save to disk physical memory dump starting at 'addr' of size 'size'", }, - { "boot_set", "s", do_boot_set, - "bootdevice", "define new values for the boot device list" }, -#if defined(TARGET_I386) - { "nmi", "i", do_inject_nmi, - "cpu", "inject an NMI on the given CPU", }, -#endif - { "migrate", "-ds", do_migrate, - "[-d] uri", "migrate to URI (using -d to not wait for completion)" }, - { "migrate_cancel", "", do_migrate_cancel, - "", "cancel the current VM migration" }, - { "migrate_set_speed", "s", do_migrate_set_speed, - "value", "set maximum speed (in bytes) for migrations" }, -#if defined(TARGET_I386) - { "drive_add", "ss", drive_hot_add, "pci_addr=[[:]:]\n" - "[file=file][,if=type][,bus=n]\n" - "[,unit=m][,media=d][index=i]\n" - "[,cyls=c,heads=h,secs=s[,trans=t]]\n" - "[snapshot=on|off][,cache=on|off]", - "add drive to PCI storage controller" }, - { "pci_add", "sss", pci_device_hot_add, "pci_addr=auto|[[:]:] nic|storage [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]...", "hot-add PCI device" }, - { "pci_del", "s", pci_device_hot_remove, "pci_addr=[[:]:]", "hot remove PCI device" }, - { "host_net_add", "ss", net_host_device_add, - "[tap,user,socket,vde] options", "add host VLAN client" }, - { "host_net_remove", "is", net_host_device_remove, - "vlan_id name", "remove host VLAN client" }, -#endif - { "balloon", "i", do_balloon, - "target", "request VM to change it's memory allocation (in MB)" }, - { "set_link", "ss", do_set_link, - "name [up|down]", "change the link status of a network adapter" }, +#include "qemu-monitor.h" { NULL, NULL, }, }; -/* Please update qemu-doc.texi when adding or changing commands */ +/* Please update qemu-monitor.hx when adding or changing commands */ static const mon_cmd_t info_cmds[] = { { "version", "", do_info_version, "", "show the version of QEMU" }, @@ -1671,6 +1704,8 @@ static const mon_cmd_t info_cmds[] = { "", "show KQEMU information", }, { "kvm", "", do_info_kvm, "", "show KVM information", }, + { "numa", "", do_info_numa, + "", "show NUMA information", }, { "usb", "", usb_info, "", "show guest USB devices", }, { "usbhost", "", usb_host_info, @@ -1704,6 +1739,8 @@ static const mon_cmd_t info_cmds[] = { { "migrate", "", do_info_migrate, "", "show migration status" }, { "balloon", "", do_info_balloon, "", "show balloon information" }, + { "qtree", "", do_info_qtree, + "", "show device tree" }, { NULL, NULL, }, }; @@ -1744,7 +1781,7 @@ static target_long monitor_get_ccr (const struct MonitorDef *md, int val) u = 0; for (i = 0; i < 8; i++) - u |= env->crf[i] << (32 - (4 * i)); + u |= env->crf[i] << (32 - (4 * i)); return u; } @@ -2862,6 +2899,9 @@ static void monitor_find_completion(const char *cmdline) cmd_completion(str, cmd->name); } } else if (!strcmp(cmd->name, "sendkey")) { + char *sep = strrchr(str, '-'); + if (sep) + str = sep + 1; readline_set_completion_index(cur_mon->rs, strlen(str)); for(key = key_defs; key->name != NULL; key++) { cmd_completion(str, key->name); @@ -2890,8 +2930,15 @@ static void monitor_read(void *opaque, const uint8_t *buf, int size) cur_mon = opaque; - for (i = 0; i < size; i++) - readline_handle_byte(cur_mon->rs, buf[i]); + if (cur_mon->rs) { + for (i = 0; i < size; i++) + readline_handle_byte(cur_mon->rs, buf[i]); + } else { + if (size == 0 || buf[size - 1] != 0) + monitor_printf(cur_mon, "corrupted command\n"); + else + monitor_handle_command(cur_mon, (char *)buf); + } cur_mon = old_mon; } @@ -2903,13 +2950,18 @@ static void monitor_command_cb(Monitor *mon, const char *cmdline, void *opaque) monitor_resume(mon); } -void monitor_suspend(Monitor *mon) +int monitor_suspend(Monitor *mon) { + if (!mon->rs) + return -ENOTTY; mon->suspend_cnt++; + return 0; } void monitor_resume(Monitor *mon) { + if (!mon->rs) + return; if (--mon->suspend_cnt == 0) readline_show_prompt(mon->rs); } @@ -2941,6 +2993,15 @@ static void monitor_event(void *opaque, int event) } } + +/* + * Local variables: + * c-indent-level: 4 + * c-basic-offset: 4 + * tab-width: 8 + * End: + */ + void monitor_init(CharDriverState *chr, int flags) { static int is_first_init = 1; @@ -2957,8 +3018,10 @@ void monitor_init(CharDriverState *chr, int flags) mon->flags = flags; if (mon->chr->focus != 0) mon->suspend_cnt = 1; /* mux'ed monitors start suspended */ - mon->rs = readline_init(mon, monitor_find_completion); - monitor_read_command(mon, 0); + if (flags & MONITOR_USE_READLINE) { + mon->rs = readline_init(mon, monitor_find_completion); + monitor_read_command(mon, 0); + } qemu_chr_add_handlers(chr, monitor_can_read, monitor_read, monitor_event, mon); @@ -2987,6 +3050,8 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, BlockDriverCompletionFunc *completion_cb, void *opaque) { + int err; + if (!bdrv_key_required(bs)) { if (completion_cb) completion_cb(opaque, 0); @@ -2999,5 +3064,8 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs, mon->password_completion_cb = completion_cb; mon->password_opaque = opaque; - monitor_read_password(mon, bdrv_password_cb, bs); + err = monitor_read_password(mon, bdrv_password_cb, bs); + + if (err && completion_cb) + completion_cb(opaque, err); }