diff mbox

[v3,1/2] move vm_start to cpus.c

Message ID 1477674916-6795-2-git-send-email-imbrenda@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Claudio Imbrenda Oct. 28, 2016, 5:15 p.m. UTC
This patch:

* moves vm_start to cpus.c .
* exports qemu_vmstop_requested, since it's needed by vm_start .
* extracts vm_prepare_start from vm_start; it does what vm_start did,
  except restarting the cpus. vm_start now calls vm_prepare_start.
* moves the call to qemu_clock_enable away from resume_all_vcpus, and
  add an explicit call to it before each instance of resume_all_vcpus
  in the code.

Signed-off-by: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
---
 cpus.c                     | 44 +++++++++++++++++++++++++++++++++++++++++++-
 hw/i386/kvmvapic.c         |  2 ++
 include/sysemu/cpus.h      |  1 +
 include/sysemu/sysemu.h    |  2 ++
 target-s390x/misc_helper.c |  2 ++
 vl.c                       | 32 +++-----------------------------
 6 files changed, 53 insertions(+), 30 deletions(-)

Comments

Paolo Bonzini Jan. 25, 2017, 10:21 a.m. UTC | #1
On 28/10/2016 19:15, Claudio Imbrenda wrote:
> * moves the call to qemu_clock_enable away from resume_all_vcpus, and
>   add an explicit call to it before each instance of resume_all_vcpus
>   in the code.

This change adds useless duplication, and isn't matched by a similar
change to pause_all_vcpus.  You need to justify it; I suppose it is
because the next patch will not call resume_all_cpus?

Most of the callers of pause_all_vcpus/resume_all_vcpus don't let timers
run, so the clock need not be disabled and enabled.  Maybe the right
places to call qemu_clock_enable are cpu_disable_ticks and
cpu_enable_ticks?  That should work for you.

In that case, please make the first patch the qemu_clock_enable
movement; the second patch the introduction of vm_prepare_start; the
third patch the gdbstub change.

> diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h
> index 3728a1e..5fa074b 100644
> --- a/include/sysemu/cpus.h
> +++ b/include/sysemu/cpus.h
> @@ -5,6 +5,7 @@
>  bool qemu_in_vcpu_thread(void);
>  void qemu_init_cpu_loop(void);
>  void resume_all_vcpus(void);
> +void resume_some_vcpus(CPUState **cpus);
>  void pause_all_vcpus(void);
>  void cpu_stop_current(void);
>  void cpu_ticks_init(void);

This function doesn't exist.

Paolo
Claudio Imbrenda Jan. 25, 2017, 5:53 p.m. UTC | #2
On 25/01/17 11:21, Paolo Bonzini wrote:
> 
> 
> On 28/10/2016 19:15, Claudio Imbrenda wrote:
>> * moves the call to qemu_clock_enable away from resume_all_vcpus, and
>>   add an explicit call to it before each instance of resume_all_vcpus
>>   in the code.
> 
> This change adds useless duplication, and isn't matched by a similar
> change to pause_all_vcpus.  You need to justify it; I suppose it is
> because the next patch will not call resume_all_cpus?

Actually it is because the next patch used to call resume_all_vcpus, and
we didn't want it to restart the clock too. But then I ended up not
using resume_all_vcpus.

And now I have actually no idea why we didn't want to restart the clock.
Maybe we should? After all some CPUs are running. I can patch
gdb_continue_partial to check if any CPU was actually restarted, and if
so start the clock.

So in the end it should still be correct, but the changes would be kept
small.

> Most of the callers of pause_all_vcpus/resume_all_vcpus don't let timers
> run, so the clock need not be disabled and enabled.  Maybe the right
> places to call qemu_clock_enable are cpu_disable_ticks and
> cpu_enable_ticks?  That should work for you.
> 
> In that case, please make the first patch the qemu_clock_enable
> movement; the second patch the introduction of vm_prepare_start; the
> third patch the gdbstub change.
> 
>> diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h
>> index 3728a1e..5fa074b 100644
>> --- a/include/sysemu/cpus.h
>> +++ b/include/sysemu/cpus.h
>> @@ -5,6 +5,7 @@
>>  bool qemu_in_vcpu_thread(void);
>>  void qemu_init_cpu_loop(void);
>>  void resume_all_vcpus(void);
>> +void resume_some_vcpus(CPUState **cpus);
>>  void pause_all_vcpus(void);
>>  void cpu_stop_current(void);
>>  void cpu_ticks_init(void);
> 
> This function doesn't exist.

