qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: peter.maydell@linaro.org
Cc: qemu-devel@nongnu.org, "Alex Bennée" <alex.bennee@linaro.org>
Subject: [Qemu-devel] [RISU PATCH v6 06/10] risu: add simple trace and replay support
Date: Wed, 21 Jun 2017 16:42:40 +0100	[thread overview]
Message-ID: <20170621154244.28309-7-alex.bennee@linaro.org> (raw)
In-Reply-To: <20170621154244.28309-1-alex.bennee@linaro.org>

This adds a very dumb and easily breakable trace and replay support. In
--master mode the various risu ops trigger a write of register/memory
state into a binary file which can be played back to an apprentice.
Currently there is no validation of the image source so feeding the
wrong image will fail straight away.

The trace files will get very big for any appreciable sized test file
and this will be addressed in later patches.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
v5
  - re-base without formatting fixes
  - unify socket/file descriptors
  - count number of signals/checkpoint
  - all output from sigjmp (not in signhandlers)
v4
  - fix formatting mess
  - abort() instead of reporting de-sync
  - don't fake return for compiler
v3
  - fix options parsing
  - re-factored so no need for copy & paste
v2
  - moved read/write functions into main risu.c
  - cleaned up formatting
  - report more in apprentice --trace mode
---
 risu.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 93 insertions(+), 19 deletions(-)

diff --git a/risu.c b/risu.c
index 88e586c..93c274b 100644
--- a/risu.c
+++ b/risu.c
@@ -30,7 +30,9 @@
 
 void *memblock;
 
-int apprentice_socket, master_socket;
+int apprentice_fd, master_fd;
+int trace;
+size_t signal_count;
 
 sigjmp_buf jmpbuf;
 
