All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Pavel Dovgaluk" <Pavel.Dovgaluk@ispras.ru>
To: 'QEMU Developers' <qemu-devel@nongnu.org>
Subject: [Qemu-devel] [RFC PATCH 08/22] Monitor commands
Date: Tue, 1 Jul 2014 15:23:42 +0400	[thread overview]
Message-ID: <007c01cf951e$ea84e850$bf8eb8f0$@Dovgaluk@ispras.ru> (raw)

This patch adds commands to control replay from the monitor.

Signed-off-by: Pavel Dovgalyuk <pavel.dovgaluk@gmail.com>
---

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[] = {
     {

             reply	other threads:[~2014-07-01 11:24 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-01 11:23 Pavel Dovgaluk [this message]
2014-07-01 17:33 ` [Qemu-devel] [RFC PATCH 08/22] Monitor commands Eric Blake
2014-07-02 10:43   ` Pavel Dovgaluk
2014-07-02 10:54     ` Kirill Batuzov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='007c01cf951e$ea84e850$bf8eb8f0$@Dovgaluk@ispras.ru' \
    --to=pavel.dovgaluk@ispras.ru \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.