All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution.
@ 2014-06-25  8:26 fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 01/13] icount: put icount variables into TimerState fred.konrad
                   ` (12 more replies)
  0 siblings, 13 replies; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

Hi everybody,

This is the fourth version of this RFC (see the changes below).

Those are the two first patch-set we have been worked on for reverse execution.

The first part is fully reviewed except the "icount: introduce icount timer"
patch maybe we can merge them?

The first series:
  icount: put icount variables into TimerState.
  migration: migrate icount fields.
  migration: make qemu_savevm_state public.
  icount: introduce icount timer.
  icount: check for icount clock deadline when cpu loop exits.
  icount: make icount extra computed on icount clock as well.
  timer: add cpu_icount_to_ns function.

are various preparation patches for reverse execution.

The last patches:
  trace-events: add reverse-execution events.
  introduce reverse execution mechanism.
  gdbstub: allow reverse execution in gdb stub.
  cpu-exec: trigger a debug request when rexec stops.
  cexe: synchronize icount on the next event.
  cexe: allow to enable reverse execution.

are reverse execution introduction.

They can be clone at: git://git.greensocs.com/qemu_cexe.git:cexe_2_3_v4

The third series will be sent as soon as possible and have some issues with
QEMU's thread as it use fork.

This implementation of reverse execution works with instruction counting:

A new clock is implemented which is icount clock. It grows each time an
instruction is executed and is totally independant of host clock.

Snapshots are taken regularly (based on icount clock) with help of migration
code and written on the disk.

When user wants to use reverse-stepi:
 * Last snapshot is reloaded.
 * A stop callback is created to be triggered at the previous instruction.

This stop callback generates a debug exception so QEMU stops in debug mode.

Command line:
 * -cexe option is added to enable reverse execution, it needs icount 1.

About non determinism in QEMU:
 * This implementation doesn't take IO in account so any IO will cause non
   determinism and break reverse execution.

 * The icount warp mechanism have been disabled when reverse execution is
   enabled so the time grow differently inside the VM.

Testing:
 * It has been tested on ARM without any IO such as network or asynchronous file
   access to keep the deterministic behaviour of icount.

Known issues:
 * On ARM stepi seems to do some additional steps which are added to icount
   counter so reverse-stepi just after stepi is broken.

 * The IO replay explained above.

Changes:
 v3 -> v4:
  * Fix icount_state_needed (As suggested by Amit).
  * Rebase.

 v2 -> v3:
  * Use trace instead of debug printfs (As suggested by Lluis).

 v1 -> v2:
  * Use subsection for icount migration (As suggested by Paolo).

  * Use with_bias parameters to get_icount instead of get_icount_wo_bias
    function (As suggested by Paolo).

KONRAD Frederic (13):
  icount: put icount variables into TimerState.
  migration: migrate icount fields.
  migration: make qemu_savevm_state public.
  icount: introduce icount timer.
  icount: check for icount clock deadline when cpu loop exits.
  icount: make icount extra computed on icount clock as well.
  timer: add cpu_icount_to_ns function.
  trace-events: add reverse-execution events.
  introduce reverse execution mechanism.
  gdbstub: allow reverse execution in gdb stub.
  cpu-exec: trigger a debug request when rexec stops.
  cexe: synchronize icount on the next event.
  cexe: allow to enable reverse execution.

 Makefile.target             |   1 +
 cpu-exec.c                  |  13 ++
 cpus.c                      | 117 ++++++++++++++---
 gdbstub.c                   |  31 ++++-
 include/qemu/timer.h        |  18 ++-
 include/reverse-execution.h |  43 +++++++
 include/sysemu/sysemu.h     |   1 +
 main-loop.c                 |  10 ++
 qemu-options.hx             |   9 ++
 qemu-timer.c                |   8 +-
 reverse-execution.c         | 306 ++++++++++++++++++++++++++++++++++++++++++++
 savevm.c                    |   2 +-
 stubs/Makefile.objs         |   1 +
 stubs/cexe-stub.c           |  32 +++++
 stubs/cpu-get-icount.c      |  10 +-
 trace-events                |   6 +
 vl.c                        |  23 +++-
 17 files changed, 605 insertions(+), 26 deletions(-)
 create mode 100644 include/reverse-execution.h
 create mode 100644 reverse-execution.c
 create mode 100644 stubs/cexe-stub.c

-- 
1.9.0

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 01/13] icount: put icount variables into TimerState.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 02/13] migration: migrate icount fields fred.konrad
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

This puts qemu_icount and qemu_icount_bias into TimerState structure to allow
them to be migrated.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
 cpus.c | 29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/cpus.c b/cpus.c
index 5e7f2cf..127de1c 100644
--- a/cpus.c
+++ b/cpus.c
@@ -102,17 +102,12 @@ static bool all_cpu_threads_idle(void)
 
 /* Protected by TimersState seqlock */
 
-/* Compensate for varying guest execution speed.  */
-static int64_t qemu_icount_bias;
 static int64_t vm_clock_warp_start;
 /* Conversion factor from emulated instructions to virtual clock ticks.  */
 static int icount_time_shift;
 /* Arbitrarily pick 1MIPS as the minimum allowable speed.  */
 #define MAX_ICOUNT_SHIFT 10
 
-/* Only written by TCG thread */
-static int64_t qemu_icount;
-
 static QEMUTimer *icount_rt_timer;
 static QEMUTimer *icount_vm_timer;
 static QEMUTimer *icount_warp_timer;
@@ -129,6 +124,11 @@ typedef struct TimersState {
     int64_t cpu_clock_offset;
     int32_t cpu_ticks_enabled;
     int64_t dummy;
+
+    /* Compensate for varying guest execution speed.  */
+    int64_t qemu_icount_bias;
+    /* Only written by TCG thread */
+    int64_t qemu_icount;
 } TimersState;
 
 static TimersState timers_state;
@@ -139,14 +139,14 @@ static int64_t cpu_get_icount_locked(void)
     int64_t icount;
     CPUState *cpu = current_cpu;
 
-    icount = qemu_icount;
+    icount = timers_state.qemu_icount;
     if (cpu) {
         if (!cpu_can_do_io(cpu)) {
             fprintf(stderr, "Bad clock read\n");
         }
         icount -= (cpu->icount_decr.u16.low + cpu->icount_extra);
     }
-    return qemu_icount_bias + (icount << icount_time_shift);
+    return timers_state.qemu_icount_bias + (icount << icount_time_shift);
 }
 
 int64_t cpu_get_icount(void)
@@ -284,7 +284,8 @@ static void icount_adjust(void)
         icount_time_shift++;
     }
     last_delta = delta;
-    qemu_icount_bias = cur_icount - (qemu_icount << icount_time_shift);
+    timers_state.qemu_icount_bias = cur_icount
+                              - (timers_state.qemu_icount << icount_time_shift);
     seqlock_write_unlock(&timers_state.vm_clock_seqlock);
 }
 
@@ -333,7 +334,7 @@ static void icount_warp_rt(void *opaque)
             int64_t delta = cur_time - cur_icount;
             warp_delta = MIN(warp_delta, delta);
         }
-        qemu_icount_bias += warp_delta;
+        timers_state.qemu_icount_bias += warp_delta;
     }
     vm_clock_warp_start = -1;
     seqlock_write_unlock(&timers_state.vm_clock_seqlock);
@@ -351,7 +352,7 @@ void qtest_clock_warp(int64_t dest)
         int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
         int64_t warp = qemu_soonest_timeout(dest - clock, deadline);
         seqlock_write_lock(&timers_state.vm_clock_seqlock);
-        qemu_icount_bias += warp;
+        timers_state.qemu_icount_bias += warp;
         seqlock_write_unlock(&timers_state.vm_clock_seqlock);
 
         qemu_clock_run_timers(QEMU_CLOCK_VIRTUAL);
@@ -1250,7 +1251,8 @@ static int tcg_cpu_exec(CPUArchState *env)
         int64_t count;
         int64_t deadline;
         int decr;
-        qemu_icount -= (cpu->icount_decr.u16.low + cpu->icount_extra);
+        timers_state.qemu_icount -= (cpu->icount_decr.u16.low
+                                    + cpu->icount_extra);
         cpu->icount_decr.u16.low = 0;
         cpu->icount_extra = 0;
         deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
@@ -1265,7 +1267,7 @@ static int tcg_cpu_exec(CPUArchState *env)
         }
 
         count = qemu_icount_round(deadline);
-        qemu_icount += count;
+        timers_state.qemu_icount += count;
         decr = (count > 0xffff) ? 0xffff : count;
         count -= decr;
         cpu->icount_decr.u16.low = decr;
@@ -1278,7 +1280,8 @@ static int tcg_cpu_exec(CPUArchState *env)
     if (use_icount) {
         /* Fold pending instructions back into the
            instruction counter, and clear the interrupt flag.  */
-        qemu_icount -= (cpu->icount_decr.u16.low + cpu->icount_extra);
+        timers_state.qemu_icount -= (cpu->icount_decr.u16.low
+                        + cpu->icount_extra);
         cpu->icount_decr.u32 = 0;
         cpu->icount_extra = 0;
     }
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 02/13] migration: migrate icount fields.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 01/13] icount: put icount variables into TimerState fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  2014-06-25 12:17   ` Juan Quintela
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 03/13] migration: make qemu_savevm_state public fred.konrad
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

