node_device: detecting mdev_types capability on ap_matrix device

Add detection of mdev_types capability to Adjunct Processor Matrix device.

Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
Reviewed-by: Shalini Chellathurai Saroja <shalini@linux.ibm.com>
Reviewed-by: Jonathon Jongsma<jjongsma@redhat.com>
Signed-off-by: Shalini Chellathurai Saroja <shalini@linux.ibm.com>
Reviewed-by: Erik Skultety <eskultet@redhat.com>
This commit is contained in:
Boris Fiuczynski 2020-12-03 18:59:43 +01:00 committed by Erik Skultety
parent a0ab006d5a
commit 53cc495179
9 changed files with 168 additions and 6 deletions

View File

@ -456,7 +456,26 @@
</dd> </dd>
<dt><code>ap_matrix</code></dt> <dt><code>ap_matrix</code></dt>
<dd>Describes an AP Matrix device on a S390 architecture providing <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> </dl>
</dd> </dd>
</dl> </dl>
@ -464,7 +483,8 @@
<h3><a id="MDEVTypesCap">mdev_types capability</a></h3> <h3><a id="MDEVTypesCap">mdev_types capability</a></h3>
<p> <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. devices can be capable of creating mediated devices.
If they indeed are capable, then the parent <code>capability</code> If they indeed are capable, then the parent <code>capability</code>
element for <code>mdev_types</code> type will contain a list of element for <code>mdev_types</code> type will contain a list of

View File

@ -696,6 +696,9 @@
<attribute name='type'> <attribute name='type'>
<value>ap_matrix</value> <value>ap_matrix</value>
</attribute> </attribute>
<optional>
<ref name="mdev_types"/>
</optional>
</define> </define>
<define name="address"> <define name="address">
@ -736,6 +739,7 @@
<choice> <choice>
<value>vfio-pci</value> <value>vfio-pci</value>
<value>vfio-ccw</value> <value>vfio-ccw</value>
<value>vfio-ap</value>
</choice> </choice>
</element> </element>
<element name="availableInstances"> <element name="availableInstances">

View File

@ -663,10 +663,15 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def)
virBufferAsprintf(&buf, "<ap-domain>0x%04x</ap-domain>\n", virBufferAsprintf(&buf, "<ap-domain>0x%04x</ap-domain>\n",
data->ap_queue.ap_domain); data->ap_queue.ap_domain);
break; 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_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:
case VIR_NODE_DEV_CAP_AP_MATRIX:
case VIR_NODE_DEV_CAP_LAST: case VIR_NODE_DEV_CAP_LAST:
break; 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 static int
virNodeDevCSSCapabilityParseXML(xmlXPathContextPtr ctxt, virNodeDevCSSCapabilityParseXML(xmlXPathContextPtr ctxt,
xmlNodePtr node, 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 static int
virNodeDevCapStorageParseXML(xmlXPathContextPtr ctxt, virNodeDevCapStorageParseXML(xmlXPathContextPtr ctxt,
virNodeDeviceDefPtr def, virNodeDeviceDefPtr def,
@ -2080,7 +2137,8 @@ virNodeDevCapsDefParseXML(xmlXPathContextPtr ctxt,
&caps->data.ap_queue); &caps->data.ap_queue);
break; break;
case VIR_NODE_DEV_CAP_AP_MATRIX: case VIR_NODE_DEV_CAP_AP_MATRIX:
ret = 0; ret = virNodeDevCapAPMatrixParseXML(ctxt, def, node,
&caps->data.ap_matrix);
break; 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:
@ -2405,6 +2463,9 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
break; break;
case VIR_NODE_DEV_CAP_AP_MATRIX: case VIR_NODE_DEV_CAP_AP_MATRIX:
VIR_FREE(data->ap_matrix.addr); 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; 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:
@ -2456,6 +2517,11 @@ virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def)
&cap->data.ccw_dev) < 0) &cap->data.ccw_dev) < 0)
return -1; return -1;
break; 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 /* all types that (supposedly) don't require any updates
* relative to what's in the cache. * 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_VDPA:
case VIR_NODE_DEV_CAP_AP_CARD: case VIR_NODE_DEV_CAP_AP_CARD:
case VIR_NODE_DEV_CAP_AP_QUEUE: case VIR_NODE_DEV_CAP_AP_QUEUE:
case VIR_NODE_DEV_CAP_AP_MATRIX:
case VIR_NODE_DEV_CAP_LAST: case VIR_NODE_DEV_CAP_LAST:
break; break;
} }
@ -2558,6 +2623,15 @@ virNodeDeviceCapsListExport(virNodeDeviceDefPtr def,
ncaps++; 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 #undef MAYBE_ADD_CAP
@ -2845,6 +2919,27 @@ virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath,
return 0; 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 #else
int int
@ -2874,4 +2969,11 @@ virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath G_GNUC_UNUSED,
return -1; return -1;
} }
int
virNodeDeviceGetAPMatrixDynamicCaps(const char *sysfsPath G_GNUC_UNUSED,
virNodeDevCapAPMatrixPtr ap_matrix G_GNUC_UNUSED)
{
return -1;
}
#endif /* __linux__ */ #endif /* __linux__ */

