diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index dc89eb30a2..9dbb0dfcdb 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -288,6 +288,9 @@ unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu) cpu_state); exit(1); } + if (kvm_enabled() && cpu->env.cpu_state != cpu_state) { + kvm_s390_set_cpu_state(cpu, cpu_state); + } cpu->env.cpu_state = cpu_state; return s390_count_running_cpus(); diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 7b9300e573..6b3aaed842 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -1072,6 +1072,7 @@ int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch, int kvm_s390_cpu_restart(S390CPU *cpu); int kvm_s390_get_memslot_count(KVMState *s); void kvm_s390_clear_cmma_callback(void *opaque); +int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state); #else static inline void kvm_s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, @@ -1102,6 +1103,10 @@ static inline int kvm_s390_get_memslot_count(KVMState *s) { return MAX_AVAIL_SLOTS; } +static inline int kvm_s390_set_cpu_state(S390CPU *cpu, uint8_t cpu_state) +{ + return -ENOSYS; +} #endif static inline void cmma_reset(S390CPU *cpu) diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 415baea514..7c90b18631 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; } @@ -1321,3 +1322,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; +} diff --git a/trace-events b/trace-events index 5202f205a0..529080640a 100644 --- a/trace-events +++ b/trace-events @@ -1369,6 +1369,7 @@ mhp_pc_dimm_assigned_address(uint64_t addr) "0x%"PRIx64 # target-s390x/kvm.c kvm_enable_cmma(int rc) "CMMA: enabling with result code %d" kvm_clear_cmma(int rc) "CMMA: clearing with result code %d" +kvm_failed_cpu_state_set(int cpu_index, uint8_t state, const char *msg) "Warning: Unable to set cpu %d state %" PRIu8 " to KVM: %s" # hw/dma/i8257.c i8257_unregistered_dma(int nchan, int dma_pos, int dma_len) "unregistered DMA channel used nchan=%d dma_pos=%d dma_len=%d"