From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58023) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X1wAE-0001BC-4g for qemu-devel@nongnu.org; Tue, 01 Jul 2014 07:24:01 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1X1wA2-00019R-LW for qemu-devel@nongnu.org; Tue, 01 Jul 2014 07:23:54 -0400 Received: from mail.ispras.ru ([83.149.199.45]:33164) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1X1wA2-00019L-9y for qemu-devel@nongnu.org; Tue, 01 Jul 2014 07:23:42 -0400 Received: from PASHAISP (unknown [80.250.189.177]) by mail.ispras.ru (Postfix) with ESMTPSA id 88559540157 for ; Tue, 1 Jul 2014 15:23:41 +0400 (MSK) From: "Pavel Dovgaluk" Date: Tue, 1 Jul 2014 15:23:42 +0400 Message-ID: <007c01cf951e$ea84e850$bf8eb8f0$@Dovgaluk@ispras.ru> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Language: ru Subject: [Qemu-devel] [RFC PATCH 08/22] Monitor commands List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: 'QEMU Developers' This patch adds commands to control replay from the monitor. Signed-off-by: Pavel Dovgalyuk --- diff --git a/hmp-commands.hx b/hmp-commands.hx index d0943b1..01d3203 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1629,6 +1629,107 @@ passed since 1970, i.e. unix epoch. ETEXI { + .name = "replay_info", + .args_type = "", + .params = "", + .help = "show replay info", + .mhandler.cmd = do_replay_info, + }, + +STEXI +@item replay_info +Shows information about replay process. + +ETEXI + + { + .name = "replay_break", + .args_type = "step:l", + .params = "step", + .help = "stop replaying at the specified replay step", + .mhandler.cmd = do_replay_break, + }, + +STEXI +@item replay_break @var{step} +Stops replaying at the specified @var{step}. + +ETEXI + + { + .name = "replay_seek", + .args_type = "step:l", + .params = "step", + .help = "seeks the replay log to the specified step", + .mhandler.cmd = do_replay_seek, + }, + +STEXI +@item replay_seek @var{step} +Seeks the replay log to the specified @var{step}. + +ETEXI + + { + .name = "replay_events", + .args_type = "", + .params = "", + .help = "shows events information from the replay log", + .mhandler.cmd = do_replay_events, + }, + +STEXI +@item replay_events +Shows events information from the replay log. + +ETEXI + + { + .name = "replay_get_packet", + .args_type = "id:l", + .params = "id", + .help = "retrieves network packet with the specified id", + .mhandler.cmd = do_replay_get_packet, + }, + +STEXI +@item replay_get_packet @var{id} +Retrieves network packet with the specified @var{id}. + +ETEXI + + { + .name = "replay_set_packet", + .args_type = "id:l,bytes:s?", + .params = "id [bytes]", + .help = "sets network packet with the specified id", + .mhandler.cmd = do_replay_set_packet, + }, + +STEXI +@item replay_set_packet @var{id} @var{bytes} +Sets network packet with the specified @var{id}. While replaying, +packet with this @var{id} will be replaced with the specified @var{bytes}. +If @var{bytes} parameter is not specified, removes packet from storage of +modified packets. + +ETEXI + + { + .name = "replay_change", + .args_type = "", + .params = "", + .help = "start execution of VM from the current replay step", + .mhandler.cmd = do_replay_change, + }, + +STEXI +@item replay_change +Start execution of VM from the current replay step. + +ETEXI + + { .name = "chardev-add", .args_type = "args:s", .params = "args", diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index 3d6929d..d569a83 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -40,6 +40,7 @@ int monitor_handle_fd_param2(Monitor *mon, const char *fdname, Error **errp); void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) GCC_FMT_ATTR(2, 0); void monitor_printf(Monitor *mon, const char *fmt, ...) GCC_FMT_ATTR(2, 3); +void monitor_print_bytes(Monitor *mon, const uint8_t *bytes, uint64_t length); void monitor_flush(Monitor *mon); int monitor_set_cpu(int cpu_index); int monitor_get_cpu_index(void); diff --git a/monitor.c b/monitor.c index 799131b..7bd4770 --- a/monitor.c +++ b/monitor.c @@ -73,6 +73,8 @@ #include "block/qapi.h" #include "qapi/qmp-event.h" #include "qapi-event.h" +#include "replay/replay.h" +#include "block/block_int.h" /* for pic/irq_info */ #if defined(TARGET_SPARC) @@ -379,6 +381,13 @@ void monitor_printf(Monitor *mon, const char *fmt, ...) va_end(ap); } +void monitor_print_bytes(Monitor *mon, const uint8_t *bytes, uint64_t length) +{ + while (length--) { + monitor_printf(mon, "%02x", *bytes++); + } +} + static int GCC_FMT_ATTR(2, 3) monitor_fprintf(FILE *stream, const char *fmt, ...) { @@ -1173,6 +1182,135 @@ static void do_watchdog_action(Monitor *mon, const QDict *qdict) } } +static void do_replay_info(Monitor *mon, const QDict *qdict) +{ + switch (replay_mode) { + case REPLAY_NONE: + monitor_printf(mon, "Replay is not enabled.\n"); + break; + case REPLAY_SAVE: + monitor_printf(mon, "Saving replay log.\n"); + monitor_printf(mon, "\tcurrent step: %" PRId64 "\n", replay_get_current_step()); + break; + case REPLAY_PLAY: + monitor_printf(mon, "Playing replay log "); + switch (replay_get_play_submode()) { + case REPLAY_PLAY_NORMAL: + monitor_printf(mon, "(normal mode)"); + break; + case REPLAY_PLAY_REVERSE: + monitor_printf(mon, "(reverse debugging)"); + break; + case REPLAY_PLAY_CHANGED: + monitor_printf(mon, "(changed mode)"); + break; + case REPLAY_PLAY_GOTO: + monitor_printf(mon, "(preparing to trace)"); + break; + case REPLAY_PLAY_UNKNOWN: + default: + monitor_printf(mon, "(unknown mode)"); + break; + } + monitor_printf(mon, "\n"); + monitor_printf(mon, "\tcurrent step: %" PRId64 "\n", replay_get_current_step()); + break; + } +} + + +static void do_replay_break(Monitor *mon, const QDict *qdict) +{ + if (replay_mode == REPLAY_PLAY) { + if (replay_get_play_submode() == REPLAY_PLAY_CHANGED) { + monitor_printf(mon, "Cannot stop on the specified step in the changed mode.\n"); + return; + } + uint64_t step = qdict_get_int(qdict, "step"); + if (step >= replay_get_current_step()) { + monitor_printf(mon, "Setting break at step: %" PRId64 "\n", step); + replay_set_break(step); + } else { + monitor_printf(mon, "Cannot stop on the preceding step.\n"); + } + } else { + monitor_printf(mon, "You can stop at the specific step only in PLAY mode.\n"); + } +} + + +static void do_replay_seek(Monitor *mon, const QDict *qdict) +{ + if (replay_mode == REPLAY_PLAY) { + uint64_t step = qdict_get_int(qdict, "step"); + if (replay_seek_step(step)) { + monitor_printf(mon, "Seeking for step: %" PRId64 "\n", step); + if (!runstate_is_running()) { + vm_start(); + } + } else { + monitor_printf(mon, "Cannot seek to the specified step.\n"); + } + } else { + monitor_printf(mon, "You can go to the specific step only in PLAY mode.\n"); + } +} + + +static void do_replay_events(Monitor *mon, const QDict *qdict) +{ + if (replay_mode == REPLAY_PLAY) { + replay_events(mon); + } else { + monitor_printf(mon, "You can go to the specific step only in PLAY mode.\n"); + } +} + + +static void do_replay_get_packet(Monitor *mon, const QDict *qdict) +{ + if (replay_mode == REPLAY_PLAY) { + if (!replay_get_packet(mon, qdict_get_int(qdict, "id"))) { + monitor_printf(mon, "Could not print specified network packet.\n"); + } + } else { + monitor_printf(mon, "You can print packets only in replay PLAY mode.\n"); + } +} + + +static void do_replay_set_packet(Monitor *mon, const QDict *qdict) +{ + if (replay_mode == REPLAY_PLAY) { + if (!replay_set_packet(mon, qdict_get_int(qdict, "id"), qdict_get_try_str(qdict, "bytes"))) { + monitor_printf(mon, "Could not set specified network packet.\n"); + } + } else { + monitor_printf(mon, "You can set packets' contents only in replay PLAY mode.\n"); + } +} + +static void do_replay_change(Monitor *mon, const QDict *qdict) +{ + if (replay_mode != REPLAY_PLAY) { + monitor_printf(mon, "Cannot start execution from non-play mode.\n"); + return; + } + + if (!replay_icount) { + monitor_printf(mon, "Execution can only be started from icount mode.\n"); + return; + } + + if (runstate_is_running()) { + monitor_printf(mon, "Stop the VM before executing of replay_change.\n"); + return; + } + + replay_change(mon); +} + + static void monitor_printc(Monitor *mon, int c) { monitor_printf(mon, "'"); @@ -2596,6 +2734,7 @@ int monitor_handle_fd_param2(Monitor *mon, const char *fdname, Error **errp) return fd; } + /* Please update hmp-commands.hx when adding or changing commands */ static mon_cmd_t info_cmds[] = { {