All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH 00/12] Reverse execution.
@ 2014-03-21 19:17 fred.konrad
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 01/12] icount: put icount variables into TimerState fred.konrad
                   ` (11 more replies)
  0 siblings, 12 replies; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, fred.konrad

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

Hi everybody,

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

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:
  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

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.

KONRAD Frederic (12):
  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.
  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                      | 121 +++++++++++++---
 gdbstub.c                   |  31 ++++-
 include/qemu/timer.h        |  17 +++
 include/reverse-execution.h |  43 ++++++
 include/sysemu/sysemu.h     |   1 +
 main-loop.c                 |  10 ++
 qemu-options.hx             |   9 ++
 qemu-timer.c                |   6 +
 reverse-execution.c         | 326 ++++++++++++++++++++++++++++++++++++++++++++
 savevm.c                    |   2 +-
 stubs/Makefile.objs         |   1 +
 stubs/cexe-stub.c           |  32 +++++
 stubs/cpu-get-icount.c      |  13 ++
 vl.c                        |  23 +++-
 16 files changed, 627 insertions(+), 22 deletions(-)
 create mode 100644 include/reverse-execution.h
 create mode 100644 reverse-execution.c
 create mode 100644 stubs/cexe-stub.c

-- 
1.8.1.4

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

* [Qemu-devel] [RFC PATCH 01/12] icount: put icount variables into TimerState.
  2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
@ 2014-03-21 19:17 ` fred.konrad
  2014-03-22  8:58   ` Paolo Bonzini
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 02/12] migration: migrate icount fields fred.konrad
                   ` (10 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, 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>
---
 cpus.c | 29 ++++++++++++++++-------------
 1 file changed, 16 insertions(+), 13 deletions(-)

diff --git a/cpus.c b/cpus.c
index 1104d61..687717f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -100,17 +100,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;
@@ -127,6 +122,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;
@@ -137,14 +137,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)
@@ -282,7 +282,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);
 }
 
@@ -331,7 +332,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);
@@ -349,7 +350,7 @@ void qtest_clock_warp(int64_t dest)
         int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
         int64_t warp = MIN(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);
@@ -1248,7 +1249,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);
@@ -1263,7 +1265,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;
@@ -1276,7 +1278,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.8.1.4

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

* [Qemu-devel] [RFC PATCH 02/12] migration: migrate icount fields.
  2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 01/12] icount: put icount variables into TimerState fred.konrad
@ 2014-03-21 19:17 ` fred.konrad
  2014-03-22  8:57   ` Paolo Bonzini
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 03/12] migration: make qemu_savevm_state public fred.konrad
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, fred.konrad

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

This fixes a bug where qemu_icount and qemu_icount_bias are not migrated.

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

diff --git a/cpus.c b/cpus.c
index 687717f..bdbc431 100644
--- a/cpus.c
+++ b/cpus.c
@@ -440,12 +440,33 @@ static const VMStateDescription vmstate_timers = {
     }
 };
 
+/*
+ * This is used instead of vmstate_timers when icount is used.
+ * cpu_ticks_offset and dummy fields are unused in icount mode so we can replace
+ * them with icount variables.
+ */
+static const VMStateDescription icount_vmstate_timers = {
+    .name = "timer",
+    .version_id = 2,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_INT64(qemu_icount_bias, TimersState),
+        VMSTATE_INT64(qemu_icount, TimersState),
+        VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
 void configure_icount(const char *option)
 {
     seqlock_init(&timers_state.vm_clock_seqlock, NULL);
-    vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
+
     if (!option) {
+        vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
         return;
+    } else {
+        vmstate_register(NULL, 0, &icount_vmstate_timers, &timers_state);
     }
 
     icount_warp_timer = timer_new_ns(QEMU_CLOCK_REALTIME,
-- 
1.8.1.4

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

* [Qemu-devel] [RFC PATCH 03/12] migration: make qemu_savevm_state public.
  2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 01/12] icount: put icount variables into TimerState fred.konrad
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 02/12] migration: migrate icount fields fred.konrad
@ 2014-03-21 19:17 ` fred.konrad
  2014-03-21 19:54   ` Dr. David Alan Gilbert
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 04/12] icount: introduce icount timer fred.konrad
                   ` (8 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, 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>
---
 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 3915ce3..fe86615 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -78,6 +78,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 d094fbb..e50b716 100644
--- a/savevm.c
+++ b/savevm.c
@@ -635,7 +635,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.8.1.4

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

* [Qemu-devel] [RFC PATCH 04/12] icount: introduce icount timer.
  2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
                   ` (2 preceding siblings ...)
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 03/12] migration: make qemu_savevm_state public fred.konrad
@ 2014-03-21 19:17 ` fred.konrad
  2014-03-22  8:59   ` Paolo Bonzini
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 05/12] icount: check for icount clock deadline when cpu loop exits fred.konrad
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, 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                 | 28 +++++++++++++++++++++++-----
 include/qemu/timer.h   |  8 ++++++++
 qemu-timer.c           |  6 ++++++
 stubs/cpu-get-icount.c |  5 +++++
 4 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/cpus.c b/cpus.c