This fixes a bug where qemu_icount and qemu_icount_bias are not migrated.
It adds a subsection "timer/icount" to vmstate_timers so icount is migrated only
when needed.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
Reviewed-by: Amit Shah <amit.shah@redhat.com>
---
 cpus.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/cpus.c b/cpus.c
index 127de1c..8d2ddf0 100644
--- a/cpus.c
+++ b/cpus.c
@@ -429,6 +429,26 @@ void qemu_clock_warp(QEMUClockType type)
     }
 }
 
+static bool icount_state_needed(void *opaque)
+{
+    return use_icount;
+}
+
+/*
+ * This is a subsection for icount migration.
+ */
+static const VMStateDescription icount_vmstate_timers = {
+    .name = "timer/icount",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT64(qemu_icount_bias, TimersState),
+        VMSTATE_INT64(qemu_icount, TimersState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 static const VMStateDescription vmstate_timers = {
     .name = "timer",
     .version_id = 2,
@@ -438,6 +458,14 @@ static const VMStateDescription vmstate_timers = {
         VMSTATE_INT64(dummy, TimersState),
         VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
         VMSTATE_END_OF_LIST()
+    },
+    .subsections = (VMStateSubsection[]) {
+        {
+            .vmsd = &icount_vmstate_timers,
+            .needed = icount_state_needed,
+        }, {
+            /* empty */
+        }
     }
 };
 
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 03/13] migration: make qemu_savevm_state public.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 01/13] icount: put icount variables into TimerState fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 02/13] migration: migrate icount fields fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  2014-06-25 12:18   ` Juan Quintela
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 04/13] icount: introduce icount timer fred.konrad
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

This makes qemu_savevm_state public for reverse-execution.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
Reviewed-by: Amit Shah <amit.shah@redhat.com>
---
 include/sysemu/sysemu.h | 1 +
 savevm.c                | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 285c45b..c2fb786 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -81,6 +81,7 @@ void do_info_snapshots(Monitor *mon, const QDict *qdict);
 
 void qemu_announce_self(void);
 
+int qemu_savevm_state(QEMUFile *f);
 bool qemu_savevm_state_blocked(Error **errp);
 void qemu_savevm_state_begin(QEMUFile *f,
                              const MigrationParams *params);
diff --git a/savevm.c b/savevm.c
index ba900d3..77fe794 100644
--- a/savevm.c
+++ b/savevm.c
@@ -782,7 +782,7 @@ void qemu_savevm_state_cancel(void)
     }
 }
 
-static int qemu_savevm_state(QEMUFile *f)
+int qemu_savevm_state(QEMUFile *f)
 {
     int ret;
     MigrationParams params = {
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 04/13] icount: introduce icount timer.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
                   ` (2 preceding siblings ...)
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 03/13] migration: make qemu_savevm_state public fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 05/13] icount: check for icount clock deadline when cpu loop exits fred.konrad
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

This introduces a new timer based only on instruction counter and without any
compensation.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
---
 cpus.c                 | 19 ++++++++++++-------
 include/qemu/timer.h   |  9 ++++++++-
 qemu-timer.c           |  8 +++++++-
 stubs/cpu-get-icount.c |  2 +-
 4 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/cpus.c b/cpus.c
index 8d2ddf0..7f99d5e 100644
--- a/cpus.c
+++ b/cpus.c
@@ -134,7 +134,7 @@ typedef struct TimersState {
 static TimersState timers_state;
 
 /* Return the virtual CPU time, based on the instruction counter.  */
-static int64_t cpu_get_icount_locked(void)
+static int64_t cpu_get_icount_locked(int with_bias)
 {
     int64_t icount;
     CPUState *cpu = current_cpu;
@@ -146,17 +146,22 @@ static int64_t cpu_get_icount_locked(void)
         }
         icount -= (cpu->icount_decr.u16.low + cpu->icount_extra);
     }
