diff options
author | David Hildenbrand <david@redhat.com> | 2018-04-24 12:18:59 +0200 |
---|---|---|
committer | Cornelia Huck <cohuck@redhat.com> | 2018-05-14 17:10:02 +0200 |
commit | a30fb811cbe940020a498d2cdac9326cac38b4d9 (patch) | |
tree | f4284495670fe38f7923834ce42012bc56c35e9c /target/s390x | |
parent | 838fb84f83c84f00d15b1bede5e080b495644458 (diff) |
s390x: refactor reset/reipl handling
Calling pause_all_vcpus()/resume_all_vcpus() from a VCPU thread might
not be the best idea. As pause_all_vcpus() temporarily drops the qemu
mutex, two parallel calls to pause_all_vcpus() can be active at a time,
resulting in a deadlock. (either by two VCPUs or by the main thread and a
VCPU)
Let's handle it via the main loop instead, as suggested by Paolo. If we
would have two parallel reset requests by two different VCPUs at the
same time, the last one would win.
We use the existing ipl device to handle it. The nice side effect is
that we can get rid of reipl_requested.
This change implies that all reset handling now goes via the common
path, so "no-reboot" handling is now active for all kinds of reboots.
Let's execute any CPU initialization code on the target CPU using
run_on_cpu.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20180424101859.10239-1-david@redhat.com>
Acked-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
Diffstat (limited to 'target/s390x')
-rw-r--r-- | target/s390x/cpu.h | 26 | ||||
-rw-r--r-- | target/s390x/diag.c | 61 | ||||
-rw-r--r-- | target/s390x/internal.h | 6 | ||||
-rw-r--r-- | target/s390x/kvm.c | 2 |
4 files changed, 31 insertions, 64 deletions
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h index 3ee40f08b7..6629a533f3 100644 --- a/target/s390x/cpu.h +++ b/target/s390x/cpu.h @@ -686,6 +686,32 @@ static inline uint64_t s390_build_validity_mcic(void) return mcic; } +static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg) +{ + cpu_reset(cs); +} + +static inline void s390_do_cpu_reset(CPUState *cs, run_on_cpu_data arg) +{ + S390CPUClass *scc = S390_CPU_GET_CLASS(cs); + + scc->cpu_reset(cs); +} + +static inline void s390_do_cpu_initial_reset(CPUState *cs, run_on_cpu_data arg) +{ + S390CPUClass *scc = S390_CPU_GET_CLASS(cs); + + scc->initial_cpu_reset(cs); +} + +static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg) +{ + S390CPUClass *scc = S390_CPU_GET_CLASS(cs); + + scc->load_normal(cs); +} + /* cpu.c */ int s390_get_clock(uint8_t *tod_high, uint64_t *tod_low); diff --git a/target/s390x/diag.c b/target/s390x/diag.c index a755837ad5..ac2c40f363 100644 --- a/target/s390x/diag.c +++ b/target/s390x/diag.c @@ -22,51 +22,6 @@ #include "hw/s390x/ipl.h" #include "hw/s390x/s390-virtio-ccw.h" -static int modified_clear_reset(S390CPU *cpu) -{ - S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); - CPUState *t; - - pause_all_vcpus(); - cpu_synchronize_all_states(); - CPU_FOREACH(t) { - run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); - } - s390_cmma_reset(); - subsystem_reset(); - s390_crypto_reset(); - scc->load_normal(CPU(cpu)); - cpu_synchronize_all_post_reset(); - resume_all_vcpus(); - return 0; -} - -static inline void s390_do_cpu_reset(CPUState *cs, run_on_cpu_data arg) -{ - S390CPUClass *scc = S390_CPU_GET_CLASS(cs); - - scc->cpu_reset(cs); -} - -static int load_normal_reset(S390CPU *cpu) -{ - S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); - CPUState *t; - - pause_all_vcpus(); - cpu_synchronize_all_states(); - CPU_FOREACH(t) { - run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL); - } - s390_cmma_reset(); - subsystem_reset(); - scc->initial_cpu_reset(CPU(cpu)); - scc->load_normal(CPU(cpu)); - cpu_synchronize_all_post_reset(); - resume_all_vcpus(); - return 0; -} - int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) { uint64_t func = env->regs[r1]; @@ -101,6 +56,7 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) { + CPUState *cs = CPU(s390_env_get_cpu(env)); uint64_t addr = env->regs[r1]; uint64_t subcode = env->regs[r3]; IplParameterBlock *iplb; @@ -117,22 +73,13 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) switch (subcode) { case 0: - modified_clear_reset(s390_env_get_cpu(env)); - if (tcg_enabled()) { - cpu_loop_exit(CPU(s390_env_get_cpu(env))); - } + s390_ipl_reset_request(cs, S390_RESET_MODIFIED_CLEAR); break; case 1: - load_normal_reset(s390_env_get_cpu(env)); - if (tcg_enabled()) { - cpu_loop_exit(CPU(s390_env_get_cpu(env))); - } + s390_ipl_reset_request(cs, S390_RESET_LOAD_NORMAL); break; case 3: - s390_reipl_request(); - if (tcg_enabled()) { - cpu_loop_exit(CPU(s390_env_get_cpu(env))); - } + s390_ipl_reset_request(cs, S390_RESET_REIPL); break; case 5: if ((r1 & 1) || (addr & 0x0fffULL)) { diff --git a/target/s390x/internal.h b/target/s390x/internal.h index d911e84958..e392a02d12 100644 --- a/target/s390x/internal.h +++ b/target/s390x/internal.h @@ -273,12 +273,6 @@ static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb, /* Base/displacement are at the same locations. */ #define decode_basedisp_rs decode_basedisp_s -static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg) -{ - cpu_reset(cs); -} - - /* arch_dump.c */ int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, int cpuid, void *opaque); diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c index 12b90cf5c5..58e4380ae3 100644 --- a/target/s390x/kvm.c +++ b/target/s390x/kvm.c @@ -1767,7 +1767,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) ret = handle_intercept(cpu); break; case KVM_EXIT_S390_RESET: - s390_reipl_request(); + s390_ipl_reset_request(cs, S390_RESET_REIPL); break; case KVM_EXIT_S390_TSCH: ret = handle_tsch(cpu); |