index bdbc431..ba096a3 100644
--- a/cpus.c
+++ b/cpus.c
@@ -132,7 +132,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;
@@ -144,7 +144,12 @@ 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)
@@ -154,7 +159,20 @@ int64_t cpu_get_icount(void)
 
     do {
         start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
-        icount = cpu_get_icount_locked();
+        icount = cpu_get_icount_locked(true);
+    } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));
+
+    return icount;
+}
+
+int64_t cpu_get_icount_wo_bias(void)
+{
+    int64_t icount;
+    unsigned start;
+
+    do {
+        start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
+        icount = cpu_get_icount_locked(false);
     } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));
 
     return icount;
@@ -265,7 +283,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.  */
@@ -328,7 +346,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..da47194 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,6 +750,7 @@ static inline int64_t get_clock(void)
 #endif
 
 /* icount */
+int64_t cpu_get_icount_wo_bias(void);
 int64_t cpu_get_icount(void);
 int64_t cpu_get_clock(void);
 
diff --git a/qemu-timer.c b/qemu-timer.c
index e15ce47..8a36906 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -563,6 +563,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_wo_bias();
+        } else {
+            return -1;
+        }
     }
 }
 
diff --git a/stubs/cpu-get-icount.c b/stubs/cpu-get-icount.c
index d685859..fa242f3 100644
--- a/stubs/cpu-get-icount.c
+++ b/stubs/cpu-get-icount.c
@@ -7,3 +7,8 @@ int64_t cpu_get_icount(void)
 {
     abort();
 }
+
+int64_t cpu_get_icount_wo_bias(void)
+{
+    abort();
+}
-- 
1.8.1.4

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

* [Qemu-devel] [RFC PATCH 05/12] icount: check for icount clock deadline when cpu loop exits.
  2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
                   ` (3 preceding siblings ...)
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 04/12] icount: introduce icount timer fred.konrad
@ 2014-03-21 19:17 ` fred.konrad
  2014-03-22  8:59   ` Paolo Bonzini
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 06/12] icount: make icount extra computed on icount clock as well fred.konrad
                   ` (6 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, 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>
---
 cpus.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/cpus.c b/cpus.c
index ba096a3..01c48e9 100644
--- a/cpus.c
+++ b/cpus.c
@@ -998,6 +998,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.8.1.4

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

* [Qemu-devel] [RFC PATCH 06/12] icount: make icount extra computed on icount clock as well.
  2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
                   ` (4 preceding siblings ...)
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 05/12] icount: check for icount clock deadline when cpu loop exits fred.konrad
@ 2014-03-21 19:17 ` fred.konrad
  2014-03-22  9:00   ` Paolo Bonzini
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 07/12] timer: add cpu_icount_to_ns function fred.konrad
                   ` (5 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, 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>
---
 cpus.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/cpus.c b/cpus.c
index 01c48e9..825d438 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1292,6 +1292,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);
@@ -1308,6 +1309,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.8.1.4

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

* [Qemu-devel] [RFC PATCH 07/12] timer: add cpu_icount_to_ns function.
  2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
                   ` (5 preceding siblings ...)
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 06/12] icount: make icount extra computed on icount clock as well fred.konrad
@ 2014-03-21 19:17 ` fred.konrad
  2014-03-22  9:00   ` Paolo Bonzini
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 08/12] introduce reverse execution mechanism fred.konrad
                   ` (4 subsequent siblings)
  11 siblings, 1 reply; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, 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>
---
 cpus.c               | 9 +++++++--
 include/qemu/timer.h | 1 +
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/cpus.c b/cpus.c
index 825d438..007de34 100644
--- a/cpus.c
+++ b/cpus.c
@@ -146,9 +146,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);
     }
 }
 