oops.


Claudio
Paolo Bonzini Jan. 25, 2017, 6:02 p.m. UTC | #3
On 25/01/2017 18:53, Claudio Imbrenda wrote:
> On 25/01/17 11:21, Paolo Bonzini wrote:
>>
>>
>> On 28/10/2016 19:15, Claudio Imbrenda wrote:
>>> * moves the call to qemu_clock_enable away from resume_all_vcpus, and
>>>   add an explicit call to it before each instance of resume_all_vcpus
>>>   in the code.
>>
>> This change adds useless duplication, and isn't matched by a similar
>> change to pause_all_vcpus.  You need to justify it; I suppose it is
>> because the next patch will not call resume_all_cpus?
> 
> Actually it is because the next patch used to call resume_all_vcpus, and
> we didn't want it to restart the clock too. But then I ended up not
> using resume_all_vcpus.
> 
> And now I have actually no idea why we didn't want to restart the clock.
> Maybe we should? After all some CPUs are running. I can patch
> gdb_continue_partial to check if any CPU was actually restarted, and if
> so start the clock.
> 
> So in the end it should still be correct, but the changes would be kept
> small.

Yeah, this sounds like a good solution.  Thanks!

Paolo

>> Most of the callers of pause_all_vcpus/resume_all_vcpus don't let timers
>> run, so the clock need not be disabled and enabled.  Maybe the right
>> places to call qemu_clock_enable are cpu_disable_ticks and
>> cpu_enable_ticks?  That should work for you.
>>
>> In that case, please make the first patch the qemu_clock_enable
>> movement; the second patch the introduction of vm_prepare_start; the
>> third patch the gdbstub change.
>>
>>> diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h
>>> index 3728a1e..5fa074b 100644
>>> --- a/include/sysemu/cpus.h
>>> +++ b/include/sysemu/cpus.h
>>> @@ -5,6 +5,7 @@
>>>  bool qemu_in_vcpu_thread(void);
>>>  void qemu_init_cpu_loop(void);
>>>  void resume_all_vcpus(void);
>>> +void resume_some_vcpus(CPUState **cpus);
>>>  void pause_all_vcpus(void);
>>>  void cpu_stop_current(void);
>>>  void cpu_ticks_init(void);
>>
>> This function doesn't exist.
> 
> oops.
> 
> 
> Claudio
>
diff mbox

Patch

diff --git a/cpus.c b/cpus.c
index cfd5cdc..34667fa 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1260,7 +1260,6 @@  void resume_all_vcpus(void)
 {
     CPUState *cpu;
 
-    qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
     CPU_FOREACH(cpu) {
         cpu_resume(cpu);
     }
@@ -1396,6 +1395,49 @@  int vm_stop(RunState state)
     return do_vm_stop(state);
 }
 
+/**
+ * Prepare for (re)starting the VM.
+ * Returns -1 if the vCPUs are not to be restarted (e.g. if they are already
+ * running or in case of an error condition), 0 otherwise.
+ */
+int vm_prepare_start(void)
+{
+    RunState requested;
+    int res = 0;
+
+    qemu_vmstop_requested(&requested);
+    if (runstate_is_running() && requested == RUN_STATE__MAX) {
+        return -1;
+    }
+
+    /* Ensure that a STOP/RESUME pair of events is emitted if a
+     * vmstop request was pending.  The BLOCK_IO_ERROR event, for
+     * example, according to documentation is always followed by
+     * the STOP event.
+     */
+    if (runstate_is_running()) {
+        qapi_event_send_stop(&error_abort);
+        res = -1;
+    } else {
+        replay_enable_events();
+        cpu_enable_ticks();
+        runstate_set(RUN_STATE_RUNNING);
+        vm_state_notify(1, RUN_STATE_RUNNING);
+    }
+
+    /* XXX: is it ok to send this even before actually resuming the CPUs? */
+    qapi_event_send_resume(&error_abort);
+    return res;
+}
+
+void vm_start(void)
+{
+    if (!vm_prepare_start()) {
+        qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
+        resume_all_vcpus();
+    }
+}
+
 /* does a state transition even if the VM is already stopped,
    current state is forgotten forever */
 int vm_stop_force_state(RunState state)
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index 74a549b..3101860 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -446,6 +446,7 @@  static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
         abort();
     }
 
