Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 4531

kernel-2.6.18-194.11.1.el5.src.rpm

From: Don Dugger <ddugger@redhat.com>
Date: Thu, 31 Dec 2009 18:31:20 -0500
Subject: BZ 537734: xen: change interface of hvm_mmio_access V3
Message-id: <200912311831.nBVIVKZG012940@sobek.n0ano.com>
Patchwork-id: 22284
O-Subject: [RHEL5.5 PATCH 2/3 V3] BZ 537734: xen: change interface of
	hvm_mmio_access V3
Bugzilla: 537734
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>

[This is the same as V1 of this patch, there were no changes needed for this
version.]

hvm_mmio_access now return a status from read/write handler,
so that the handler can give an indication whether it can
handle the request.

partly backporting xen-unstable changeset 17452

Signed-off-by: Qing He <qing.he@intel.com>
Signed-off-by: Don Dugger <donald.d.dugger@intel.com>

---
 arch/x86/hvm/hpet.c      |   21 +++++++++----
 arch/x86/hvm/intercept.c |   75 ++++++++++++++++++++++++----------------------
 arch/x86/hvm/vioapic.c   |   21 +++++++-----
 arch/x86/hvm/vlapic.c    |   27 ++++++++++-------
 include/asm-x86/hvm/io.h |   12 ++++----
 5 files changed, 88 insertions(+), 68 deletions(-)

Signed-off-by: Jarod Wilson <jarod@redhat.com>

diff --git a/arch/x86/hvm/hpet.c b/arch/x86/hvm/hpet.c
index dd05da6..f2fc8f5 100644
--- a/arch/x86/hvm/hpet.c
+++ b/arch/x86/hvm/hpet.c
@@ -122,8 +122,9 @@ static inline uint64_t hpet_read_maincounter(HPETState *h)
         return h->hpet.mc64;
 }
 