-    return timers_state.qemu_icount_bias + (icount << icount_time_shift);
+
+    if (with_bias) {
+        return timers_state.qemu_icount_bias + (icount << icount_time_shift);
+    } else {
+        return icount << icount_time_shift;
+    }
 }
 
-int64_t cpu_get_icount(void)
+int64_t cpu_get_icount(int with_bias)
 {
     int64_t icount;
     unsigned start;
 
     do {
         start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
-        icount = cpu_get_icount_locked();
+        icount = cpu_get_icount_locked(with_bias);
     } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));
 
     return icount;
@@ -169,7 +174,7 @@ int64_t cpu_get_ticks(void)
     int64_t ticks;
 
     if (use_icount) {
-        return cpu_get_icount();
+        return cpu_get_icount(true);
     }
 
     ticks = timers_state.cpu_ticks_offset;
@@ -267,7 +272,7 @@ static void icount_adjust(void)
 
     seqlock_write_lock(&timers_state.vm_clock_seqlock);
     cur_time = cpu_get_clock_locked();
-    cur_icount = cpu_get_icount_locked();
+    cur_icount = cpu_get_icount_locked(true);
 
     delta = cur_icount - cur_time;
     /* FIXME: This is a very crude algorithm, somewhat prone to oscillation.  */
@@ -330,7 +335,7 @@ static void icount_warp_rt(void *opaque)
              * far ahead of real time.
              */
             int64_t cur_time = cpu_get_clock_locked();
-            int64_t cur_icount = cpu_get_icount_locked();
+            int64_t cur_icount = cpu_get_icount_locked(true);
             int64_t delta = cur_time - cur_icount;
             warp_delta = MIN(warp_delta, delta);
         }
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 7f9a074..6204cab 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -36,12 +36,19 @@
  * is suspended, and it will reflect system time changes the host may
  * undergo (e.g. due to NTP). The host clock has the same precision as
  * the virtual clock.
+ *
+ * @QEMU_CLOCK_ICOUNT: icount clock
+ *
+ * The icount clock is based on instruction counter without any compensation for
+ * speed. It will run only when instruction are executed and make only sense in
+ * icount mode.
  */
 
 typedef enum {
     QEMU_CLOCK_REALTIME = 0,
     QEMU_CLOCK_VIRTUAL = 1,
     QEMU_CLOCK_HOST = 2,
+    QEMU_CLOCK_ICOUNT = 3,
     QEMU_CLOCK_MAX
 } QEMUClockType;
 
@@ -743,7 +750,7 @@ static inline int64_t get_clock(void)
 #endif
 
 /* icount */
-int64_t cpu_get_icount(void);
+int64_t cpu_get_icount(int with_bias);
 int64_t cpu_get_clock(void);
 
 /*******************************************/
diff --git a/qemu-timer.c b/qemu-timer.c
index 00a5d35..3be80b1 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -554,7 +554,7 @@ int64_t qemu_clock_get_ns(QEMUClockType type)
     default:
     case QEMU_CLOCK_VIRTUAL:
         if (use_icount) {
-            return cpu_get_icount();
+            return cpu_get_icount(true);
         } else {
             return cpu_get_clock();
         }
@@ -566,6 +566,12 @@ int64_t qemu_clock_get_ns(QEMUClockType type)
             notifier_list_notify(&clock->reset_notifiers, &now);
         }
         return now;
+    case QEMU_CLOCK_ICOUNT:
+        if (use_icount) {
+            return cpu_get_icount(false);
+        } else {
+            return -1;
+        }
     }
 }
 
diff --git a/stubs/cpu-get-icount.c b/stubs/cpu-get-icount.c
index d685859..1968de7 100644
--- a/stubs/cpu-get-icount.c
+++ b/stubs/cpu-get-icount.c
@@ -3,7 +3,7 @@
 
 int use_icount;
 
-int64_t cpu_get_icount(void)
+int64_t cpu_get_icount(int with_bias)
 {
     abort();
 }
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 05/13] icount: check for icount clock deadline when cpu loop exits.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
                   ` (3 preceding siblings ...)
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 04/13] icount: introduce icount timer fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 06/13] icount: make icount extra computed on icount clock as well fred.konrad
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

Notify events on icount clock when CPU loop exits.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
 cpus.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/cpus.c b/cpus.c
index 7f99d5e..76de504 100644
--- a/cpus.c
+++ b/cpus.c
@@ -993,6 +993,11 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
             if (deadline == 0) {
                 qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
             }
+
+            deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_ICOUNT);
+            if (deadline == 0) {
+                qemu_clock_notify(QEMU_CLOCK_ICOUNT);
+            }
         }
         qemu_tcg_wait_io_event();
     }
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 06/13] icount: make icount extra computed on icount clock as well.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
                   ` (4 preceding siblings ...)
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 05/13] icount: check for icount clock deadline when cpu loop exits fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 07/13] timer: add cpu_icount_to_ns function fred.konrad
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

This takes icount clock in account for icount extra computation so icount
clock's timers will be triggered at the exact time.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
 cpus.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/cpus.c b/cpus.c
index 76de504..4b551f1 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1288,6 +1288,7 @@ static int tcg_cpu_exec(CPUArchState *env)
     if (use_icount) {
         int64_t count;
         int64_t deadline;
+        int64_t icount_deadline;
         int decr;
         timers_state.qemu_icount -= (cpu->icount_decr.u16.low
                                     + cpu->icount_extra);
@@ -1304,6 +1305,15 @@ static int tcg_cpu_exec(CPUArchState *env)
             deadline = INT32_MAX;
         }
 
