[PATCH libvirt v3 11/11] node_device: detecting mdev_types capability on ap_matrix device

Shalini Chellathurai Saroja posted 11 patches 4 years ago
There is a newer version of this series
[PATCH libvirt v3 11/11] node_device: detecting mdev_types capability on ap_matrix device
Posted by Shalini Chellathurai Saroja 4 years ago
From: Boris Fiuczynski <fiuczy@linux.ibm.com>

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>
---
 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 25cf45da..65bbeb5b 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,
@@ -1038,6 +1070,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,
@@ -2085,7 +2142,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:
@@ -2410,6 +2468,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:
@@ -2461,6 +2522,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.
@@ -2480,7 +2546,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;
         }
@@ -2563,6 +2628,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
@@ -2850,6 +2924,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
@@ -2879,4 +2974,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 1d98f013..e67ac05b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -823,6 +823,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 d244b53c..172cfeb5 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -1259,6 +1259,10 @@ udevProcessAPMatrix(struct udev_device *device,
             *(def->name + i) = '_';
     }
 
+    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