@@ -178,6 +178,11 @@ int64_t cpu_get_icount_wo_bias(void)
     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 da47194..0861d99 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -753,6 +753,7 @@ static inline int64_t get_clock(void)
 int64_t cpu_get_icount_wo_bias(void);
 int64_t cpu_get_icount(void);
 int64_t cpu_get_clock(void);
+int64_t cpu_icount_to_ns(int64_t icount);
 
 /*******************************************/
 /* host CPU ticks (if available) */
-- 
1.8.1.4

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

* [Qemu-devel] [RFC PATCH 08/12] introduce reverse execution mechanism.
  2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
                   ` (6 preceding siblings ...)
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 07/12] timer: add cpu_icount_to_ns function fred.konrad
@ 2014-03-21 19:17 ` fred.konrad
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 09/12] gdbstub: allow reverse execution in gdb stub fred.konrad
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, 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         | 326 ++++++++++++++++++++++++++++++++++++++++++++
 vl.c                        |   7 +-
 5 files changed, 380 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 ba12340..6720e0c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -110,6 +110,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
+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 007de34..20940bb 100644
--- a/cpus.c
+++ b/cpus.c
@@ -61,6 +61,8 @@
 
 #endif /* CONFIG_LINUX */
 
+#include "reverse-execution.h"
+
 static CPUState *next_cpu;
 
 bool cpu_is_stopped(CPUState *cpu)
@@ -598,7 +600,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..44d1b80
--- /dev/null
+++ b/reverse-execution.c
@@ -0,0 +1,326 @@
+/*
+ *  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"
+
+#define DEBUG_REV_EXEC
+
+#ifdef DEBUG_REV_EXEC
+#define DPRINTF(fmt, ...) \
+do { printf("rexec: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do { } while (0)
+#endif
+
+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);
+
+        DPRINTF("*** snapshooting. ***\n");
+        DPRINTF("actual time: %li\n", snap->time);
+        DPRINTF("file: %s\n", filename);
+        DPRINTF("*********************\n\n");
+
+        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)
+{
+    DPRINTF("*** stopping now. ***\n");
+    DPRINTF("current time: %li\n", 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)
+{
+    DPRINTF("stop stepping back.\n");
+    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);
+    DPRINTF("*** stepping back. ***\n");
+    DPRINTF("current time: %li\n", qemu_clock_get_ns(QEMU_CLOCK_ICOUNT));
+    DPRINTF("**********************\n\n");
+
+    file = qemu_fopen(filename, "rb");
+    qemu_loadvm_state(file);
+    qemu_fclose(file);
+
+    DPRINTF("*** vm reloaded. ***\n");
+    DPRINTF("snapshot time: %li\n", snap->time);
+    DPRINTF("current time: %li\n", qemu_clock_get_ns(QEMU_CLOCK_ICOUNT));
+    DPRINTF("stop time: %li\n", stop_time);
+    DPRINTF("******************\n\n");
+
+    /*
+     * 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) {
+        DPRINTF("*** stop continue backward. ***\n");
+        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 02bf8ec..c9e849b 100644
--- a/vl.c
+++ b/vl.c
@@ -118,6 +118,8 @@ int main(int argc, char **argv)
 #include "qapi/string-input-visitor.h"
 #include "qom/object_interfaces.h"
 
+#include "reverse-execution.h"
+
 #define DEFAULT_RAM_SIZE 128
 
 #define MAX_VIRTIO_CONSOLES 1
@@ -1994,7 +1996,7 @@ void qemu_system_vmstop_request(RunState state)
 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()) {
@@ -2044,6 +2046,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.8.1.4

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

* [Qemu-devel] [RFC PATCH 09/12] gdbstub: allow reverse execution in gdb stub.
  2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
                   ` (7 preceding siblings ...)
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 08/12] introduce reverse execution mechanism fred.konrad
@ 2014-03-21 19:17 ` fred.konrad
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 10/12] cpu-exec: trigger a debug request when rexec stops fred.konrad
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, 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.8.1.4

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

* [Qemu-devel] [RFC PATCH 10/12] cpu-exec: trigger a debug request when rexec stops.
  2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
                   ` (8 preceding siblings ...)
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 09/12] gdbstub: allow reverse execution in gdb stub fred.konrad
@ 2014-03-21 19:17 ` fred.konrad
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 11/12] cexe: synchronize icount on the next event fred.konrad
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 12/12] cexe: allow to enable reverse execution fred.konrad
  11 siblings, 0 replies; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, 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 0914d3c..851d101 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)
 {
@@ -228,6 +229,18 @@ int cpu_exec(CPUArchState *env)
     uint8_t *tc_ptr;
     uintptr_t next_tb;
 
+    #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.8.1.4

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

* [Qemu-devel] [RFC PATCH 11/12] cexe: synchronize icount on the next event.
  2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
                   ` (9 preceding siblings ...)
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 10/12] cpu-exec: trigger a debug request when rexec stops fred.konrad
@ 2014-03-21 19:17 ` fred.konrad
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 12/12] cexe: allow to enable reverse execution fred.konrad
  11 siblings, 0 replies; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, 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 20940bb..3b0a4c3 100644
--- a/cpus.c
+++ b/cpus.c
@@ -332,8 +332,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.
      */