View File

@ -109,6 +109,10 @@ typedef enum {
VIR_NODE_DEV_CAP_FLAG_CSS_MDEV = (1 << 0), VIR_NODE_DEV_CAP_FLAG_CSS_MDEV = (1 << 0),
} virNodeDevCCWCapFlags; } virNodeDevCCWCapFlags;
typedef enum {
VIR_NODE_DEV_CAP_FLAG_AP_MATRIX_MDEV = (1 << 0),
} virNodeDevAPMatrixCapFlags;
typedef enum { typedef enum {
/* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */ /* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */
VIR_NODE_DEV_DRM_PRIMARY, VIR_NODE_DEV_DRM_PRIMARY,
@ -309,6 +313,9 @@ typedef struct _virNodeDevCapAPMatrix virNodeDevCapAPMatrix;
typedef virNodeDevCapAPMatrix *virNodeDevCapAPMatrixPtr; typedef virNodeDevCapAPMatrix *virNodeDevCapAPMatrixPtr;
struct _virNodeDevCapAPMatrix { struct _virNodeDevCapAPMatrix {
char *addr; char *addr;
unsigned int flags; /* enum virNodeDevAPMatrixCapFlags */
virMediatedDeviceTypePtr *mdev_types;
size_t nmdev_types;
}; };
typedef struct _virNodeDevCapData virNodeDevCapData; typedef struct _virNodeDevCapData virNodeDevCapData;
@ -430,6 +437,10 @@ int
virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath, virNodeDeviceGetCSSDynamicCaps(const char *sysfsPath,
virNodeDevCapCCWPtr ccw_dev); virNodeDevCapCCWPtr ccw_dev);
int
virNodeDeviceGetAPMatrixDynamicCaps(const char *sysfsPath,
virNodeDevCapAPMatrixPtr ap_matrix);
int int
virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def); virNodeDeviceUpdateCaps(virNodeDeviceDefPtr def);

View File

@ -702,6 +702,12 @@ virNodeDeviceObjHasCap(const virNodeDeviceObj *obj,
return true; return true;
break; 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_SYSTEM:
case VIR_NODE_DEV_CAP_USB_DEV: case VIR_NODE_DEV_CAP_USB_DEV:
case VIR_NODE_DEV_CAP_USB_INTERFACE: 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_VDPA:
case VIR_NODE_DEV_CAP_AP_CARD: case VIR_NODE_DEV_CAP_AP_CARD:
case VIR_NODE_DEV_CAP_AP_QUEUE: case VIR_NODE_DEV_CAP_AP_QUEUE:
case VIR_NODE_DEV_CAP_AP_MATRIX:
case VIR_NODE_DEV_CAP_LAST: case VIR_NODE_DEV_CAP_LAST:
break; break;
} }

View File

@ -823,6 +823,7 @@ virNodeDeviceDefFree;
virNodeDeviceDefParseFile; virNodeDeviceDefParseFile;
virNodeDeviceDefParseNode; virNodeDeviceDefParseNode;
virNodeDeviceDefParseString; virNodeDeviceDefParseString;
virNodeDeviceGetAPMatrixDynamicCaps;
virNodeDeviceGetCSSDynamicCaps; virNodeDeviceGetCSSDynamicCaps;
virNodeDeviceGetPCIDynamicCaps; virNodeDeviceGetPCIDynamicCaps;
virNodeDeviceGetSCSIHostCaps; virNodeDeviceGetSCSIHostCaps;

View File

@ -1247,6 +1247,10 @@ udevProcessAPMatrix(struct udev_device *device,
data->ap_matrix.addr = g_strdup(udev_device_get_sysname(device)); data->ap_matrix.addr = g_strdup(udev_device_get_sysname(device));
def->name = g_strdup("ap_matrix"); def->name = g_strdup("ap_matrix");
if (virNodeDeviceGetAPMatrixDynamicCaps(def->sysfs_path,
&data->ap_matrix) < 0)
return -1;
return 0; return 0;
} }

View File

@ -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>

View File

@ -128,6 +128,7 @@ mymain(void)
DO_TEST("ap_card07"); DO_TEST("ap_card07");
DO_TEST("ap_07_0038"); DO_TEST("ap_07_0038");
DO_TEST("ap_matrix"); DO_TEST("ap_matrix");
DO_TEST("ap_matrix_mdev_types");
DO_TEST("mdev_ee0b88c4_f554_4dc1_809d_b2a01e8e48ad"); DO_TEST("mdev_ee0b88c4_f554_4dc1_809d_b2a01e8e48ad");
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;