+        /*
+         * Take icount clock deadline in account too, and keep the nearest
+         * deadline.
+         */
+        icount_deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_ICOUNT);
+        if ((icount_deadline >= 0) && (icount_deadline < deadline)) {
+            deadline = icount_deadline;
+        }
+
         count = qemu_icount_round(deadline);
         timers_state.qemu_icount += count;
         decr = (count > 0xffff) ? 0xffff : count;
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 07/13] timer: add cpu_icount_to_ns function.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
                   ` (5 preceding siblings ...)
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 06/13] icount: make icount extra computed on icount clock as well fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 08/13] trace-events: add reverse-execution events fred.konrad
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

This adds cpu_icount_to_ns function which is needed for reverse execution.

It returns the time for a specific instruction.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
---
 cpus.c               | 9 +++++++--
 include/qemu/timer.h | 1 +
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/cpus.c b/cpus.c
index 4b551f1..89c7a1a 100644
--- a/cpus.c
+++ b/cpus.c
@@ -148,9 +148,9 @@ static int64_t cpu_get_icount_locked(int with_bias)
     }
 
     if (with_bias) {
-        return timers_state.qemu_icount_bias + (icount << icount_time_shift);
+        return timers_state.qemu_icount_bias + cpu_icount_to_ns(icount);
     } else {
-        return icount << icount_time_shift;
+        return cpu_icount_to_ns(icount);
     }
 }
 
@@ -167,6 +167,11 @@ int64_t cpu_get_icount(int with_bias)
     return icount;
 }
 
+int64_t cpu_icount_to_ns(int64_t icount)
+{
+    return icount << icount_time_shift;
+}
+
 /* return the host CPU cycle counter and handle stop/restart */
 /* Caller must hold the BQL */
 int64_t cpu_get_ticks(void)
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 6204cab..0ae7f28 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -752,6 +752,7 @@ static inline int64_t get_clock(void)
 /* icount */
 int64_t cpu_get_icount(int with_bias);
 int64_t cpu_get_clock(void);
+int64_t cpu_icount_to_ns(int64_t icount);
 
 /*******************************************/
 /* host CPU ticks (if available) */
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 08/13] trace-events: add reverse-execution events.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
                   ` (6 preceding siblings ...)
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 07/13] timer: add cpu_icount_to_ns function fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 09/13] introduce reverse execution mechanism fred.konrad
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

This adds some trace-events for reverse execution.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
---
 trace-events | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/trace-events b/trace-events
index ba01ad5..c1423e0 100644
--- a/trace-events
+++ b/trace-events
@@ -1292,3 +1292,9 @@ mhp_pc_dimm_assigned_address(uint64_t addr) "0x%"PRIx64
 # target-s390x/kvm.c
 kvm_enable_cmma(int rc) "CMMA: enabling with result code %d"
 kvm_clear_cmma(int rc) "CMMA: clearing with result code %d"
