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

[Xen-changelog] [xen-unstable] vt-d: Detect and report failure to assign a pass-thru PCI device.



# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1192782663 -3600
# Node ID bc4afcd4c612afcee7f2fa2fc0ca400c26758876
# Parent  3ad0080ad9b56a8eb19433c61f6e3c5644fb6f2e
vt-d: Detect and report failure to assign a pass-thru PCI device.
Signed-off-by: Weidong Han <weidong.han@xxxxxxxxx>
---
 tools/ioemu/hw/pass-through.c           |   93 ++++++++++++++++----------------
 tools/python/xen/lowlevel/xc/xc.c       |   88 ++++++++++++++++++++++++++++++
 tools/python/xen/xend/XendDomainInfo.py |   14 ++++
 3 files changed, 149 insertions(+), 46 deletions(-)

diff -r 3ad0080ad9b5 -r bc4afcd4c612 tools/ioemu/hw/pass-through.c
--- a/tools/ioemu/hw/pass-through.c     Fri Oct 19 09:28:21 2007 +0100
+++ b/tools/ioemu/hw/pass-through.c     Fri Oct 19 09:31:03 2007 +0100
@@ -28,40 +28,52 @@
 #include "pci/pci.h"
 
 extern FILE *logfile;
-char *token;
-
-int pci_devs(const char *direct_pci)
-{
-    int count = 0;
-    const char *c;
-
-    /* skip first "[" character */
-    c = direct_pci + 1;
-    while ((c = strchr(c, '[')) != NULL) {
-        c++;
-        count++;
-    }
-    return (count);
-}
-
-int next_token(char *direct_pci)
-{
-    if (token == NULL)
-        token = strtok(direct_pci, ",");
-    else 
-        token = strtok(NULL, ",");
+
+static int token_value(char *token)
+{
     token = strchr(token, 'x');
     token = token + 1;
+
     return ((int) strtol(token, NULL, 16));
 }
 
-void next_bdf(char *direct_pci, int *seg,
-              int *bus, int *dev, int *func)
-{
-    *seg  = next_token(direct_pci);
-    *bus  = next_token(direct_pci);
-    *dev  = next_token(direct_pci);
-    *func = next_token(direct_pci);
+static int first_bdf(char *pci_str, char **last,
+                     int *seg, int *bus, int *dev, int *func)
+{
+    char *token;
+
+    token = strtok_r(pci_str, ",", last);
+    if ( !token )
+        return 0;
+
+    *seg  = token_value(token);
+    token = strtok_r(NULL, ",", last);
+    *bus  = token_value(token);
+    token = strtok_r(NULL, ",", last);
+    *dev  = token_value(token);
+    token = strtok_r(NULL, ",", last);
+    *func  = token_value(token);
+
+    return 1;
+}
+
+static int next_bdf(char **last, int *seg, int *bus, int *dev, int *func)
+{
+    char *token;
+
+    token = strtok_r(NULL, ",", last);
+    if ( !token )
+        return 0;
+
+    *seg  = token_value(token);
+    token = strtok_r(NULL, ",", last);
+    *bus  = token_value(token);
+    token = strtok_r(NULL, ",", last);
+    *dev  = token_value(token);
+    token = strtok_r(NULL, ",", last);
+    *func  = token_value(token);
+
+    return 1;
 }
 
 uint8_t find_cap_offset(struct pci_dev *pci_dev, uint8_t cap)
@@ -333,7 +345,6 @@ struct pt_dev * register_real_device(PCI
     int rc, i;
     struct pt_dev *assigned_device = NULL;
     struct pci_dev *pci_dev;
-    struct pci_config_cf8 machine_bdf;
     uint8_t e_device, e_intx;
 
     PT_LOG("Assigning real physical device %02x:%02x.%x ...\n",
@@ -367,15 +378,6 @@ struct pt_dev * register_real_device(PCI
 
     /* Issue PCIe FLR */
     pdev_flr(pci_dev);
-
-    /* Tell XEN vmm to change iommu settings */
-    machine_bdf.reg = 0;
-    machine_bdf.bus = r_bus;
-    machine_bdf.dev = r_dev;
-    machine_bdf.func = r_func;
-    rc = xc_assign_device(xc_handle, domid, machine_bdf.value);
-    if ( rc < 0 )
-        PT_LOG("Error: xc_domain_assign_device error %d\n", rc);
 
     /* Initialize virtualized PCI configuration (Extended 256 Bytes) */
     for ( i = 0; i < PCI_CONFIG_SIZE; i++ )
@@ -417,11 +419,11 @@ struct pt_dev * register_real_device(PCI
 
 int pt_init(PCIBus *e_bus, char *direct_pci)
 {
-    int i;
     int seg, b, d, f;
     struct pt_dev *pt_dev;
     struct pci_access *pci_access;
-    int dev_count = pci_devs(direct_pci);
+    int get_bdf;
+    char *last = NULL;
 
     /* Initialize libpci */
     pci_access = pci_alloc();
@@ -434,11 +436,10 @@ int pt_init(PCIBus *e_bus, char *direct_
     pci_scan_bus(pci_access);
 
     /* Assign given devices to guest */
-    for ( i = 0; i < dev_count; i++ )
-    {
-        /* Get next device bdf (bus, device, function) */
-        next_bdf(direct_pci, &seg, &b, &d, &f);
-
+    for ( get_bdf = first_bdf(direct_pci, &last, &seg, &b, &d, &f);
+          get_bdf;
+          get_bdf = next_bdf(&last, &seg, &b, &d, &f) )
+    {
         /* Register real device with the emulated bus */
         pt_dev = register_real_device(e_bus, "DIRECT PCI", PT_VIRT_DEVFN_AUTO,
             b, d, f, PT_MACHINE_IRQ_AUTO, pci_access);
diff -r 3ad0080ad9b5 -r bc4afcd4c612 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Fri Oct 19 09:28:21 2007 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c Fri Oct 19 09:31:03 2007 +0100
@@ -529,6 +529,86 @@ static PyObject *pyxc_set_hvm_param(XcOb
     return zero;
 }
 
+static int token_value(char *token)
+{
+    token = strchr(token, 'x');
+    token = token + 1;
+
+    return ((int) strtol(token, NULL, 16));
+}
+
+static int first_bdf(char *pci_str, char **last,
+                     int *seg, int *bus, int *dev, int *func)
+{
+    char *token;
+
+    token = strtok_r(pci_str, ",", last);
+    if ( !token )
+        return 0;
+
+    *seg  = token_value(token);
+    token = strtok_r(NULL, ",", last);
+    *bus  = token_value(token);
+    token = strtok_r(NULL, ",", last);
+    *dev  = token_value(token);
+    token = strtok_r(NULL, ",", last);
+    *func  = token_value(token);
+
+    return 1;
+}
+
+static int next_bdf(char **last, int *seg, int *bus, int *dev, int *func)
+{
+    char *token;
+
+    token = strtok_r(NULL, ",", last);
+    if ( !token )
+        return 0;
+
+    *seg  = token_value(token);
+    token = strtok_r(NULL, ",", last);
+    *bus  = token_value(token);
+    token = strtok_r(NULL, ",", last);
+    *dev  = token_value(token);
+    token = strtok_r(NULL, ",", last);
+    *func  = token_value(token);
+
+    return 1;
+}
+
+static PyObject *pyxc_assign_device(XcObject *self,
+                                    PyObject *args,
+                                    PyObject *kwds)
+{
+    uint32_t dom;
+    char *pci_str;
+    uint32_t bdf = 0;
+    int seg, bus, dev, func;
+    int get_bdf;
+    char *last = NULL;
+
+    static char *kwd_list[] = { "domid", "pci", NULL };
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|s", kwd_list,
+                                      &dom, &pci_str) )
+        return NULL;
+
+    for ( get_bdf = first_bdf(pci_str, &last, &seg, &bus, &dev, &func);
+          get_bdf;
+          get_bdf = next_bdf(&last, &seg, &bus, &dev, &func) )
+    {
+        bdf |= (bus & 0xff) << 16;
+        bdf |= (dev & 0x1f) << 11;
+        bdf |= (func & 0x7) << 8;
+
+        if ( xc_assign_device(self->xc_handle, dom, bdf) != 0 )
+            break;
+
+        bdf = 0;
+    }
+
+    return Py_BuildValue("i", bdf);
+}
+
 #ifdef __ia64__
 static PyObject *pyxc_nvram_init(XcObject *self,
                                  PyObject *args)
@@ -1349,6 +1429,14 @@ static PyMethodDef pyxc_methods[] = {
       " value   [long]:     Value of param.\n"
       "Returns: [int] 0 on success.\n" },
 
+     { "assign_device",
+       (PyCFunction)pyxc_assign_device,
+       METH_VARARGS | METH_KEYWORDS, "\n"
+       "assign device with VT-d.\n"
+       " dom     [int]:      Identifier of domain to build into.\n"
+       " pci_str [str]:      PCI devices.\n"
+       "Returns: [int] 0 on success, or device bdf that can't be assigned.\n" 
},
+  
     { "sched_id_get",
       (PyCFunction)pyxc_sched_id_get,
       METH_NOARGS, "\n"
diff -r 3ad0080ad9b5 -r bc4afcd4c612 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Fri Oct 19 09:28:21 2007 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Fri Oct 19 09:31:03 2007 +0100
@@ -1586,6 +1586,20 @@ class XendDomainInfo:
         # Set maximum number of vcpus in domain
         xc.domain_max_vcpus(self.domid, int(self.info['VCPUs_max']))
 
+        # Assign devices with VT-d
+        pci_str = str(self.info["platform"].get("pci"))
+        if hvm and pci_str:
+            bdf = xc.assign_device(self.domid, pci_str)
+            if bdf != 0:
+                bus = (bdf >> 16) & 0xff
+                devfn = (bdf >> 8) & 0xff
+                dev = (devfn >> 3) & 0x1f
+                func = devfn & 0x7
+                raise VmError("Fail to assign device(%x:%x.%x): maybe VT-d is "
+                              "not enabled, or the device is not exist, or it "
+                              "has already been assigned to other domain"
+                              % (bus, dev, func))
+
         # register the domain in the list 
         from xen.xend import XendDomain
         XendDomain.instance().add_domain(self)

_______________________________________________
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®.