From: Boris Fiuczynski <fiuczy@xxxxxxxxxxxxx> Add detection of mdev_types capability to Adjunct Processor Matrix device. Signed-off-by: Boris Fiuczynski <fiuczy@xxxxxxxxxxxxx> Reviewed-by: Shalini Chellathurai Saroja <shalini@xxxxxxxxxxxxx> Reviewed-by: Jonathon Jongsma<jjongsma@xxxxxxxxxx> Signed-off-by: Shalini Chellathurai Saroja <shalini@xxxxxxxxxxxxx> --- docs/formatnode.html.in | 24 +++- docs/schemas/nodedev.rng | 4 + src/conf/node_device_conf.c | 108 +++++++++++++++++- src/conf/node_device_conf.h | 11 ++ src/conf/virnodedeviceobj.c | 7 +- src/libvirt_private.syms | 1 + src/node_device/node_device_udev.c | 4 + .../ap_matrix_mdev_types.xml | 14 +++ tests/nodedevxml2xmltest.c | 1 + 9 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 tests/nodedevschemadata/ap_matrix_mdev_types.xml diff --git a/docs/formatnode.html.in b/docs/formatnode.html.in index f76b3981..1010a37a 100644 --- a/docs/formatnode.html.in +++ b/docs/formatnode.html.in @@ -456,7 +456,26 @@ </dd> <dt><code>ap_matrix</code></dt> <dd>Describes an AP Matrix device on a S390 architecture providing - cryptographic host resources usable for virtualization.</dd> + cryptographic host resources usable for virtualization. + Sub-elements include: + <dl> + <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: + <dl> + <dt><code><a id="MDEVTypesCapAP">mdev_types</a></code></dt> + <dd> + <span class="since">Since 6.10.0</span> + This device is capable of creating mediated devices. + The sub-elements are summarized in + <a href="#MDEVTypesCap">mdev_types capability</a>. + </dd> + </dl> + </dd> + </dl> + </dd> </dl> </dd> </dl> @@ -464,7 +483,8 @@ <h3><a id="MDEVTypesCap">mdev_types capability</a></h3> <p> - <a href="#MDEVTypesCapPCI">PCI</a> and <a href="#MDEVTypesCapCSS">CSS</a> + <a href="#MDEVTypesCapPCI">PCI</a>, <a href="#MDEVTypesCapCSS">CSS</a> + and <a href="#MDEVTypesCapAP">AP Matrix</a> devices can be capable of creating mediated devices. If they indeed are capable, then the parent <code>capability</code> element for <code>mdev_types</code> type will contain a list of diff --git a/docs/schemas/nodedev.rng b/docs/schemas/nodedev.rng index 1024ba59..5840dc9f 100644 --- a/docs/schemas/nodedev.rng +++ b/docs/schemas/nodedev.rng @@ -696,6 +696,9 @@ <attribute name='type'> <value>ap_matrix</value> </attribute> + <optional> + <ref name="mdev_types"/> + </optional> </define> <define name="address"> @@ -736,6 +739,7 @@ <choice> <value>vfio-pci</value> <value>vfio-ccw</value> + <value>vfio-ap</value> </choice> </element> <element name="availableInstances"> diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index d32a6afc..35f34b10 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -663,10 +663,15 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def) virBufferAsprintf(&buf, "<ap-domain>0x%04x</ap-domain>\n", data->ap_queue.ap_domain); break; + case VIR_NODE_DEV_CAP_AP_MATRIX: + if (data->ap_matrix.flags & VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV) + virNodeDeviceCapMdevTypesFormat(&buf, + data->ap_matrix.mdev_types, + data->ap_matrix.nmdev_types); + case VIR_NODE_DEV_CAP_MDEV_TYPES: case VIR_NODE_DEV_CAP_FC_HOST: case VIR_NODE_DEV_CAP_VPORTS: - case VIR_NODE_DEV_CAP_AP_MATRIX: case VIR_NODE_DEV_CAP_LAST: break; } @@ -861,6 +866,33 @@ virNodeDevCapMdevTypesParseXML(xmlXPathContextPtr ctxt, } +static int +virNodeDevAPMatrixCapabilityParseXML(xmlXPathContextPtr ctxt, + xmlNodePtr node, + virNodeDevCapAPMatrixPtr apm_dev) +{ + g_autofree char *type = virXMLPropString(node, "type"); + VIR_XPATH_NODE_AUTORESTORE(ctxt) + + ctxt->node = node; + + if (!type) { + virReportError(VIR_ERR_XML_ERROR, "%s", _("Missing capability type")); + return -1; + } + + if (STREQ(type, "mdev_types")) { + if (virNodeDevCapMdevTypesParseXML(ctxt, + &apm_dev->mdev_types, + &apm_dev->nmdev_types) < 0) + return -1; + apm_dev->flags |= VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV; + } + + return 0; +} + + static int virNodeDevCSSCapabilityParseXML(xmlXPathContextPtr ctxt, xmlNodePtr node, @@ -1033,6 +1065,31 @@ virNodeDevCapAPQueueParseXML(xmlXPathContextPtr ctxt, } +static int +virNodeDevCapAPMatrixParseXML(xmlXPathContextPtr ctxt, + virNodeDeviceDefPtr def G_GNUC_UNUSED, + xmlNodePtr node, + virNodeDevCapAPMatrixPtr ap_matrix) +{ + VIR_XPATH_NODE_AUTORESTORE(ctxt) + g_autofree xmlNodePtr *nodes = NULL; + int n = 0; + size_t i = 0; + + ctxt->node = node; + + if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0) + return -1; + + for (i = 0; i < n; i++) { + if (virNodeDevAPMatrixCapabilityParseXML(ctxt, nodes[i], ap_matrix) < 0) + return -1; + } + + return 0; +} + + static int virNodeDevCapStorageParseXML(xmlXPathContextPtr ctxt, virNodeDeviceDefPtr def, @@ -2080,7 +2137,8 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt, &caps->data.ap_queue); break; case VIR_NODE_DEV_CAP_AP_MATRIX: - ret = 0; + ret = virNodeDevCapAPMatrixParseXML(ctxt, def, node, + &caps->data.ap_matrix); break; case VIR_NODE_DEV_CAP_MDEV_TYPES: case VIR_NODE_DEV_CAP_FC_HOST: @@ -2405,6 +2463,9 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps) break; case VIR_NODE_DEV_CAP_AP_MATRIX: VIR_FREE(data->ap_matrix.addr); + for (i = 0; i < data->ap_matrix.nmdev_types; i++) + virMediatedDeviceTypeFree(data->ap_matrix.mdev_types[i]); + VIR_FREE(data->ap_matrix.mdev_types); break; case VIR_NODE_DEV_CAP_MDEV_TYPES: case VIR_NODE_DEV_CAP_DRM: @@ -2456,6 +2517,11 @@ virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def) &cap->data.ccw_dev) < 0) return -1; break; + case VIR_NODE_DEV_CAP_AP_MATRIX: + if (virNodeDeviceGetAPMatrixDynamicCaps(def->sysfs_path, + &cap->data.ap_matrix) < 0) + return -1; + break; /* all types that (supposedly) don't require any updates * relative to what's in the cache. @@ -2475,7 +2541,6 @@ virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def) case VIR_NODE_DEV_CAP_VDPA: case VIR_NODE_DEV_CAP_AP_CARD: case VIR_NODE_DEV_CAP_AP_QUEUE: - case VIR_NODE_DEV_CAP_AP_MATRIX: case VIR_NODE_DEV_CAP_LAST: break; } @@ -2558,6 +2623,15 @@ virNodeDeviceCapsListExport(virNodeDeviceDefPtr def, ncaps++; } } + + if (caps->data.type == VIR_NODE_DEV_CAP_AP_MATRIX) { + flags = caps->data.ap_matrix.flags; + + if (flags & VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV) { + MAYBE_ADD_CAP(VIR_NODE_DEV_CAP_MDEV_TYPES); + ncaps++; + } + } } #undef MAYBE_ADD_CAP @@ -2845,6 +2919,27 @@ virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath, return 0; } +/* virNodeDeviceGetAPMatrixDynamicCaps() get info that is stored in sysfs + * about devices related to this device, i.e. things that can change + * without this device itself changing. These must be refreshed + * anytime full XML of the device is requested, because they can + * change with no corresponding notification from the kernel/udev. + */ +int +virNodeDeviceGetAPMatrixDynamicCaps(const char *sysfsPath, + virNodeDevCapAPMatrixPtr ap_matrix) +{ + ap_matrix->flags &= ~VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV; + if (virNodeDeviceGetMdevTypesCaps(sysfsPath, + &ap_matrix->mdev_types, + &ap_matrix->nmdev_types) < 0) + return -1; + if (ap_matrix->nmdev_types > 0) + ap_matrix->flags |= VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV; + + return 0; +} + #else int @@ -2874,4 +2969,11 @@ virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath G_GNUC_UNUSED, return -1; } +int +virNodeDeviceGetAPMatrixDynamicCaps(const char *sysfsPath G_GNUC_UNUSED, + virNodeDevCapAPMatrixPtr ap_matrix G_GNUC_UNUSED) +{ + return -1; +} + #endif /* __linux__ */ diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index b8397128..c67b8e2a 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -109,6 +109,10 @@ typedef enum { VIR_NODE_DEV_CAP_FLAG_CSS_MDEV = (1 << 0), } virNodeDevCCWCapFlags; +typedef enum { + VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV = (1 << 0), +} virNodeDevAPMatrixCapFlags; + typedef enum { /* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */ VIR_NODE_DEV_DRM_PRIMARY, @@ -309,6 +313,9 @@ typedef struct _virNodeDevCapAPMatrix virNodeDevCapAPMatrix; typedef virNodeDevCapAPMatrix *virNodeDevCapAPMatrixPtr; struct _virNodeDevCapAPMatrix { char *addr; + unsigned int flags; /* enum virNodeDevAPMatrixCapFlags */ + virMediatedDeviceTypePtr *mdev_types; + size_t nmdev_types; }; typedef struct _virNodeDevCapData virNodeDevCapData; @@ -430,6 +437,10 @@ int virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath, virNodeDevCapCCWPtr ccw_dev); +int +virNodeDeviceGetAPMatrixDynamicCaps(const char *sysfsPath, + virNodeDevCapAPMatrixPtr ap_matrix); + int virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def); diff --git a/src/conf/virnodedeviceobj.c b/src/conf/virnodedeviceobj.c index 25d12776..c9bda77b 100644 --- a/src/conf/virnodedeviceobj.c +++ b/src/conf/virnodedeviceobj.c @@ -702,6 +702,12 @@ virNodeDeviceObjHasCap(const virNodeDeviceObj *obj, return true; break; + case VIR_NODE_DEV_CAP_AP_MATRIX: + if (type == VIR_NODE_DEV_CAP_MDEV_TYPES && + (cap->data.ap_matrix.flags & VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV)) + return true; + break; + case VIR_NODE_DEV_CAP_SYSTEM: case VIR_NODE_DEV_CAP_USB_DEV: case VIR_NODE_DEV_CAP_USB_INTERFACE: @@ -719,7 +725,6 @@ virNodeDeviceObjHasCap(const virNodeDeviceObj *obj, case VIR_NODE_DEV_CAP_VDPA: case VIR_NODE_DEV_CAP_AP_CARD: case VIR_NODE_DEV_CAP_AP_QUEUE: - case VIR_NODE_DEV_CAP_AP_MATRIX: case VIR_NODE_DEV_CAP_LAST: break; } diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 2f640ef1..6b168508 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -824,6 +824,7 @@ virNodeDeviceDefFree; virNodeDeviceDefParseFile; virNodeDeviceDefParseNode; virNodeDeviceDefParseString; +virNodeDeviceGetAPMatrixDynamicCaps; virNodeDeviceGetCSSDynamicCaps; virNodeDeviceGetPCIDynamicCaps; virNodeDeviceGetSCSIHostCaps; diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index 3f425a6f..efaf0068 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -1243,6 +1243,10 @@ udevProcessAPMatrix(struct udev_device *device, data->ap_matrix.addr = g_strdup(udev_device_get_sysname(device)); def->name = g_strdup("ap_matrix"); + if (virNodeDeviceGetAPMatrixDynamicCaps(def->sysfs_path, + &data->ap_matrix) < 0) + return -1; + return 0; } diff --git a/tests/nodedevschemadata/ap_matrix_mdev_types.xml b/tests/nodedevschemadata/ap_matrix_mdev_types.xml new file mode 100644 index 00000000..b3802e6d --- /dev/null +++ b/tests/nodedevschemadata/ap_matrix_mdev_types.xml @@ -0,0 +1,14 @@ +<device> + <name>ap_matrix</name> + <path>/sys/devices/vfio_ap/matrix</path> + <parent>computer</parent> + <capability type='ap_matrix'> + <capability type='mdev_types'> + <type id='vfio_ap-passthrough'> + <name>VFIO AP Passthrough Device</name> + <deviceAPI>vfio-ap</deviceAPI> + <availableInstances>65536</availableInstances> + </type> + </capability> + </capability> +</device> diff --git a/tests/nodedevxml2xmltest.c b/tests/nodedevxml2xmltest.c index dc8cb04f..a2321d13 100644 --- a/tests/nodedevxml2xmltest.c +++ b/tests/nodedevxml2xmltest.c @@ -128,6 +128,7 @@ mymain(void) DO_TEST("ap_card07"); DO_TEST("ap_07_0038"); DO_TEST("ap_matrix"); + DO_TEST("ap_matrix_mdev_types"); DO_TEST("mdev_ee0b88c4_f554_4dc1_809d_b2a01e8e48ad"); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; -- 2.26.2