Commit ebd05fea authored by David Hildenbrand's avatar David Hildenbrand Committed by Paolo Bonzini
Browse files

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: default avatarDavid Hildenbrand <david@redhat.com>
Message-Id: <20171129191215.11323-1-david@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 09df29b6
Loading
Loading
Loading
Loading
+19 −13
Original line number Diff line number Diff line
@@ -1057,14 +1057,23 @@ static void qemu_tcg_destroy_vcpu(CPUState *cpu)
{
}

static void qemu_wait_io_event_common(CPUState *cpu)
static void qemu_cpu_stop(CPUState *cpu, bool exit)
{
    atomic_mb_set(&cpu->thread_kicked, false);
    if (cpu->stop) {
    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) {
        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) {
        if (qemu_cpu_is_self(cpu)) {
            qemu_cpu_stop(cpu, true);
        } else {
            cpu->stop = true;
            qemu_cpu_kick(cpu);
        }

    if (qemu_in_vcpu_thread()) {
        cpu_stop_current();
    }

    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);
    }
}