cpus: make pause_all_cpus() play with SMP on single threaded TCG

pause_all_cpus() is sometimes called from a VCPU thread (e.g. s390x
during special reset). It cannot deal with multiple VCPUs per Thread
(single threaded TCG) yet.

Booting an s390x guest with -smp 2 and single threaded TCG from disk
currently fails. The DIAG 308 will issue a pause_all_cpus() and wait
forever for the CPUs to actually stop. But it is waiting for itself.

So let's stop all VCPUs belonging to the current thread. Factor out
stopping of a VCPU.

Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20171129191215.11323-1-david@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
master
David Hildenbrand 2017-11-29 20:12:15 +01:00 committed by Paolo Bonzini
parent 09df29b665
commit ebd05fea9b
1 changed files with 19 additions and 13 deletions

32
cpus.c
View File

@ -1057,13 +1057,22 @@ static void qemu_tcg_destroy_vcpu(CPUState *cpu)
{
}
static void qemu_cpu_stop(CPUState *cpu, bool exit)
{
g_assert(qemu_cpu_is_self(cpu));
cpu->stop = false;
cpu->stopped = true;
if (exit) {
cpu_exit(cpu);
}
qemu_cond_broadcast(&qemu_pause_cond);
}
static void qemu_wait_io_event_common(CPUState *cpu)
{
atomic_mb_set(&cpu->thread_kicked, false);
if (cpu->stop) {
cpu->stop = false;
cpu->stopped = true;
qemu_cond_broadcast(&qemu_pause_cond);
qemu_cpu_stop(cpu, false);
}
process_queued_cpu_work(cpu);
}
@ -1610,12 +1619,12 @@ void pause_all_vcpus(void)
qemu_clock_enable(QEMU_CLOCK_VIRTUAL, false);
CPU_FOREACH(cpu) {
cpu->stop = true;
qemu_cpu_kick(cpu);
}
if (qemu_in_vcpu_thread()) {
cpu_stop_current();
if (qemu_cpu_is_self(cpu)) {
qemu_cpu_stop(cpu, true);
} else {
cpu->stop = true;
qemu_cpu_kick(cpu);
}
}
while (!all_vcpus_paused()) {
@ -1799,10 +1808,7 @@ void qemu_init_vcpu(CPUState *cpu)
void cpu_stop_current(void)
{
if (current_cpu) {
current_cpu->stop = false;
current_cpu->stopped = true;
cpu_exit(current_cpu);
qemu_cond_broadcast(&qemu_pause_cond);
qemu_cpu_stop(current_cpu, true);
}
}