[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] PCI passthru: VT-d I/O hooks.



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1190189526 -3600
# Node ID aad813d8a8ad6f9d7d4f0d04a14fe088dd671e96
# Parent  b7eb2bb9b6251c0533bac7361218c398ad3e8cbf
PCI passthru: VT-d I/O hooks.
Signed-off-by: Allen Kay <allen.m.kay@xxxxxxxxx>
Signed-off-by: Guy Zana <guy@xxxxxxxxxxxx>
---
 xen/arch/x86/hvm/hvm.c                 |    5 +
 xen/arch/x86/hvm/intercept.c           |    4 +
 xen/arch/x86/hvm/io.c                  |  118 +++++++++++++++++++++++++++++++++
 xen/arch/x86/hvm/vmx/vtd/intel-iommu.c |   19 ++---
 xen/arch/x86/hvm/vmx/vtd/io.c          |   32 ++++++++
 xen/drivers/acpi/tables.c              |    1 
 xen/include/asm-x86/hvm/iommu.h        |    7 +
 xen/include/asm-x86/iommu.h            |    5 +
 8 files changed, 181 insertions(+), 10 deletions(-)

diff -r b7eb2bb9b625 -r aad813d8a8ad xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Tue Sep 18 16:09:19 2007 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Wed Sep 19 09:12:06 2007 +0100
@@ -48,6 +48,7 @@
 #include <public/hvm/ioreq.h>
 #include <public/version.h>
 #include <public/memory.h>
+#include <asm/iommu.h>
 
 int hvm_enabled __read_mostly;
 
@@ -214,6 +215,10 @@ int hvm_domain_initialise(struct domain 
 
     spin_lock_init(&d->arch.hvm_domain.pbuf_lock);
     spin_lock_init(&d->arch.hvm_domain.irq_lock);
+
+    rc = iommu_domain_init(d);
+    if ( rc != 0 )
+        return rc;
 
     rc = paging_enable(d, PG_refcounts|PG_translate|PG_external);
     if ( rc != 0 )
diff -r b7eb2bb9b625 -r aad813d8a8ad xen/arch/x86/hvm/intercept.c
--- a/xen/arch/x86/hvm/intercept.c      Tue Sep 18 16:09:19 2007 +0100
+++ b/xen/arch/x86/hvm/intercept.c      Wed Sep 19 09:12:06 2007 +0100
@@ -29,6 +29,7 @@
 #include <asm/current.h>
 #include <io_ports.h>
 #include <xen/event.h>
+#include <asm/iommu.h>
 
 
 extern struct hvm_mmio_handler hpet_mmio_handler;
@@ -242,6 +243,9 @@ int hvm_io_intercept(ioreq_t *p, int typ
                            &(v->domain->arch.hvm_domain.io_handler);
     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)
diff -r b7eb2bb9b625 -r aad813d8a8ad xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c     Tue Sep 18 16:09:19 2007 +0100
+++ b/xen/arch/x86/hvm/io.c     Wed Sep 19 09:12:06 2007 +0100
@@ -42,6 +42,7 @@
 #include <asm/hvm/vlapic.h>
 
 #include <public/sched.h>
+#include <xen/iocap.h>
 #include <public/hvm/ioreq.h>
 
 #if defined (__i386__)
@@ -864,6 +865,123 @@ void hvm_io_assist(void)
     vcpu_end_shutdown_deferral(v);
 }
 
