qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Alex Bennée" <alex.bennee@linaro.org>
To: Peter Maydell <peter.maydell@linaro.org>
Cc: QEMU Developers <qemu-devel@nongnu.org>
Subject: Re: [Qemu-devel] [RISU PATCH v4 07/10] risu: add simple trace and replay support
Date: Tue, 06 Jun 2017 15:19:02 +0100	[thread overview]
Message-ID: <87poehci7d.fsf@linaro.org> (raw)
In-Reply-To: <CAFEAcA-8wW2qBEsk-awcsRsaAKdnERmYTfwsoSMBwQqiahDfnw@mail.gmail.com>


Peter Maydell <peter.maydell@linaro.org> writes:

> On 2 June 2017 at 17:08, Alex Bennée <alex.bennee@linaro.org> wrote:
>> 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>
>>
>> ---
>> 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 | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
>>  1 file changed, 84 insertions(+), 13 deletions(-)
>>
>> diff --git a/risu.c b/risu.c
>> index 22571cd..137cbbf 100644
>> --- a/risu.c
>> +++ b/risu.c
>> @@ -31,6 +31,7 @@
>>  void *memblock = 0;
>>
>>  int apprentice_socket, master_socket;
>> +int trace_file = 0;
>>
>>  sigjmp_buf jmpbuf;
>>
>> @@ -40,10 +41,12 @@ int test_fp_exc = 0;
>>  long executed_tests = 0;
>>  void report_test_status(void *pc)
>>  {
>> -   executed_tests += 1;
>> -   if (executed_tests % 100 == 0) {
>> -      fprintf(stderr,"Executed %ld test instructions (pc=%p)\r",
>> -              executed_tests, pc);
>> +   if (ismaster || trace_file) {
>> +      executed_tests += 1;
>> +      if (executed_tests % 100 == 0) {
>> +         fprintf(stderr,"Executed %ld test instructions (pc=%p)\r",
>> +                 executed_tests, pc);
>> +      }
>>     }
>>  }
>>
>> @@ -54,6 +57,12 @@ int read_sock(void *ptr, size_t bytes)
>>     return recv_data_pkt(master_socket, ptr, bytes);
>>  }
>>
>> +int write_trace(void *ptr, size_t bytes)
>> +{
>> +   size_t res = write(trace_file, ptr, bytes);
>> +   return (res == bytes) ? 0 : 1;
>> +}
>> +
>>  void respond_sock(int r)
>>  {
>>     send_response_byte(master_socket, r);
>> @@ -66,9 +75,36 @@ int write_sock(void *ptr, size_t bytes)
>>     return send_data_pkt(apprentice_socket, ptr, bytes);
>>  }
>>
>> +int read_trace(void *ptr, size_t bytes)
>> +{
>> +   size_t res = read(trace_file, 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:
>> +         /* should not get here */
>> +         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;
>> +
>> +   if (trace_file) {
>> +      r = send_register_info(write_trace, uc);
>> +   } else {
>> +      r = recv_and_compare_register_info(read_sock, respond_sock, uc);
>> +   }
>
> It's a bit weird that in the trace file case we send the data
> from the master, but in the normal case we send it from
> the apprentice end.

It seemed the natural way round (master generating the "gold" stream
that the apprentice checks). I could switch it or make the apprentice
responsible for checking it's own work?

>
>> +
>> +   switch (r)
>>     {
>>        case 0:
>>           /* match OK */
>> @@ -82,7 +118,15 @@ 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;
>> +
>> +   if (trace_file) {
>> +      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 */
>> @@ -94,6 +138,9 @@ void apprentice_sigill(int sig, siginfo_t *si, void *uc)
>>           exit(0);
>>        default:
>>           /* mismatch */
>> +         if (trace_file) {
>> +            report_match_status();
>> +         }
>
> report_match_status() uses stdio, you can't call it from a signal
> handler.

Oops, I'll sigjmp.

>
>>           exit(1);
>>     }
>>  }
>> @@ -155,7 +202,13 @@ int master(int sock)
>>  {
>>     if (sigsetjmp(jmpbuf, 1))
>>     {
>> -      return report_match_status();
>> +      if (trace_file) {
>> +         close(trace_file);
>> +         fprintf(stderr,"\nDone...\n");
>> +         return 0;
>> +      } else {
>> +         return report_match_status();
>> +      }
>>     }
>>     master_socket = sock;
>>     set_sigill_handler(&master_sigill);
>> @@ -184,6 +237,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");
>>     fprintf(stderr, "  -p, --port=PORT   Specify the port to connect to/listen on (default 9191)\n");
>>  }
>> @@ -194,6 +248,7 @@ int main(int argc, char **argv)
>>     uint16_t port = 9191;
>>     char *hostname = "localhost";
>>     char *imgfile;
>> +   char *trace_fn = NULL;
>>     int sock;
>>
>>     // TODO clean this up later
>> @@ -204,13 +259,14 @@ int main(int argc, char **argv)
>>           {
>>              { "help", no_argument, 0, '?'},
>>              { "master", no_argument, &ismaster, 1 },
>> +            { "trace", required_argument, 0, 't' },
>>              { "host", required_argument, 0, 'h' },
>>              { "port", required_argument, 0, 'p' },
>>              { "test-fp-exc", no_argument, &test_fp_exc, 1 },
>>              { 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;
>> @@ -223,6 +279,11 @@ int main(int argc, char **argv)
>>              /* flag set by getopt_long, do nothing */
>>              break;
>>           }
>> +         case 't':
>> +         {
>> +           trace_fn = optarg;
>> +           break;
>> +         }
>>           case 'h':
>>           {
>>              hostname = optarg;
>> @@ -253,17 +314,27 @@ int main(int argc, char **argv)
>>     }
>>
>>     load_image(imgfile);
>> -
>> +
>>     if (ismaster)
>>     {
>> -      fprintf(stderr, "master port %d\n", port);
>> -      sock = master_connect(port);
>> +      if (trace_fn)
>> +      {
>> +         trace_file = open(trace_fn, O_WRONLY|O_CREAT, S_IRWXU);
>> +      } else {
>> +         fprintf(stderr, "master port %d\n", port);
>> +         sock = master_connect(port);
>> +      }
>>        return master(sock);
>
> Doesn't this call master() with an uninitialized sock if
> the trace file is in use ?

Hmm yes I can clean that up.

>
>>     }
>>     else
>>     {
>> -      fprintf(stderr, "apprentice host %s port %d\n", hostname, port);
>> -      sock = apprentice_connect(hostname, port);
>> +      if (trace_fn)
>> +      {
>> +         trace_file = open(trace_fn, O_RDONLY);
>> +      } else {
>> +         fprintf(stderr, "apprentice host %s port %d\n", hostname, port);
>> +         sock = apprentice_connect(hostname, port);
>> +      }
>>        return apprentice(sock);
>>     }
>>  }
>> --
>> 2.13.0
>>
>
> thanks
> -- PMM


--
Alex Bennée

  reply	other threads:[~2017-06-06 14:18 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-02 16:08 [Qemu-devel] [RISU PATCH v4 00/10] record/replay patches Alex Bennée
2017-06-02 16:08 ` [Qemu-devel] [RISU PATCH v4 01/10] .gitignore: ignore build directories Alex Bennée
2017-06-06  9:51   ` Peter Maydell
2017-06-02 16:08 ` [Qemu-devel] [RISU PATCH v4 02/10] build-all-archs: support cross building via docker Alex Bennée
2017-06-02 16:08 ` [Qemu-devel] [RISU PATCH v4 03/10] build-all-archs: support --static flag Alex Bennée
2017-06-02 16:08 ` [Qemu-devel] [RISU PATCH v4 04/10] risu: a bit more verbosity when running Alex Bennée
2017-06-06  9:55   ` Peter Maydell
2017-06-02 16:08 ` [Qemu-devel] [RISU PATCH v4 05/10] risu: paramterise send/receive functions Alex Bennée
2017-06-06  9:57   ` Peter Maydell
2017-06-06 10:13     ` Alex Bennée
2017-06-06 11:37       ` Peter Maydell
2017-06-02 16:08 ` [Qemu-devel] [RISU PATCH v4 06/10] risu: add header to trace stream Alex Bennée
2017-06-02 16:08 ` [Qemu-devel] [RISU PATCH v4 07/10] risu: add simple trace and replay support Alex Bennée
2017-06-06 13:39   ` Peter Maydell
2017-06-06 14:19     ` Alex Bennée [this message]
2017-06-06 14:32       ` Peter Maydell
2017-06-02 16:08 ` [Qemu-devel] [RISU PATCH v4 08/10] risu: add support compressed tracefiles Alex Bennée
2017-06-06 13:45   ` Peter Maydell
2017-06-06 14:24     ` Alex Bennée
2017-06-02 16:08 ` [Qemu-devel] [RISU PATCH v4 09/10] new: record_traces.sh helper script Alex Bennée
2017-06-06 13:47   ` Peter Maydell
2017-06-06 14:25     ` Alex Bennée
2017-06-02 16:08 ` [Qemu-devel] [RISU PATCH v4 10/10] new: run_risu.sh script Alex Bennée

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=87poehci7d.fsf@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).