@@ -341,6 +343,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);
@@ -357,7 +366,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 0861d99..dea86a1 100644
--- a/include/qemu/timer.h
+++ b/include/qemu/timer.h
@@ -755,6 +755,14 @@ int64_t cpu_get_icount(void);
 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 5ed1d38..60c29cb 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -30,3 +30,4 @@ stub-obj-y += vmstate.o
 stub-obj-$(CONFIG_WIN32) += fd-register.o
 stub-obj-y += cpus.o
 stub-obj-y += kvm.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 fa242f3..d4701f2 100644
--- a/stubs/cpu-get-icount.c
+++ b/stubs/cpu-get-icount.c
@@ -12,3 +12,11 @@ int64_t cpu_get_icount_wo_bias(void)
 {
     abort();
 }
+
+void icount_warp_rt(void *opaque)
+{
+    /*
+     * Should not happen, as cexe_is_enabled() always return false.
+     */
+    abort();
+}
-- 
1.8.1.4

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

* [Qemu-devel] [RFC PATCH 12/12] cexe: allow to enable reverse execution.
  2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
                   ` (10 preceding siblings ...)
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 11/12] cexe: synchronize icount on the next event fred.konrad
@ 2014-03-21 19:17 ` fred.konrad
  11 siblings, 0 replies; 25+ messages in thread
From: fred.konrad @ 2014-03-21 19:17 UTC (permalink / raw)
  To: qemu-devel; +Cc: mark.burton, 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 ee5437b..bd730f6 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2828,6 +2828,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 c9e849b..1312f46 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;
@@ -3795,6 +3796,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);
@@ -4508,6 +4512,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()) {
@@ -4524,5 +4537,8 @@ int main(int argc, char **argv, char **envp)
     tpm_cleanup();
 #endif
 
+    if (cexe_is_enabled()) {
+        cexe_cleanup();
+    }
     return 0;
 }
-- 
1.8.1.4

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

* Re: [Qemu-devel] [RFC PATCH 03/12] migration: make qemu_savevm_state public.
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 03/12] migration: make qemu_savevm_state public fred.konrad
@ 2014-03-21 19:54   ` Dr. David Alan Gilbert
  2014-03-24 15:05     ` Frederic Konrad
  0 siblings, 1 reply; 25+ messages in thread
From: Dr. David Alan Gilbert @ 2014-03-21 19:54 UTC (permalink / raw)
  To: fred.konrad; +Cc: quintela, mark.burton, qemu-devel, mrhines

* fred.konrad@greensocs.com (fred.konrad@greensocs.com) wrote:
> From: KONRAD Frederic <fred.konrad@greensocs.com>
> 
> This makes qemu_savevm_state public for reverse-execution.

It's interesting that you're doing this repetitive snapshot;
in some ways it's similar to Michael Hines's code for
Fault tolerance ( http://lists.gnu.org/archive/html/qemu-devel/2014-02/msg03042.html )

Dave

> Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.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 3915ce3..fe86615 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -78,6 +78,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 d094fbb..e50b716 100644
> --- a/savevm.c
> +++ b/savevm.c
> @@ -635,7 +635,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.8.1.4
> 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [RFC PATCH 02/12] migration: migrate icount fields.
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 02/12] migration: migrate icount fields fred.konrad
@ 2014-03-22  8:57   ` Paolo Bonzini
  2014-03-24 14:49     ` Frederic Konrad
  0 siblings, 1 reply; 25+ messages in thread
From: Paolo Bonzini @ 2014-03-22  8:57 UTC (permalink / raw)
  To: fred.konrad, qemu-devel; +Cc: mark.burton

