return r;
}
+/*
+ * The number of running CPUs. On s390 a shutdown is the state of all CPUs
+ * being either stopped or disabled (for interrupts) waiting. We have to
+ * track this number to call the shutdown sequence accordingly. This
+ * number is modified either on startup or while holding the big qemu lock.
+ */
+static unsigned s390_running_cpus;
+
+void s390_add_running_cpu(CPUState *env)
+{
+ if (env->halted) {
+ s390_running_cpus++;
+ env->halted = 0;
+ env->exception_index = -1;
+ }
+}
+
+unsigned s390_del_running_cpu(CPUState *env)
+{
+ if (env->halted == 0) {
+ assert(s390_running_cpus >= 1);
+ s390_running_cpus--;
+ env->halted = 1;
+ env->exception_index = EXCP_HLT;
+ }
+ return s390_running_cpus;
+}
+
/* PC hardware initialisation */
static void s390_init(ram_addr_t my_ram_size,
const char *boot_device,
tmp_env->storage_keys = storage_keys;
}
- env->halted = 0;
- env->exception_index = 0;
+ /* One CPU has to run */
+ s390_add_running_cpu(env);
if (kernel_filename) {
kernel_size = load_image(kernel_filename, qemu_get_ram_ptr(0));
}
#endif
CPUState *s390_cpu_addr2state(uint16_t cpu_addr);
+void s390_add_running_cpu(CPUState *env);
+unsigned s390_del_running_cpu(CPUState *env);
/* from s390-virtio-bus */
extern const target_phys_addr_t virtio_size;
return;
}
- env->halted = 0;
- env->exception_index = -1;
+ s390_add_running_cpu(env);
qemu_cpu_kick(env);
kvmint.type = type;
static int s390_cpu_restart(CPUState *env)
{
kvm_s390_interrupt(env, KVM_S390_RESTART, 0);
- env->halted = 0;
- env->exception_index = -1;
+ s390_add_running_cpu(env);
qemu_cpu_kick(env);
dprintf("DONE: SIGP cpu restart: %p\n", env);
return 0;
r = handle_instruction(env, run);
break;
case ICPT_WAITPSW:
- /* XXX What to do on system shutdown? */
- env->halted = 1;
- env->exception_index = EXCP_HLT;
+ case ICPT_CPU_STOP:
+ if (s390_del_running_cpu(env) == 0) {
+ qemu_system_shutdown_request();
+ }
+ r = EXCP_HALTED;
break;
case ICPT_SOFT_INTERCEPT:
fprintf(stderr, "KVM unimplemented icpt SOFT\n");
exit(1);
break;
- case ICPT_CPU_STOP:
- qemu_system_shutdown_request();
- break;
case ICPT_IO:
fprintf(stderr, "KVM unimplemented icpt IO\n");
exit(1);
if (ret == 0) {
ret = EXCP_INTERRUPT;
- } else if (ret > 0) {
- ret = 0;
}
return ret;
}