const char *help;
} term_cmd_t;
-static CharDriverState *monitor_hd;
+#define MAX_MON 4
+static CharDriverState *monitor_hd[MAX_MON];
+static int hide_banner;
static term_cmd_t term_cmds[];
static term_cmd_t info_cmds[];
void term_flush(void)
{
+ int i;
if (term_outbuf_index > 0) {
- qemu_chr_write(monitor_hd, term_outbuf, term_outbuf_index);
+ for (i = 0; i < MAX_MON; i++)
+ if (monitor_hd[i] && monitor_hd[i]->focus == 0)
+ qemu_chr_write(monitor_hd[i], term_outbuf, term_outbuf_index);
term_outbuf_index = 0;
}
}
va_end(ap);
}
+void term_print_filename(const char *filename)
+{
+ int i;
+
+ for (i = 0; filename[i]; i++) {
+ switch (filename[i]) {
+ case ' ':
+ case '"':
+ case '\\':
+ term_printf("\\%c", filename[i]);
+ break;
+ case '\t':
+ term_printf("\\t");
+ break;
+ case '\r':
+ term_printf("\\r");
+ break;
+ case '\n':
+ term_printf("\\n");
+ break;
+ default:
+ term_printf("%c", filename[i]);
+ break;
+ }
+ }
+}
+
static int monitor_fprintf(FILE *stream, const char *fmt, ...)
{
va_list ap;
help_cmd(name);
}
-static void do_commit(void)
+static void do_commit(const char *device)
{
- int i;
-
+ int i, all_devices;
+
+ all_devices = !strcmp(device, "all");
for (i = 0; i < MAX_DISKS; i++) {
if (bs_table[i]) {
- bdrv_commit(bs_table[i]);
+ if (all_devices ||
+ !strcmp(bdrv_get_device_name(bs_table[i]), device))
+ bdrv_commit(bs_table[i]);
}
}
}
term_printf("%s\n", QEMU_VERSION);
}
+static void do_info_name(void)
+{
+ if (qemu_name)
+ term_printf("%s\n", qemu_name);
+}
+
static void do_info_block(void)
{
bdrv_info();
}
}
+#if defined(TARGET_PPC)
+/* XXX: not implemented in other targets */
+static void do_info_cpu_stats (void)
+{
+ CPUState *env;
+
+ env = mon_get_cpu();
+ cpu_dump_statistics(env, NULL, &monitor_fprintf, 0);
+}
+#endif
+
static void do_quit(void)
{
exit(0);
cpu_set_log(mask);
}
-static void do_savevm(const char *filename)
-{
- if (qemu_savevm(filename) < 0)
- term_printf("I/O error when saving VM to '%s'\n", filename);
-}
-
-static void do_loadvm(const char *filename)
-{
- if (qemu_loadvm(filename) < 0)
- term_printf("I/O error when loading VM from '%s'\n", filename);
-}
-
static void do_stop(void)
{
vm_stop(EXCP_INTERRUPT);
}
#ifdef CONFIG_GDBSTUB
-static void do_gdbserver(int has_port, int port)
+static void do_gdbserver(const char *port)
{
- if (!has_port)
+ if (!port)
port = DEFAULT_GDBSTUB_PORT;
if (gdbserver_start(port) < 0) {
- qemu_printf("Could not open gdbserver socket on port %d\n", port);
+ qemu_printf("Could not open gdbserver socket on port '%s'\n", port);
} else {
- qemu_printf("Waiting gdb connection on port %d\n", port);
+ qemu_printf("Waiting gdb connection on port '%s'\n", port);
}
}
#endif
term_printf("\n");
}
+static void do_memory_save(unsigned int valh, unsigned int vall,
+ uint32_t size, const char *filename)
+{
+ FILE *f;
+ target_long addr = GET_TLONG(valh, vall);
+ uint32_t l;
+ CPUState *env;
+ uint8_t buf[1024];
+
+ env = mon_get_cpu();
+ if (!env)
+ return;
+
+ f = fopen(filename, "wb");
+ if (!f) {
+ term_printf("could not open '%s'\n", filename);
+ return;
+ }
+ while (size != 0) {
+ l = sizeof(buf);
+ if (l > size)
+ l = size;
+ cpu_memory_rw_debug(env, addr, buf, l, 0);
+ fwrite(buf, 1, l, f);
+ addr += l;
+ size -= l;
+ }
+ fclose(f);
+}
+
static void do_sum(uint32_t start, uint32_t size)
{
uint32_t addr;
static term_cmd_t term_cmds[] = {
{ "help|?", "s?", do_help,
"[cmd]", "show the help" },
- { "commit", "", do_commit,
- "", "commit changes to the disk images (if -snapshot is used)" },
+ { "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 media (use -f to force it)" },
+ "[-f] device", "eject a removable medium (use -f to force it)" },
{ "change", "BF", do_change,
- "device filename", "change a removable media" },
+ "device filename", "change a removable medium" },
{ "screendump", "F", do_screen_dump,
"filename", "save screen into PPM image 'filename'" },
{ "log", "s", do_log,
"item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
- { "savevm", "F", do_savevm,
- "filename", "save the whole virtual machine state to 'filename'" },
- { "loadvm", "F", do_loadvm,
- "filename", "restore the whole virtual machine state from 'filename'" },
+ { "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", "i?", do_gdbserver,
+ { "gdbserver", "s?", do_gdbserver,
"[port]", "start gdbserver session (default port=1234)", },
#endif
{ "x", "/l", do_memory_dump,
"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]",
#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'", },
{ NULL, NULL, },
};
{ "profile", "", do_info_profile,
"", "show profiling information", },
{ "capture", "", do_info_capture,
- "show capture information" },
+ "", "show capture information" },
+ { "snapshots", "", do_info_snapshots,
+ "", "show the currently saved VM snapshots" },
+ { "mice", "", do_info_mice,
+ "", "show which guest mouse is receiving events" },
+ { "vnc", "", do_info_vnc,
+ "", "show the vnc server status"},
+ { "name", "", do_info_name,
+ "", "show the current VM name" },
+#if defined(TARGET_PPC)
+ { "cpustats", "", do_info_cpu_stats,
+ "", "show CPU statistics", },
+#endif
{ NULL, NULL, },
};
readline_start("(qemu) ", 0, monitor_handle_command1, NULL);
}
+static void term_event(void *opaque, int event)
+{
+ if (event != CHR_EVENT_RESET)
+ return;
+
+ if (!hide_banner)
+ term_printf("QEMU %s monitor - type 'help' for more information\n",
+ QEMU_VERSION);
+ monitor_start_input();
+}
+
+static int is_first_init = 1;
+
void monitor_init(CharDriverState *hd, int show_banner)
{
- monitor_hd = hd;
- if (show_banner) {
- term_printf("QEMU %s monitor - type 'help' for more information\n",
- QEMU_VERSION);
+ int i;
+
+ if (is_first_init) {
+ for (i = 0; i < MAX_MON; i++) {
+ monitor_hd[i] = NULL;
+ }
+ is_first_init = 0;
}
- qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL);
- monitor_start_input();
+ for (i = 0; i < MAX_MON; i++) {
+ if (monitor_hd[i] == NULL) {
+ monitor_hd[i] = hd;
+ break;
+ }
+ }
+
+ hide_banner = !show_banner;
+
+ qemu_chr_add_handlers(hd, term_can_read, term_read, term_event, NULL);
}
/* XXX: use threads ? */
void monitor_readline(const char *prompt, int is_password,
char *buf, int buf_size)
{
+ int i;
+
if (is_password) {
- qemu_chr_send_event(monitor_hd, CHR_EVENT_FOCUS);
+ for (i = 0; i < MAX_MON; i++)
+ if (monitor_hd[i] && monitor_hd[i]->focus == 0)
+ qemu_chr_send_event(monitor_hd[i], CHR_EVENT_FOCUS);
}
readline_start(prompt, is_password, monitor_readline_cb, NULL);
monitor_readline_buf = buf;