From ebd05fea9be1dfd043aaa763fb6d2cd971346a58 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Wed, 29 Nov 2017 20:12:15 +0100 Subject: 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 Message-Id: <20171129191215.11323-1-david@redhat.com> Signed-off-by: Paolo Bonzini --- cpus.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'cpus.c') diff --git a/cpus.c b/cpus.c index 114c29b6a0..3740c4db62 100644 --- a/cpus.c +++ b/cpus.c @@ -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); } } -- cgit 1.4.1 From 80ceb07a83375e3a0091591f96bd47bce2f640ce Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Thu, 23 Nov 2017 17:23:32 +0800 Subject: cpu: refactor cpu_address_space_init() Normally we create an address space for that CPU and pass that address space into the function. Let's just do it inside to unify address space creations. It'll simplify my next patch to rename those address spaces. Signed-off-by: Peter Xu Message-Id: <20171123092333.16085-3-peterx@redhat.com> Signed-off-by: Paolo Bonzini --- cpus.c | 5 +---- exec.c | 7 ++++++- include/exec/exec-all.h | 6 ++++-- target/arm/cpu.c | 13 +++---------- target/i386/cpu.c | 10 ++-------- 5 files changed, 16 insertions(+), 25 deletions(-) (limited to 'cpus.c') diff --git a/cpus.c b/cpus.c index 3740c4db62..83700c1716 100644 --- a/cpus.c +++ b/cpus.c @@ -1787,11 +1787,8 @@ void qemu_init_vcpu(CPUState *cpu) /* If the target cpu hasn't set up any address spaces itself, * give it the default one. */ - AddressSpace *as = g_new0(AddressSpace, 1); - - address_space_init(as, cpu->memory, "cpu-memory"); cpu->num_ases = 1; - cpu_address_space_init(cpu, as, 0); + cpu_address_space_init(cpu, 0, "cpu-memory", cpu->memory); } if (kvm_enabled()) { diff --git a/exec.c b/exec.c index 3e7c57e914..3ab515e47c 100644 --- a/exec.c +++ b/exec.c @@ -705,9 +705,14 @@ CPUState *qemu_get_cpu(int index) } #if !defined(CONFIG_USER_ONLY) -void cpu_address_space_init(CPUState *cpu, AddressSpace *as, int asidx) +void cpu_address_space_init(CPUState *cpu, int asidx, + const char *prefix, MemoryRegion *mr) { CPUAddressSpace *newas; + AddressSpace *as = g_new0(AddressSpace, 1); + + assert(mr); + address_space_init(as, mr, prefix); /* Target code should have set num_ases before calling us */ assert(asidx < cpu->num_ases); diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 0f51c92adb..b37f7d8d92 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -74,8 +74,9 @@ void cpu_reloading_memory_map(void); /** * cpu_address_space_init: * @cpu: CPU to add this address space to - * @as: address space to add * @asidx: integer index of this address space + * @prefix: prefix to be used as name of address space + * @mr: the root memory region of address space * * Add the specified address space to the CPU's cpu_ases list. * The address space added with @asidx 0 is the one used for the @@ -89,7 +90,8 @@ void cpu_reloading_memory_map(void); * * Note that with KVM only one address space is supported. */ -void cpu_address_space_init(CPUState *cpu, AddressSpace *as, int asidx); +void cpu_address_space_init(CPUState *cpu, int asidx, + const char *prefix, MemoryRegion *mr); #endif #if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG) diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 7f7a3d1e32..cc1856c32b 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -705,9 +705,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) CPUARMState *env = &cpu->env; int pagebits; Error *local_err = NULL; -#ifndef CONFIG_USER_ONLY - AddressSpace *as; -#endif cpu_exec_realizefn(cs, &local_err); if (local_err != NULL) { @@ -912,21 +909,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) #ifndef CONFIG_USER_ONLY if (cpu->has_el3 || arm_feature(env, ARM_FEATURE_M_SECURITY)) { - as = g_new0(AddressSpace, 1); - cs->num_ases = 2; if (!cpu->secure_memory) { cpu->secure_memory = cs->memory; } - address_space_init(as, cpu->secure_memory, "cpu-secure-memory"); - cpu_address_space_init(cs, as, ARMASIdx_S); + cpu_address_space_init(cs, ARMASIdx_S, "cpu-secure-memory", + cpu->secure_memory); } else { cs->num_ases = 1; } - as = g_new0(AddressSpace, 1); - address_space_init(as, cs->memory, "cpu-memory"); - cpu_address_space_init(cs, as, ARMASIdx_NS); + cpu_address_space_init(cs, ARMASIdx_NS, "cpu-memory", cs->memory); #endif qemu_init_vcpu(cs); diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 325b52e325..b069eafcc6 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -3736,11 +3736,6 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) #ifndef CONFIG_USER_ONLY if (tcg_enabled()) { - AddressSpace *as_normal = g_new0(AddressSpace, 1); - AddressSpace *as_smm = g_new(AddressSpace, 1); - - address_space_init(as_normal, cs->memory, "cpu-memory"); - cpu->cpu_as_mem = g_new(MemoryRegion, 1); cpu->cpu_as_root = g_new(MemoryRegion, 1); @@ -3755,11 +3750,10 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) get_system_memory(), 0, ~0ull); memory_region_add_subregion_overlap(cpu->cpu_as_root, 0, cpu->cpu_as_mem, 0); memory_region_set_enabled(cpu->cpu_as_mem, true); - address_space_init(as_smm, cpu->cpu_as_root, "CPU"); cs->num_ases = 2; - cpu_address_space_init(cs, as_normal, 0); - cpu_address_space_init(cs, as_smm, 1); + cpu_address_space_init(cs, 0, "cpu-memory", cs->memory); + cpu_address_space_init(cs, 1, "cpu-smm", cpu->cpu_as_root); /* ... SMRAM with higher priority, linked from /machine/smram. */ cpu->machine_done.notify = x86_cpu_machine_done; -- cgit 1.4.1