Migrate HyperV SynIC SINT MSRs. We can only read/write those if SCONTROL
is enabled in the guest, hence we have to split the SINT MSR out and
make reading/writing them dependent on that MSR.
Signed-off-by: Magnus Kulke <magnuskulke@linux.microsoft.com>
---
target/i386/mshv/msr.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/target/i386/mshv/msr.c b/target/i386/mshv/msr.c
index 240ee84447..d19b79d729 100644
--- a/target/i386/mshv/msr.c
+++ b/target/i386/mshv/msr.c
@@ -298,6 +298,8 @@ int mshv_get_msrs(CPUState *cpu)
struct hv_register_assoc assocs[MSHV_MSR_TOTAL_COUNT];
size_t i, j;
uint32_t name;
+ X86CPU *x86cpu = X86_CPU(cpu);
+ bool synic_enabled;
set_hv_name_in_assocs(assocs, n_assocs);
@@ -324,6 +326,27 @@ int mshv_get_msrs(CPUState *cpu)
store_in_env(cpu, assocs, n_assocs);
+ /* Read SINT MSRs only if SynIC is enabled */
+ synic_enabled = x86cpu->env.msr_hv_synic_control & 1;
+ if (synic_enabled) {
+ QEMU_BUILD_BUG_ON(MSHV_MSR_TOTAL_COUNT < HV_SINT_COUNT);
+
+ for (i = 0; i < HV_SINT_COUNT; i++) {
+ assocs[i].name = HV_REGISTER_SINT0 + i;
+ }
+
+ ret = mshv_get_generic_regs(cpu, assocs, HV_SINT_COUNT);
+ if (ret < 0) {
+ error_report("Failed to get SynIC SINT MSRs");
+ return -errno;
+ }
+
+ for (i = 0; i < HV_SINT_COUNT; i++) {
+ uint64_t hv_sint_value = assocs[i].value.reg64;
+ x86cpu->env.msr_hv_synic_sint[i] = hv_sint_value;
+ }
+ }
+
return 0;
}
@@ -358,6 +381,8 @@ int mshv_set_msrs(const CPUState *cpu)
struct hv_register_assoc assocs[MSHV_MSR_TOTAL_COUNT];
int ret;
size_t i, j;
+ X86CPU *x86cpu = X86_CPU(cpu);
+ bool synic_enabled = x86cpu->env.msr_hv_synic_control & 1;
load_from_env(cpu, assocs, n_assocs);
@@ -390,5 +415,21 @@ int mshv_set_msrs(const CPUState *cpu)
return -errno;
}
+ /* SINT MSRs can only be written if SCONTROL has been set, so we split */
+ if (synic_enabled) {
+ QEMU_BUILD_BUG_ON(MSHV_MSR_TOTAL_COUNT < HV_SINT_COUNT);
+
+ for (i = 0; i < HV_SINT_COUNT; i++) {
+ assocs[i].name = HV_REGISTER_SINT0 + i;
+ assocs[i].value.reg64 = x86cpu->env.msr_hv_synic_sint[i];
+ }
+
+ ret = mshv_set_generic_regs(cpu, assocs, HV_SINT_COUNT);
+ if (ret < 0) {
+ error_report("Failed to set SynIC SINT MSRs");
+ return -errno;
+ }
+ }
+
return 0;
}
--
2.34.1