Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 126

kvm-83-270.el5_11.src.rpm

From 58d6ab0c556f259615737949ab3d9a79c345111e Mon Sep 17 00:00:00 2001
From: Dor Laor <dlaor@redhat.com>
Date: Wed, 30 Dec 2009 11:04:03 -0200
Subject: [PATCH 3/6] Fix a race in the device that cuased guest stack on 100% cpu

RH-Author: Dor Laor <dlaor@redhat.com>
Message-id: <4B3B33A3.7050201@redhat.com>
Patchwork-id: 6002
O-Subject: [kvm 5.4.z, 5.5][PATCH] Fix a race in the device that cuased guest
	stack on 100% cpu
Bugzilla: 503759
RH-Acked-by: Juan Quintela <quintela@redhat.com>
RH-Acked-by: Gleb Natapov <gleb@redhat.com>
RH-Acked-by: Naphtali Sprei <nsprei@redhat.com>

>From 897a3be846169ec7a70a13b97023c154a8e0ea15 Mon Sep 17 00:00:00 2001
From: Dor Laor <dor@redhat.com>
Date: Tue, 29 Dec 2009 18:11:23 +0200
Subject: [PATCH] Fix a race in the device that cuased guest stack on 100% cpu
 The code assumed that the status register pending bit - HSR_PENDING
 marks that the buffer is busy and thus the channel cannot accept data.

The problem was that if the driver will turn it off after copying the
data, data overrun might happen in the windows until device irq is turned on
again. Fixing it by having both the pending status off and the irq flag on as
a must for getting data in the channel.
bz 503759

Signed-off-by: Dor Laor <dor@redhat.com>
---
 qemu/hw/hypercall.c |   19 +++++++++++--------
 1 files changed, 11 insertions(+), 8 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 qemu/hw/hypercall.c |   19 +++++++++++--------
 1 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/qemu/hw/hypercall.c b/qemu/hw/hypercall.c
index 1536ffd..71f5bf4 100644
--- a/qemu/hw/hypercall.c
+++ b/qemu/hw/hypercall.c
@@ -345,17 +345,19 @@ int pci_hypercall_init(PCIBus *bus,int devfn)
 	return devfn;
 }
 
+// It's ok to read only when the driver didn't turn off the IRQS
+// and there is no data pending (HSR on)
+static int vmchannel_ok_to_read(long index)
+{
+    return (!(pHypercallStates[index]->hsr & HSR_PENDING) &&
+            !!(pHypercallStates[index]->hcr & HCR_IRQ_ON));
+}
 
-// If the VDR is set, data is waiting to be read by the guest.
-// don't let the vmchannel device write into
-// the buffer since the guest might be in the middle of a read
 static int vmchannel_can_read(void *opaque)
 {
     long index = (long)opaque;
-    if (pHypercallStates[index]->hsr & HSR_PENDING)
-        return 0;
-    else
-        return HP_MEM_SIZE;
+
+    return (vmchannel_ok_to_read(index))? HP_MEM_SIZE:0;
 }
 
 static void vmchannel_event(void *opaque, int event)
@@ -381,8 +383,9 @@ static void vmchannel_read(void *opaque, const uint8_t *buf, int size)
 #endif
 
     // if the hypercall device is in interrupts disabled state, don't accept the data
-    if (!(pHypercallStates[index]->hcr & HCR_IRQ_ON)) {
+    if (!vmchannel_ok_to_read(index)) {
         printf("%s: error: got read during interrupt disabled\n", __FUNCTION__);
+        hp_reset(pHypercallStates[index]);
         return;
     }
 
-- 
1.6.3.rc4.29.g8146