qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

cpus: avoid pause_all_vcpus getting stuck due to race

We found an issue when repeat reboot in guest during migration, it cause the
migration thread never be waken up again.

<main loop> |<migration_thread>
|
LOCK BQL |
... |
main_loop_should_exit |
pause_all_vcpus |
1. set all cpus ->stop=true |
and then kick |
2. return if all cpus is paused |
(by '->stopped == true'), else|
3. qemu_cond_wait [BQL UNLOCK] |
|LOCK BQL
|...
|do_vm_stop
| pause_all_vcpus
| (A)set all cpus ->stop=true
| and then kick
| (B)return if all cpus is paused
| (by '->stopped == true'), else
| (C)qemu_cond_wait [BQL UNLOCK]
4. be waken up and LOCK BQL | (D)be waken up BUT wait for BQL
5. goto 2. |
(BQL is still LOCKed) |
resume_all_vcpus |
1. set all cpus ->stop=false |
and ->stopped=false |
... |
BQL UNLOCK | (E)LOCK BQL
| (F)goto B. [but stopped is false now!]
|Finally, sleep at step 3 forever.

resume_all_vcpus should notice this race, so we need to move the change
of runstate before pause_all_vcpus in do_vm_stop() and ignore the resume
request if runstate is not running.

Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: Longpeng <longpeng2@huawei.com>
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
Message-Id: <20200316083732.2010-1-longpeng2@huawei.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Longpeng and committed by
Paolo Bonzini
f962cac4 5073b5d3

+5 -1
+5 -1
cpus.c
··· 1026 1026 int ret = 0; 1027 1027 1028 1028 if (runstate_is_running()) { 1029 + runstate_set(state); 1029 1030 cpu_disable_ticks(); 1030 1031 pause_all_vcpus(); 1031 - runstate_set(state); 1032 1032 vm_state_notify(0, state); 1033 1033 if (send_stop) { 1034 1034 qapi_event_send_stop(); ··· 1898 1898 void resume_all_vcpus(void) 1899 1899 { 1900 1900 CPUState *cpu; 1901 + 1902 + if (!runstate_is_running()) { 1903 + return; 1904 + } 1901 1905 1902 1906 qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true); 1903 1907 CPU_FOREACH(cpu) {