Sophie

Sophie

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

kernel-2.6.18-194.11.1.el5.src.rpm

From: ddugger@redhat.com <ddugger@redhat.com>
Date: Mon, 23 Mar 2009 10:23:01 -0600
Subject: [xen] x86: intercept I/O for assigned device
Message-id: 200903231623.n2NGN14a022058@sobek.n0ano.com
O-Subject: [RHEL5.4 PATCH 6/21 V2] Intercept I/O for assigned device
Bugzilla: 484227
RH-Acked-by: Chris Lalancette <clalance@redhat.com>
RH-Acked-by: Gerd Hoffmann <kraxel@redhat.com>
RH-Acked-by: Chris Lalancette <clalance@redhat.com>

hook pio for assigned devices, thus improve pio performance.

Upstream Status: Accepted (CS 15904, 17452)

BZ: 484227

Signed-off-by: Weidong Han <weidong.han@intel.com>
Signed-off-by: Gerd Hoffman <kraxel@redhat.com>
Signed-off-by: Don Dugger <donald.d.dugger@intel.com>

diff --git a/arch/x86/hvm/intercept.c b/arch/x86/hvm/intercept.c
index e9712ce..e555f3c 100644
--- a/arch/x86/hvm/intercept.c
+++ b/arch/x86/hvm/intercept.c
@@ -243,6 +243,9 @@ int hvm_io_intercept(ioreq_t *p, int type)
     int i;
     unsigned long addr, size;
 
+    if ( (type == HVM_PORTIO) && (dpci_ioport_intercept(p)) )
+        return 1;
+
     for (i = 0; i < handler->num_slot; i++) {
         if( type != handler->hdl_list[i].type)
             continue;
diff --git a/arch/x86/hvm/io.c b/arch/x86/hvm/io.c
index 97e1215..b9b5f62 100644
--- a/arch/x86/hvm/io.c
+++ b/arch/x86/hvm/io.c
@@ -43,6 +43,7 @@
 
 #include <public/sched.h>
 #include <public/hvm/ioreq.h>
+#include <xen/iocap.h>
 
 #if defined (__i386__)
 static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value)
@@ -873,6 +874,108 @@ void hvm_io_assist(void)
     vcpu_end_shutdown_deferral(v);
 }
 
+void dpci_ioport_read(uint32_t mport, ioreq_t *p)
+{
+    int i, sign = p->df ? -1 : 1;
+    uint32_t data = 0;
+
+    for ( i = 0; i < p->count; i++ )
+    {
+        switch ( p->size )
+        {
+        case 1:
+            data = inb(mport);
+            break;
+        case 2:
+            data = inw(mport);
+            break;
+        case 4:
+            data = inl(mport);
+            break;
+        default:
+            BUG();
+        }
+
+        if ( p->data_is_ptr )
+            (void)hvm_copy_to_guest_phys(
+                p->data + (sign * i * p->size), &data, p->size);
+        else
+            p->data = data;
+    }
+}
+
+void dpci_ioport_write(uint32_t mport, ioreq_t *p)
+{
+    int i, sign = p->df ? -1 : 1;
+    uint32_t data;
+
+    for ( i = 0; i < p->count; i++ )
+    {
+        data = p->data;
+        if ( p->data_is_ptr )
+            (void)hvm_copy_from_guest_phys(
+                &data, p->data + (sign * i * p->size), p->size);
+
+        switch ( p->size )
+        {
+        case 1:
+            outb(data, mport);
+            break;
+        case 2:
+            outw(data, mport);
+            break;
+        case 4:
+            outl(data, mport);
+            break;
+        default:
+            BUG();
+        }
+    }
+}
+
+int dpci_ioport_intercept(ioreq_t *p)
+{
+    struct domain *d = current->domain;
+    struct hvm_iommu *hd = domain_hvm_iommu(d);
+    struct g2m_ioport *g2m_ioport;
+    unsigned int mport, gport = p->addr;
+    unsigned int s = 0, e = 0;
+
+    list_for_each_entry( g2m_ioport, &hd->g2m_ioport_list, list )
+    {
+        s = g2m_ioport->gport;
+        e = s + g2m_ioport->np;
+        if ( (gport >= s) && (gport < e) )
+            goto found;
+    }
+
+    return 0;
+
+ found:
+    mport = (gport - s) + g2m_ioport->mport;
+
+    if ( !ioports_access_permitted(d, mport, mport + p->size - 1) )
+    {
+        gdprintk(XENLOG_ERR, "Error: access to gport=0x%x denied!\n",
+                 (uint32_t)p->addr);
+        return 0;
+    }
+
+    switch ( p->dir )
+    {
+    case IOREQ_READ:
+        dpci_ioport_read(mport, p);
+        break;
+    case IOREQ_WRITE:
+        dpci_ioport_write(mport, p);
+        break;
+    default:
+        gdprintk(XENLOG_ERR, "Error: couldn't handle p->dir = %d", p->dir);
+    }
+
+    return 1;
+}
+
 /*
  * Local variables:
  * mode: C