+void dpci_ioport_read(uint32_t mport, ioreq_t *p)
+{
+    uint64_t i;
+    uint64_t z_data;
+    uint64_t length = (p->count * p->size);
+
+    for ( i = 0; i < length; i += p->size )
+    {
+        z_data = ~0ULL;
+        
+        switch ( p->size )
+        {
+        case BYTE:
+            z_data = (uint64_t)inb(mport);
+            break;
+        case WORD:
+            z_data = (uint64_t)inw(mport);
+            break;
+        case LONG:
+            z_data = (uint64_t)inl(mport);
+            break;
+        default:
+            gdprintk(XENLOG_ERR, "Error: unable to handle size: %"
+                     PRId64 "\n", p->size);
+            return;
+        }
+
+        p->data = z_data;
+        if ( p->data_is_ptr &&
+             hvm_copy_to_guest_phys(p->data + i, (void *)&z_data,
+                                    (int)p->size) )
+        {
+            gdprintk(XENLOG_ERR, "Error: couldn't copy to hvm phys\n");
+            return;
+        }
+    }
+}
+
+void dpci_ioport_write(uint32_t mport, ioreq_t *p)
+{
+    uint64_t i;
+    uint64_t z_data = 0;
+    uint64_t length = (p->count * p->size);
+
+    for ( i = 0; i < length; i += p->size )
+    {
+        z_data = p->data;
+        if ( p->data_is_ptr &&
+             hvm_copy_from_guest_phys((void *)&z_data,
+                                      p->data + i, (int)p->size) )
+        {
+            gdprintk(XENLOG_ERR, "Error: couldn't copy from hvm phys\n");
+            return;
+        }
+
+        switch ( p->size )
+        {
+        case BYTE:
+            outb((uint8_t) z_data, mport);
+            break;
+        case WORD:
+            outw((uint16_t) z_data, mport);
+            break;
+        case LONG:
+            outl((uint32_t) z_data, mport);
+            break;
+        default:
+            gdprintk(XENLOG_ERR, "Error: unable to handle size: %"
+                     PRId64 "\n", p->size);
+            break;
+        }
+    }
+}
+
+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
diff -r b7eb2bb9b625 -r aad813d8a8ad xen/arch/x86/hvm/vmx/vtd/intel-iommu.c
--- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c    Tue Sep 18 16:09:19 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c    Wed Sep 19 09:12:06 2007 +0100
@@ -929,18 +929,16 @@ int iommu_domain_init(struct domain *dom
     unsigned long sagaw;
     struct acpi_drhd_unit *drhd;
 
-    if (list_empty(&acpi_drhd_units))
-        return 0;
     spin_lock_init(&hd->mapping_lock);
     spin_lock_init(&hd->iommu_list_lock);
     INIT_LIST_HEAD(&hd->pdev_list);
-
-    for_each_drhd_unit(drhd) {
-        if (drhd->iommu)
-            iommu = drhd->iommu;
-        else
-            iommu = iommu_alloc(drhd);
-    }
+    INIT_LIST_HEAD(&hd->g2m_ioport_list);
+
+    if ( !vtd_enabled || list_empty(&acpi_drhd_units) )
+        return 0;
+
+    for_each_drhd_unit ( drhd )
+        iommu = drhd->iommu ? : iommu_alloc(drhd);
 
     /* calculate AGAW */
     if (guest_width > cap_mgaw(iommu->cap))
@@ -949,7 +947,8 @@ int iommu_domain_init(struct domain *dom
     agaw = width_to_agaw(adjust_width);
     /* FIXME: hardware doesn't support it, choose a bigger one? */
     sagaw = cap_sagaw(iommu->cap);
-    if (!test_bit(agaw, &sagaw)) {
+    if ( !test_bit(agaw, &sagaw) )
+    {
         gdprintk(XENLOG_ERR VTDPREFIX,
             "IOMMU: hardware doesn't support the agaw\n");
         agaw = find_next_bit(&sagaw, 5, agaw);
diff -r b7eb2bb9b625 -r aad813d8a8ad xen/arch/x86/hvm/vmx/vtd/io.c
--- a/xen/arch/x86/hvm/vmx/vtd/io.c     Tue Sep 18 16:09:19 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vtd/io.c     Wed Sep 19 09:12:06 2007 +0100
@@ -43,7 +43,39 @@
 #include <public/sched.h>
 #include <xen/iocap.h>
 #include <public/hvm/ioreq.h>
+#include <public/domctl.h>
 
+int pt_irq_create_bind_vtd(
+    struct domain *d,
+    xen_domctl_bind_pt_irq_t * pt_irq_bind)
+{
+    struct hvm_domain *hd = &d->arch.hvm_domain;
+    uint32_t machine_gsi, guest_gsi;
+    uint32_t device, intx;
+
+    machine_gsi = pt_irq_bind->machine_irq;
+    device = pt_irq_bind->u.pci.device;
+    intx = pt_irq_bind->u.pci.intx;
+    guest_gsi = hvm_pci_intx_gsi(device, intx);
+
+    hd->irq.mirq[machine_gsi].valid = 1;
+    hd->irq.mirq[machine_gsi].device = device;
+    hd->irq.mirq[machine_gsi].intx = intx;
+    hd->irq.mirq[machine_gsi].guest_gsi = guest_gsi;
+
+    hd->irq.girq[guest_gsi].valid = 1;
+    hd->irq.girq[guest_gsi].device = device;
+    hd->irq.girq[guest_gsi].intx = intx;
+    hd->irq.girq[guest_gsi].machine_gsi = machine_gsi;
+
+    /* Deal with gsi for legacy devices */
+    pirq_guest_bind(d->vcpu[0], machine_gsi, BIND_PIRQ__WILL_SHARE);
+    gdprintk(XENLOG_ERR,
+        "XEN_DOMCTL_irq_mapping: m_irq = %x device = %x intx = %x\n",
+        machine_gsi, device, intx);
+
+    return 0;
+}
 int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq)
 {
     uint32_t device, intx;
diff -r b7eb2bb9b625 -r aad813d8a8ad xen/drivers/acpi/tables.c
--- a/xen/drivers/acpi/tables.c Tue Sep 18 16:09:19 2007 +0100
+++ b/xen/drivers/acpi/tables.c Wed Sep 19 09:12:06 2007 +0100
@@ -59,6 +59,7 @@ static char *acpi_table_signatures[ACPI_
        [ACPI_SPMI] = "SPMI",
        [ACPI_HPET] = "HPET",
        [ACPI_MCFG] = "MCFG",
+       [ACPI_DMAR] = "DMAR",
 };
 
 static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
diff -r b7eb2bb9b625 -r aad813d8a8ad xen/include/asm-x86/hvm/iommu.h
--- a/xen/include/asm-x86/hvm/iommu.h   Tue Sep 18 16:09:19 2007 +0100
+++ b/xen/include/asm-x86/hvm/iommu.h   Wed Sep 19 09:12:06 2007 +0100
@@ -28,6 +28,13 @@
 #include <public/hvm/params.h>
 #include <public/hvm/save.h>
 
+struct g2m_ioport {
+    struct list_head list;
+    unsigned int gport;
+    unsigned int mport;
+    unsigned int np;
+};
+
 struct hvm_iommu {
     spinlock_t iommu_list_lock;    /* protect iommu specific lists */
     struct list_head pdev_list;    /* direct accessed pci devices */
diff -r b7eb2bb9b625 -r aad813d8a8ad xen/include/asm-x86/iommu.h
--- a/xen/include/asm-x86/iommu.h       Tue Sep 18 16:09:19 2007 +0100
+++ b/xen/include/asm-x86/iommu.h       Wed Sep 19 09:12:06 2007 +0100
@@ -28,6 +28,7 @@
 #include <xen/xmalloc.h>
 #include <asm/hvm/vmx/intel-iommu.h>
 #include <public/hvm/ioreq.h>
+#include <public/domctl.h>
 
 extern int vtd_enabled;
 
@@ -75,5 +76,9 @@ void iommu_set_pgd(struct domain *d);
 void iommu_set_pgd(struct domain *d);
 void iommu_domain_teardown(struct domain *d);
 int hvm_do_IRQ_dpci(struct domain *d, unsigned int irq);
+int dpci_ioport_intercept(ioreq_t *p);
+int pt_irq_create_bind_vtd(struct domain *d,
+    xen_domctl_bind_pt_irq_t * pt_irq_bind);
+
 
 #endif // _IOMMU_H_

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.