qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/3] implement a new icount sleep=no mode
@ 2015-05-29 15:14 Victor CLEMENT
  2015-05-29 15:14 ` [Qemu-devel] [PATCH v2 1/3] icount: implement a new icount_sleep mode toggleing real-time cpu sleep Victor CLEMENT
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Victor CLEMENT @ 2015-05-29 15:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: francois.guerret, pbonzini, Victor CLEMENT, julien.viarddegalbert

This patch adds a new icount_sleep mode set by the new 'sleep' parameter
of the icount option.
When using sleep=no mode, the QEMU_VIRTUAL_CLOCK will be running at
the maximal possible speed by warping the CPU sleep times to the soonest
virtual clock deadline.
The goal is to get deterministic execution times by preventing potential
latencies from qemu execution on the host machine.
The virtual cpus sleep time will be calculated but not spent, hence the
virtual time will not be realistic when looking from the host point of view
(ex. a 'sleep 10' on the guest will return almost instantly while the
guest clock wil act like 10s have really passed)

This new mode will be used for testing real-time applications inside qemu.
It makes the virtual clock "purely" virtual by removing any reference to
host clocks in the calculation of QEMU_VIRTUAL_CLOCK value.

To test real-time software using this mode, one need to write some scenario
which will simulate inputs on an emulated device then record traces from
this inputs and the associated outputs from the tested software.


Victor CLEMENT (3):
  icount: implement a new icount_sleep mode toggleing real-time cpu
    sleep
  icount: add sleep parameter to the icount option to set icount_sleep
    mode
  icount: print a warning if there is no more deadline in sleep=no mode

 cpus.c          | 85 +++++++++++++++++++++++++++++++++++++++------------------
 qemu-options.hx | 12 ++++++--
 vl.c            |  3 ++
 3 files changed, 72 insertions(+), 28 deletions(-)

-- 
2.4.2

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

* [Qemu-devel] [PATCH v2 1/3] icount: implement a new icount_sleep mode toggleing real-time cpu sleep
  2015-05-29 15:14 [Qemu-devel] [PATCH v2 0/3] implement a new icount sleep=no mode Victor CLEMENT
@ 2015-05-29 15:14 ` Victor CLEMENT
  2015-05-29 15:14 ` [Qemu-devel] [PATCH v2 2/3] icount: add sleep parameter to the icount option to set icount_sleep mode Victor CLEMENT
  2015-05-29 15:14 ` [Qemu-devel] [PATCH v2 3/3] icount: print a warning if there is no more deadline in sleep=no mode Victor CLEMENT
  2 siblings, 0 replies; 5+ messages in thread
From: Victor CLEMENT @ 2015-05-29 15:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: francois.guerret, pbonzini, Victor CLEMENT, julien.viarddegalbert

When the icount_sleep mode is disabled, the QEMU_VIRTUAL_CLOCK runs at the
maximum possible speed by warping the sleep times of the virtual cpu to the
soonest clock deadline. The virtual clock will be updated only according
the instruction counter.

Signed-off-by: Victor CLEMENT <victor.clement@openwide.fr>
---
 cpus.c | 70 +++++++++++++++++++++++++++++++++++++++++-------------------------
 1 file changed, 44 insertions(+), 26 deletions(-)

diff --git a/cpus.c b/cpus.c
index de6469f..688eb73 100644
--- a/cpus.c
+++ b/cpus.c
@@ -105,6 +105,7 @@ static bool all_cpu_threads_idle(void)
 
 /* Protected by TimersState seqlock */
 
+static bool icount_sleep = true;
 static int64_t vm_clock_warp_start = -1;
 /* Conversion factor from emulated instructions to virtual clock ticks.  */
 static int icount_time_shift;
@@ -393,15 +394,18 @@ void qemu_clock_warp(QEMUClockType type)
         return;
     }
 