+
+# reverse-execution.c
+snap_callback(uint64_t time, const char *filename) "snapshot @%li -> %s"
+stop_callback(uint64_t time) "stopping @%li"
+cexe_stop_reverse_continue(void) "stop reverse continue."
+cexe_step_backward(uint64_t time, uint64_t stop) "stepping backward @%li stop @%li"
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 09/13] introduce reverse execution mechanism.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
                   ` (7 preceding siblings ...)
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 08/13] trace-events: add reverse-execution events fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 10/13] gdbstub: allow reverse execution in gdb stub fred.konrad
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

This introduces the basic reverse-execution mechanism.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
---
 Makefile.target             |   1 +
 cpus.c                      |   6 +
 include/reverse-execution.h |  41 ++++++
 reverse-execution.c         | 306 ++++++++++++++++++++++++++++++++++++++++++++
 vl.c                        |   7 +-
 5 files changed, 360 insertions(+), 1 deletion(-)
 create mode 100644 include/reverse-execution.h
 create mode 100644 reverse-execution.c

diff --git a/Makefile.target b/Makefile.target
index 6089d29..7cb5cae 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -120,6 +120,7 @@ endif #CONFIG_BSD_USER
 # System emulator target
 ifdef CONFIG_SOFTMMU
 obj-y += arch_init.o cpus.o monitor.o gdbstub.o balloon.o ioport.o numa.o
+obj-y += reverse-execution.o
 obj-y += qtest.o
 obj-y += hw/
 obj-$(CONFIG_FDT) += device_tree.o
diff --git a/cpus.c b/cpus.c
index 89c7a1a..e86045e 100644
--- a/cpus.c
+++ b/cpus.c
@@ -63,6 +63,8 @@
 
 #endif /* CONFIG_LINUX */
 
+#include "reverse-execution.h"
+
 static CPUState *next_cpu;
 
 bool cpu_is_stopped(CPUState *cpu)
@@ -593,7 +595,11 @@ static bool cpu_can_run(CPUState *cpu)
 
 static void cpu_handle_guest_debug(CPUState *cpu)
 {
+    if (cexe_is_continuing_backward()) {
+        cexe_step_done();
+    }
     gdb_set_stop_cpu(cpu);
+    cexe_stop_stepping_back_mode();
     qemu_system_debug_request();
     cpu->stopped = true;
 }
diff --git a/include/reverse-execution.h b/include/reverse-execution.h
new file mode 100644
index 0000000..bf42003
--- /dev/null
+++ b/include/reverse-execution.h
@@ -0,0 +1,41 @@
+/*
+ *  reverse execution.
+ *
+ *  Copyright (C) 2014 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef REVERSE_EXECUTION
+#define REVERSE_EXECUTION
+
+void cexe_setup(void);
+void cexe_step_backward(CPUState *cpu, uint64_t steps);
+void cexe_stop_stepping_back_mode(void);
+void cexe_continue_backward(CPUState *cpu);
+int cexe_is_continuing_backward(void);
+void cexe_next_reverse_continue_step(void);
+void cexe_stop_reverse_continue(void);
+void cexe_step_done(void);
+bool cexe_is_step_done(void);
+bool cexe_is_enabled(void);
+void cexe_cleanup(void);
+bool cexe_dbg_requested(void);
+
+#endif /* REVERSE_EXECUTION */
diff --git a/reverse-execution.c b/reverse-execution.c
new file mode 100644
index 0000000..9bf2ee8
--- /dev/null
+++ b/reverse-execution.c
@@ -0,0 +1,306 @@
+/*
+ *  reverse execution.
+ *
+ *  Copyright (C) 2014 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "migration/qemu-file.h"
+
+#include "reverse-execution.h"
+
+#include "trace.h"  /* needed for trace event prototype */
+
+typedef struct snapshot_entry {
+    uint32_t id;
+    int64_t time;
+    QLIST_ENTRY(snapshot_entry) next;
+} snapshot_entry;
+
+static QLIST_HEAD(, snapshot_entry) snapshot = QLIST_HEAD_INITIALIZER(snapshot);
+
+QEMUTimer *snap_timer;
+QEMUTimer *stop_timer;
+
+struct cexe_state {
+    int stepping_back;
+    int continue_backward_mode;
+    int singlestep_was_enabled;
+    bool step_done;
+    bool stop_requested;
+};
+
+static bool cexe_enabled;
+struct cexe_state cexe_state;
+
+static snapshot_entry *new_snapshot(void)
+{
+    snapshot_entry *snap = NULL;
+    snap = g_malloc(sizeof(snapshot_entry));
+    assert(snap);
+
+    if (QLIST_FIRST(&snapshot) != NULL) {
+        snap->id = QLIST_FIRST(&snapshot)->id + 1;
+    } else {
+        snap->id = 0;
+    }
+
+    QLIST_INSERT_HEAD(&snapshot, snap, next);
+    return snap;
+}
+
+/*
+ * Timer callback called when a snapshot must be done.
+ */
+static void snap_callback(void *opaque)
+{
+    QEMUFile *file = NULL;
+    int saved_vm_running;
+    snapshot_entry *snap = NULL;
+    CPUArchState *cpu = NULL;
+    char filename[20];
+
+    cpu = qemu_get_cpu(0)->env_ptr;
+    assert(cpu != NULL);
+
+    if (!cexe_state.stepping_back) {
+        snap = new_snapshot();
+
+        saved_vm_running = runstate_is_running();
+        vm_stop(RUN_STATE_SAVE_VM);
+        snap->time = qemu_clock_get_ns(QEMU_CLOCK_ICOUNT);
+        sprintf(filename, ".save%04u", snap->id);
+
+        trace_snap_callback(snap->time, filename);
+
+        file = qemu_fopen(filename, "wb");
+        qemu_savevm_state(file);
+        qemu_fclose(file);
+
+        if (saved_vm_running) {
+            vm_start();
+        }
+        timer_mod_ns(snap_timer, snap->time + 100000000);
+    }
+}
+
+/*
+ * Timer callback called when the VM have to stop.
+ */
+static void stop_callback(void *opaque)
+{
+    trace_stop_callback(qemu_clock_get_ns(QEMU_CLOCK_ICOUNT));
+    cexe_state.stop_requested = true;
+}
+
+void cexe_setup(void)
+{
+    snap_timer = timer_new_ns(QEMU_CLOCK_ICOUNT, snap_callback, NULL);
+    stop_timer = timer_new_ns(QEMU_CLOCK_ICOUNT, stop_callback, NULL);
+
+    timer_mod_ns(snap_timer, qemu_clock_get_ns(QEMU_CLOCK_ICOUNT));
+    cexe_enabled = true;
+    cexe_state.stepping_back = 0;
+    cexe_state.continue_backward_mode = 0;
+    cexe_state.stop_requested = false;
+}
+
+void cexe_stop_stepping_back_mode(void)
+{
+    if (cexe_state.stepping_back) {
+        singlestep = cexe_state.singlestep_was_enabled;
+        cexe_state.stepping_back = 0;
+    }
+    cexe_state.stop_requested = false;
+}
+
+static void cexe_start_stepping_back_mode(CPUState *cpu)
+{
+    assert(!cexe_state.stepping_back);
+    /*
+     * Flushing tb.
+     * FIXME: might not be necessary with counter.
+     */
+    tb_flush(cpu->env_ptr);
+
+    /*
+     * Single step to the right PC.
+     */
+    cexe_state.singlestep_was_enabled = singlestep;
+    singlestep = 1;
+
+    cexe_state.stepping_back = 1;
+}
+
+/**
+ * \func cexe_step_backward
+ * \param cpu GDBStub's cpu.
+ * \param steps Number of steps to step back.
+ * \brief Steps backward: "reverse-step" in GDB.
+ *
+ */
+void cexe_step_backward(CPUState *cpu, uint64_t steps)
+{
+    QEMUFile *file = NULL;
+    char filename[20];
+    snapshot_entry *snap = QLIST_FIRST(&snapshot);
+
+    int64_t stop_time = qemu_clock_get_ns(QEMU_CLOCK_ICOUNT)
+                      - cpu_icount_to_ns(steps);
+
+    /*
+     * FIXME: Remove the file?
+     */
+    while ((stop_time > 0) && ((snap = QLIST_FIRST(&snapshot)) != NULL)
+                           && (snap->time >= stop_time)) {
+        /*
+         * Remove the snapshot from the list and mod the snapshot timer to its
+         * time. This will cause the snapshot to be taken at the same value in
+         * case of a forward execution.
+         */
+        QLIST_REMOVE(snap, next);
+        timer_mod_ns(snap_timer, snap->time);
+        g_free(snap);
+    }
+
+    if ((stop_time <= 0) || (snap == NULL)) {
+        /*
+         * This happens when an instruction behind the first snapshot is asked.
+         * Just trigger a debug event so it won't move.
+         */
+        cexe_state.stop_requested = true;
+        vm_start();
+        return;
+    }
+
+    sprintf(filename, ".save%04u", snap->id);
+
+    /*
+     * Load the previous state.
+     */
+    vm_stop(RUN_STATE_RESTORE_VM);
+
+    trace_cexe_step_backward(qemu_clock_get_ns(QEMU_CLOCK_ICOUNT), stop_time);
+
+    file = qemu_fopen(filename, "rb");
+    qemu_loadvm_state(file);
+    qemu_fclose(file);
+
+    /*
+     * Mod the timer so it will stop at the exact instruction.
+     */
+    timer_mod_ns(stop_timer, stop_time);
+
+    cexe_start_stepping_back_mode(cpu);
+    /*
+     * Restart the vm.
+     */
+    vm_start();
+}
+
+/**
+ * \func cexe_continue_backward
+ * \brief Continue execution backward.
+ * \param cpu GDB's stub cpu.
+ *
+ */
+void cexe_continue_backward(CPUState *cpu)
+{
+    cexe_state.continue_backward_mode = 1;
+    cexe_state.step_done = false;
+    cexe_step_backward(cpu, 1);
+}
+
+/**
+ * \func cexe_is_continuing_backward
+ * \brief Check if we are continuing backward.
+ * \return Return true if we are continuing backward.
+ *
+ */
+int cexe_is_continuing_backward(void)
+{
+    return cexe_state.continue_backward_mode;
+}
+
+void cexe_next_reverse_continue_step(void)
+{
+    CPUState *cpu = qemu_get_cpu(0);
+
+    assert(cpu != NULL);
+    cexe_state.step_done = false;
+
+    /*
+     * FIXME:
+     *         - Stop at breakpoint in reverse order.
+     *         - The reverse execution speed is not constant as the snapshot
+     *           replay is not constant.
+     */
+    cexe_step_backward(cpu, 10000000);
+}
+
+void cexe_stop_reverse_continue(void)
+{
+    if (cexe_state.continue_backward_mode) {
+        trace_cexe_stop_reverse_continue();
+        cexe_state.continue_backward_mode = false;
+        cexe_state.step_done = false;
+        cexe_stop_stepping_back_mode();
+    }
+}
+
+void cexe_step_done(void)
+{
+    cexe_state.step_done = true;
+}
+
+bool cexe_is_step_done(void)
+{
+    return cexe_state.step_done;
+}
+
+bool cexe_is_enabled(void)
+{
+    return cexe_enabled;
+}
+
+void cexe_cleanup(void)
+{
+    snapshot_entry *snap = QLIST_FIRST(&snapshot);
+
+    /*
+     * FIXME: Remove the file?
+     */
+    while ((snap = QLIST_FIRST(&snapshot)) != NULL) {
+        /*
+         * Remove the snapshot from the list and mod the snapshot timer to its
+         * time. This will cause the snapshot to be taken at the same value in
+         * case of a forward execution.
+         */
+        QLIST_REMOVE(snap, next);
+        g_free(snap);
+    }
+}
+
+bool cexe_dbg_requested(void)
+{
+    return cexe_state.stop_requested;
+}
diff --git a/vl.c b/vl.c
index a1686ef..d0352e3 100644
--- a/vl.c
+++ b/vl.c
@@ -119,6 +119,8 @@ int main(int argc, char **argv)
 #include "qom/object_interfaces.h"
 #include "qapi-event.h"
 
+#include "reverse-execution.h"
+
 #define DEFAULT_RAM_SIZE 128
 
 #define MAX_VIRTIO_CONSOLES 1
@@ -1950,7 +1952,7 @@ void qemu_system_debug_request(void)
 static bool main_loop_should_exit(void)
 {
     RunState r;
-    if (qemu_debug_requested()) {
+    if (qemu_debug_requested() && !cexe_is_continuing_backward()) {
         vm_stop(RUN_STATE_DEBUG);
     }
     if (qemu_suspend_requested()) {
@@ -2000,6 +2002,9 @@ static void main_loop(void)
     int64_t ti;
 #endif
     do {
+        if (cexe_is_continuing_backward() && cexe_is_step_done()) {
+            cexe_next_reverse_continue_step();
+        }
         nonblocking = !kvm_enabled() && !xen_enabled() && last_io > 0;
 #ifdef CONFIG_PROFILER
         ti = profile_getclock();
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 10/13] gdbstub: allow reverse execution in gdb stub.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
                   ` (8 preceding siblings ...)
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 09/13] introduce reverse execution mechanism fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 11/13] cpu-exec: trigger a debug request when rexec stops fred.konrad
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

