@@ -1847,6 +1847,7 @@ static void pc_machine_reset(MachineState *machine)
{
CPUState *cs;
X86CPU *cpu;
+ const X86CPUClass *cpuc;
qemu_devices_reset();
@@ -1855,6 +1856,11 @@ static void pc_machine_reset(MachineState *machine)
*/
CPU_FOREACH(cs) {
cpu = X86_CPU(cs);
+ cpuc = X86_CPU_GET_CLASS(cpu);
+
+ if (cpuc->after_reset) {
+ cpuc->after_reset(cpu);
+ }
if (cpu->apic_state) {
device_legacy_reset(cpu->apic_state);
@@ -43,6 +43,7 @@ typedef struct X86CPUModel X86CPUModel;
* @static_model: See CpuDefinitionInfo::static
* @parent_realize: The parent class' realize handler.
* @parent_reset: The parent class' reset handler.
+ * @after_reset: Reset handler to be called only after all other devices have been reset.
*
* An x86 CPU model or family.
*/
@@ -68,6 +69,7 @@ struct X86CPUClass {
DeviceRealize parent_realize;
DeviceUnrealize parent_unrealize;
DeviceReset parent_reset;
+ void (*after_reset)(X86CPU *cpu);
};
@@ -6029,6 +6029,15 @@ static void x86_cpu_reset(DeviceState *dev)
#endif
}
+static void x86_cpu_after_reset(X86CPU *cpu)
+{
+#ifndef CONFIG_USER_ONLY
+ if (kvm_enabled()) {
+ kvm_arch_after_reset_vcpu(cpu);
+ }
+#endif
+}
+
static void mce_init(X86CPU *cpu)
{
CPUX86State *cenv = &cpu->env;
@@ -7094,6 +7103,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
device_class_set_props(dc, x86_cpu_properties);
device_class_set_parent_reset(dc, x86_cpu_reset, &xcc->parent_reset);
+ xcc->after_reset = x86_cpu_after_reset;
cc->reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP;
cc->class_by_name = x86_cpu_class_by_name;
@@ -23,6 +23,10 @@ int hyperv_x86_synic_add(X86CPU *cpu)
return 0;
}
+/*
+ * All devices possibly using SynIC have to be reset before calling this to let
+ * them remove their SINT routes first.
+ */
void hyperv_x86_synic_reset(X86CPU *cpu)
{
hyperv_synic_reset(CPU(cpu));
@@ -2188,18 +2188,28 @@ void kvm_arch_reset_vcpu(X86CPU *cpu)
env->mp_state = KVM_MP_STATE_RUNNABLE;
}
+ /* enabled by default */
+ env->poll_control_msr = 1;
+
+ sev_es_set_reset_vector(CPU(cpu));
+}
+
+void kvm_arch_after_reset_vcpu(X86CPU *cpu)
+{
+ CPUX86State *env = &cpu->env;
+ int i;
+
+ /*
+ * Reset SynIC after all other devices have been reset to let them remove
+ * their SINT routes first.
+ */
if (hyperv_feat_enabled(cpu, HYPERV_FEAT_SYNIC)) {
- int i;
for (i = 0; i < ARRAY_SIZE(env->msr_hv_synic_sint); i++) {
env->msr_hv_synic_sint[i] = HV_SINT_MASKED;
}
hyperv_x86_synic_reset(cpu);
}
- /* enabled by default */
- env->poll_control_msr = 1;
-
- sev_es_set_reset_vector(CPU(cpu));
}
void kvm_arch_do_init_vcpu(X86CPU *cpu)
@@ -38,6 +38,7 @@ bool kvm_has_adjust_clock_stable(void);
bool kvm_has_exception_payload(void);
void kvm_synchronize_all_tsc(void);
void kvm_arch_reset_vcpu(X86CPU *cs);
+void kvm_arch_after_reset_vcpu(X86CPU *cpu);
void kvm_arch_do_init_vcpu(X86CPU *cs);
void kvm_put_apicbase(X86CPU *cpu, uint64_t value);