mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 13:45:38 +00:00
nodedev: Introduce mdev capability for mediated devices
Start discovering the mediated devices on the host system and format the attributes for the mediated device into the XML. Compared to the parent device which reports generic information about the abstract mediated devices types, a child device only reports the type name it has been instantiated from and the IOMMU group number, since that's device specific compared to the rest of the info that can be gathered about mediated devices at the moment. This patch introduces both the formatting and parsing routines, updates nodedev.rng schema, adding a testcase as well. The resulting mdev child device XML: <device> <name>mdev_4b20d080_1b54_4048_85b3_a6a62d165c01</name> <path>/sys/devices/.../4b20d080-1b54-4048-85b3-a6a62d165c01</path> <parent>pci_0000_06_00_0</parent> <driver> <name>vfio_mdev</name> </driver> <capability type='mdev'> <type id='vendor_supplied_type_id'/> <iommuGroup number='NUM'/> <capability/> <device/> https://bugzilla.redhat.com/show_bug.cgi?id=1452072 Signed-off-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
parent
500cbc066a
commit
88ef73e13c
@ -83,6 +83,7 @@
|
|||||||
<ref name="capscsi"/>
|
<ref name="capscsi"/>
|
||||||
<ref name="capstorage"/>
|
<ref name="capstorage"/>
|
||||||
<ref name="capdrm"/>
|
<ref name="capdrm"/>
|
||||||
|
<ref name="capmdev"/>
|
||||||
</choice>
|
</choice>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
@ -580,6 +581,22 @@
|
|||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
|
||||||
|
<define name='capmdev'>
|
||||||
|
<attribute name='type'>
|
||||||
|
<value>mdev</value>
|
||||||
|
</attribute>
|
||||||
|
<element name='type'>
|
||||||
|
<attribute name='id'>
|
||||||
|
<data type='string'/>
|
||||||
|
</attribute>
|
||||||
|
</element>
|
||||||
|
<element name='iommuGroup'>
|
||||||
|
<attribute name='number'>
|
||||||
|
<ref name='unsignedInt'/>
|
||||||
|
</attribute>
|
||||||
|
</element>
|
||||||
|
</define>
|
||||||
|
|
||||||
<define name='address'>
|
<define name='address'>
|
||||||
<element name='address'>
|
<element name='address'>
|
||||||
<attribute name='domain'><ref name='hexuint'/></attribute>
|
<attribute name='domain'><ref name='hexuint'/></attribute>
|
||||||
|
@ -577,6 +577,10 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def)
|
|||||||
virBufferEscapeString(&buf, "<type>%s</type>\n", virNodeDevDRMTypeToString(data->drm.type));
|
virBufferEscapeString(&buf, "<type>%s</type>\n", virNodeDevDRMTypeToString(data->drm.type));
|
||||||
break;
|
break;
|
||||||
case VIR_NODE_DEV_CAP_MDEV:
|
case VIR_NODE_DEV_CAP_MDEV:
|
||||||
|
virBufferEscapeString(&buf, "<type id='%s'/>\n", data->mdev.type);
|
||||||
|
virBufferAsprintf(&buf, "<iommuGroup number='%u'/>\n",
|
||||||
|
data->mdev.iommuGroupNumber);
|
||||||
|
break;
|
||||||
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
||||||
case VIR_NODE_DEV_CAP_FC_HOST:
|
case VIR_NODE_DEV_CAP_FC_HOST:
|
||||||
case VIR_NODE_DEV_CAP_VPORTS:
|
case VIR_NODE_DEV_CAP_VPORTS:
|
||||||
@ -1647,6 +1651,39 @@ virNodeDevCapSystemParseXML(xmlXPathContextPtr ctxt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
virNodeDevCapMdevParseXML(xmlXPathContextPtr ctxt,
|
||||||
|
virNodeDeviceDefPtr def,
|
||||||
|
xmlNodePtr node,
|
||||||
|
virNodeDevCapMdevPtr mdev)
|
||||||
|
{
|
||||||
|
xmlNodePtr orignode;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
orignode = ctxt->node;
|
||||||
|
ctxt->node = node;
|
||||||
|
|
||||||
|
if (!(mdev->type = virXPathString("string(./type[1]/@id)", ctxt))) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("missing type id attribute for '%s'"), def->name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virNodeDevCapsDefParseULong("number(./iommuGroup[1]/@number)", ctxt,
|
||||||
|
&mdev->iommuGroupNumber, def,
|
||||||
|
_("missing iommuGroup number attribute for "
|
||||||
|
"'%s'"),
|
||||||
|
_("invalid iommuGroup number attribute for "
|
||||||
|
"'%s'")) < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
out:
|
||||||
|
ctxt->node = orignode;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static virNodeDevCapsDefPtr
|
static virNodeDevCapsDefPtr
|
||||||
virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
|
virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
|
||||||
virNodeDeviceDefPtr def,
|
virNodeDeviceDefPtr def,
|
||||||
@ -1715,6 +1752,8 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
|
|||||||
ret = virNodeDevCapDRMParseXML(ctxt, def, node, &caps->data.drm);
|
ret = virNodeDevCapDRMParseXML(ctxt, def, node, &caps->data.drm);
|
||||||
break;
|
break;
|
||||||
case VIR_NODE_DEV_CAP_MDEV:
|
case VIR_NODE_DEV_CAP_MDEV:
|
||||||
|
ret = virNodeDevCapMdevParseXML(ctxt, def, node, &caps->data.mdev);
|
||||||
|
break;
|
||||||
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
||||||
case VIR_NODE_DEV_CAP_FC_HOST:
|
case VIR_NODE_DEV_CAP_FC_HOST:
|
||||||
case VIR_NODE_DEV_CAP_VPORTS:
|
case VIR_NODE_DEV_CAP_VPORTS:
|
||||||
@ -2038,6 +2077,8 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
|
|||||||
VIR_FREE(data->sg.path);
|
VIR_FREE(data->sg.path);
|
||||||
break;
|
break;
|
||||||
case VIR_NODE_DEV_CAP_MDEV:
|
case VIR_NODE_DEV_CAP_MDEV:
|
||||||
|
VIR_FREE(data->mdev.type);
|
||||||
|
break;
|
||||||
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
||||||
case VIR_NODE_DEV_CAP_DRM:
|
case VIR_NODE_DEV_CAP_DRM:
|
||||||
case VIR_NODE_DEV_CAP_FC_HOST:
|
case VIR_NODE_DEV_CAP_FC_HOST:
|
||||||
|
@ -143,6 +143,13 @@ struct _virNodeDevCapMdevType {
|
|||||||
unsigned int available_instances;
|
unsigned int available_instances;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _virNodeDevCapMdev virNodeDevCapMdev;
|
||||||
|
typedef virNodeDevCapMdev *virNodeDevCapMdevPtr;
|
||||||
|
struct _virNodeDevCapMdev {
|
||||||
|
char *type;
|
||||||
|
unsigned int iommuGroupNumber;
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct _virNodeDevCapPCIDev virNodeDevCapPCIDev;
|
typedef struct _virNodeDevCapPCIDev virNodeDevCapPCIDev;
|
||||||
typedef virNodeDevCapPCIDev *virNodeDevCapPCIDevPtr;
|
typedef virNodeDevCapPCIDev *virNodeDevCapPCIDevPtr;
|
||||||
struct _virNodeDevCapPCIDev {
|
struct _virNodeDevCapPCIDev {
|
||||||
@ -276,6 +283,7 @@ struct _virNodeDevCapData {
|
|||||||
virNodeDevCapStorage storage;
|
virNodeDevCapStorage storage;
|
||||||
virNodeDevCapSCSIGeneric sg;
|
virNodeDevCapSCSIGeneric sg;
|
||||||
virNodeDevCapDRM drm;
|
virNodeDevCapDRM drm;
|
||||||
|
virNodeDevCapMdev mdev;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1068,6 +1068,42 @@ udevProcessSCSIGeneric(struct udev_device *dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
udevProcessMediatedDevice(struct udev_device *dev,
|
||||||
|
virNodeDeviceDefPtr def)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
const char *uuidstr = NULL;
|
||||||
|
int iommugrp = -1;
|
||||||
|
char *linkpath = NULL;
|
||||||
|
char *realpath = NULL;
|
||||||
|
virNodeDevCapMdevPtr data = &def->caps->data.mdev;
|
||||||
|
|
||||||
|
if (virAsprintf(&linkpath, "%s/mdev_type", udev_device_get_syspath(dev)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virFileResolveLink(linkpath, &realpath) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (VIR_STRDUP(data->type, last_component(realpath)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
uuidstr = udev_device_get_sysname(dev);
|
||||||
|
if ((iommugrp = virMediatedDeviceGetIOMMUGroupNum(uuidstr)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (udevGenerateDeviceName(dev, def, NULL) != 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
data->iommuGroupNumber = iommugrp;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(linkpath);
|
||||||
|
VIR_FREE(realpath);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
udevGetDeviceNodes(struct udev_device *device,
|
udevGetDeviceNodes(struct udev_device *device,
|
||||||
virNodeDeviceDefPtr def)
|
virNodeDeviceDefPtr def)
|
||||||
@ -1136,12 +1172,16 @@ udevGetDeviceType(struct udev_device *device,
|
|||||||
if (udevHasDeviceProperty(device, "INTERFACE"))
|
if (udevHasDeviceProperty(device, "INTERFACE"))
|
||||||
*type = VIR_NODE_DEV_CAP_NET;
|
*type = VIR_NODE_DEV_CAP_NET;
|
||||||
|
|
||||||
/* SCSI generic device doesn't set DEVTYPE property */
|
/* Neither SCSI generic devices nor mediated devices set DEVTYPE
|
||||||
|
* property, therefore we need to rely on the SUBSYSTEM property */
|
||||||
if (udevGetStringProperty(device, "SUBSYSTEM", &subsystem) < 0)
|
if (udevGetStringProperty(device, "SUBSYSTEM", &subsystem) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (STREQ_NULLABLE(subsystem, "scsi_generic"))
|
if (STREQ_NULLABLE(subsystem, "scsi_generic"))
|
||||||
*type = VIR_NODE_DEV_CAP_SCSI_GENERIC;
|
*type = VIR_NODE_DEV_CAP_SCSI_GENERIC;
|
||||||
|
else if (STREQ_NULLABLE(subsystem, "mdev"))
|
||||||
|
*type = VIR_NODE_DEV_CAP_MDEV;
|
||||||
|
|
||||||
VIR_FREE(subsystem);
|
VIR_FREE(subsystem);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1181,6 +1221,7 @@ static int udevGetDeviceDetails(struct udev_device *device,
|
|||||||
case VIR_NODE_DEV_CAP_DRM:
|
case VIR_NODE_DEV_CAP_DRM:
|
||||||
return udevProcessDRMDevice(device, def);
|
return udevProcessDRMDevice(device, def);
|
||||||
case VIR_NODE_DEV_CAP_MDEV:
|
case VIR_NODE_DEV_CAP_MDEV:
|
||||||
|
return udevProcessMediatedDevice(device, def);
|
||||||
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
case VIR_NODE_DEV_CAP_MDEV_TYPES:
|
||||||
case VIR_NODE_DEV_CAP_SYSTEM:
|
case VIR_NODE_DEV_CAP_SYSTEM:
|
||||||
case VIR_NODE_DEV_CAP_FC_HOST:
|
case VIR_NODE_DEV_CAP_FC_HOST:
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
<device>
|
||||||
|
<name>mdev_3627463d_b7f0_4fea_b468_f1da537d301b</name>
|
||||||
|
<parent>computer</parent>
|
||||||
|
<capability type='mdev'>
|
||||||
|
<type id='mtty-1'/>
|
||||||
|
<iommuGroup number='12'/>
|
||||||
|
</capability>
|
||||||
|
</device>
|
@ -102,6 +102,7 @@ mymain(void)
|
|||||||
DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all_header_type");
|
DO_TEST("pci_0000_02_10_7_sriov_pf_vfs_all_header_type");
|
||||||
DO_TEST("drm_renderD129");
|
DO_TEST("drm_renderD129");
|
||||||
DO_TEST("pci_0000_02_10_7_mdev_types");
|
DO_TEST("pci_0000_02_10_7_mdev_types");
|
||||||
|
DO_TEST("mdev_3627463d_b7f0_4fea_b468_f1da537d301b");
|
||||||
|
|
||||||
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user