-    /*
-     * If the CPUs have been sleeping, advance QEMU_CLOCK_VIRTUAL timer now.
-     * This ensures that the deadline for the timer is computed correctly below.
-     * This also makes sure that the insn counter is synchronized before the
-     * CPU starts running, in case the CPU is woken by an event other than
-     * the earliest QEMU_CLOCK_VIRTUAL timer.
-     */
-    icount_warp_rt(NULL);
-    timer_del(icount_warp_timer);
+    if (icount_sleep) {
+        /*
+         * If the CPUs have been sleeping, advance QEMU_CLOCK_VIRTUAL timer now.
+         * This ensures that the deadline for the timer is computed correctly
+         * below.
+         * This also makes sure that the insn counter is synchronized before
+         * the CPU starts running, in case the CPU is woken by an event other
+         * than the earliest QEMU_CLOCK_VIRTUAL timer.
+         */
+        icount_warp_rt(NULL);
+        timer_del(icount_warp_timer);
+    }
     if (!all_cpu_threads_idle()) {
         return;
     }
@@ -425,23 +429,35 @@ void qemu_clock_warp(QEMUClockType type)
          * interrupt to wake it up, but the interrupt never comes because
          * the vCPU isn't running any insns and thus doesn't advance the
          * QEMU_CLOCK_VIRTUAL.
-         *
-         * An extreme solution for this problem would be to never let VCPUs
-         * sleep in icount mode if there is a pending QEMU_CLOCK_VIRTUAL
-         * timer; rather time could just advance to the next QEMU_CLOCK_VIRTUAL
-         * event.  Instead, we do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL
-         * after some "real" time, (related to the time left until the next
-         * event) has passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this.
-         * This avoids that the warps are visible externally; for example,
-         * you will not be sending network packets continuously instead of
-         * every 100ms.
          */
-        seqlock_write_lock(&timers_state.vm_clock_seqlock);
-        if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) {
-            vm_clock_warp_start = clock;
+        if (!icount_sleep) {
+            /*
+             * We never let VCPUs sleep in no sleep icount mode.
+             * If there is a pending QEMU_CLOCK_VIRTUAL timer we just advance
+             * to the next QEMU_CLOCK_VIRTUAL event and notify it.
+             * It is useful when we want a deterministic execution time,
+             * isolated from host latencies.
+             */
+            seqlock_write_lock(&timers_state.vm_clock_seqlock);
+            timers_state.qemu_icount_bias += deadline;
+            seqlock_write_unlock(&timers_state.vm_clock_seqlock);
+            qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
+        } else {
+            /*
+             * We do stop VCPUs and only advance QEMU_CLOCK_VIRTUAL after some
+             * "real" time, (related to the time left until the next event) has
+             * passed. The QEMU_CLOCK_VIRTUAL_RT clock will do this.
+             * This avoids that the warps are visible externally; for example,
+             * you will not be sending network packets continuously instead of
+             * every 100ms.
+             */
+            seqlock_write_lock(&timers_state.vm_clock_seqlock);
+            if (vm_clock_warp_start == -1 || vm_clock_warp_start > clock) {
+                vm_clock_warp_start = clock;
+            }
+            seqlock_write_unlock(&timers_state.vm_clock_seqlock);
+            timer_mod_anticipate(icount_warp_timer, clock + deadline);
         }
-        seqlock_write_unlock(&timers_state.vm_clock_seqlock);
-        timer_mod_anticipate(icount_warp_timer, clock + deadline);
     } else if (deadline == 0) {
         qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
     }
@@ -504,9 +520,11 @@ void configure_icount(QemuOpts *opts, Error **errp)
         }
         return;
     }
+    if (icount_sleep) {
+        icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
+                                         icount_warp_rt, NULL);
+    }
     icount_align_option = qemu_opt_get_bool(opts, "align", false);
