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

[libvirt] patch for pci passthrough



Hi,

This patch adds support for the -pcidevice host=bus:dev.func
added in kvm-79

I used the structure as already defined in src/domain_conf.h

so analog to usb one now can add pci devices

as example:

lspci: 06:02.0 Network controller: Eicon Networks Corporation Diva Server 2FX (rev 01)


<hostdev mode='subsystem' type='pci'>
   <source>
       <address bus="0x06" slot="0x02" function="0x0"/>
   </source>
</hostdev>


values are hex so for bus: 0 to ff, slot: 0 to 1f and function: 0 to 7

Hope this patch is useful it applies to libvirt-0.5.1 and cvs checkout
from today (with some hunks)

Regards Jason

--
Collax GmbH . Burkheimer Str. 3 . 79111 Freiburg . Germany

p: +49 (0) 89-990157-0
f: +49 (0) 89-990157-11 . http://www.collax.com

diff -urp libvirt-0.5.1/src/domain_conf.c libvirt-0.5.1.new/src/domain_conf.c
--- libvirt-0.5.1/src/domain_conf.c	2008-12-04 13:51:39.000000000 +0100
+++ libvirt-0.5.1.new/src/domain_conf.c	2008-12-16 01:33:14.000000000 +0100
@@ -1531,6 +1531,95 @@ out:
 }
 
 
+static int
+virDomainHostdevSubsysPciDefParseXML(virConnectPtr conn,
+                                     const xmlNodePtr node,
+                                     virDomainHostdevDefPtr def) {
+
+    int ret = -1;
+    xmlNodePtr cur;
+
+    cur = node->children;
+    while (cur != NULL) {
+        if (cur->type == XML_ELEMENT_NODE) {
+            if (xmlStrEqual(cur->name, BAD_CAST "address")) {
+
+                char *domain = virXMLPropString(cur, "domain");
+                if (domain) {
+                    if (virStrToLong_ui(domain, NULL, 0,
+                                        &def->source.subsys.pci.domain) < 0) {
+                        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                             _("cannot parse domain %s"), domain);
+                        VIR_FREE(domain);
+                        goto out;
+                    }
+                    VIR_FREE(domain);
+                }
+
+                char *bus = virXMLPropString(cur, "bus");
+                if (bus) {
+                    if (virStrToLong_ui(bus, NULL, 0,
+                                        &def->source.subsys.pci.bus) < 0) {
+                        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                             _("cannot parse bus %s"), bus);
+                        VIR_FREE(bus);
+                        goto out;
+                    }
+                    VIR_FREE(bus);
+                } else {
+                    virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                         "%s", _("pci address needs bus id"));
+                    goto out;
+                }
+
+                char *slot = virXMLPropString(cur, "slot");
+                if (slot) {
+                    if (virStrToLong_ui(slot, NULL, 0,
+                                        &def->source.subsys.pci.slot) < 0)  {
+                        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                             _("cannot parse slot %s"),
+                                             slot);
+                        VIR_FREE(slot);
+                        goto out;
+                    }
+                    VIR_FREE(slot);
+                } else {
+                    virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                         "%s", _("pci address needs slot id"));
+                    goto out;
+                }
+
+                char *function = virXMLPropString(cur, "function");
+                if (function) {
+                    if (virStrToLong_ui(function, NULL, 0,
+                                        &def->source.subsys.pci.function) < 0)  {
+                        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                             _("cannot parse function %s"),
+                                             function);
+                        VIR_FREE(function);
+                        goto out;
+                    }
+                    VIR_FREE(function);
+                } else {
+                    virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                         "%s", _("pci address needs function id"));
+                    goto out;
+                }
+            } else {
+                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                     _("unknown pci source type '%s'"), cur->name);
+                goto out;
+            }
+        }
+        cur = cur->next;
+    }
+
+    ret = 0;
+out:
+    return ret;
+}
+
+
 static virDomainHostdevDefPtr
 virDomainHostdevDefParseXML(virConnectPtr conn,
                             const xmlNodePtr node) {
@@ -1578,6 +1667,11 @@ virDomainHostdevDefParseXML(virConnectPt
                         if (virDomainHostdevSubsysUsbDefParseXML(conn, cur, def) < 0)
                             goto error;
                 }
+                if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+                    def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+                        if (virDomainHostdevSubsysPciDefParseXML(conn, cur, def) < 0)
+                            goto error;
+                }
             } else {
                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
                                      _("unknown node %s"), cur->name);
