qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC PATCH 08/22] Monitor commands


From: Pavel Dovgaluk
Subject: [Qemu-devel] [RFC PATCH 08/22] Monitor commands
Date: Tue, 1 Jul 2014 15:23:42 +0400

This patch adds commands to control replay from the monitor.

Signed-off-by: Pavel Dovgalyuk <address@hidden>
---

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
address@hidden 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
address@hidden 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
address@hidden 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
address@hidden 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
address@hidden 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
address@hidden 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
address@hidden 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 via email to

[Prev in Thread] Current Thread [Next in Thread]