diff options
Diffstat (limited to 'target-s390x/kvm.c')
-rw-r--r-- | target-s390x/kvm.c | 58 |
1 files changed, 50 insertions, 8 deletions
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index a85a480c6a..5b10a255ed 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -181,9 +181,10 @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu) return cpu->cpu_index; } -int kvm_arch_init_vcpu(CPUState *cpu) +int kvm_arch_init_vcpu(CPUState *cs) { - /* nothing todo yet */ + S390CPU *cpu = S390_CPU(cs); + kvm_s390_set_cpu_state(cpu, cpu->env.cpu_state); return 0; } @@ -197,7 +198,7 @@ void kvm_s390_reset_vcpu(S390CPU *cpu) * Before this ioctl cpu_synchronize_state() is called in common kvm * code (kvm-all) */ if (kvm_vcpu_ioctl(cs, KVM_S390_INITIAL_RESET, NULL)) { - perror("Can't reset vcpu\n"); + error_report("Initial CPU reset failed on CPU %i\n", cs->cpu_index); } } @@ -921,7 +922,7 @@ static void sigp_cpu_start(void *arg) CPUState *cs = arg; S390CPU *cpu = S390_CPU(cs); - s390_add_running_cpu(cpu); + s390_cpu_set_state(CPU_STATE_OPERATING, cpu); DPRINTF("DONE: KVM cpu start: %p\n", &cpu->env); } @@ -934,7 +935,7 @@ static void sigp_cpu_restart(void *arg) }; kvm_s390_vcpu_interrupt(cpu, &irq); - s390_add_running_cpu(cpu); + s390_cpu_set_state(CPU_STATE_OPERATING, cpu); } int kvm_s390_cpu_restart(S390CPU *cpu) @@ -951,6 +952,7 @@ static void sigp_initial_cpu_reset(void *arg) cpu_synchronize_state(cpu); scc->initial_cpu_reset(cpu); + cpu_synchronize_post_reset(cpu); } static void sigp_cpu_reset(void *arg) @@ -960,6 +962,7 @@ static void sigp_cpu_reset(void *arg) cpu_synchronize_state(cpu); scc->cpu_reset(cpu); + cpu_synchronize_post_reset(cpu); } #define SIGP_ORDER_MASK 0x000000ff @@ -1074,7 +1077,7 @@ static void unmanageable_intercept(S390CPU *cpu, const char *str, int pswoffset) error_report("Unmanageable %s! CPU%i new PSW: 0x%016lx:%016lx", str, cs->cpu_index, ldq_phys(cs->as, cpu->env.psa + pswoffset), ldq_phys(cs->as, cpu->env.psa + pswoffset + 8)); - s390_del_running_cpu(cpu); + s390_cpu_halt(cpu); guest_panicked(); } @@ -1103,7 +1106,8 @@ static int handle_intercept(S390CPU *cpu) break; case ICPT_WAITPSW: /* disabled wait, since enabled wait is handled in kernel */ - if (s390_del_running_cpu(cpu) == 0) { + cpu_synchronize_state(cs); + if (s390_cpu_halt(cpu) == 0) { if (is_special_wait_psw(cs)) { qemu_system_shutdown_request(); } else { @@ -1113,7 +1117,7 @@ static int handle_intercept(S390CPU *cpu) r = EXCP_HALTED; break; case ICPT_CPU_STOP: - if (s390_del_running_cpu(cpu) == 0) { + if (s390_cpu_set_state(CPU_STATE_STOPPED, cpu) == 0) { qemu_system_shutdown_request(); } r = EXCP_HALTED; @@ -1320,3 +1324,41 @@ int kvm_s390_get_memslot_count(KVMState *s) { return kvm_check_extension(s, KVM_CAP_NR_MEMSLOTS); } + +int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) +{ + struct kvm_mp_state mp_state = {}; + int ret; + + /* the kvm part might not have been initialized yet */ + if (CPU(cpu)->kvm_state == NULL) { + return 0; + } + + switch (cpu_state) { + case CPU_STATE_STOPPED: + mp_state.mp_state = KVM_MP_STATE_STOPPED; + break; + case CPU_STATE_CHECK_STOP: + mp_state.mp_state = KVM_MP_STATE_CHECK_STOP; + break; + case CPU_STATE_OPERATING: + mp_state.mp_state = KVM_MP_STATE_OPERATING; + break; + case CPU_STATE_LOAD: + mp_state.mp_state = KVM_MP_STATE_LOAD; + break; + default: + error_report("Requested CPU state is not a valid S390 CPU state: %u", + cpu_state); + exit(1); + } + + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MP_STATE, &mp_state); + if (ret) { + trace_kvm_failed_cpu_state_set(CPU(cpu)->cpu_index, cpu_state, + strerror(-ret)); + } + + return ret; +} |