@@ -2951,7 +3045,7 @@ virDomainHostdevDefFormat(virConnectPtr 
     }
 
     type = virDomainHostdevSubsysTypeToString(def->source.subsys.type);
-    if (!type || def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
+    if (!type || (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB && def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) ) {
         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
                              _("unexpected hostdev type %d"),
                              def->source.subsys.type);
@@ -2960,16 +3054,25 @@ virDomainHostdevDefFormat(virConnectPtr 
 
     virBufferVSprintf(buf, "    <hostdev mode='%s' type='%s'>\n", mode, type);
     virBufferAddLit(buf, "      <source>\n");
-
-    if (def->source.subsys.usb.vendor) {
-        virBufferVSprintf(buf, "        <vendor id='0x%.4x'/>\n",
-                          def->source.subsys.usb.vendor);
-        virBufferVSprintf(buf, "        <product id='0x%.4x'/>\n",
-                          def->source.subsys.usb.product);
-    } else {
-        virBufferVSprintf(buf, "        <address bus='%d' device='%d'/>\n",
-                          def->source.subsys.usb.bus,
-                          def->source.subsys.usb.device);
+    
+    if ( def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB ) {
+	    if (def->source.subsys.usb.vendor) {
+		virBufferVSprintf(buf, "        <vendor id='0x%.4x'/>\n",
+				  def->source.subsys.usb.vendor);
+		virBufferVSprintf(buf, "        <product id='0x%.4x'/>\n",
+				  def->source.subsys.usb.product);
+	    } else {
+		virBufferVSprintf(buf, "        <address bus='%d' device='%d'/>\n",
+				  def->source.subsys.usb.bus,
+				  def->source.subsys.usb.device);
+	    }
+    }
+    if ( def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI ) {
+		virBufferVSprintf(buf, "        <address domain='0x%.4x' bus='0x%.2x' slot='0x%.2x' function='0x%.1x'/>\n",
+				  def->source.subsys.pci.domain,
+				  def->source.subsys.pci.bus,
+				  def->source.subsys.pci.slot,
+				  def->source.subsys.pci.function);
     }
 
     virBufferAddLit(buf, "      </source>\n");
diff -urp libvirt-0.5.1/src/qemu_conf.c libvirt-0.5.1.new/src/qemu_conf.c
--- libvirt-0.5.1/src/qemu_conf.c	2008-12-16 02:11:04.000000000 +0100
+++ libvirt-0.5.1.new/src/qemu_conf.c	2008-12-16 01:33:14.000000000 +0100
@@ -1265,8 +1265,10 @@ int qemudBuildCommandLine(virConnectPtr 
     for (i = 0 ; i < vm->def->nhostdevs ; i++) {
         int ret;
         char* usbdev;
+        char* pcidev;
         virDomainHostdevDefPtr hostdev = vm->def->hostdevs[i];
-
+	
+	/* USB */
         if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
             hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
             if(hostdev->source.subsys.usb.vendor) {
@@ -1287,6 +1289,23 @@ int qemudBuildCommandLine(virConnectPtr 
             ADD_ARG_LIT(usbdev);
             VIR_FREE(usbdev);
         }
+
+	/* PCI */
+        if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+            hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+            ret = asprintf(&pcidev, "host=%0.2x:%0.2x.%.1x",
+                           hostdev->source.subsys.pci.bus,
+                           hostdev->source.subsys.pci.slot,
+                           hostdev->source.subsys.pci.function);
+            if (ret < 0) {
+                pcidev = NULL;
+                goto error;
+            }
+            ADD_ARG_LIT("-pcidevice");
+            ADD_ARG_LIT(pcidev);
+            VIR_FREE(pcidev);
+        }
+
     }
 
     if (migrateFrom) {

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