This includes adding it to the nodedev parser and formatter, docs, and test. --- docs/formatnode.html.in | 63 +++++++++++++++- docs/schemas/nodedev.rng | 11 +++ src/conf/node_device_conf.c | 86 +++++++++++++++++++++- src/conf/node_device_conf.h | 5 +- src/node_device/node_device_udev.c | 21 +++++- tests/nodedevschemadata/pci_8086_10c9_sriov_pf.xml | 16 ++++ tests/nodedevxml2xmltest.c | 1 + 7 files changed, 199 insertions(+), 4 deletions(-) create mode 100644 tests/nodedevschemadata/pci_8086_10c9_sriov_pf.xml diff --git a/docs/formatnode.html.in b/docs/formatnode.html.in index 11654e5..ad05a70 100644 --- a/docs/formatnode.html.in +++ b/docs/formatnode.html.in @@ -80,6 +80,36 @@ <dd>Vendor details from the device ROM, including an attribute <code>id</code> with the hexadecimal vendor id, and an optional text name of that vendor.</dd> + <dt><code>iommuGroup</code></dt> + <dd> + This optional element describes the "IOMMU group" this + device belongs to. If the element exists, it has a + mandatory <code>number</code> attribute which tells + the group number used for management of the group (all + devices in group "n" will be found in + "/sys/kernel/iommu_groups/n"). It will also have a + list of <code>address</code> subelements, each + containing the PCI address of a device in the same + group. The toplevel device will itself be included in + this list. + </dd> + <dt><code>capability</code></dt> + <dd> + This optional element can occur multiple times. If it + exists, it has a mandatory <code>type</code> attribute + which will be set to + either <code>physical_function</code> + or <code>virtual_functions</code>. If the type + is <code>physical_function</code>, there will be a + single <code>address</code> subelement which contains + the PCI address of the SRIOV Physical Function (PF) + that is the parent of this device (and this device is, + by implication, an SRIOV Virtual Function (VF)). If + the type is <code>virtual_functions</code>, then this + device is an SRIOV PF, and the capability element will + have a list of <code>address</code> subelements, one + for each VF on this PF. + </dd> </dl> </dd> <dt><code>usb_device</code></dt> @@ -232,7 +262,38 @@ <address>00:27:13:6a:fe:00</address> <capability type='80203'/> </capability> -</device></pre> +</device> + +<device> + <name>pci_0000_02_00_0</name> + <path>/sys/devices/pci0000:00/0000:00:04.0/0000:02:00.0</path> + <parent>pci_0000_00_04_0</parent> + <driver> + <name>igb</name> + </driver> + <capability type='pci'> + <domain>0</domain> + <bus>2</bus> + <slot>0</slot> + <function>0</function> + <product id='0x10c9'>82576 Gigabit Network Connection</product> + <vendor id='0x8086'>Intel Corporation</vendor> + <capability type='virt_functions'> + <address domain='0x0000' bus='0x02' slot='0x10' function='0x0'/> + <address domain='0x0000' bus='0x02' slot='0x10' function='0x2'/> + <address domain='0x0000' bus='0x02' slot='0x10' function='0x4'/> + <address domain='0x0000' bus='0x02' slot='0x10' function='0x6'/> + <address domain='0x0000' bus='0x02' slot='0x11' function='0x0'/> + <address domain='0x0000' bus='0x02' slot='0x11' function='0x2'/> + <address domain='0x0000' bus='0x02' slot='0x11' function='0x4'/> + </capability> + <iommuGroup number='12'> + <address domain='0x0000' bus='0x02' slot='0x00' function='0x0'/> + <address domain='0x0000' bus='0x02' slot='0x00' function='0x1'/> + </iommuGroup> + </capability> +</device> + </pre> </body> </html> diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng index 1f5dcb9..d2bebff 100644 --- a/docs/schemas/nodedev.rng +++ b/docs/schemas/nodedev.rng @@ -144,6 +144,17 @@ </element> </optional> + <optional> + <element name='iommuGroup'> + <attribute name='number'> + <ref name='unsignedInt'/> + </attribute> + <oneOrMore> + <ref name='address'/> + </oneOrMore> + </element> + </optional> + </define> <define name='capusbdev'> diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index 548cd8f..96742ef 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -1,6 +1,7 @@ /* * node_device_conf.c: config handling for node devices * + * Copyright (C) 2009-2013 Red Hat, Inc. * Copyright (C) 2008 Virtual Iron Software, Inc. * Copyright (C) 2008 David F. Lively * @@ -31,6 +32,7 @@ #include "viralloc.h" #include "virstring.h" #include "node_device_conf.h" +#include "device_conf.h" #include "virxml.h" #include "virbuffer.h" #include "viruuid.h" @@ -330,6 +332,20 @@ char *virNodeDeviceDefFormat(const virNodeDeviceDefPtr def) } virBufferAddLit(&buf, " </capability>\n"); } + if (data->pci_dev.nIommuGroupDevices) { + virBufferAsprintf(&buf, " <iommuGroup number='%d'>\n", + data->pci_dev.iommuGroupNumber); + for (i = 0; i < data->pci_dev.nIommuGroupDevices; i++) { + virBufferAsprintf(&buf, + " <address domain='0x%.4x' bus='0x%.2x' " + "slot='0x%.2x' function='0x%.1x'/>\n", + data->pci_dev.iommuGroupDevices[i]->domain, + data->pci_dev.iommuGroupDevices[i]->bus, + data->pci_dev.iommuGroupDevices[i]->slot, + data->pci_dev.iommuGroupDevices[i]->function); + } + virBufferAddLit(&buf, " </iommuGroup>\n"); + } break; case VIR_NODE_DEV_CAP_USB_DEV: virBufferAsprintf(&buf, " <bus>%d</bus>\n", data->usb_dev.bus); @@ -966,12 +982,71 @@ out: } static int +virNodeDevCapPciDevIommuGroupParseXML(xmlXPathContextPtr ctxt, + xmlNodePtr iommuGroupNode, + union _virNodeDevCapData *data) +{ + xmlNodePtr origNode = ctxt->node; + xmlNodePtr *addrNodes = NULL; + char *numberStr = NULL; + int nAddrNodes, ii, ret = -1; + virPCIDeviceAddressPtr pciAddr = NULL; + + ctxt->node = iommuGroupNode; + + numberStr = virXMLPropString(iommuGroupNode, "number"); + if (!numberStr) { + virReportError(VIR_ERR_XML_ERROR, + "%s", _("missing iommuGroup number attribute")); + goto cleanup; + } + if (virStrToLong_ui(numberStr, NULL, 10, + &data->pci_dev.iommuGroupNumber) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("invalid iommuGroup number attribute '%s'"), + numberStr); + goto cleanup; + } + + if ((nAddrNodes = virXPathNodeSet("./address", ctxt, &addrNodes)) < 0) + goto cleanup; + + for (ii = 0; ii < nAddrNodes; ii++) { + virDevicePCIAddress addr = { 0, 0, 0, 0, 0 }; + if (virDevicePCIAddressParseXML(addrNodes[ii], &addr) < 0) + goto cleanup; + if (VIR_ALLOC(pciAddr) < 0) { + virReportOOMError(); + goto cleanup; + } + pciAddr->domain = addr.domain; + pciAddr->bus = addr.bus; + pciAddr->slot = addr.slot; + pciAddr->function = addr.function; + if (VIR_APPEND_ELEMENT(data->pci_dev.iommuGroupDevices, + data->pci_dev.nIommuGroupDevices, + pciAddr) < 0) { + virReportOOMError(); + goto cleanup; + } + } + + ret = 0; +cleanup: + ctxt->node = origNode; + VIR_FREE(addrNodes); + VIR_FREE(pciAddr); + return ret; +} + + +static int virNodeDevCapPciDevParseXML(xmlXPathContextPtr ctxt, virNodeDeviceDefPtr def, xmlNodePtr node, union _virNodeDevCapData *data) { - xmlNodePtr orignode; + xmlNodePtr orignode, iommuGroupNode; int ret = -1; orignode = ctxt->node; @@ -1016,6 +1091,12 @@ virNodeDevCapPciDevParseXML(xmlXPathContextPtr ctxt, data->pci_dev.vendor_name = virXPathString("string(./vendor[1])", ctxt); data->pci_dev.product_name = virXPathString("string(./product[1])", ctxt); + if ((iommuGroupNode = virXPathNode("./iommuGroup[1]", ctxt))) { + if (virNodeDevCapPciDevIommuGroupParseXML(ctxt, iommuGroupNode, + data) < 0) { + goto out; + } + } ret = 0; out: ctxt->node = orignode; @@ -1385,6 +1466,9 @@ void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps) for (i = 0; i < data->pci_dev.num_virtual_functions; i++) { VIR_FREE(data->pci_dev.virtual_functions[i]); } + for (i = 0; i < data->pci_dev.nIommuGroupDevices; i++) { + VIR_FREE(data->pci_dev.iommuGroupDevices[i]); + } break; case VIR_NODE_DEV_CAP_USB_DEV: VIR_FREE(data->usb_dev.product_name); diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index 17240be..ec35da2 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -1,7 +1,7 @@ /* * node_device_conf.h: config handling for node devices * - * Copyright (C) 2010-2011 Red Hat, Inc. + * Copyright (C) 2009-2013 Red Hat, Inc. * Copyright (C) 2008 Virtual Iron Software, Inc. * Copyright (C) 2008 David F. Lively * @@ -112,6 +112,9 @@ struct _virNodeDevCapsDef { virPCIDeviceAddressPtr *virtual_functions; unsigned int num_virtual_functions; unsigned int flags; + virPCIDeviceAddressPtr *iommuGroupDevices; + size_t nIommuGroupDevices; + unsigned int iommuGroupNumber; } pci_dev; struct { unsigned int bus; diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index b94be80..9bb4a17 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -421,7 +421,8 @@ static int udevProcessPCI(struct udev_device *device, { const char *syspath = NULL; union _virNodeDevCapData *data = &def->caps->data; - int ret = -1; + virPCIDeviceAddress addr; + int tmpGroup, ret = -1; char *p; int rc; @@ -501,6 +502,24 @@ static int udevProcessPCI(struct udev_device *device, else if (!rc && (data->pci_dev.num_virtual_functions > 0)) data->pci_dev.flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION; + /* iommu group */ + addr.domain = data->pci_dev.domain; + addr.bus = data->pci_dev.bus; + addr.slot = data->pci_dev.slot; + addr.function = data->pci_dev.function; + tmpGroup = virPCIGetIOMMUGroupNum(&addr); + if (tmpGroup == -1) { + /* error was already reported */ + goto out; + /* -2 return means there is no iommu_group data */ + } else if (tmpGroup >= 0) { + if (virPCIGetIOMMUGroupAddresses(&addr, &data->pci_dev.iommuGroupDevices, + &data->pci_dev.nIommuGroupDevices) < 0) { + goto out; + } + data->pci_dev.iommuGroupNumber = tmpGroup; + } + ret = 0; out: diff --git a/tests/nodedevschemadata/pci_8086_10c9_sriov_pf.xml b/tests/nodedevschemadata/pci_8086_10c9_sriov_pf.xml new file mode 100644 index 0000000..eff8932 --- /dev/null +++ b/tests/nodedevschemadata/pci_8086_10c9_sriov_pf.xml @@ -0,0 +1,16 @@ +<device> + <name>pci_0000_02_00_0</name> + <parent>pci_0000_00_04_0</parent> + <capability type='pci'> + <domain>0</domain> + <bus>2</bus> + <slot>0</slot> + <function>0</function> + <product id='0x10c9'>82576 Gigabit Network Connection</product> + <vendor id='0x8086'>Intel Corporation</vendor> + <iommuGroup number='12'> + <address domain='0x0000' bus='0x02' slot='0x00' function='0x0'/> + <address domain='0x0000' bus='0x02' slot='0x00' function='0x1'/> + </iommuGroup> + </capability> +</device> diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c index e81c617..ed49857 100644 --- a/tests/nodedevxml2xmltest.c +++ b/tests/nodedevxml2xmltest.c @@ -78,6 +78,7 @@ mymain(void) DO_TEST("net_00_13_02_b9_f9_d3"); DO_TEST("net_00_15_58_2f_e9_55"); DO_TEST("pci_1002_71c4"); + DO_TEST("pci_8086_10c9_sriov_pf"); DO_TEST("pci_8086_27c5_scsi_host_0"); DO_TEST("pci_8086_27c5_scsi_host_scsi_device_lun0"); DO_TEST("pci_8086_27c5_scsi_host_scsi_host"); -- 1.7.11.7 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list