[Devel,RHEL7,COMMIT] kvm/x86: clear hyperv synic pages only when guest modifies MSRs

Submitted by Konstantin Khorenko on April 18, 2017, 12:56 p.m.


Message ID 201704181256.v3ICuZQ7031714@finist_cl7.x64_64.work.ct
State New
Series "kvm/x86: clear hyperv synic pages only when guest modifies MSRs"
Headers show

Commit Message

Konstantin Khorenko April 18, 2017, 12:56 p.m.
The commit is pushed to "branch-rh7-3.10.0-514.16.1.vz7.30.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-514.16.1.vz7.30.2
commit 9f24caf30ffe8c9d4e751aa38898fb33d2dbab62
Author: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
Date:   Tue Apr 18 16:56:35 2017 +0400

    kvm/x86: clear hyperv synic pages only when guest modifies MSRs
    Existing code resets guest synic message and event flag pages to zero
    when host (but not guest) updates their guest PAs by writing to
    corresponding MSRs.
    This turned out to be a problem for migration code when guest had a
    SYNIC irq to inject before suspending. After resuming qemu resets MSRs to
    saved values and KVM zeroes out migrated guest memory as a side effect.
    Following that guest sees an IRQ but doesn't see any event flags in event
    flags page, skips this IRQ and hangs indefinitely.
    This change fixes failing migration scenario by checking that pages are
    cleared by guest MSR write only.
    Signed-off-by: Evgeny Yakovlev <eyakovlev@virtuozzo.com>
    Reviewed-by: Roman Kagan <rkagan@virtuozzo.com>
 arch/x86/kvm/hyperv.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index eae314b..c8efdce 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -219,7 +219,7 @@  static int synic_set_msr(struct kvm_vcpu_hv_synic *synic,
 		synic->version = data;
 	case HV_X64_MSR_SIEFP:
-		if (data & HV_SYNIC_SIEFP_ENABLE)
+		if (data & HV_SYNIC_SIEFP_ENABLE && !host)
 			if (kvm_clear_guest(vcpu->kvm,
 					    data & PAGE_MASK, PAGE_SIZE)) {
 				ret = 1;
@@ -230,7 +230,7 @@  static int synic_set_msr(struct kvm_vcpu_hv_synic *synic,
 			synic_exit(synic, msr);
 	case HV_X64_MSR_SIMP:
-		if (data & HV_SYNIC_SIMP_ENABLE)
+		if (data & HV_SYNIC_SIMP_ENABLE && !host)
 			if (kvm_clear_guest(vcpu->kvm,
 					    data & PAGE_MASK, PAGE_SIZE)) {
 				ret = 1;