From nobody Mon Feb 9 02:43:20 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1492693765664534.4749422474011; Thu, 20 Apr 2017 06:09:25 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8DFEF75EAE; Thu, 20 Apr 2017 13:09:23 +0000 (UTC) Received: from colo-mx.corp.redhat.com (unknown [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 5AA5417110; Thu, 20 Apr 2017 13:09:23 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id D66B25EC62; Thu, 20 Apr 2017 13:09:04 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v3KD6H77027936 for ; Thu, 20 Apr 2017 09:06:17 -0400 Received: by smtp.corp.redhat.com (Postfix) id 0108E4DA37; Thu, 20 Apr 2017 13:06:17 +0000 (UTC) Received: from beluga.usersys.redhat.com (dhcp129-94.brq.redhat.com [10.34.129.94]) by smtp.corp.redhat.com (Postfix) with ESMTP id 569365C886; Thu, 20 Apr 2017 13:06:16 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 8DFEF75EAE Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=libvir-list-bounces@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 8DFEF75EAE From: Erik Skultety To: libvir-list@redhat.com Date: Thu, 20 Apr 2017 15:05:57 +0200 Message-Id: <1c35dd502560708964c2b49a649262ba59761bbf.1492692116.git.eskultet@redhat.com> In-Reply-To: References: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-loop: libvir-list@redhat.com Cc: Erik Skultety Subject: [libvirt] [PATCH v2 07/10] nodedev: Introduce the mdev capability to a PCI parent device X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Thu, 20 Apr 2017 13:09:24 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" The parent device needs to report the generic stuff about the supported mediated devices types, like device API, available instances, type name, etc. Therefore this patch introduces a new nested capability element of type 'mdev' with the resulting XML of the following format: ... ... optional, raw, unstructured resource allocation data vfio-pci NUM ... ... ... Signed-off-by: Erik Skultety --- docs/schemas/nodedev.rng | 24 ++++ src/conf/node_device_conf.c | 103 +++++++++++++++++ src/conf/node_device_conf.h | 17 +++ src/libvirt_private.syms | 1 + src/node_device/node_device_udev.c | 133 ++++++++++++++++++= ++++ tests/nodedevschemadata/pci_0000_02_10_7_mdev.xml | 27 +++++ 6 files changed, 305 insertions(+) create mode 100644 tests/nodedevschemadata/pci_0000_02_10_7_mdev.xml diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng index 0f90a73c8..4b5dca777 100644 --- a/docs/schemas/nodedev.rng +++ b/docs/schemas/nodedev.rng @@ -205,6 +205,30 @@ =20 + + + mdev + + + + + + + + + + + vfio-pci + + + + + + + + + + diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index fdddc97eb..fe4f1bc60 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -87,6 +87,26 @@ virNodeDevCapsDefParseString(const char *xpath, } =20 =20 +static void +virNodeDevCapMdevClear(virNodeDevCapMdevPtr mdev) +{ + VIR_FREE(mdev->type); + VIR_FREE(mdev->name); + VIR_FREE(mdev->device_api); +} + + +void +virNodeDevCapMdevFree(virNodeDevCapMdevPtr mdev) +{ + if (!mdev) + return; + + virNodeDevCapMdevClear(mdev); + VIR_FREE(mdev); +} + + void virNodeDeviceDefFree(virNodeDeviceDefPtr def) { @@ -264,6 +284,27 @@ virNodeDeviceCapPCIDefFormat(virBufferPtr buf, virBufferAsprintf(buf, "\n", virPCIHeaderTypeToString(data->pci_dev.hdrType)); } + if (data->pci_dev.flags & VIR_NODE_DEV_CAP_FLAG_PCI_MDEV) { + virBufferAddLit(buf, "\n"); + virBufferAdjustIndent(buf, 2); + for (i =3D 0; i < data->pci_dev.nmdevs; i++) { + virNodeDevCapMdevPtr mdev =3D data->pci_dev.mdevs[i]; + virBufferEscapeString(buf, "\n", mdev->type); + virBufferAdjustIndent(buf, 2); + if (mdev->name) + virBufferAsprintf(buf, "%s\n", + mdev->name); + virBufferAsprintf(buf, "%s\n", + mdev->device_api); + virBufferAsprintf(buf, + "%u= \n", + mdev->available_instances); + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + } + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "\n"); + } if (data->pci_dev.nIommuGroupDevices) { virBufferAsprintf(buf, "\n", data->pci_dev.iommuGroupNumber); @@ -1358,6 +1399,62 @@ virNodeDevPCICapSRIOVParseXML(xmlXPathContextPtr ctx= t, =20 =20 static int +virNodeDevPCICapMediatedDevParseXML(xmlXPathContextPtr ctxt, + virNodeDevCapPCIDevPtr pci_dev) +{ + int ret =3D -1; + xmlNodePtr orignode =3D NULL; + xmlNodePtr *nodes =3D NULL; + int nmdevs =3D virXPathNodeSet("./type", ctxt, &nodes); + virNodeDevCapMdevPtr mdev =3D NULL; + size_t i; + + orignode =3D ctxt->node; + for (i =3D 0; i < nmdevs; i++) { + ctxt->node =3D nodes[i]; + + if (VIR_ALLOC(mdev) < 0) + goto cleanup; + + if (!(mdev->type =3D virXPathString("string(./@id[1])", ctxt))) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("missing 'id' attribute for mediated device's= " + " element")); + goto cleanup; + } + + if (!(mdev->device_api =3D virXPathString("string(./deviceAPI[1])"= , ctxt))) { + virReportError(VIR_ERR_XML_ERROR, + _("missing device API for mediated device type = '%s'"), + mdev->type); + goto cleanup; + } + + if (virXPathUInt("number(./availableInstances)", ctxt, + &mdev->available_instances) < 0) { + virReportError(VIR_ERR_XML_ERROR, + _("missing number of available instances for " + "mediated device type '%s'"), + mdev->type); + goto cleanup; + } + + mdev->name =3D virXPathString("string(./name)", ctxt); + + if (VIR_APPEND_ELEMENT(pci_dev->mdevs, pci_dev->nmdevs, mdev) < 0) + goto cleanup; + } + + pci_dev->flags |=3D VIR_NODE_DEV_CAP_FLAG_PCI_MDEV; + ret =3D 0; + cleanup: + virNodeDevCapMdevFree(mdev); + ctxt->node =3D orignode; + return ret; +} + + +static int virNodeDevPCICapabilityParseXML(xmlXPathContextPtr ctxt, xmlNodePtr node, virNodeDevCapPCIDevPtr pci_dev) @@ -1382,6 +1479,9 @@ virNodeDevPCICapabilityParseXML(xmlXPathContextPtr ct= xt, if (sriov_cap && virNodeDevPCICapSRIOVParseXML(ctxt, node, pci_dev, sriov_cap) < 0)= { goto cleanup; + } if (STREQ(type, "mdev") && + virNodeDevPCICapMediatedDevParseXML(ctxt, pci_dev)) { + goto cleanup; } else { int hdrType =3D virPCIHeaderTypeFromString(type); =20 @@ -1894,6 +1994,9 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps) VIR_FREE(data->pci_dev.iommuGroupDevices[i]); VIR_FREE(data->pci_dev.iommuGroupDevices); virPCIEDeviceInfoFree(data->pci_dev.pci_express); + for (i =3D 0; i < data->pci_dev.nmdevs; i++) + virNodeDevCapMdevFree(data->pci_dev.mdevs[i]); + VIR_FREE(data->pci_dev.mdevs); 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 375f97256..883fa017e 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -94,6 +94,7 @@ typedef enum { VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION =3D (1 << 0), VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION =3D (1 << 1), VIR_NODE_DEV_CAP_FLAG_PCIE =3D (1 << 2), + VIR_NODE_DEV_CAP_FLAG_PCI_MDEV =3D (1 << 3), } virNodeDevPCICapFlags; =20 typedef enum { @@ -132,6 +133,16 @@ struct _virNodeDevCapSystem { virNodeDevCapSystemFirmware firmware; }; =20 +typedef struct _virNodeDevCapMdev virNodeDevCapMdev; +typedef virNodeDevCapMdev *virNodeDevCapMdevPtr; +struct _virNodeDevCapMdev { + char *type; + char *name; + char *device_api; + unsigned int available_instances; + unsigned int iommuGroupNumber; +}; + typedef struct _virNodeDevCapPCIDev virNodeDevCapPCIDev; typedef virNodeDevCapPCIDev *virNodeDevCapPCIDevPtr; struct _virNodeDevCapPCIDev { @@ -155,6 +166,8 @@ struct _virNodeDevCapPCIDev { int numa_node; virPCIEDeviceInfoPtr pci_express; int hdrType; /* enum virPCIHeaderType or -1 */ + virNodeDevCapMdevPtr *mdevs; + size_t nmdevs; }; =20 typedef struct _virNodeDevCapUSBDev virNodeDevCapUSBDev; @@ -263,6 +276,7 @@ struct _virNodeDevCapData { virNodeDevCapStorage storage; virNodeDevCapSCSIGeneric sg; virNodeDevCapDRM drm; + virNodeDevCapMdev mdev; }; }; =20 @@ -339,6 +353,9 @@ virNodeDeviceDefFree(virNodeDeviceDefPtr def); void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps); =20 +void +virNodeDevCapMdevFree(virNodeDevCapMdevPtr mdev); + # define VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_CAP \ (VIR_CONNECT_LIST_NODE_DEVICES_CAP_SYSTEM | \ VIR_CONNECT_LIST_NODE_DEVICES_CAP_PCI_DEV | \ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 181e17875..d1e872e60 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -665,6 +665,7 @@ virNetDevIPRouteParseXML; =20 =20 # conf/node_device_conf.h +virNodeDevCapMdevFree; virNodeDevCapsDefFree; virNodeDevCapTypeFromString; virNodeDevCapTypeToString; diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_devi= ce_udev.c index 95c1aee29..79f1537d9 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -314,6 +314,133 @@ static int udevTranslatePCIIds(unsigned int vendor, } =20 =20 +static int +udevGetMdevCaps(struct udev_device *device, + const char *sysfspath, + virNodeDevCapMdevPtr mdev) +{ + int ret =3D -1; + char *attrpath =3D NULL; /* relative path to the actual sysfs attribu= te */ + const char *devpath =3D NULL; /* base sysfs path as reported by udev= */ + const char *relpath =3D NULL; /* diff between @sysfspath and @devpat= h */ + char *tmp =3D NULL; + +#define MDEV_GET_SYSFS_ATTR(attr_name, dir, cb, ...) = \ + do { = \ + if (virAsprintf(&attrpath, "%s/%s", dir, #attr_name) < 0) = \ + goto cleanup; = \ + = \ + if (cb(device, attrpath, __VA_ARGS__) < 0) = \ + goto cleanup; = \ + = \ + VIR_FREE(attrpath); = \ + } while (0) = \ + + /* UDEV doesn't report attributes under subdirectories by default but = is + * able to query them if the path to the attribute is relative to the + * device's base path, e.g. /sys/devices/../0000:00:01.0/ is the devic= e's + * base path as udev reports it, but we're interested in attributes un= der + * /sys/devices/../0000:00:01.0/mdev_supported_types//. So, let's + * strip the common part of the path and let udev chew the relative bi= t. + */ + devpath =3D udev_device_get_syspath(device); + relpath =3D sysfspath + strlen(devpath); + + /* When calling from the mdev child device, @sysfspath is a symbolic l= ink + * to the actual mdev type (rather than a physical path), so we need to + * resolve it in order to get the type's name. + */ + if (virFileResolveLink(sysfspath, &tmp) < 0) + goto cleanup; + + if (VIR_STRDUP(mdev->type, last_component(tmp)) < 0) + goto cleanup; + + MDEV_GET_SYSFS_ATTR(name, relpath, + udevGetStringSysfsAttr, &mdev->name); + MDEV_GET_SYSFS_ATTR(device_api, relpath, + udevGetStringSysfsAttr, &mdev->device_api); + MDEV_GET_SYSFS_ATTR(available_instances, relpath, + udevGetUintSysfsAttr, &mdev->available_instances, = 10); + +#undef MDEV_GET_SYSFS_ATTR + + ret =3D 0; + cleanup: + VIR_FREE(attrpath); + VIR_FREE(tmp); + return ret; +} + + +static int +udevPCIGetMdevCaps(struct udev_device *device, + virNodeDevCapPCIDevPtr pcidata) +{ + int ret =3D -1; + int direrr =3D -1; + DIR *dir =3D NULL; + struct dirent *entry; + char *path =3D NULL; + char *tmppath =3D NULL; + virNodeDevCapMdevPtr mdev =3D NULL; + virNodeDevCapMdevPtr *mdevs =3D NULL; + size_t nmdevs =3D 0; + size_t i; + + if (virAsprintf(&path, "%s/mdev_supported_types", + udev_device_get_syspath(device)) < 0) + return -1; + + if ((direrr =3D virDirOpenIfExists(&dir, path)) < 0) + goto cleanup; + + if (direrr =3D=3D 0) { + ret =3D 0; + goto cleanup; + } + + if (VIR_ALLOC(mdevs) < 0) + goto cleanup; + + /* since udev doesn't provide means to list other than top-level + * attributes, we need to scan the subdirectories ourselves + */ + while ((direrr =3D virDirRead(dir, &entry, path)) > 0) { + if (VIR_ALLOC(mdev) < 0) + goto cleanup; + + if (virAsprintf(&tmppath, "%s/%s", path, entry->d_name) < 0) + goto cleanup; + + if (udevGetMdevCaps(device, tmppath, mdev) < 0) + goto cleanup; + + if (VIR_APPEND_ELEMENT(mdevs, nmdevs, mdev) < 0) + goto cleanup; + + VIR_FREE(tmppath); + } + + if (direrr < 0) + goto cleanup; + + VIR_STEAL_PTR(pcidata->mdevs, mdevs); + pcidata->nmdevs =3D nmdevs; + nmdevs =3D 0; + ret =3D 0; + cleanup: + virNodeDevCapMdevFree(mdev); + for (i =3D 0; i < nmdevs; i++) + virNodeDevCapMdevFree(mdevs[i]); + VIR_FREE(mdevs); + VIR_FREE(path); + VIR_FREE(tmppath); + VIR_DIR_CLOSE(dir); + return ret; +} + + static int udevProcessPCI(struct udev_device *device, virNodeDeviceDefPtr def) { @@ -400,6 +527,12 @@ static int udevProcessPCI(struct udev_device *device, } } =20 + /* check whether the device is mediated devices framework capable, if = so, + * process it + */ + if (udevPCIGetMdevCaps(device, pci_dev) < 0) + goto cleanup; + ret =3D 0; =20 cleanup: diff --git a/tests/nodedevschemadata/pci_0000_02_10_7_mdev.xml b/tests/node= devschemadata/pci_0000_02_10_7_mdev.xml new file mode 100644 index 000000000..b745686d3 --- /dev/null +++ b/tests/nodedevschemadata/pci_0000_02_10_7_mdev.xml @@ -0,0 +1,27 @@ + + pci_0000_02_10_7 + pci_0000_00_04_0 + + 0 + 2 + 16 + 7 + 82576 Virtual Function + Intel Corporation + + + bar + vfio-pci + 1 + + + +
+ + + + + + + + --=20 2.12.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list