]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
node_device: detecting mdev_types capability on ap_matrix device
authorBoris Fiuczynski <fiuczy@linux.ibm.com>
Thu, 3 Dec 2020 17:59:43 +0000 (18:59 +0100)
committerErik Skultety <eskultet@redhat.com>
Wed, 9 Dec 2020 13:03:05 +0000 (14:03 +0100)
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>
docs/formatnode.html.in
docs/schemas/nodedev.rng
src/conf/node_device_conf.c
src/conf/node_device_conf.h
src/conf/virnodedeviceobj.c
src/libvirt_private.syms
src/node_device/node_device_udev.c
tests/nodedevschemadata/ap_matrix_mdev_types.xml [new file with mode: 0644]
tests/nodedevxml2xmltest.c

index f76b398140c8d96c9dfebedb7bc261a885c5ee59..1010a37a3def9e3c01f16c7dc2d9c4a80f68ef15 100644 (file)
           </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>
     <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
index 1024ba59f90d4e097d33ff82badb982fef40b511..5840dc9f0df3d0b4899fb85dde095df44e1a011f 100644 (file)
     <attribute name='type'>
       <value>ap_matrix</value>
     </attribute>
+    <optional>
+      <ref name="mdev_types"/>
+    </optional>
   </define>
 
   <define name="address">
             <choice>
               <value>vfio-pci</value>
               <value>vfio-ccw</value>
+              <value>vfio-ap</value>
             </choice>
           </element>
           <element name="availableInstances">
index d32a6afcafbae3c19531b29abfcf49a9bbaf17a0..35f34b10e98a04d99e3ebf747d5783c1605bf133 100644 (file)
@@ -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__ */
index b8397128116d816e777d58738e66c44ae30ce2bb..c67b8e2aebd7810bb5fc458b4f866b45c2f87d4e 100644 (file)
@@ -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);
 
index 25d12776a5660c3838345943b7d6655436c8d308..c9bda77b2e7d8abb8ad2eaed9e94dddb3fb06981 100644 (file)
@@ -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;
         }
index 5cf39bdf6c7cf6fabaad65cd03f76bb4e322c5dc..992488f754ca173aeaed531bb6a6a80db198950b 100644 (file)
@@ -823,6 +823,7 @@ virNodeDeviceDefFree;
 virNodeDeviceDefParseFile;
 virNodeDeviceDefParseNode;
 virNodeDeviceDefParseString;
+virNodeDeviceGetAPMatrixDynamicCaps;
 virNodeDeviceGetCSSDynamicCaps;
 virNodeDeviceGetPCIDynamicCaps;
 virNodeDeviceGetSCSIHostCaps;
index f10337be1f048053f878ca4e052445bdbd3ac871..55a273168118fffd8d307d7900bc83ebf14eb193 100644 (file)
@@ -1247,6 +1247,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 (file)
index 0000000..b3802e6
--- /dev/null
@@ -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>
index dc8cb04fcd5292ace9b43268c9ff4e66c87b7f3b..a2321d13946ae1c6627f7ab294346d7d5239fd5f 100644 (file)
@@ -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;