@@ -139,8 +139,18 @@ static void s390_cpu_reset(CPUState *s, cpu_reset_type type)
}
/* Reset state inside the kernel that we cannot access yet from QEMU. */
- if (kvm_enabled() && type != S390_CPU_RESET_NORMAL) {
- kvm_s390_reset_vcpu(cpu);
+ if (kvm_enabled()) {
+ switch (type) {
+ case S390_CPU_RESET_CLEAR:
+ kvm_s390_reset_vcpu_clear(cpu);
+ break;
+ case S390_CPU_RESET_INITIAL:
+ kvm_s390_reset_vcpu_initial(cpu);
+ break;
+ case S390_CPU_RESET_NORMAL:
+ kvm_s390_reset_vcpu_normal(cpu);
+ break;
+ }
}
}
@@ -83,7 +83,15 @@ void kvm_s390_cmma_reset(void)
{
}
-void kvm_s390_reset_vcpu(S390CPU *cpu)
+void kvm_s390_reset_vcpu_initial(S390CPU *cpu)
+{
+}
+
+void kvm_s390_reset_vcpu_clear(S390CPU *cpu)
+{
+}
+
+void kvm_s390_reset_vcpu_normal(S390CPU *cpu)
{
}
@@ -151,6 +151,7 @@ static int cap_s390_irq;
static int cap_ri;
static int cap_gs;
static int cap_hpage_1m;
+static int cap_vcpu_resets;
static int active_cmma;
@@ -342,6 +343,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
cap_async_pf = kvm_check_extension(s, KVM_CAP_ASYNC_PF);
cap_mem_op = kvm_check_extension(s, KVM_CAP_S390_MEM_OP);
cap_s390_irq = kvm_check_extension(s, KVM_CAP_S390_INJECT_IRQ);
+ cap_vcpu_resets = kvm_check_extension(s, KVM_CAP_S390_VCPU_RESETS);
if (!kvm_check_extension(s, KVM_CAP_S390_GMAP)
|| !kvm_check_extension(s, KVM_CAP_S390_COW)) {
@@ -403,17 +405,41 @@ int kvm_arch_destroy_vcpu(CPUState *cs)
return 0;
}
-void kvm_s390_reset_vcpu(S390CPU *cpu)
+static void kvm_s390_reset_vcpu(S390CPU *cpu, unsigned long type)
{
CPUState *cs = CPU(cpu);
- /* The initial reset call is needed here to reset in-kernel
- * vcpu data that we can't access directly from QEMU
- * (i.e. with older kernels which don't support sync_regs/ONE_REG).
- * Before this ioctl cpu_synchronize_state() is called in common kvm
- * code (kvm-all) */
- if (kvm_vcpu_ioctl(cs, KVM_S390_INITIAL_RESET, NULL)) {
- error_report("Initial CPU reset failed on CPU %i", cs->cpu_index);
+ /*
+ * The reset call is needed here to reset in-kernel vcpu data that
+ * we can't access directly from QEMU (i.e. with older kernels
+ * which don't support sync_regs/ONE_REG). Before this ioctl
+ * cpu_synchronize_state() is called in common kvm code
+ * (kvm-all).
+ */
+ if (kvm_vcpu_ioctl(cs, type)) {
+ error_report("CPU reset failed on CPU %i type %lx",
+ cs->cpu_index, type);
+ }
+}
+
+void kvm_s390_reset_vcpu_initial(S390CPU *cpu)
+{
+ kvm_s390_reset_vcpu(cpu, KVM_S390_INITIAL_RESET);
+}
+
+void kvm_s390_reset_vcpu_clear(S390CPU *cpu)
+{
+ if (cap_vcpu_resets) {
+ kvm_s390_reset_vcpu(cpu, KVM_S390_CLEAR_RESET);
+ } else {
+ kvm_s390_reset_vcpu(cpu, KVM_S390_INITIAL_RESET);
+ }
+}
+
+void kvm_s390_reset_vcpu_normal(S390CPU *cpu)
+{
+ if (cap_vcpu_resets) {
+ kvm_s390_reset_vcpu(cpu, KVM_S390_NORMAL_RESET);
}
}
@@ -34,7 +34,9 @@ int kvm_s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch,
int vq, bool assign);
int kvm_s390_cmma_active(void);
void kvm_s390_cmma_reset(void);
-void kvm_s390_reset_vcpu(S390CPU *cpu);
+void kvm_s390_reset_vcpu_clear(S390CPU *cpu);
+void kvm_s390_reset_vcpu_normal(S390CPU *cpu);
+void kvm_s390_reset_vcpu_initial(S390CPU *cpu);
int kvm_s390_set_mem_limit(uint64_t new_limit, uint64_t *hw_limit);
void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp);
void kvm_s390_crypto_reset(void);