@samitouri / QOSamiQemu / commits / ec38b3d54c

target/i386/mshv: migrate MP_STATE

MSHV's "internal activity state" roughly maps to QEMU's env->mp_state and cpu->halted states that describe state of APs in a guest. We don't invoke set_mp_state as part of store_vcpu_state() b/c we would put all BSP + APs in a RUNNABLE (0) state immediately, breaking SMP boot Instead we store the mp state as part of the load_cleanup() routine after a migration. Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com> Link: https://lore.kernel.org/r/20260710101534.664604-11-magnuskulke@linux.microsoft.com Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Magnus Kulke committed Jul 10, 2026 at 12:15 UTC ec38b3d54c4ff314670b923a50daf0bd7c040b8a
3 files changed +91
accel/mshv/mshv-all.c
+10
@@ -62,6 +62,7 @@ static int init_mshv(int *mshv_fd)
62
63 static int mshv_load_cleanup(void *opaque)
64 {
65 + CPUState *cpu;
66 int ret;
67
68 ret = mshv_arch_set_partition_msrs(first_cpu);
@@ -70,6 +71,15 @@ static int mshv_load_cleanup(void *opaque)
71 return -1;
72 }
73
74 + CPU_FOREACH(cpu) {
75 + ret = mshv_arch_set_mp_state(cpu);
76 + if (ret < 0) {
77 + error_report("Failed to set mp state for vCPU %d: %s",
78 + cpu->cpu_index, strerror(-ret));
79 + return -1;
80 + }
81 + }
82 +
83 return 0;
84 }
85
include/system/mshv_int.h
+1
@@ -99,6 +99,7 @@ int mshv_get_generic_regs(CPUState *cpu, hv_register_assoc *assocs,
99 int mshv_arch_store_vcpu_state(const CPUState *cpu);
100 int mshv_arch_load_vcpu_state(CPUState *cpu);
101 int mshv_arch_set_partition_msrs(const CPUState *cpu);
102 +int mshv_arch_set_mp_state(const CPUState *cpu);
103 void mshv_arch_init_vcpu(CPUState *cpu);
104 void mshv_arch_destroy_vcpu(CPUState *cpu);
105 void mshv_arch_amend_proc_features(
target/i386/mshv/mshv-cpu.c
+80
@@ -35,6 +35,11 @@
35
36 #include <sys/ioctl.h>
37
38 +#define MSHV_MP_STATE_RUNNABLE 0
39 +#define MSHV_MP_STATE_UNINITIALIZED 1
40 +#define MSHV_MP_STATE_INIT_RECEIVED 2
41 +#define MSHV_MP_STATE_HALTED 3
42 +
43 #define MAX_REGISTER_COUNT (MAX_CONST(ARRAY_SIZE(STANDARD_REGISTER_NAMES), \
44 MAX_CONST(ARRAY_SIZE(SPECIAL_REGISTER_NAMES), \
45 ARRAY_SIZE(FPU_REGISTER_NAMES))))
@@ -950,6 +955,76 @@ static int set_vcpu_events(const CPUState *cpu)
955 return 0;
956 }
957
958 +static int get_mp_state(CPUState *cpu)
959 +{
960 + X86CPU *x86cpu = X86_CPU(cpu);
961 + CPUX86State *env = &x86cpu->env;
962 + struct hv_register_assoc assoc = {
963 + .name = HV_REGISTER_INTERNAL_ACTIVITY_STATE,
964 + };
965 + union hv_internal_activity_register activity;
966 + int ret;
967 +
968 + ret = mshv_get_generic_regs(cpu, &assoc, 1);
969 + if (ret < 0) {
970 + error_report("failed to get internal activity state");
971 + return -1;
972 + }
973 +
974 + activity.as_uint64 = assoc.value.reg64;
975 +
976 + /*
977 + * map MSHV activity state to KVM mp_state values, which are used as the
978 + * shared representation in env->mp_state and serialized by vmstate_x86_cpu.
979 + */
980 +
981 + if (activity.startup_suspend) {
982 + env->mp_state = MSHV_MP_STATE_UNINITIALIZED;
983 + } else if (activity.halt_suspend) {
984 + env->mp_state = MSHV_MP_STATE_HALTED;
985 + } else {
986 + env->mp_state = MSHV_MP_STATE_RUNNABLE;
987 + }
988 +
989 + cpu->halted = (env->mp_state == MSHV_MP_STATE_HALTED);
990 +
991 + return 0;
992 +}
993 +
994 +int mshv_arch_set_mp_state(const CPUState *cpu)
995 +{
996 + X86CPU *x86cpu = X86_CPU(cpu);
997 + CPUX86State *env = &x86cpu->env;
998 + union hv_internal_activity_register activity = { 0 };
999 + struct hv_register_assoc assoc = {
1000 + .name = HV_REGISTER_INTERNAL_ACTIVITY_STATE,
1001 + };
1002 + int ret;
1003 +
1004 + switch (env->mp_state) {
1005 + case MSHV_MP_STATE_HALTED:
1006 + activity.halt_suspend = 1;
1007 + break;
1008 + case MSHV_MP_STATE_UNINITIALIZED:
1009 + case MSHV_MP_STATE_INIT_RECEIVED:
1010 + activity.startup_suspend = 1;
1011 + break;
1012 + case MSHV_MP_STATE_RUNNABLE:
1013 + default:
1014 + break;
1015 + }
1016 +
1017 + assoc.value.reg64 = activity.as_uint64;
1018 +
1019 + ret = mshv_set_generic_regs(cpu, &assoc, 1);
1020 + if (ret < 0) {
1021 + error_report("failed to set internal activity state");
1022 + return -1;
1023 + }
1024 +
1025 + return 0;
1026 +}
1027 +
1028 static int update_hflags(CPUState *cpu)
1029 {
1030 X86CPU *x86cpu = X86_CPU(cpu);
@@ -1012,6 +1087,11 @@ int mshv_arch_load_vcpu_state(CPUState *cpu)
1087 return ret;
1088 }
1089
1090 + ret = get_mp_state(cpu);
1091 + if (ret < 0) {
1092 + return ret;
1093 + }
1094 +
1095 return 0;
1096 }
1097