@@ -41,24 +43,60 @@ int test_fp_exc;
 
 int read_sock(void *ptr, size_t bytes)
 {
-    return recv_data_pkt(master_socket, ptr, bytes);
+    return recv_data_pkt(master_fd, ptr, bytes);
+}
+
+int write_trace(void *ptr, size_t bytes)
+{
+    size_t res = write(master_fd, ptr, bytes);
+    return (res == bytes) ? 0 : 1;
 }
 
 void respond_sock(int r)
 {
-    send_response_byte(master_socket, r);
+    send_response_byte(master_fd, r);
 }
 
 /* Apprentice function */
 
 int write_sock(void *ptr, size_t bytes)
 {
-    return send_data_pkt(apprentice_socket, ptr, bytes);
+    return send_data_pkt(apprentice_fd, ptr, bytes);
+}
+
+int read_trace(void *ptr, size_t bytes)
+{
+    size_t res = read(apprentice_fd, ptr, bytes);
+    return (res == bytes) ? 0 : 1;
+}
+
+void respond_trace(int r)
+{
+    switch (r) {
+    case 0: /* test ok */
+    case 1: /* end of test */
+        break;
+    default:
+        /* mismatch - if tracing we need to report, otherwise barf */
+        if (!trace) {
+           abort();
+        }
+        break;
+    }
 }
 
 void master_sigill(int sig, siginfo_t *si, void *uc)
 {
-    switch (recv_and_compare_register_info(read_sock, respond_sock, uc)) {
+    int r;
+    signal_count++;
+
+    if (trace) {
+        r = send_register_info(write_trace, uc);
+    } else {
+        r = recv_and_compare_register_info(read_sock, respond_sock, uc);
+    }
+
+    switch (r) {
     case 0:
         /* match OK */
         advance_pc(uc);
@@ -71,7 +109,16 @@ void master_sigill(int sig, siginfo_t *si, void *uc)
 
 void apprentice_sigill(int sig, siginfo_t *si, void *uc)
 {
-    switch (send_register_info(write_sock, uc)) {
+    int r;
+    signal_count++;
+
+    if (trace) {
+        r = recv_and_compare_register_info(read_trace, respond_trace, uc);
+    } else {
+        r = send_register_info(write_sock, uc);
+    }
+
+    switch (r) {
     case 0:
         /* match OK */
         advance_pc(uc);
@@ -81,6 +128,9 @@ void apprentice_sigill(int sig, siginfo_t *si, void *uc)
         exit(0);
     default:
         /* mismatch */
+        if (trace) {
+            siglongjmp(jmpbuf, 1);
+        }
         exit(1);
     }
 }
@@ -136,12 +186,17 @@ void load_image(const char *imgfile)
     image_start_address = (uintptr_t) addr;
 }
 
-int master(int sock)
+int master(void)
 {
     if (sigsetjmp(jmpbuf, 1)) {
-        return report_match_status();
+        close(master_fd);
+        if (trace) {
+            fprintf(stderr, "trace complete after %zd checkpoints\n", signal_count);
+            return 0;
+        } else {
+            return report_match_status();
+        }
     }
-    master_socket = sock;
     set_sigill_handler(&master_sigill);
     fprintf(stderr, "starting master image at 0x%"PRIxPTR"\n",
             image_start_address);
@@ -151,9 +206,13 @@ int master(int sock)
     exit(1);
 }
 
-int apprentice(int sock)
+int apprentice(void)
 {
-    apprentice_socket = sock;
+    if (sigsetjmp(jmpbuf, 1)) {
+        close(apprentice_fd);
+        fprintf(stderr, "finished early after %zd checkpoints\n", signal_count);
+        return report_match_status();
+    }
     set_sigill_handler(&apprentice_sigill);
     fprintf(stderr, "starting apprentice image at 0x%"PRIxPTR"\n",
             image_start_address);
@@ -175,6 +234,7 @@ void usage(void)
     fprintf(stderr, "between master and apprentice risu processes.\n\n");
     fprintf(stderr, "Options:\n");
     fprintf(stderr, "  --master          Be the master (server)\n");
+    fprintf(stderr, "  -t, --trace=FILE  Record/playback trace file\n");
     fprintf(stderr,
             "  -h, --host=HOST   Specify master host machine (apprentice only)"
             "\n");
@@ -189,7 +249,7 @@ int main(int argc, char **argv)
     uint16_t port = 9191;
     char *hostname = "localhost";
     char *imgfile;
-    int sock;
+    char *trace_fn = NULL;
 
     /* TODO clean this up later */
 
@@ -203,7 +263,7 @@ int main(int argc, char **argv)
             {0, 0, 0, 0}
         };
         int optidx = 0;
-        int c = getopt_long(argc, argv, "h:p:", longopts, &optidx);
+        int c = getopt_long(argc, argv, "h:p:t:", longopts, &optidx);
         if (c == -1) {
             break;
         }
@@ -214,6 +274,12 @@ int main(int argc, char **argv)
             /* flag set by getopt_long, do nothing */
             break;
         }
+        case 't':
+        {
+            trace_fn = optarg;
+            trace = 1;
+            break;
+        }
         case 'h':
         {
             hostname = optarg;
@@ -245,12 +311,20 @@ int main(int argc, char **argv)
     load_image(imgfile);
 
     if (ismaster) {
-        fprintf(stderr, "master port %d\n", port);
-        sock = master_connect(port);
-        return master(sock);
+        if (trace) {
+            master_fd = open(trace_fn, O_WRONLY|O_CREAT, S_IRWXU);
+        } else {
+            fprintf(stderr, "master port %d\n", port);
+            master_fd = master_connect(port);
+        }
+        return master();
     } else {
-        fprintf(stderr, "apprentice host %s port %d\n", hostname, port);
-        sock = apprentice_connect(hostname, port);
-        return apprentice(sock);
+        if (trace) {
+            apprentice_fd = open(trace_fn, O_RDONLY);
+        } else {
+            fprintf(stderr, "apprentice host %s port %d\n", hostname, port);
+            apprentice_fd = apprentice_connect(hostname, port);
+        }
+        return apprentice();
     }
 }
-- 
2.13.0

  parent reply	other threads:[~2017-06-21 15:42 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-21 15:42 [Qemu-devel] [RISU PATCH v6 00/10] Record/replay patches Alex Bennée
2017-06-21 15:42 ` [Qemu-devel] [RISU PATCH v6 01/10] README: document the coding style used for risu Alex Bennée
2017-06-21 15:42 ` [Qemu-devel] [RISU PATCH v6 02/10] build-all-archs: support cross building via docker Alex Bennée
2017-06-29 13:07   ` Philippe Mathieu-Daudé
2017-06-29 13:27     ` Alex Bennée
2017-06-29 13:43       ` Philippe Mathieu-Daudé
2017-06-21 15:42 ` [Qemu-devel] [RISU PATCH v6 03/10] risu: a bit more verbosity when starting Alex Bennée
2017-06-21 15:42 ` [Qemu-devel] [RISU PATCH v6 04/10] risu: paramterise send/receive functions Alex Bennée
2017-06-21 15:42 ` [Qemu-devel] [RISU PATCH v6 05/10] risu: add header to trace stream Alex Bennée
2017-06-21 15:42 ` Alex Bennée [this message]
2017-06-21 15:42 ` [Qemu-devel] [RISU PATCH v6 07/10] risu: handle trace through stdin/stdout Alex Bennée
2017-06-21 15:42 ` [Qemu-devel] [RISU PATCH v6 08/10] risu: add support compressed tracefiles Alex Bennée
2017-06-21 15:42 ` [Qemu-devel] [RISU PATCH v6 09/10] new: record_traces.sh helper script Alex Bennée
2017-06-21 15:42 ` [Qemu-devel] [RISU PATCH v6 10/10] new: run_risu.sh script Alex Bennée
2017-06-29 11:15 ` [Qemu-devel] [RISU PATCH v6 00/10] Record/replay patches Peter Maydell

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=20170621154244.28309-7-alex.bennee@linaro.org \
    --to=alex.bennee@linaro.org \
    --cc=peter.maydell@linaro.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).