This allows gdb to reverse step QEMU: reverse-stepi and reverse-cont commands
are allowed.

When step_backward is called, QEMU restores a snapshot before the actual
instruction and stops (with a debug exit) when the previous instruction is
reached.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
---
 gdbstub.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/gdbstub.c b/gdbstub.c
index 8afe0b7..99769af 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -33,6 +33,7 @@
 #include "sysemu/char.h"
 #include "sysemu/sysemu.h"
 #include "exec/gdbstub.h"
+#include "reverse-execution.h"
 #endif
 
 #define MAX_PACKET_LENGTH 4096
@@ -1113,6 +1114,17 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
             if (cc->gdb_core_xml_file != NULL) {
                 pstrcat(buf, sizeof(buf), ";qXfer:features:read+");
             }
+
+            #ifndef CONFIG_USER_ONLY
+            /*
+             * When reverse execution is enabled those additional features must
+             * be set so GDB allows reverse-stepi and reverse-continue command.
+             */
+            if (cexe_is_enabled()) {
+                pstrcat(buf, sizeof(buf), ";ReverseStep+;ReverseContinue+");
+            }
+            #endif /* !CONFIG_USER_ONLY */
+
             put_packet(s, buf);
             break;
         }
@@ -1161,7 +1173,23 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
         }
         /* Unrecognised 'q' command.  */
         goto unknown_command;
-
+    #ifndef CONFIG_USER_ONLY
+    case 'b':
+        /* Reverse execution. */
+        switch (*p) {
+        case 's':
+            cexe_step_backward(s->c_cpu, 1);
+            break;
+        case 'c':
+            cexe_continue_backward(s->c_cpu);
+            break;
+        default:
+            buf[0] = '\0';
+            put_packet(s, buf);
+            break;
+        }
+        break;
+    #endif /* !CONFIG_USER_ONLY */
     default:
     unknown_command:
         /* put empty packet */
@@ -1221,6 +1249,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
         ret = GDB_SIGNAL_TRAP;
         break;
     case RUN_STATE_PAUSED:
+        cexe_stop_reverse_continue();
         ret = GDB_SIGNAL_INT;
         break;
     case RUN_STATE_SHUTDOWN:
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 11/13] cpu-exec: trigger a debug request when rexec stops.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
                   ` (9 preceding siblings ...)
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 10/13] gdbstub: allow reverse execution in gdb stub fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 12/13] cexe: synchronize icount on the next event fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 13/13] cexe: allow to enable reverse execution fred.konrad
  12 siblings, 0 replies; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

This allows QEMU to trigger a debug exception when cexe_dbg_requested
is set.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
---
 cpu-exec.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/cpu-exec.c b/cpu-exec.c
index 38e5f02..c92cfd1 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -22,6 +22,7 @@
 #include "tcg.h"
 #include "qemu/atomic.h"
 #include "sysemu/qtest.h"
+#include "reverse-execution.h"
 
 void cpu_loop_exit(CPUState *cpu)
 {
@@ -230,6 +231,18 @@ int cpu_exec(CPUArchState *env)
     /* This must be volatile so it is not trashed by longjmp() */
     volatile bool have_tb_lock = false;
 
+    #ifndef CONFIG_USER_ONLY
+    if (cexe_is_enabled() && cexe_dbg_requested()) {
+        /*
+         * Reverse execution need to stop right now.
+         * So just generate a EXCP_DEBUG.
+         */
+        cpu->exception_index = EXCP_DEBUG;
+        cpu_handle_debug_exception(env);
+        return EXCP_DEBUG;
+    }
+    #endif /* !CONFIG_USER_ONLY */
+
     if (cpu->halted) {
         if (!cpu_has_work(cpu)) {
             return EXCP_HALTED;
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 12/13] cexe: synchronize icount on the next event.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
                   ` (10 preceding siblings ...)
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 11/13] cpu-exec: trigger a debug request when rexec stops fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 13/13] cexe: allow to enable reverse execution fred.konrad
  12 siblings, 0 replies; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

We don't want to warp on host clock as it is not deterministic for replay.
So this patch warp icount on the next QEMU_VIRTUAL_CLOCK event if reverse
execution is enabled.