-    icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
-                                     icount_warp_rt, NULL);
     if (strcmp(option, "auto") != 0) {
         errno = 0;
         icount_time_shift = strtol(option, &rem_str, 0);
-- 
2.4.2

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

* [Qemu-devel] [PATCH v2 2/3] icount: add sleep parameter to the icount option to set icount_sleep mode
  2015-05-29 15:14 [Qemu-devel] [PATCH v2 0/3] implement a new icount sleep=no mode Victor CLEMENT
  2015-05-29 15:14 ` [Qemu-devel] [PATCH v2 1/3] icount: implement a new icount_sleep mode toggleing real-time cpu sleep Victor CLEMENT
@ 2015-05-29 15:14 ` Victor CLEMENT
  2015-05-29 15:14 ` [Qemu-devel] [PATCH v2 3/3] icount: print a warning if there is no more deadline in sleep=no mode Victor CLEMENT
  2 siblings, 0 replies; 5+ messages in thread
From: Victor CLEMENT @ 2015-05-29 15:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: francois.guerret, pbonzini, Victor CLEMENT, julien.viarddegalbert

The 'sleep' parameter sets the icount_sleep mode, which is enabled by
default. To disable it, add the 'sleep=no' parameter (or 'nosleep') to the
qemu -icount option.

Signed-off-by: Victor CLEMENT <victor.clement@openwide.fr>
---
 cpus.c          |  9 +++++++++
 qemu-options.hx | 12 ++++++++++--
 vl.c            |  3 +++
 3 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/cpus.c b/cpus.c
index 688eb73..4e90e63 100644
--- a/cpus.c
+++ b/cpus.c
@@ -520,11 +520,18 @@ void configure_icount(QemuOpts *opts, Error **errp)
         }
         return;
     }
+
+    icount_sleep = qemu_opt_get_bool(opts, "sleep", true);
     if (icount_sleep) {
         icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
                                          icount_warp_rt, NULL);
     }
+
     icount_align_option = qemu_opt_get_bool(opts, "align", false);
+
+    if (icount_align_option && !icount_sleep) {
+        error_setg(errp, "align=on and sleep=no are incompatible");
+    }
     if (strcmp(option, "auto") != 0) {
         errno = 0;
         icount_time_shift = strtol(option, &rem_str, 0);
@@ -535,6 +542,8 @@ void configure_icount(QemuOpts *opts, Error **errp)
         return;
     } else if (icount_align_option) {
         error_setg(errp, "shift=auto and align=on are incompatible");
+    } else if (!icount_sleep) {
+        error_setg(errp, "shift=auto and sleep=no are incompatible");
     }
 
     use_icount = 2;
diff --git a/qemu-options.hx b/qemu-options.hx
index ec356f6..c245714 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3086,9 +3086,10 @@ re-inject them.
 ETEXI
 
 DEF("icount", HAS_ARG, QEMU_OPTION_icount, \
-    "-icount [shift=N|auto][,align=on|off]\n" \
+    "-icount [shift=N|auto][,align=on|off][,sleep=no]\n" \
     "                enable virtual instruction counter with 2^N clock ticks per\n" \
-    "                instruction and enable aligning the host and virtual clocks\n", QEMU_ARCH_ALL)
+    "                instruction, enable aligning the host and virtual clocks\n" \
+    "                or disable real time cpu sleeping\n", QEMU_ARCH_ALL)
 STEXI
 @item -icount [shift=@var{N}|auto]
 @findex -icount
@@ -3097,6 +3098,13 @@ instruction every 2^@var{N} ns of virtual time.  If @code{auto} is specified
 then the virtual cpu speed will be automatically adjusted to keep virtual
 time within a few seconds of real time.
 
+When the virtual cpu is sleeping, the virtual time will advance at default
+speed unless @option{sleep=no} is specified.
+With @option{sleep=no}, the virtual time will jump to the next timer deadline
+instantly whenever the virtual cpu goes to sleep mode and will not advance
+if no timer is enabled. This behavior give deterministic execution times from
+the guest point of view.
+
 Note that while this option can give deterministic behavior, it does not
 provide cycle accurate emulation.  Modern CPUs contain superscalar out of
 order cores with complex cache hierarchies.  The number of instructions
diff --git a/vl.c b/vl.c
index 15bccc4..79e2e07 100644
--- a/vl.c
+++ b/vl.c
@@ -470,6 +470,9 @@ static QemuOptsList qemu_icount_opts = {
         }, {
             .name = "align",
             .type = QEMU_OPT_BOOL,
+        }, {
+            .name = "sleep",
+            .type = QEMU_OPT_BOOL,
         },
         { /* end of list */ }
     },
-- 
2.4.2

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

* [Qemu-devel] [PATCH v2 3/3] icount: print a warning if there is no more deadline in sleep=no mode
  2015-05-29 15:14 [Qemu-devel] [PATCH v2 0/3] implement a new icount sleep=no mode Victor CLEMENT
  2015-05-29 15:14 ` [Qemu-devel] [PATCH v2 1/3] icount: implement a new icount_sleep mode toggleing real-time cpu sleep Victor CLEMENT
  2015-05-29 15:14 ` [Qemu-devel] [PATCH v2 2/3] icount: add sleep parameter to the icount option to set icount_sleep mode Victor CLEMENT
@ 2015-05-29 15:14 ` Victor CLEMENT
  2015-05-29 16:38   ` Paolo Bonzini
  2 siblings, 1 reply; 5+ messages in thread
From: Victor CLEMENT @ 2015-05-29 15:14 UTC (permalink / raw)
  To: qemu-devel
  Cc: francois.guerret, pbonzini, Victor CLEMENT, julien.viarddegalbert

While qemu is running in sleep=no mode, a warning will be printed
when no timer deadline is set.
As this mode is intended for getting deterministic virtual time, if no
timer is set on the virtual clock this determinism is broken.

Signed-off-by: Victor CLEMENT <victor.clement@openwide.fr>
---
 cpus.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/cpus.c b/cpus.c
index 4e90e63..aec17b6 100644
--- a/cpus.c
+++ b/cpus.c
@@ -419,6 +419,12 @@ void qemu_clock_warp(QEMUClockType type)
     clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT);
     deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
     if (deadline < 0) {
+        static bool notified;
+        if (!icount_sleep && !notified) {
+            fprintf(stderr, "cpus: WARNING: icount sleep disabled and no more \
+active timer\n");
+            notified = true;
+        }
         return;
     }
 
-- 
2.4.2

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

* Re: [Qemu-devel] [PATCH v2 3/3] icount: print a warning if there is no more deadline in sleep=no mode
  2015-05-29 15:14 ` [Qemu-devel] [PATCH v2 3/3] icount: print a warning if there is no more deadline in sleep=no mode Victor CLEMENT
@ 2015-05-29 16:38   ` Paolo Bonzini
  0 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2015-05-29 16:38 UTC (permalink / raw)
  To: Victor CLEMENT, qemu-devel; +Cc: francois.guerret, julien.viarddegalbert



On 29/05/2015 17:14, Victor CLEMENT wrote:
> While qemu is running in sleep=no mode, a warning will be printed
> when no timer deadline is set.
> As this mode is intended for getting deterministic virtual time, if no
> timer is set on the virtual clock this determinism is broken.
> 
> Signed-off-by: Victor CLEMENT <victor.clement@openwide.fr>
> ---
>  cpus.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/cpus.c b/cpus.c
> index 4e90e63..aec17b6 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -419,6 +419,12 @@ void qemu_clock_warp(QEMUClockType type)
>      clock = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL_RT);
>      deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL);
>      if (deadline < 0) {
> +        static bool notified;
> +        if (!icount_sleep && !notified) {
> +            fprintf(stderr, "cpus: WARNING: icount sleep disabled and no more \
> +active timer\n");

I'm changing this to error_report, and queuing the series for 2.4 with
no other changes.  Expect it to be in a pull request next week!

Paolo

> +            notified = true;
> +        }
>          return;
>      }
>  
> 

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

end of thread, other threads:[~2015-05-29 16:38 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-29 15:14 [Qemu-devel] [PATCH v2 0/3] implement a new icount sleep=no mode Victor CLEMENT
2015-05-29 15:14 ` [Qemu-devel] [PATCH v2 1/3] icount: implement a new icount_sleep mode toggleing real-time cpu sleep Victor CLEMENT
2015-05-29 15:14 ` [Qemu-devel] [PATCH v2 2/3] icount: add sleep parameter to the icount option to set icount_sleep mode Victor CLEMENT
2015-05-29 15:14 ` [Qemu-devel] [PATCH v2 3/3] icount: print a warning if there is no more deadline in sleep=no mode Victor CLEMENT
2015-05-29 16:38   ` Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).