-static unsigned long hpet_read(
-    struct vcpu *v, unsigned long addr, unsigned long length)
+static int hpet_read(
+    struct vcpu *v, unsigned long addr, unsigned long length,
+    unsigned long *pval)
 {
     HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet;
     unsigned long result;
@@ -132,7 +133,10 @@ static unsigned long hpet_read(
     addr &= HPET_MMAP_SIZE-1;
 
     if ( hpet_check_access_length(addr, length) != 0 )
-        return ~0UL;
+    {
+        result = ~0ul;
+        goto out;
+    }
 
     spin_lock(&h->lock);
 
@@ -146,7 +150,9 @@ static unsigned long hpet_read(
 
     spin_unlock(&h->lock);
 
-    return result;
+ out:
+    *pval = result;
+    return 1;
 }
 
 static void hpet_stop_timer(HPETState *h, unsigned int tn)
@@ -209,7 +215,7 @@ static inline uint64_t hpet_fixup_reg(
     return new;
 }
 
-static void hpet_write(
+static int hpet_write(
     struct vcpu *v, unsigned long addr,
     unsigned long length, unsigned long val)
 {
@@ -220,7 +226,7 @@ static void hpet_write(
     addr &= HPET_MMAP_SIZE-1;
 
     if ( hpet_check_access_length(addr, length) != 0 )
-        return;
+        goto out;
 
     spin_lock(&h->lock);
 
@@ -315,6 +321,9 @@ static void hpet_write(
     }
 
     spin_unlock(&h->lock);
+
+ out:
+    return 1;
 }
 
 static int hpet_range(struct vcpu *v, unsigned long addr)
diff --git a/arch/x86/hvm/intercept.c b/arch/x86/hvm/intercept.c
index e555f3c..8e8ee9a 100644
--- a/arch/x86/hvm/intercept.c
+++ b/arch/x86/hvm/intercept.c
@@ -58,30 +58,33 @@ static struct hvm_buffered_io_range
     &buffered_stdvga_range
 };
 
-static inline void hvm_mmio_access(struct vcpu *v,
-                                   ioreq_t *p,
-                                   hvm_mmio_read_t read_handler,
-                                   hvm_mmio_write_t write_handler)
+static inline int hvm_mmio_access(struct vcpu *v,
+                                  ioreq_t *p,
+                                  hvm_mmio_read_t read_handler,
+                                  hvm_mmio_write_t write_handler)
 {
-    unsigned int tmp1, tmp2;
+    unsigned long tmp1, tmp2;
     unsigned long data;
+    int rc = 1;
 
     switch ( p->type ) {
     case IOREQ_TYPE_COPY:
     {
         if ( !p->data_is_ptr ) {
-            if ( p->dir == IOREQ_READ )
-                p->data = read_handler(v, p->addr, p->size);
+            if ( p->dir == IOREQ_READ ) {
+                rc = read_handler(v, p->addr, p->size, &data);
+                p->data = data;
+            }
             else    /* p->dir == IOREQ_WRITE */
-                write_handler(v, p->addr, p->size, p->data);
+                rc = write_handler(v, p->addr, p->size, p->data);
         } else {    /* p->data_is_ptr */
             int i, sign = (p->df) ? -1 : 1;
 
             if ( p->dir == IOREQ_READ ) {
                 for ( i = 0; i < p->count; i++ ) {
-                    data = read_handler(v,
+                    rc = read_handler(v,
                         p->addr + (sign * i * p->size),
-                        p->size);
+                        p->size, &data);
                     (void)hvm_copy_to_guest_phys(
                         p->data + (sign * i * p->size),
                         &data,
@@ -93,7 +96,7 @@ static inline void hvm_mmio_access(struct vcpu *v,
                         &data,
                         p->data + (sign * i * p->size),
                         p->size);
-                    write_handler(v,
+                    rc = write_handler(v,
                         p->addr + (sign * i * p->size),
                         p->size, data);
                 }
@@ -103,37 +106,37 @@ static inline void hvm_mmio_access(struct vcpu *v,
     }
 
     case IOREQ_TYPE_AND:
-        tmp1 = read_handler(v, p->addr, p->size);
-        if ( p->dir == IOREQ_WRITE ) {
+        rc = read_handler(v, p->addr, p->size, &tmp1);
+        if ( rc && p->dir == IOREQ_WRITE ) {
             tmp2 = tmp1 & (unsigned long) p->data;
-            write_handler(v, p->addr, p->size, tmp2);
+            rc = write_handler(v, p->addr, p->size, tmp2);
         }
         p->data = tmp1;
         break;
 
     case IOREQ_TYPE_ADD:
-        tmp1 = read_handler(v, p->addr, p->size);
-        if (p->dir == IOREQ_WRITE) {
+        rc = read_handler(v, p->addr, p->size, &tmp1);
+        if ( rc && p->dir == IOREQ_WRITE) {
             tmp2 = tmp1 + (unsigned long) p->data;
-            write_handler(v, p->addr, p->size, tmp2);
+            rc = write_handler(v, p->addr, p->size, tmp2);
         }
         p->data = tmp1;
         break;
 
     case IOREQ_TYPE_OR:
-        tmp1 = read_handler(v, p->addr, p->size);
-        if ( p->dir == IOREQ_WRITE ) {
+        rc = read_handler(v, p->addr, p->size, &tmp1);
+        if ( rc && p->dir == IOREQ_WRITE ) {
             tmp2 = tmp1 | (unsigned long) p->data;
-            write_handler(v, p->addr, p->size, tmp2);
+            rc = write_handler(v, p->addr, p->size, tmp2);
         }
         p->data = tmp1;
         break;
 
     case IOREQ_TYPE_XOR:
-        tmp1 = read_handler(v, p->addr, p->size);
-        if ( p->dir == IOREQ_WRITE ) {
+        rc = read_handler(v, p->addr, p->size, &tmp1);
+        if ( rc && p->dir == IOREQ_WRITE ) {
             tmp2 = tmp1 ^ (unsigned long) p->data;
-            write_handler(v, p->addr, p->size, tmp2);
+            rc = write_handler(v, p->addr, p->size, tmp2);
         }
         p->data = tmp1;
         break;
@@ -143,25 +146,29 @@ static inline void hvm_mmio_access(struct vcpu *v,
          * Note that we don't need to be atomic here since VCPU is accessing
          * its own local APIC.
          */
-        tmp1 = read_handler(v, p->addr, p->size);
-        write_handler(v, p->addr, p->size, (unsigned long) p->data);
+        rc = read_handler(v, p->addr, p->size, &tmp1);
+        if ( rc )
+            rc = write_handler(v, p->addr, p->size, (unsigned long) p->data);
         p->data = tmp1;
         break;
 
     case IOREQ_TYPE_SUB:
-        tmp1 = read_handler(v, p->addr, p->size);
-        if ( p->dir == IOREQ_WRITE ) {
+        rc = read_handler(v, p->addr, p->size, &tmp1);
+        if ( rc && p->dir == IOREQ_WRITE ) {
             tmp2 = tmp1 - (unsigned long) p->data;
-            write_handler(v, p->addr, p->size, tmp2);
+            rc = write_handler(v, p->addr, p->size, tmp2);
         }
         p->data = tmp1;
         break;
 
     default:
+        rc = 0;
         printk("hvm_mmio_access: error ioreq type %x\n", p->type);
         domain_crash_synchronous();
         break;
     }
+
+    return rc;
 }
 
 int hvm_buffered_io_send(ioreq_t *p)
@@ -218,15 +225,11 @@ int hvm_mmio_intercept(ioreq_t *p)
     int i;
 
     for ( i = 0; i < HVM_MMIO_HANDLER_NR; i++ )
-    {
         if ( hvm_mmio_handlers[i]->check_handler(v, p->addr) )
-        {
-            hvm_mmio_access(v, p,
-                            hvm_mmio_handlers[i]->read_handler,
-                            hvm_mmio_handlers[i]->write_handler);
-            return 1;
-        }
-    }
+            return hvm_mmio_access(
+                v, p,
+                hvm_mmio_handlers[i]->read_handler,
+                hvm_mmio_handlers[i]->write_handler);
 
     return 0;
 }
diff --git a/arch/x86/hvm/vioapic.c b/arch/x86/hvm/vioapic.c
index c86cbfa..7f17a15 100644
--- a/arch/x86/hvm/vioapic.c
+++ b/arch/x86/hvm/vioapic.c
@@ -92,9 +92,9 @@ static unsigned long vioapic_read_indirect(struct hvm_hw_vioapic *vioapic,
     return result;
 }
 
-static unsigned long vioapic_read(struct vcpu *v,
-                                  unsigned long addr,
-                                  unsigned long length)
+static int vioapic_read(
+    struct vcpu *v, unsigned long addr,
+    unsigned long length, unsigned long *pval)
 {
     struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain);
     uint32_t result;
@@ -118,11 +118,13 @@ static unsigned long vioapic_read(struct vcpu *v,
         break;
     }
 
-    return result;
+    *pval = result;
+    return 1;
 }
 
 static void vioapic_write_redirent(
-    struct hvm_hw_vioapic *vioapic, unsigned int idx, int top_word, uint32_t val)
+    struct hvm_hw_vioapic *vioapic, unsigned int idx,
+    int top_word, uint32_t val)
 {
     struct domain *d = vioapic_domain(vioapic);
     struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
@@ -200,10 +202,9 @@ static void vioapic_write_indirect(
     }
 }
 
-static void vioapic_write(struct vcpu *v,
-                          unsigned long addr,
-                          unsigned long length,
-                          unsigned long val)
+static int vioapic_write(
+    struct vcpu *v, unsigned long addr,
+    unsigned long length, unsigned long val)
 {
     struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain);
 
@@ -228,6 +229,8 @@ static void vioapic_write(struct vcpu *v,
     default:
         break;
     }
+
+    return 1;
 }
 
 static int vioapic_range(struct vcpu *v, unsigned long addr)
diff --git a/arch/x86/hvm/vlapic.c b/arch/x86/hvm/vlapic.c
index b039bcf..58712f4 100644
--- a/arch/x86/hvm/vlapic.c
+++ b/arch/x86/hvm/vlapic.c
@@ -475,17 +475,18 @@ static void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
     }
 }
 
-static unsigned long vlapic_read(struct vcpu *v, unsigned long address,
-                                 unsigned long len)
+static int vlapic_read(
+    struct vcpu *v, unsigned long address,
+    unsigned long len, unsigned long *pval)
 {
     unsigned int alignment;
     unsigned int tmp;
-    unsigned long result;
+    unsigned long result = 0;
     struct vlapic *vlapic = vcpu_vlapic(v);
     unsigned int offset = address - vlapic_base_address(vlapic);
 
     if ( offset > APIC_TDCR )
-        return 0;
+        goto out;
 
     /* some bugs on kernel cause read this with byte*/
     if ( len != 4 )
@@ -521,11 +522,13 @@ static unsigned long vlapic_read(struct vcpu *v, unsigned long address,
     HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "offset 0x%x with length 0x%lx, "
                 "and the result is 0x%lx", offset, len, result);
 
-    return result;
+    goto out;
 
  exit_and_crash:
     domain_crash(v->domain);
-    return 0;
+ out:
+    *pval = result;
+    return 1;
 }
 
 void vlapic_pt_cb(struct vcpu *v, void *data)
@@ -533,8 +536,8 @@ void vlapic_pt_cb(struct vcpu *v, void *data)
     *(s_time_t *)data = hvm_get_guest_time(v);
 }
 
-static void vlapic_write(struct vcpu *v, unsigned long address,
-                         unsigned long len, unsigned long val)
+static int vlapic_write(struct vcpu *v, unsigned long address,
+                        unsigned long len, unsigned long val)
 {
     struct vlapic *vlapic = vcpu_vlapic(v);
     unsigned int offset = address - vlapic_base_address(vlapic);
@@ -551,13 +554,13 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
     val &= 0xffffffff;
     if ( len != 4 )
     {
-        unsigned int tmp;
+        unsigned long tmp;
         unsigned char alignment;
 
         gdprintk(XENLOG_INFO, "Notice: Local APIC write with len = %lx\n",len);
 
         alignment = offset & 0x3;
-        tmp = vlapic_read(v, offset & ~0x3, 4);
+        (void)vlapic_read(v, offset & ~0x3, 4, &tmp);
 
         switch ( len )
         {
@@ -583,7 +586,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
                      "should be 4 instead\n", len);
         exit_and_crash:
             domain_crash(v->domain);
-            return;
+            return 0;
         }
     }
 
@@ -684,6 +687,8 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
                  "Local APIC Write to read-only register 0x%x\n", offset);
         break;
     }
+
+    return 1;
 }
 
 static int vlapic_range(struct vcpu *v, unsigned long addr)
diff --git a/include/asm-x86/hvm/io.h b/include/asm-x86/hvm/io.h
index a7b2846..4459db2 100644
--- a/include/asm-x86/hvm/io.h
+++ b/include/asm-x86/hvm/io.h
@@ -86,14 +86,14 @@ struct hvm_io_op {
 #define HVM_MMIO                    1
 
 typedef int (*intercept_action_t)(ioreq_t *);
-typedef unsigned long (*hvm_mmio_read_t)(struct vcpu *v,
-                                         unsigned long addr,
-                                         unsigned long length);
-
-typedef void (*hvm_mmio_write_t)(struct vcpu *v,
+typedef int (*hvm_mmio_read_t)(struct vcpu *v,
                                unsigned long addr,
                                unsigned long length,
-                               unsigned long val);
+                               unsigned long *val);
+typedef int (*hvm_mmio_write_t)(struct vcpu *v,
+                                unsigned long addr,
+                                unsigned long length,
+                                unsigned long val);
 
 typedef int (*hvm_mmio_check_t)(struct vcpu *v, unsigned long addr);