Il 21/03/2014 20:17, fred.konrad@greensocs.com ha scritto:
> From: KONRAD Frederic <fred.konrad@greensocs.com>
>
> This fixes a bug where qemu_icount and qemu_icount_bias are not migrated.
>
> Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
> ---
>  cpus.c | 23 ++++++++++++++++++++++-
>  1 file changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/cpus.c b/cpus.c
> index 687717f..bdbc431 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -440,12 +440,33 @@ static const VMStateDescription vmstate_timers = {
>      }
>  };
>
> +/*
> + * This is used instead of vmstate_timers when icount is used.
> + * cpu_ticks_offset and dummy fields are unused in icount mode so we can replace
> + * them with icount variables.
> + */
> +static const VMStateDescription icount_vmstate_timers = {
> +    .name = "timer",
> +    .version_id = 2,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,
> +    .fields      = (VMStateField[]) {
> +        VMSTATE_INT64(qemu_icount_bias, TimersState),
> +        VMSTATE_INT64(qemu_icount, TimersState),
> +        VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
>  void configure_icount(const char *option)
>  {
>      seqlock_init(&timers_state.vm_clock_seqlock, NULL);
> -    vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
> +
>      if (!option) {
> +        vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
>          return;
> +    } else {
> +        vmstate_register(NULL, 0, &icount_vmstate_timers, &timers_state);
>      }
>
>      icount_warp_timer = timer_new_ns(QEMU_CLOCK_REALTIME,
>

You can also use a subsection for this.

Paolo

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

* Re: [Qemu-devel] [RFC PATCH 01/12] icount: put icount variables into TimerState.
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 01/12] icount: put icount variables into TimerState fred.konrad
@ 2014-03-22  8:58   ` Paolo Bonzini
  0 siblings, 0 replies; 25+ messages in thread
From: Paolo Bonzini @ 2014-03-22  8:58 UTC (permalink / raw)
  To: fred.konrad, qemu-devel; +Cc: mark.burton

Il 21/03/2014 20:17, fred.konrad@greensocs.com ha scritto:
> 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>
> ---
>  cpus.c | 29 ++++++++++++++++-------------
>  1 file changed, 16 insertions(+), 13 deletions(-)
>
> diff --git a/cpus.c b/cpus.c
> index 1104d61..687717f 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -100,17 +100,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;
> @@ -127,6 +122,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;
> @@ -137,14 +137,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)
> @@ -282,7 +282,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);
>  }
>
> @@ -331,7 +332,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);
> @@ -349,7 +350,7 @@ void qtest_clock_warp(int64_t dest)
>          int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
>          int64_t warp = MIN(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);
> @@ -1248,7 +1249,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);
> @@ -1263,7 +1265,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;
> @@ -1276,7 +1278,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;
>      }
>

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

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

* Re: [Qemu-devel] [RFC PATCH 04/12] icount: introduce icount timer.
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 04/12] icount: introduce icount timer fred.konrad
@ 2014-03-22  8:59   ` Paolo Bonzini
  0 siblings, 0 replies; 25+ messages in thread
From: Paolo Bonzini @ 2014-03-22  8:59 UTC (permalink / raw)
  To: fred.konrad, qemu-devel; +Cc: mark.burton

Il 21/03/2014 20:17, fred.konrad@greensocs.com ha scritto:
> @@ -154,7 +159,20 @@ int64_t cpu_get_icount(void)
>
>      do {
>          start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
> -        icount = cpu_get_icount_locked();
> +        icount = cpu_get_icount_locked(true);
> +    } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));
> +
> +    return icount;
> +}
> +
> +int64_t cpu_get_icount_wo_bias(void)
> +{
> +    int64_t icount;
> +    unsigned start;
> +
> +    do {
> +        start = seqlock_read_begin(&timers_state.vm_clock_seqlock);
> +        icount = cpu_get_icount_locked(false);
>      } while (seqlock_read_retry(&timers_state.vm_clock_seqlock, start));

Why not add an argument to cpu_get_icount() as well?

Paolo

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

* Re: [Qemu-devel] [RFC PATCH 05/12] icount: check for icount clock deadline when cpu loop exits.
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 05/12] icount: check for icount clock deadline when cpu loop exits fred.konrad
@ 2014-03-22  8:59   ` Paolo Bonzini
  0 siblings, 0 replies; 25+ messages in thread
From: Paolo Bonzini @ 2014-03-22  8:59 UTC (permalink / raw)
  To: fred.konrad, qemu-devel; +Cc: mark.burton

Il 21/03/2014 20:17, fred.konrad@greensocs.com ha scritto:
> 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>
> ---
>  cpus.c | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/cpus.c b/cpus.c
> index ba096a3..01c48e9 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -998,6 +998,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();
>      }
>

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

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

* Re: [Qemu-devel] [RFC PATCH 06/12] icount: make icount extra computed on icount clock as well.
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 06/12] icount: make icount extra computed on icount clock as well fred.konrad
@ 2014-03-22  9:00   ` Paolo Bonzini
  0 siblings, 0 replies; 25+ messages in thread
