From 4aa743788cd217a680d8f0ea2cb040088967be3e Mon Sep 17 00:00:00 2001 From: Glauber Costa <glommer@redhat.com> Date: Wed, 23 Jun 2010 13:33:29 -0300 Subject: [PATCH 1/3] turn off kvmclock when resetting cpu RH-Author: Glauber Costa <glommer@redhat.com> Message-id: <1277300009-24438-1-git-send-email-glommer@redhat.com> Patchwork-id: 10113 O-Subject: [RHEL5 PATCH] turn off kvmclock when resetting cpu Bugzilla: 588878 RH-Acked-by: Avi Kivity <avi@redhat.com> RH-Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com> RH-Acked-by: Zachary Amsden <zamsden@redhat.com> Ackers, you already did it for RHEL6, please re-ack for 5. RH-Bugzilla: 588878 RH-Upstream-status: qemu-kvm/master RH-Author: Glauber Costa <glommer@gmail.com> Difference from upstream: To avoid risking regressions in the RHEL5 timeframe, we skip loading the TSC. Upstream changelog: Currently, in the linux kernel, we reset kvmclock if we are rebooting into a crash kernel through kexec. The rationale, is that a new kernel won't follow the same memory addresses, and the memory where kvmclock is located in the first kernel, will be something else in the second one. We don't do it in normal reboots, because the second kernel ends up registering kvmclock again, which has the effect of turning off the first instance. This is, however, totally wrong. This assumes we're booting into a kernel that also has kvmclock enabled. If by some reason we reboot into something that doesn't do kvmclock including but not limited to: * rebooting into an older kernel without kvmclock support, * rebooting with no-kvmclock, * rebootint into another O.S, we'll simply have the hypervisor writting into a random memory position into the guest. Neat, uh? Moreover, I believe the fix belongs in qemu, since it is the entity more prepared to detect all kinds of reboots (by means of a cpu_reset), not to mention the presence of misbehaving guests, that can forget to turn kvmclock off. It is also necessary to reset other msrs, so this patch resets everything that kvm exports through its MSR list. This patch fixes the issue for me. Signed-off-by: Glauber Costa <glommer@redhat.com> --- qemu-kvm-x86.c | 26 ++++++++++++++++++++++++++ 1 files changed, 26 insertions(+), 0 deletions(-) Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> --- qemu/qemu-kvm-x86.c | 28 ++++++++++++++++++++++++++++ 1 files changed, 28 insertions(+), 0 deletions(-) diff --git a/qemu/qemu-kvm-x86.c b/qemu/qemu-kvm-x86.c index 899f0ad..97c106d 100644 --- a/qemu/qemu-kvm-x86.c +++ b/qemu/qemu-kvm-x86.c @@ -767,8 +767,36 @@ int handle_tpr_access(void *opaque, int vcpu, return 0; } +static void kvm_reset_msrs(CPUState *env) +{ + struct { + struct kvm_msrs info; + struct kvm_msr_entry entries[100]; + } msr_data; + int n, n_msrs; + int rc; + struct kvm_msr_entry *msrs = msr_data.entries; + + if (!kvm_msr_list) + return; + + n_msrs = 0; + for (n = 0; n < kvm_msr_list->nmsrs; n++) { + if (kvm_msr_list->indices[n] == MSR_IA32_TSC) + continue; + set_msr_entry(&msrs[n_msrs++], kvm_msr_list->indices[n], 0); + } + + msr_data.info.nmsrs = n_msrs; + + rc = kvm_set_msrs(kvm_context, env->cpu_index, msrs, n_msrs); + if (rc == -1) + perror("kvm_set_msrs FAILED"); +} + void kvm_arch_cpu_reset(CPUState *env) { + kvm_reset_msrs(env); env->nmi_injected = 0; env->nmi_pending = 0; kvm_load_vcpu_events(env); -- 1.7.0.3