The normal behaviour is kept when reverse execution is disabled.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
---
 cpus.c                      | 19 +++++++++++++++++--
 include/qemu/timer.h        |  8 ++++++++
 include/reverse-execution.h |  2 ++
 main-loop.c                 | 10 ++++++++++
 stubs/Makefile.objs         |  1 +
 stubs/cexe-stub.c           | 32 ++++++++++++++++++++++++++++++++
 stubs/cpu-get-icount.c      |  8 ++++++++
 7 files changed, 78 insertions(+), 2 deletions(-)
 create mode 100644 stubs/cexe-stub.c

diff --git a/cpus.c b/cpus.c
index e86045e..77d4700 100644
--- a/cpus.c
+++ b/cpus.c
@@ -321,8 +321,10 @@ static int64_t qemu_icount_round(int64_t count)
     return (count + (1 << icount_time_shift) - 1) >> icount_time_shift;
 }
 
-static void icount_warp_rt(void *opaque)
+void icount_warp_rt(void *opaque)
 {
+    int64_t next_vm_deadline = -1;
+
     /* The icount_warp_timer is rescheduled soon after vm_clock_warp_start
      * changes from -1 to another value, so the race here is okay.
      */
@@ -330,6 +332,13 @@ static void icount_warp_rt(void *opaque)
         return;
     }
 
+    if (cexe_is_enabled()) {
+        /*
+         * We need this because the standard warp_delta is not deterministic.
+         */
+        next_vm_deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
+    }
+
     seqlock_write_lock(&timers_state.vm_clock_seqlock);
     if (runstate_is_running()) {
         int64_t clock = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
@@ -346,7 +355,13 @@ static void icount_warp_rt(void *opaque)
             int64_t delta = cur_time - cur_icount;
             warp_delta = MIN(warp_delta, delta);
         }
-        timers_state.qemu_icount_bias += warp_delta;
+        if (cexe_is_enabled()) {
+            if (next_vm_deadline > 0) {
+                timers_state.qemu_icount_bias += next_vm_deadline;
+            }
+        } else {
+            timers_state.qemu_icount_bias += warp_delta;
+        }
     }
     vm_clock_warp_start = -1;
     seqlock_write_unlock(&timers_state.vm_clock_seqlock);
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
index 0ae7f28..de2641a 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -754,6 +754,14 @@ int64_t cpu_get_icount(int with_bias);
 int64_t cpu_get_clock(void);
 int64_t cpu_icount_to_ns(int64_t icount);
 
+/**
+ * void icount_warp_rt:
+ *
+ * Move icount to the realtime clock or to the next QEMU_VIRTUAL_CLOCK event
+ * when reverse execution is enabled.
+ */
+void icount_warp_rt(void *opaque);
+
 /*******************************************/
 /* host CPU ticks (if available) */
 
diff --git a/include/reverse-execution.h b/include/reverse-execution.h
index bf42003..739572e 100644
--- a/include/reverse-execution.h
+++ b/include/reverse-execution.h
@@ -25,6 +25,8 @@
 #ifndef REVERSE_EXECUTION
 #define REVERSE_EXECUTION
 
+#include "qom/cpu.h"
+
 void cexe_setup(void);
 void cexe_step_backward(CPUState *cpu, uint64_t steps);
 void cexe_stop_stepping_back_mode(void);
diff --git a/main-loop.c b/main-loop.c
index 8a85493..6130438 100644
--- a/main-loop.c
+++ b/main-loop.c
@@ -34,6 +34,8 @@
 
 #include "qemu/compatfd.h"
 
+#include "reverse-execution.h"
+
 /* If we have signalfd, we mask out the signals we want to handle and then
  * use signalfd to listen for them.  We rely on whatever the current signal
  * handler is to dispatch the signals when we receive them.
@@ -489,6 +491,14 @@ int main_loop_wait(int nonblocking)
 
     qemu_clock_run_all_timers();
 
+    /*
+     * Sometimes deadlock can appears because there is no pending event on
+     * virtual clock.
+     */
+    if (cexe_is_enabled()) {
+        icount_warp_rt(NULL);
+    }
+
     return ret;
 }
 
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 528e161..5e362f6 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -39,3 +39,4 @@ stub-obj-$(CONFIG_WIN32) += fd-register.o
 stub-obj-y += cpus.o
 stub-obj-y += kvm.o
 stub-obj-y += qmp_pc_dimm_device_list.o
+stub-obj-y += cexe-stub.o
diff --git a/stubs/cexe-stub.c b/stubs/cexe-stub.c
new file mode 100644
index 0000000..7723998
--- /dev/null
+++ b/stubs/cexe-stub.c
@@ -0,0 +1,32 @@
+/*
+ *  cexe-stub.c
+ *
+ *  Copyright (C) 2014 : GreenSocs Ltd
+ *      http://www.greensocs.com/ , email: info@greensocs.com
+ *
+ *  Developed by :
+ *  Frederic Konrad   <fred.konrad@greensocs.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdbool.h>
+
+bool cexe_is_enabled(void);
+
+bool cexe_is_enabled(void)
+{
+    return false;
+}
diff --git a/stubs/cpu-get-icount.c b/stubs/cpu-get-icount.c
index 1968de7..231e659 100644
--- a/stubs/cpu-get-icount.c
+++ b/stubs/cpu-get-icount.c
@@ -7,3 +7,11 @@ int64_t cpu_get_icount(int with_bias)
 {
     abort();
 }
+
+void icount_warp_rt(void *opaque)
+{
+    /*
+     * Should not happen, as cexe_is_enabled() always return false.
+     */
+    abort();
+}
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [RFC PATCH v4 13/13] cexe: allow to enable reverse execution.
  2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
                   ` (11 preceding siblings ...)
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 12/13] cexe: synchronize icount on the next event fred.konrad
@ 2014-06-25  8:26 ` fred.konrad
  12 siblings, 0 replies; 17+ messages in thread
From: fred.konrad @ 2014-06-25  8:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, quintela, mark.burton, dgilbert, amit.shah,
	pbonzini, vilanova, fred.konrad

From: KONRAD Frederic <fred.konrad@greensocs.com>

This creates QEMU options for reverse execution.

Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
---
 qemu-options.hx |  9 +++++++++
 vl.c            | 16 ++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/qemu-options.hx b/qemu-options.hx
index ff76ad4..2afb85d 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2946,6 +2946,15 @@ order cores with complex cache hierarchies.  The number of instructions
 executed often has little or no correlation with actual performance.
 ETEXI
 
