From: Boris Fiuczynski <fiuczy(a)linux.ibm.com>
Add detection of mdev_types capability to Adjunct Processor Matrix device.
Signed-off-by: Boris Fiuczynski <fiuczy(a)linux.ibm.com>
Reviewed-by: Shalini Chellathurai Saroja <shalini(a)linux.ibm.com>
Reviewed-by: Jonathon Jongsma<jjongsma(a)redhat.com>
Signed-off-by: Shalini Chellathurai Saroja <shalini(a)linux.ibm.com>
---
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