summaryrefslogtreecommitdiffstats
path: root/target/i386/kvm.c
diff options
context:
space:
mode:
authorEvgeny Yakovlev2017-11-22 19:14:16 +0100
committerPaolo Bonzini2017-12-21 09:22:44 +0100
commitda1cc323b8aee60d4816ce7521177b14ec3008b4 (patch)
tree641adae380c2a2cc82bd846cb39c9bd279b9d176 /target/i386/kvm.c
parentx86/cpu: Enable new SSE/AVX/AVX512 cpu features (diff)
downloadqemu-da1cc323b8aee60d4816ce7521177b14ec3008b4.tar.gz
qemu-da1cc323b8aee60d4816ce7521177b14ec3008b4.tar.xz
qemu-da1cc323b8aee60d4816ce7521177b14ec3008b4.zip
hyperv: set partition-wide MSRs only on first vcpu
Hyper-V has a notion of partition-wide MSRs. Those MSRs are read and written as usual on each VCPU, however the hypervisor maintains a single global value for all VCPUs. Thus writing such an MSR from any single VCPU affects the global value that is read by all other VCPUs. This leads to an issue during VCPU hotplug: the zero-initialzied values of those MSRs get synced into KVM and override the global values as has already been set by the guest. This change makes the partition-wide MSRs only be synchronized on the first vcpu. Signed-off-by: Evgeny Yakovlev <eyakovlev@virtuozzo.com> Signed-off-by: Roman Kagan <rkagan@virtuozzo.com> Message-Id: <20171122181418.14180-2-rkagan@virtuozzo.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'target/i386/kvm.c')
-rw-r--r--target/i386/kvm.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index d4b2ce2e94..89fa65e243 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -1678,19 +1678,26 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
kvm_msr_entry_add(cpu, MSR_CORE_PERF_GLOBAL_CTRL,
env->msr_global_ctrl);
}
- if (has_msr_hv_hypercall) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_GUEST_OS_ID,
- env->msr_hv_guest_os_id);
- kvm_msr_entry_add(cpu, HV_X64_MSR_HYPERCALL,
- env->msr_hv_hypercall);
+ /*
+ * Hyper-V partition-wide MSRs: to avoid clearing them on cpu hot-add,
+ * only sync them to KVM on the first cpu
+ */
+ if (current_cpu == first_cpu) {
+ if (has_msr_hv_hypercall) {
+ kvm_msr_entry_add(cpu, HV_X64_MSR_GUEST_OS_ID,
+ env->msr_hv_guest_os_id);
+ kvm_msr_entry_add(cpu, HV_X64_MSR_HYPERCALL,
+ env->msr_hv_hypercall);
+ }
+ if (cpu->hyperv_time) {
+ kvm_msr_entry_add(cpu, HV_X64_MSR_REFERENCE_TSC,
+ env->msr_hv_tsc);
+ }
}
if (cpu->hyperv_vapic) {
kvm_msr_entry_add(cpu, HV_X64_MSR_APIC_ASSIST_PAGE,
env->msr_hv_vapic);
}
- if (cpu->hyperv_time) {
- kvm_msr_entry_add(cpu, HV_X64_MSR_REFERENCE_TSC, env->msr_hv_tsc);
- }
if (has_msr_hv_crash) {
int j;