diff --git a/cpus.c b/cpus.c index b9e5685e160755e110fcab98286e000f7ad7368b..d74cc117b38b947961db8ea5611de09230621d54 100644 --- a/cpus.c +++ b/cpus.c @@ -1401,6 +1401,20 @@ void qmp_inject_nmi(Error **errp) apic_deliver_nmi(env->apic_state); } } +#elif defined(TARGET_S390X) + CPUState *cs; + S390CPU *cpu; + + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + cpu = S390_CPU(cs); + if (cpu->env.cpu_num == monitor_get_cpu_index()) { + if (s390_cpu_restart(S390_CPU(cs)) == -1) { + error_set(errp, QERR_UNSUPPORTED); + return; + } + break; + } + } #else error_set(errp, QERR_UNSUPPORTED); #endif diff --git a/hmp-commands.hx b/hmp-commands.hx index 8c6b91a9c70ce8ff5ef5421b1e7e7eed7da6665a..628807f68454e0d7ea1bac427de235cedfb517a8 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -822,7 +822,7 @@ The values that can be specified here depend on the machine type, but are the same that can be specified in the @code{-boot} command line option. ETEXI -#if defined(TARGET_I386) +#if defined(TARGET_I386) || defined(TARGET_S390X) { .name = "nmi", .args_type = "", @@ -834,7 +834,7 @@ ETEXI STEXI @item nmi @var{cpu} @findex nmi -Inject an NMI on the given CPU (x86 only). +Inject an NMI (x86) or RESTART (s390x) on the given CPU. ETEXI diff --git a/qmp-commands.hx b/qmp-commands.hx index cf47e3fe72f183f5dbe843be9f7210e907a62a7e..bb09e72712d90cd3825fa52016beff96fe69c3da 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -487,7 +487,7 @@ Example: <- { "return": {} } Note: inject-nmi fails when the guest doesn't support injecting. - Currently, only x86 guests do. + Currently, only x86 (NMI) and s390x (RESTART) guests do. EQMP diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index b866ea189db0f0729a6324d0828aa85876651c77..8be56488061ed66369113d84d1c21d0b361a05f3 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1069,6 +1069,7 @@ void kvm_s390_enable_css_support(S390CPU *cpu); int kvm_s390_get_registers_partial(CPUState *cpu); int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, int vq, bool assign); +int kvm_s390_cpu_restart(S390CPU *cpu); #else static inline void kvm_s390_io_interrupt(S390CPU *cpu, uint16_t subchannel_id, @@ -1093,8 +1094,20 @@ static inline int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, { return -ENOSYS; } +static inline int kvm_s390_cpu_restart(S390CPU *cpu) +{ + return -ENOSYS; +} #endif +static inline int s390_cpu_restart(S390CPU *cpu) +{ + if (kvm_enabled()) { + return kvm_s390_cpu_restart(cpu); + } + return -ENOSYS; +} + static inline void s390_io_interrupt(S390CPU *cpu, uint16_t subchannel_id, uint16_t subchannel_nr, diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index c7fcdfa8827f90fecf1707cc2a52837b625299e2..185c8f5a457cf5bb9297a94007d595346dda97f9 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -612,12 +612,12 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, int ipb_code) return r; } -static int s390_cpu_restart(S390CPU *cpu) +int kvm_s390_cpu_restart(S390CPU *cpu) { kvm_s390_interrupt(cpu, KVM_S390_RESTART, 0); s390_add_running_cpu(cpu); qemu_cpu_kick(CPU(cpu)); - DPRINTF("DONE: SIGP cpu restart: %p\n", &cpu->env); + DPRINTF("DONE: KVM cpu restart: %p\n", &cpu->env); return 0; } @@ -686,7 +686,7 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1) switch (order_code) { case SIGP_RESTART: - r = s390_cpu_restart(target_cpu); + r = kvm_s390_cpu_restart(target_cpu); break; case SIGP_STORE_STATUS_ADDR: r = s390_store_status(target_env, parameter);