From: Paolo Bonzini @ 2014-03-22  9:00 UTC (permalink / raw)
  To: fred.konrad, qemu-devel; +Cc: mark.burton

Il 21/03/2014 20:17, fred.konrad@greensocs.com ha scritto:
> 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>
> ---
>  cpus.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/cpus.c b/cpus.c
> index 01c48e9..825d438 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -1292,6 +1292,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);
> @@ -1308,6 +1309,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;
>

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

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

* Re: [Qemu-devel] [RFC PATCH 07/12] timer: add cpu_icount_to_ns function.
  2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 07/12] timer: add cpu_icount_to_ns function fred.konrad
@ 2014-03-22  9:00   ` Paolo Bonzini
  0 siblings, 0 replies; 25+ messages in thread
From: Paolo Bonzini @ 2014-03-22  9:00 UTC (permalink / raw)
  To: fred.konrad, qemu-devel; +Cc: mark.burton

Il 21/03/2014 20:17, fred.konrad@greensocs.com ha scritto:
> 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>
> ---
>  cpus.c               | 9 +++++++--
>  include/qemu/timer.h | 1 +
>  2 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/cpus.c b/cpus.c
> index 825d438..007de34 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -146,9 +146,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);
>      }
>  }
>
> @@ -178,6 +178,11 @@ int64_t cpu_get_icount_wo_bias(void)
>      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 da47194..0861d99 100644
> --- a/include/qemu/timer.h
> +++ b/include/qemu/timer.h
> @@ -753,6 +753,7 @@ static inline int64_t get_clock(void)
>  int64_t cpu_get_icount_wo_bias(void);
>  int64_t cpu_get_icount(void);
>  int64_t cpu_get_clock(void);
> +int64_t cpu_icount_to_ns(int64_t icount);
>
>  /*******************************************/
>  /* host CPU ticks (if available) */
>

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

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

* Re: [Qemu-devel] [RFC PATCH 02/12] migration: migrate icount fields.
  2014-03-22  8:57   ` Paolo Bonzini
@ 2014-03-24 14:49     ` Frederic Konrad
  2014-03-24 15:42       ` Paolo Bonzini
  0 siblings, 1 reply; 25+ messages in thread
From: Frederic Konrad @ 2014-03-24 14:49 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: mark.burton

On 22/03/2014 09:57, Paolo Bonzini wrote:
> Il 21/03/2014 20:17, fred.konrad@greensocs.com ha scritto:
>> From: KONRAD Frederic <fred.konrad@greensocs.com>
>>
>> This fixes a bug where qemu_icount and qemu_icount_bias are not 
>> migrated.
>>
>> Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.com>
>> ---
>>  cpus.c | 23 ++++++++++++++++++++++-
>>  1 file changed, 22 insertions(+), 1 deletion(-)
>>
>> diff --git a/cpus.c b/cpus.c
>> index 687717f..bdbc431 100644
>> --- a/cpus.c
>> +++ b/cpus.c
>> @@ -440,12 +440,33 @@ static const VMStateDescription vmstate_timers = {
>>      }
>>  };
>>
>> +/*
>> + * This is used instead of vmstate_timers when icount is used.
>> + * cpu_ticks_offset and dummy fields are unused in icount mode so we 
>> can replace
>> + * them with icount variables.
>> + */
>> +static const VMStateDescription icount_vmstate_timers = {
>> +    .name = "timer",
>> +    .version_id = 2,
>> +    .minimum_version_id = 1,
>> +    .minimum_version_id_old = 1,
>> +    .fields      = (VMStateField[]) {
>> +        VMSTATE_INT64(qemu_icount_bias, TimersState),
>> +        VMSTATE_INT64(qemu_icount, TimersState),
>> +        VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2),
>> +        VMSTATE_END_OF_LIST()
>> +    }
>> +};
>> +
>>  void configure_icount(const char *option)
>>  {
>>      seqlock_init(&timers_state.vm_clock_seqlock, NULL);
>> -    vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
>> +
>>      if (!option) {
>> +        vmstate_register(NULL, 0, &vmstate_timers, &timers_state);
>>          return;
>> +    } else {
>> +        vmstate_register(NULL, 0, &icount_vmstate_timers, 
>> &timers_state);
>>      }
>>
>>      icount_warp_timer = timer_new_ns(QEMU_CLOCK_REALTIME,
>>
>
> You can also use a subsection for this.
>
> Paolo

Hi Paolo,
Thanks for review!

Did you mean something like that:

--- a/cpus.c
+++ b/cpus.c
@@ -427,6 +427,26 @@ void qemu_clock_warp(QEMUClockType type)
      }
  }