+    qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
     resume_all_vcpus();
 
     if (!kvm_enabled()) {
@@ -686,6 +687,7 @@  static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
             pause_all_vcpus();
             patch_byte(cpu, env->eip - 2, 0x66);
             patch_byte(cpu, env->eip - 1, 0x90);
+            qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
             resume_all_vcpus();
         }
 
diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h
index 3728a1e..5fa074b 100644
--- a/include/sysemu/cpus.h
+++ b/include/sysemu/cpus.h
@@ -5,6 +5,7 @@ 
 bool qemu_in_vcpu_thread(void);
 void qemu_init_cpu_loop(void);
 void resume_all_vcpus(void);
+void resume_some_vcpus(CPUState **cpus);
 void pause_all_vcpus(void);
 void cpu_stop_current(void);
 void cpu_ticks_init(void);
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 66c6f15..ebe8b76 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -37,6 +37,7 @@  void vm_state_notify(int running, RunState state);
 #define VMRESET_REPORT   true
 
 void vm_start(void);
+int vm_prepare_start(void);
 int vm_stop(RunState state);
 int vm_stop_force_state(RunState state);
 
@@ -60,6 +61,7 @@  void qemu_register_powerdown_notifier(Notifier *notifier);
 void qemu_system_debug_request(void);
 void qemu_system_vmstop_request(RunState reason);
 void qemu_system_vmstop_request_prepare(void);
+bool qemu_vmstop_requested(RunState *r);
 int qemu_shutdown_requested_get(void);
 int qemu_reset_requested_get(void);
 void qemu_system_killed(int signal, pid_t pid);
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index 4df2ec6..2b74710 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -133,6 +133,7 @@  static int modified_clear_reset(S390CPU *cpu)
     s390_crypto_reset();
     scc->load_normal(CPU(cpu));
     cpu_synchronize_all_post_reset();
+    qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
     resume_all_vcpus();
     return 0;
 }
@@ -152,6 +153,7 @@  static int load_normal_reset(S390CPU *cpu)
     scc->initial_cpu_reset(CPU(cpu));
     scc->load_normal(CPU(cpu));
     cpu_synchronize_all_post_reset();
+    qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
     resume_all_vcpus();
     return 0;
 }
diff --git a/vl.c b/vl.c
index 4ec8120..e2dbc45 100644
--- a/vl.c
+++ b/vl.c
@@ -746,7 +746,7 @@  StatusInfo *qmp_query_status(Error **errp)
     return info;
 }
 
-static bool qemu_vmstop_requested(RunState *r)
+bool qemu_vmstop_requested(RunState *r)
 {
     qemu_mutex_lock(&vmstop_lock);
     *r = vmstop_requested;
@@ -767,34 +767,6 @@  void qemu_system_vmstop_request(RunState state)
     qemu_notify_event();
 }
 
-void vm_start(void)
-{
-    RunState requested;
-
-    qemu_vmstop_requested(&requested);
-    if (runstate_is_running() && requested == RUN_STATE__MAX) {
-        return;
-    }
-
-    /* Ensure that a STOP/RESUME pair of events is emitted if a
-     * vmstop request was pending.  The BLOCK_IO_ERROR event, for
-     * example, according to documentation is always followed by
-     * the STOP event.
-     */
-    if (runstate_is_running()) {
-        qapi_event_send_stop(&error_abort);
-    } else {
-        replay_enable_events();
-        cpu_enable_ticks();
-        runstate_set(RUN_STATE_RUNNING);
-        vm_state_notify(1, RUN_STATE_RUNNING);
-        resume_all_vcpus();
-    }
-
-    qapi_event_send_resume(&error_abort);
-}
-
-
 /***********************************************************/
 /* real time host monotonic timer */
 
@@ -1914,6 +1886,7 @@  static bool main_loop_should_exit(void)
     if (qemu_reset_requested()) {
         pause_all_vcpus();
         qemu_system_reset(VMRESET_REPORT);
+        qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
         resume_all_vcpus();
         if (!runstate_check(RUN_STATE_RUNNING) &&
                 !runstate_check(RUN_STATE_INMIGRATE)) {
@@ -1925,6 +1898,7 @@  static bool main_loop_should_exit(void)
         qemu_system_reset(VMRESET_SILENT);
         notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
         wakeup_reason = QEMU_WAKEUP_REASON_NONE;
+        qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
         resume_all_vcpus();
         qapi_event_send_wakeup(&error_abort);
     }