[PATCH V4 1/3] Xen: Add writeFiltering option for PCI devices

Jim Fehlig jfehlig at suse.com
Mon Aug 24 14:26:55 UTC 2020


By default Xen only allows guests to write "known safe" values into PCI
configuration space, yet many devices require writes to other areas of
the configuration space in order to operate properly. To allow writing
any values Xen supports the 'permissive' setting, see xl.cfg(5) man page.

This change models Xen's permissive setting by adding a writeFiltering
attribute on the <source> element of a PCI hostdev. When writeFiltering
is set to 'no', the Xen permissive setting will be enabled and guests
will be able to write any values into the device's configuration space.
The permissive setting remains disabled in the absense of the
writeFiltering attribute, of if it is explicitly set to 'yes'.

Signed-off-by: Jim Fehlig <jfehlig at suse.com>
Signed-off-by: Simon Gaiser <simon at invisiblethingslab.com>
Signed-off-by: Marek Marczykowski-Górecki <marmarek at invisiblethingslab.com>
---
 docs/formatdomain.rst                          |  7 ++++++-
 docs/schemas/domaincommon.rng                  |  5 +++++
 src/conf/domain_conf.c                         | 14 ++++++++++++++
 src/conf/domain_conf.h                         |  1 +
 src/libxl/libxl_conf.c                         |  1 +
 src/qemu/qemu_validate.c                       |  7 +++++++
 tests/libxlxml2domconfigdata/moredevs-hvm.json |  6 ++++++
 tests/libxlxml2domconfigdata/moredevs-hvm.xml  |  5 +++++
 8 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 8365fc8bbb..a7ab690b96 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -3733,7 +3733,7 @@ or:
    ...
    <devices>
      <hostdev mode='subsystem' type='pci' managed='yes'>
-       <source>
+       <source writeFiltering='no'>
          <address domain='0x0000' bus='0x06' slot='0x02' function='0x0'/>
        </source>
        <boot order='1'/>
@@ -3899,6 +3899,11 @@ or:
 
    ``pci``
       PCI devices can only be described by their ``address``.
+      :since:`Since 6.7.0 (Xen only)` , the ``source`` element of a PCI device
+      may contain the ``writeFiltering`` attribute to control write access to
+      the PCI configuration space. By default Xen only allows writes of known
+      safe values to the configuration space. Setting ``writeFiltering='no'``
+      will allow all writes to the device's PCI configuration space.
    ``scsi``
       SCSI devices are described by both the ``adapter`` and ``address``
       elements. The ``address`` element includes a ``bus`` attribute (a 2-digit
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 0d0dcbc5ce..b4eb7486b9 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -4982,6 +4982,11 @@
         <optional>
           <ref name="startupPolicy"/>
         </optional>
+        <optional>
+          <attribute name="writeFiltering">
+            <ref name="virYesNo"/>
+          </attribute>
+        </optional>
         <element name="address">
           <ref name="pciaddress"/>
         </element>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 8e7981bf25..bba31cfddb 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -8095,8 +8095,18 @@ virDomainHostdevSubsysPCIDefParseXML(xmlNodePtr node,
                                      virDomainHostdevDefPtr def,
                                      unsigned int flags)
 {
+    g_autofree char *filtering = NULL;
     xmlNodePtr cur;
 
+    if ((filtering = virXMLPropString(node, "writeFiltering"))) {
+        if ((def->writeFiltering = virTristateBoolTypeFromString(filtering)) < 0) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("unknown pci writeFiltering setting '%s'"),
+                           filtering);
+            return -1;
+        }
+    }
+
     cur = node->children;
     while (cur != NULL) {
         if (cur->type == XML_ELEMENT_NODE) {
@@ -26119,6 +26129,10 @@ virDomainHostdevDefFormatSubsysPCI(virBufferPtr buf,
     g_auto(virBuffer) origstatesChildBuf = VIR_BUFFER_INIT_CHILD(&sourceChildBuf);
     virDomainHostdevSubsysPCIPtr pcisrc = &def->source.subsys.u.pci;
 
+    if (def->writeFiltering != VIR_TRISTATE_BOOL_ABSENT)
+            virBufferAsprintf(&sourceAttrBuf, " writeFiltering='%s'",
+                              virTristateBoolTypeToString(def->writeFiltering));
+
     if (pcisrc->backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) {
         const char *backend = virDomainHostdevSubsysPCIBackendTypeToString(pcisrc->backend);
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 68be32614c..2f17053198 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -345,6 +345,7 @@ struct _virDomainHostdevDef {
     bool missing;
     bool readonly;
     bool shareable;
+    virTristateBool writeFiltering;
     union {
         virDomainHostdevSubsys subsys;
         virDomainHostdevCaps caps;
diff --git a/src/libxl/libxl_conf.c b/src/libxl/libxl_conf.c
index 7c2c015015..0056f6fe66 100644
--- a/src/libxl/libxl_conf.c
+++ b/src/libxl/libxl_conf.c
@@ -2279,6 +2279,7 @@ libxlMakePCI(virDomainHostdevDefPtr hostdev, libxl_device_pci *pcidev)
     pcidev->bus = pcisrc->addr.bus;
     pcidev->dev = pcisrc->addr.slot;
     pcidev->func = pcisrc->addr.function;
+    pcidev->permissive = hostdev->writeFiltering == VIR_TRISTATE_BOOL_NO;
 
     return 0;
 }
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index 488f258d00..97a9d25570 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -1833,6 +1833,13 @@ qemuValidateDomainDeviceDefHostdev(const virDomainHostdevDef *hostdev,
                     return -1;
                 }
             }
+
+            if (hostdev->writeFiltering != VIR_TRISTATE_BOOL_ABSENT) {
+                virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                               _("Write filtering of PCI device configuration "
+                                 "space is not supported by qemu"));
+                return -1;
+            }
             break;
 
         case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST:
diff --git a/tests/libxlxml2domconfigdata/moredevs-hvm.json b/tests/libxlxml2domconfigdata/moredevs-hvm.json
index 7bfd68bd67..474aa2cef6 100644
--- a/tests/libxlxml2domconfigdata/moredevs-hvm.json
+++ b/tests/libxlxml2domconfigdata/moredevs-hvm.json
@@ -88,6 +88,12 @@
             "dev": 16,
             "bus": 10,
 	    "rdm_policy": "invalid"
+        },
+        {
+            "dev": 8,
+            "bus": 10,
+            "permissive": true,
+	    "rdm_policy": "invalid"
         }
     ],
     "vfbs": [
diff --git a/tests/libxlxml2domconfigdata/moredevs-hvm.xml b/tests/libxlxml2domconfigdata/moredevs-hvm.xml
index f7eb09fa3b..89ad80631d 100644
--- a/tests/libxlxml2domconfigdata/moredevs-hvm.xml
+++ b/tests/libxlxml2domconfigdata/moredevs-hvm.xml
@@ -48,6 +48,11 @@
         <address type='pci' domain='0x0000' bus='0x0a' slot='0x10' function='0x0'/>
       </source>
     </interface>
+    <hostdev mode='subsystem' type='pci' managed='yes'>
+      <source writeFiltering='no'>
+        <address domain='0x0000' bus='0x0a' slot='0x08' function='0x0'/>
+      </source>
+    </hostdev>
     <graphics type='vnc'/>
     <video>
       <model type='cirrus' vram='8192' heads='1' primary='yes'/>
-- 
2.28.0





More information about the libvir-list mailing list