+static bool icount_state_needed(void *opaque)
+{
+    return (use_icount != 0);
+}
+
+/*
+ * This is a subsection for icount migration.
+ */
+static const VMStateDescription icount_vmstate_timers = {
+    .name = "icount",
+    .version_id = 2,
+    .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,
@@ -437,6 +457,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 */
+        }
      }
  };

Thanks,
Fred

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

* Re: [Qemu-devel] [RFC PATCH 03/12] migration: make qemu_savevm_state public.
  2014-03-21 19:54   ` Dr. David Alan Gilbert
@ 2014-03-24 15:05     ` Frederic Konrad
  2014-03-24 17:52       ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 25+ messages in thread
From: Frederic Konrad @ 2014-03-24 15:05 UTC (permalink / raw)
  To: Dr. David Alan Gilbert; +Cc: mrhines, mark.burton, qemu-devel, quintela

On 21/03/2014 20:54, Dr. David Alan Gilbert wrote:
> * fred.konrad@greensocs.com (fred.konrad@greensocs.com) wrote:
>> From: KONRAD Frederic <fred.konrad@greensocs.com>
>>
>> This makes qemu_savevm_state public for reverse-execution.
> It's interesting that you're doing this repetitive snapshot;
> in some ways it's similar to Michael Hines's code for
> Fault tolerance ( http://lists.gnu.org/archive/html/qemu-devel/2014-02/msg03042.html )
>
> Dave

Hi,

Thanks for the link I missed this.

Seems mc is using live migration and we just checkpoint the whole machine.

That might be a good improvment.

Fred

>
>> Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.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 3915ce3..fe86615 100644
>> --- a/include/sysemu/sysemu.h
>> +++ b/include/sysemu/sysemu.h
>> @@ -78,6 +78,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 d094fbb..e50b716 100644
>> --- a/savevm.c
>> +++ b/savevm.c
>> @@ -635,7 +635,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.8.1.4
>>
>>
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
>

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

* Re: [Qemu-devel] [RFC PATCH 02/12] migration: migrate icount fields.
  2014-03-24 14:49     ` Frederic Konrad
@ 2014-03-24 15:42       ` Paolo Bonzini
  2014-03-25 10:25         ` Frederic Konrad
  0 siblings, 1 reply; 25+ messages in thread
From: Paolo Bonzini @ 2014-03-24 15:42 UTC (permalink / raw)
  To: Frederic Konrad, qemu-devel; +Cc: mark.burton

Il 24/03/2014 15:49, Frederic Konrad ha scritto:
> --- a/cpus.c
> +++ b/cpus.c
> @@ -427,6 +427,26 @@ void qemu_clock_warp(QEMUClockType type)
>      }
>  }
>
> +static bool icount_state_needed(void *opaque)
> +{
> +    return (use_icount != 0);
> +}
> +
> +/*
> + * This is a subsection for icount migration.
> + */
> +static const VMStateDescription icount_vmstate_timers = {
> +    .name = "icount",
> +    .version_id = 2,

1 here.

> +    .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,
> @@ -437,6 +457,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 */
> +        }
>      }
>  };
>
> Thanks,
> Fred

Yes, quite exactly that part from the version_id.  If you can test it, 
this patch would be good for 2.0 too.

Paolo

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

* Re: [Qemu-devel] [RFC PATCH 03/12] migration: make qemu_savevm_state public.
  2014-03-24 15:05     ` Frederic Konrad
@ 2014-03-24 17:52       ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 25+ messages in thread
From: Dr. David Alan Gilbert @ 2014-03-24 17:52 UTC (permalink / raw)
  To: Frederic Konrad; +Cc: mrhines, mark.burton, qemu-devel, quintela

* Frederic Konrad (fred.konrad@greensocs.com) wrote:
> On 21/03/2014 20:54, Dr. David Alan Gilbert wrote:
> >* fred.konrad@greensocs.com (fred.konrad@greensocs.com) wrote:
> >>From: KONRAD Frederic <fred.konrad@greensocs.com>
> >>
> >>This makes qemu_savevm_state public for reverse-execution.
> >It's interesting that you're doing this repetitive snapshot;
> >in some ways it's similar to Michael Hines's code for
> >Fault tolerance ( http://lists.gnu.org/archive/html/qemu-devel/2014-02/msg03042.html )
> >
> >Dave
> 
> Hi,
> 
> Thanks for the link I missed this.
> 
> Seems mc is using live migration and we just checkpoint the whole machine.
> 
> That might be a good improvment.

I doubt it directly; there's not that much difference between snapshot to file
and migrate to file (if you follow the paths they take basically the same route;
I think the only thing is that the snapshot mechanism allows you to save snapshots
into an existing qcow2 file).

However, I was more pointing out the overlap in problem - both of you needing
to take regular snapshots (at probably as quick a rate as you can manage)
but with different criteria for the lifetime and reason for restoration
of the snap.

Dave

> 
> Fred
> 
> >
> >>Signed-off-by: KONRAD Frederic <fred.konrad@greensocs.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 3915ce3..fe86615 100644
> >>--- a/include/sysemu/sysemu.h
> >>+++ b/include/sysemu/sysemu.h
> >>@@ -78,6 +78,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 d094fbb..e50b716 100644
> >>--- a/savevm.c
> >>+++ b/savevm.c
> >>@@ -635,7 +635,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.8.1.4
> >>
> >>
> >--
> >Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> >
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

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

* Re: [Qemu-devel] [RFC PATCH 02/12] migration: migrate icount fields.
  2014-03-24 15:42       ` Paolo Bonzini
@ 2014-03-25 10:25         ` Frederic Konrad
  0 siblings, 0 replies; 25+ messages in thread
From: Frederic Konrad @ 2014-03-25 10:25 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: mark.burton

On 24/03/2014 16:42, Paolo Bonzini wrote:
> Il 24/03/2014 15:49, Frederic Konrad ha scritto:
>> --- a/cpus.c
>> +++ b/cpus.c
>> @@ -427,6 +427,26 @@ void qemu_clock_warp(QEMUClockType type)
>>      }
>>  }
>>
>> +static bool icount_state_needed(void *opaque)
>> +{
>> +    return (use_icount != 0);
>> +}
>> +
>> +/*
>> + * This is a subsection for icount migration.
>> + */
>> +static const VMStateDescription icount_vmstate_timers = {
>> +    .name = "icount",
>> +    .version_id = 2,
>
> 1 here.
>
>> +    .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,
>> @@ -437,6 +457,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 */
>> +        }
>>      }
>>  };
>>
>> Thanks,
>> Fred
>
> Yes, quite exactly that part from the version_id.  If you can test it, 
> this patch would be good for 2.0 too.
>
> Paolo
>
Seems there is a little issue somewhere: Unknown savevm section type 5