+DEF("cexe", 0, QEMU_OPTION_cexe, \
+    "-cexe\n" \
+    "                enable reverse execution\n", QEMU_ARCH_ALL)
+STEXI
+@item -cexe
+@findex -cexe
+Enable reverse execution.
+ETEXI
+
 DEF("watchdog", HAS_ARG, QEMU_OPTION_watchdog, \
     "-watchdog i6300esb|ib700\n" \
     "                enable virtual hardware watchdog [default=none]\n",
diff --git a/vl.c b/vl.c
index d0352e3..a94563a 100644
--- a/vl.c
+++ b/vl.c
@@ -228,6 +228,7 @@ static int default_floppy = 1;
 static int default_cdrom = 1;
 static int default_sdcard = 1;
 static int default_vga = 1;
+static int default_cexe;
 
 static struct {
     const char *driver;
@@ -3821,6 +3822,9 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_icount:
                 icount_option = optarg;
                 break;
+            case QEMU_OPTION_cexe:
+                default_cexe = true;
+                break;
             case QEMU_OPTION_incoming:
                 incoming = optarg;
                 runstate_set(RUN_STATE_INMIGRATE);
@@ -4520,6 +4524,15 @@ int main(int argc, char **argv, char **envp)
         vm_start();
     }
 
+    if (default_cexe) {
+        if (!icount_option) {
+            fprintf(stderr, "Reverse execution requires icount.\n");
+            exit(1);
+        }
+
+        cexe_setup();
+    }
+
     os_setup_post();
 
     if (is_daemonized()) {
@@ -4536,5 +4549,8 @@ int main(int argc, char **argv, char **envp)
     tpm_cleanup();
 #endif
 
+    if (cexe_is_enabled()) {
+        cexe_cleanup();
+    }
     return 0;
 }
-- 
1.9.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v4 02/13] migration: migrate icount fields.
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 02/13] migration: migrate icount fields fred.konrad
@ 2014-06-25 12:17   ` Juan Quintela
  2014-06-25 15:17     ` Frederic Konrad
  0 siblings, 1 reply; 17+ messages in thread
From: Juan Quintela @ 2014-06-25 12:17 UTC (permalink / raw)
  To: fred.konrad
  Cc: peter.maydell, mark.burton, qemu-devel, dgilbert, amit.shah,
	pbonzini, vilanova

fred.konrad@greensocs.com wrote:
> From: KONRAD Frederic <fred.konrad@greensocs.com>
>
> This fixes a bug where qemu_icount and qemu_icount_bias are not migrated.
> It adds a subsection "timer/icount" to vmstate_timers so icount is migrated only
> when needed.
>
> Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
> Reviewed-by: Amit Shah <amit.shah@redhat.com>
> ---
>  cpus.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
>
> diff --git a/cpus.c b/cpus.c
> index 127de1c..8d2ddf0 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -429,6 +429,26 @@ void qemu_clock_warp(QEMUClockType type)
>      }
>  }
>  
> +static bool icount_state_needed(void *opaque)
> +{
> +    return use_icount;
> +}
> +
> +/*
> + * This is a subsection for icount migration.
> + */
> +static const VMStateDescription icount_vmstate_timers = {
> +    .name = "timer/icount",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,

Drop this line, not needed anymore.

> +    .fields      = (VMStateField[]) {

Remove spaces

> +        VMSTATE_INT64(qemu_icount_bias, TimersState),
> +        VMSTATE_INT64(qemu_icount, TimersState),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
>  static const VMStateDescription vmstate_timers = {
>      .name = "timer",
>      .version_id = 2,
> @@ -438,6 +458,14 @@ static const VMStateDescription vmstate_timers = {
>          VMSTATE_INT64(dummy, TimersState),
>          VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
>          VMSTATE_END_OF_LIST()
> +    },
> +    .subsections = (VMStateSubsection[]) {
> +        {
> +            .vmsd = &icount_vmstate_timers,
> +            .needed = icount_state_needed,
> +        }, {
> +            /* empty */
> +        }
>      }
>  };

Rest is ok.

Thanks, Juan.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v4 03/13] migration: make qemu_savevm_state public.
  2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 03/13] migration: make qemu_savevm_state public fred.konrad
@ 2014-06-25 12:18   ` Juan Quintela
  0 siblings, 0 replies; 17+ messages in thread
From: Juan Quintela @ 2014-06-25 12:18 UTC (permalink / raw)
  To: fred.konrad
  Cc: peter.maydell, mark.burton, qemu-devel, dgilbert, amit.shah,
	pbonzini, vilanova

fred.konrad@greensocs.com wrote:
> From: KONRAD Frederic <fred.konrad@greensocs.com>
>
> This makes qemu_savevm_state public for reverse-execution.
>
> Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
> Reviewed-by: Amit Shah <amit.shah@redhat.com>

Reviewed-by: Juan Quintela <quintela@redhat.com>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v4 02/13] migration: migrate icount fields.
  2014-06-25 12:17   ` Juan Quintela
@ 2014-06-25 15:17     ` Frederic Konrad
  0 siblings, 0 replies; 17+ messages in thread
From: Frederic Konrad @ 2014-06-25 15:17 UTC (permalink / raw)
  To: quintela
  Cc: peter.maydell, mark.burton, qemu-devel, dgilbert, amit.shah,
	pbonzini, vilanova

On 25/06/2014 14:17, Juan Quintela wrote:
> +    .minimum_version_id_old = 1,
> Drop this line, not needed anymore.
>
>> +    .fields      = (VMStateField[]) {
> Remove spaces

oops didn't see that sorry.
>
>> [...]
> Rest is ok.
>
> Thanks, Juan.

I will resent with this fix.

Thanks,
Fred.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2014-06-25 15:17 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-25  8:26 [Qemu-devel] [RFC PATCH v4 00/13] Reverse execution fred.konrad
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 01/13] icount: put icount variables into TimerState fred.konrad
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 02/13] migration: migrate icount fields fred.konrad
2014-06-25 12:17   ` Juan Quintela
2014-06-25 15:17     ` Frederic Konrad
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 03/13] migration: make qemu_savevm_state public fred.konrad
2014-06-25 12:18   ` Juan Quintela
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 04/13] icount: introduce icount timer fred.konrad
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 05/13] icount: check for icount clock deadline when cpu loop exits fred.konrad
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 06/13] icount: make icount extra computed on icount clock as well fred.konrad
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 07/13] timer: add cpu_icount_to_ns function fred.konrad
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 08/13] trace-events: add reverse-execution events fred.konrad
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 09/13] introduce reverse execution mechanism fred.konrad
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 10/13] gdbstub: allow reverse execution in gdb stub fred.konrad
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 11/13] cpu-exec: trigger a debug request when rexec stops fred.konrad
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 12/13] cexe: synchronize icount on the next event fred.konrad
2014-06-25  8:26 ` [Qemu-devel] [RFC PATCH v4 13/13] cexe: allow to enable reverse execution fred.konrad

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.