summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target-s390x/cpu.c3
-rw-r--r--target-s390x/cpu.h5
-rw-r--r--target-s390x/kvm.c43
-rw-r--r--trace-events1
4 files changed, 50 insertions, 2 deletions
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"