I'll try to debug this.

Fred

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

end of thread, other threads:[~2014-03-25 10:26 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-21 19:17 [Qemu-devel] [RFC PATCH 00/12] Reverse execution fred.konrad
2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 01/12] icount: put icount variables into TimerState fred.konrad
2014-03-22  8:58   ` Paolo Bonzini
2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 02/12] migration: migrate icount fields fred.konrad
2014-03-22  8:57   ` Paolo Bonzini
2014-03-24 14:49     ` Frederic Konrad
2014-03-24 15:42       ` Paolo Bonzini
2014-03-25 10:25         ` Frederic Konrad
2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 03/12] migration: make qemu_savevm_state public fred.konrad
2014-03-21 19:54   ` Dr. David Alan Gilbert
2014-03-24 15:05     ` Frederic Konrad
2014-03-24 17:52       ` Dr. David Alan Gilbert
2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 04/12] icount: introduce icount timer fred.konrad
2014-03-22  8:59   ` Paolo Bonzini
2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 05/12] icount: check for icount clock deadline when cpu loop exits fred.konrad
2014-03-22  8:59   ` Paolo Bonzini
2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 06/12] icount: make icount extra computed on icount clock as well fred.konrad
2014-03-22  9:00   ` Paolo Bonzini
2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 07/12] timer: add cpu_icount_to_ns function fred.konrad
2014-03-22  9:00   ` Paolo Bonzini
2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 08/12] introduce reverse execution mechanism fred.konrad
2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 09/12] gdbstub: allow reverse execution in gdb stub fred.konrad
2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 10/12] cpu-exec: trigger a debug request when rexec stops fred.konrad
2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 11/12] cexe: synchronize icount on the next event fred.konrad
2014-03-21 19:17 ` [Qemu-devel] [RFC PATCH 12/12] 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.