[02/18] conf: Add <disk model='virtio-{non-}transitional'/>

Message ID 9c4a237e7b9682550346cad454e3f01afd29c140.1547746867.git.crobinso@redhat.com
State Superseded
Headers show
Series
  • qemu: virtio-{non-}transitional support
Related show

Commit Message

Cole Robinson Jan. 17, 2019, 5:52 p.m.
<disk> devices lack the model= attribute which is used by
most other device types. bus= mostly acts as one, but it
serves other purposes too like determing what target=
prefix to use, and for matching against controller type=
values.

Extending bus= to handle additional virtio transitional
devices will complicate apps lives, and it isn't a clean
mapping anyways. So let's bite the bullet and add a new
<disk model=X/> attribute, and wire up common handling
for virtio and virtio-{non-}transitional

Signed-off-by: Cole Robinson <crobinso@redhat.com>

---
 docs/formatdomain.html.in                     | 10 +++++
 docs/schemas/domaincommon.rng                 |  8 ++++
 src/conf/domain_conf.c                        | 38 +++++++++++++++++
 src/conf/domain_conf.h                        | 11 +++++
 src/libvirt_private.syms                      |  2 +
 .../virtio-non-transitional.x86_64-3.1.0.args | 34 +++++++++++++++
 ...virtio-non-transitional.x86_64-latest.args | 34 +++++++++++++++
 .../virtio-non-transitional.xml               | 18 ++++++++
 .../virtio-transitional.x86_64-3.1.0.args     | 34 +++++++++++++++
 .../virtio-transitional.x86_64-latest.args    | 34 +++++++++++++++
 .../qemuxml2argvdata/virtio-transitional.xml  | 18 ++++++++
 tests/qemuxml2argvtest.c                      |  6 +++
 .../virtio-non-transitional.xml               | 42 +++++++++++++++++++
 .../virtio-transitional.xml                   | 42 +++++++++++++++++++
 tests/qemuxml2xmltest.c                       | 11 +++++
 15 files changed, 342 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/virtio-non-transitional.x86_64-3.1.0.args
 create mode 100644 tests/qemuxml2argvdata/virtio-non-transitional.x86_64-latest.args
 create mode 100644 tests/qemuxml2argvdata/virtio-non-transitional.xml
 create mode 100644 tests/qemuxml2argvdata/virtio-transitional.x86_64-3.1.0.args
 create mode 100644 tests/qemuxml2argvdata/virtio-transitional.x86_64-latest.args
 create mode 100644 tests/qemuxml2argvdata/virtio-transitional.xml
 create mode 100644 tests/qemuxml2xmloutdata/virtio-non-transitional.xml
 create mode 100644 tests/qemuxml2xmloutdata/virtio-transitional.xml

-- 
2.20.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Comments

Andrea Bolognani Jan. 18, 2019, 11:24 a.m. | #1
On Thu, 2019-01-17 at 12:52 -0500, Cole Robinson wrote:

[...]

> +          <dt><code>model</code></dt>

> +            <dd>

> +            Indicates the emulated device model of the disk. Typically

> +            this is indicated solely by the <code>bus</code> property but

> +            for <code>bus</code> "virtio" the model can be specified further

> +            with "virtio-transitional", "virtio-non-transitional", or

> +            "virtio" which matches the old behavior. These setting are


s/setting/settings/

[...]

> +++ b/docs/schemas/domaincommon.rng

> @@ -1506,6 +1506,14 @@

>            </interleave>

>          </group>

>        </choice>

> +      <optional>

> +        <attribute name="model">

> +          <choice>


You forgot to add <value>virtio</value> here.

> +            <value>virtio-transitional</value>

> +            <value>virtio-non-transitional</value>

> +          </choice>


[...]

> @@ -24311,6 +24344,11 @@ virDomainDiskDefFormat(virBufferPtr buf,

>      virBufferAsprintf(buf,

>                        "<disk type='%s' device='%s'",

>                        type, device);


Empty line here, please.

> +    if (def->model) {

> +        virBufferAsprintf(buf, " model='%s'",

> +                          virDomainDiskModelTypeToString(def->model));

> +    }


[...]

> +++ b/tests/qemuxml2xmltest.c

> @@ -1265,6 +1265,17 @@ mymain(void)

>      DO_TEST("riscv64-virt",

>              QEMU_CAPS_DEVICE_VIRTIO_MMIO);

>  

> +    DO_TEST("virtio-transitional",

> +            QEMU_CAPS_DEVICE_VIDEO_PRIMARY,

> +            QEMU_CAPS_DEVICE_PCIE_PCI_BRIDGE,

> +            QEMU_CAPS_DEVICE_PCIE_ROOT_PORT,

> +            QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY);

> +    DO_TEST("virtio-non-transitional",

> +            QEMU_CAPS_DEVICE_VIDEO_PRIMARY,

> +            QEMU_CAPS_DEVICE_PCIE_PCI_BRIDGE,

> +            QEMU_CAPS_DEVICE_PCIE_ROOT_PORT,

> +            QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY);


So you got rid of the macro from RFC's 2/6 completely? Despite the
code duplication issue I've pointed out at the time, I'd still
rather see that macro being used, after renaming it, than yet
another hardcoded list of capabilities...

Either way, with the schema and the other nits fixed,

  Reviewed-by: Andrea Bolognani <abologna@redhat.com>


-- 
Andrea Bolognani / Red Hat / Virtualization

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Cole Robinson Jan. 21, 2019, 9:59 p.m. | #2
On 01/18/2019 06:24 AM, Andrea Bolognani wrote:
> On Thu, 2019-01-17 at 12:52 -0500, Cole Robinson wrote:

> 

> [...]

> 


> 

> So you got rid of the macro from RFC's 2/6 completely? Despite the

> code duplication issue I've pointed out at the time, I'd still

> rather see that macro being used, after renaming it, than yet

> another hardcoded list of capabilities...

> 

> 


It turned out to not need too many caps adjustments throughout the
series so I dropped it incase it was a distraction. It's on my list to
send a separate series for DO_TEST_CAPS+qemuxml2xml, hopefully sharing
more with the qemuxml2argv implementation

Thanks,
Cole

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Patch

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 7f07bb7f55..29e4bb1bda 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -2922,6 +2922,16 @@ 
             <span class="since">Since 0.1.4</span>
             </p>
             </dd>
+          <dt><code>model</code></dt>
+            <dd>
+            Indicates the emulated device model of the disk. Typically
+            this is indicated solely by the <code>bus</code> property but
+            for <code>bus</code> "virtio" the model can be specified further
+            with "virtio-transitional", "virtio-non-transitional", or
+            "virtio" which matches the old behavior. These setting are
+            only applicable when using controller bus type "pci".
+            <span class="since">Since 5.1.0</span>
+            </dd>
           <dt><code>rawio</code></dt>
             <dd>
             Indicates whether the disk needs rawio capability. Valid
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index aa50eac424..425d7f851a 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1506,6 +1506,14 @@ 
           </interleave>
         </group>
       </choice>
+      <optional>
+        <attribute name="model">
+          <choice>
+            <value>virtio-transitional</value>
+            <value>virtio-non-transitional</value>
+          </choice>
+        </attribute>
+      </optional>
       <optional>
         <ref name="snapshot"/>
       </optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 222bb8c482..facb84a425 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -889,6 +889,12 @@  VIR_ENUM_IMPL(virDomainDiskDetectZeroes, VIR_DOMAIN_DISK_DETECT_ZEROES_LAST,
               "on",
               "unmap")
 
+VIR_ENUM_IMPL(virDomainDiskModel, VIR_DOMAIN_DISK_MODEL_LAST,
+              "default",
+              "virtio",
+              "virtio-transitional",
+              "virtio-non-transitional")
+
 VIR_ENUM_IMPL(virDomainDiskMirrorState, VIR_DOMAIN_DISK_MIRROR_STATE_LAST,
               "none",
               "yes",
@@ -5431,6 +5437,17 @@  virDomainDiskDefValidate(const virDomainDiskDef *disk)
         return -1;
     }
 
+    if (disk->bus != VIR_DOMAIN_DISK_BUS_VIRTIO &&
+        (disk->model == VIR_DOMAIN_DISK_MODEL_VIRTIO ||
+         disk->model == VIR_DOMAIN_DISK_MODEL_VIRTIO_TRANSITIONAL ||
+         disk->model == VIR_DOMAIN_DISK_MODEL_VIRTIO_NON_TRANSITIONAL)) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("disk model '%s' not supported for bus '%s'"),
+                       virDomainDiskModelTypeToString(disk->model),
+                       virDomainDiskBusTypeToString(disk->bus));
+        return -1;
+    }
+
     return 0;
 }
 
@@ -9518,6 +9535,14 @@  virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
     }
     VIR_FREE(tmp);
 
+    if ((tmp = virXMLPropString(node, "model")) &&
+        (def->model = virDomainDiskModelTypeFromString(tmp)) < 0) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("unknown disk model '%s'"), tmp);
+        goto error;
+    }
+    VIR_FREE(tmp);
+
     snapshot = virXMLPropString(node, "snapshot");
 
     rawio = virXMLPropString(node, "rawio");
@@ -21746,6 +21771,14 @@  virDomainDiskDefCheckABIStability(virDomainDiskDefPtr src,
         return false;
     }
 
+    if (src->model != dst->model) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target disk model %s does not match source %s"),
+                       virDomainDiskModelTypeToString(dst->model),
+                       virDomainDiskModelTypeToString(src->model));
+        return false;
+    }
+
     if (src->virtio && dst->virtio &&
         !virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
         return false;
@@ -24311,6 +24344,11 @@  virDomainDiskDefFormat(virBufferPtr buf,
     virBufferAsprintf(buf,
                       "<disk type='%s' device='%s'",
                       type, device);
+    if (def->model) {
+        virBufferAsprintf(buf, " model='%s'",
+                          virDomainDiskModelTypeToString(def->model));
+    }
+
     if (def->rawio) {
         virBufferAsprintf(buf, " rawio='%s'",
                           virTristateBoolTypeToString(def->rawio));
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index fae130668f..16c2c6e75b 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -567,6 +567,15 @@  typedef enum {
     VIR_DOMAIN_DISK_DETECT_ZEROES_LAST
 } virDomainDiskDetectZeroes;
 
+typedef enum {
+    VIR_DOMAIN_DISK_MODEL_DEFAULT = 0,
+    VIR_DOMAIN_DISK_MODEL_VIRTIO,
+    VIR_DOMAIN_DISK_MODEL_VIRTIO_TRANSITIONAL,
+    VIR_DOMAIN_DISK_MODEL_VIRTIO_NON_TRANSITIONAL,
+
+    VIR_DOMAIN_DISK_MODEL_LAST
+} virDomainDiskModel;
+
 typedef struct _virDomainBlockIoTuneInfo virDomainBlockIoTuneInfo;
 struct _virDomainBlockIoTuneInfo {
     unsigned long long total_bytes_sec;
@@ -674,6 +683,7 @@  struct _virDomainDiskDef {
     int detect_zeroes; /* enum virDomainDiskDetectZeroes */
     char *domain_name; /* backend domain name */
     unsigned int queues;
+    int model; /* enum virDomainDiskModel */
     virDomainVirtioOptionsPtr virtio;
 };
 
@@ -3408,6 +3418,7 @@  VIR_ENUM_DECL(virDomainDeviceSGIO)
 VIR_ENUM_DECL(virDomainDiskTray)
 VIR_ENUM_DECL(virDomainDiskDiscard)
 VIR_ENUM_DECL(virDomainDiskDetectZeroes)
+VIR_ENUM_DECL(virDomainDiskModel)
 VIR_ENUM_DECL(virDomainDiskMirrorState)
 VIR_ENUM_DECL(virDomainController)
 VIR_ENUM_DECL(virDomainControllerModelPCI)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index c3d6306809..0d6f054cf2 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -343,6 +343,8 @@  virDomainDiskIoTypeFromString;
 virDomainDiskIoTypeToString;
 virDomainDiskMirrorStateTypeFromString;
 virDomainDiskMirrorStateTypeToString;
+virDomainDiskModelTypeFromString;
+virDomainDiskModelTypeToString;
 virDomainDiskPathByName;
 virDomainDiskRemove;
 virDomainDiskRemoveByName;
diff --git a/tests/qemuxml2argvdata/virtio-non-transitional.x86_64-3.1.0.args b/tests/qemuxml2argvdata/virtio-non-transitional.x86_64-3.1.0.args
new file mode 100644
index 0000000000..9e11e900da
--- /dev/null
+++ b/tests/qemuxml2argvdata/virtio-non-transitional.x86_64-3.1.0.args
@@ -0,0 +1,34 @@ 
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object secret,id=masterKey0,format=raw,\
+file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
+-machine pc-q35-3.1,accel=tcg,usb=off,dump-guest-core=off \
+-m 214 \
+-realtime mlock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot strict=on \
+-device pcie-root-port,port=0x8,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,\
+addr=0x1 \
+-device pcie-root-port,port=0x9,chassis=2,id=pci.2,bus=pcie.0,addr=0x1.0x1 \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-virtio-disk0 \
+-device virtio-blk-pci,scsi=off,bus=pci.1,addr=0x0,drive=drive-virtio-disk0,\
+id=virtio-disk0,bootindex=1 \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
+resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/virtio-non-transitional.x86_64-latest.args b/tests/qemuxml2argvdata/virtio-non-transitional.x86_64-latest.args
new file mode 100644
index 0000000000..070b4b8334
--- /dev/null
+++ b/tests/qemuxml2argvdata/virtio-non-transitional.x86_64-latest.args
@@ -0,0 +1,34 @@ 
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object secret,id=masterKey0,format=raw,\
+file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
+-machine q35,accel=tcg,usb=off,dump-guest-core=off \
+-m 214 \
+-realtime mlock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot strict=on \
+-device pcie-root-port,port=0x8,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,\
+addr=0x1 \
+-device pcie-root-port,port=0x9,chassis=2,id=pci.2,bus=pcie.0,addr=0x1.0x1 \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-virtio-disk0 \
+-device virtio-blk-pci,scsi=off,bus=pci.1,addr=0x0,drive=drive-virtio-disk0,\
+id=virtio-disk0,bootindex=1 \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
+resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/virtio-non-transitional.xml b/tests/qemuxml2argvdata/virtio-non-transitional.xml
new file mode 100644
index 0000000000..7899994622
--- /dev/null
+++ b/tests/qemuxml2argvdata/virtio-non-transitional.xml
@@ -0,0 +1,18 @@ 
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <os>
+    <type arch='x86_64' machine='q35'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <devices>
+    <disk type='block' device='disk' model='virtio-non-transitional'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='vda' bus='virtio'/>
+    </disk>
+    <controller type='usb' index='0' model='none'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvdata/virtio-transitional.x86_64-3.1.0.args b/tests/qemuxml2argvdata/virtio-transitional.x86_64-3.1.0.args
new file mode 100644
index 0000000000..9e11e900da
--- /dev/null
+++ b/tests/qemuxml2argvdata/virtio-transitional.x86_64-3.1.0.args
@@ -0,0 +1,34 @@ 
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object secret,id=masterKey0,format=raw,\
+file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
+-machine pc-q35-3.1,accel=tcg,usb=off,dump-guest-core=off \
+-m 214 \
+-realtime mlock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot strict=on \
+-device pcie-root-port,port=0x8,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,\
+addr=0x1 \
+-device pcie-root-port,port=0x9,chassis=2,id=pci.2,bus=pcie.0,addr=0x1.0x1 \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-virtio-disk0 \
+-device virtio-blk-pci,scsi=off,bus=pci.1,addr=0x0,drive=drive-virtio-disk0,\
+id=virtio-disk0,bootindex=1 \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
+resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/virtio-transitional.x86_64-latest.args b/tests/qemuxml2argvdata/virtio-transitional.x86_64-latest.args
new file mode 100644
index 0000000000..070b4b8334
--- /dev/null
+++ b/tests/qemuxml2argvdata/virtio-transitional.x86_64-latest.args
@@ -0,0 +1,34 @@ 
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name guest=QEMUGuest1,debug-threads=on \
+-S \
+-object secret,id=masterKey0,format=raw,\
+file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
+-machine q35,accel=tcg,usb=off,dump-guest-core=off \
+-m 214 \
+-realtime mlock=off \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-no-acpi \
+-boot strict=on \
+-device pcie-root-port,port=0x8,chassis=1,id=pci.1,bus=pcie.0,multifunction=on,\
+addr=0x1 \
+-device pcie-root-port,port=0x9,chassis=2,id=pci.2,bus=pcie.0,addr=0x1.0x1 \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-virtio-disk0 \
+-device virtio-blk-pci,scsi=off,bus=pci.1,addr=0x0,drive=drive-virtio-disk0,\
+id=virtio-disk0,bootindex=1 \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
+resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/virtio-transitional.xml b/tests/qemuxml2argvdata/virtio-transitional.xml
new file mode 100644
index 0000000000..678a7b9132
--- /dev/null
+++ b/tests/qemuxml2argvdata/virtio-transitional.xml
@@ -0,0 +1,18 @@ 
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <os>
+    <type arch='x86_64' machine='q35'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <devices>
+    <disk type='block' device='disk' model='virtio-transitional'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='vda' bus='virtio'/>
+    </disk>
+    <controller type='usb' index='0' model='none'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 2cb8860d26..8da99fc390 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -3068,6 +3068,12 @@  mymain(void)
     DO_TEST("riscv64-virt",
             QEMU_CAPS_DEVICE_VIRTIO_MMIO);
 
+    /* Older version checks disable-legacy usage */
+    DO_TEST_CAPS_VER("virtio-transitional", "3.1.0");
+    DO_TEST_CAPS_VER("virtio-non-transitional", "3.1.0");
+    DO_TEST_CAPS_LATEST("virtio-transitional");
+    DO_TEST_CAPS_LATEST("virtio-non-transitional");
+
     /* Simple headless guests for various architectures */
     DO_TEST_CAPS_ARCH_LATEST("aarch64-virt-headless", "aarch64");
     DO_TEST_CAPS_ARCH_LATEST("ppc64-pseries-headless", "ppc64");
diff --git a/tests/qemuxml2xmloutdata/virtio-non-transitional.xml b/tests/qemuxml2xmloutdata/virtio-non-transitional.xml
new file mode 100644
index 0000000000..7e4aa16b32
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/virtio-non-transitional.xml
@@ -0,0 +1,42 @@ 
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='q35'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='block' device='disk' model='virtio-non-transitional'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='vda' bus='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
+    </disk>
+    <controller type='usb' index='0' model='none'/>
+    <controller type='sata' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
+    </controller>
+    <controller type='pci' index='0' model='pcie-root'/>
+    <controller type='pci' index='1' model='pcie-root-port'>
+      <model name='pcie-root-port'/>
+      <target chassis='1' port='0x8'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/>
+    </controller>
+    <controller type='pci' index='2' model='pcie-root-port'>
+      <model name='pcie-root-port'/>
+      <target chassis='2' port='0x9'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmloutdata/virtio-transitional.xml b/tests/qemuxml2xmloutdata/virtio-transitional.xml
new file mode 100644
index 0000000000..1d28af9abb
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/virtio-transitional.xml
@@ -0,0 +1,42 @@ 
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='x86_64' machine='q35'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu-system-x86_64</emulator>
+    <disk type='block' device='disk' model='virtio-transitional'>
+      <driver name='qemu' type='raw'/>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='vda' bus='virtio'/>
+      <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
+    </disk>
+    <controller type='usb' index='0' model='none'/>
+    <controller type='sata' index='0'>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x1f' function='0x2'/>
+    </controller>
+    <controller type='pci' index='0' model='pcie-root'/>
+    <controller type='pci' index='1' model='pcie-root-port'>
+      <model name='pcie-root-port'/>
+      <target chassis='1' port='0x8'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0' multifunction='on'/>
+    </controller>
+    <controller type='pci' index='2' model='pcie-root-port'>
+      <model name='pcie-root-port'/>
+      <target chassis='2' port='0x9'/>
+      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
+    </controller>
+    <input type='mouse' bus='ps2'/>
+    <input type='keyboard' bus='ps2'/>
+    <memballoon model='none'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 82e2c0ee0f..0eca113e23 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1265,6 +1265,17 @@  mymain(void)
     DO_TEST("riscv64-virt",
             QEMU_CAPS_DEVICE_VIRTIO_MMIO);
 
+    DO_TEST("virtio-transitional",
+            QEMU_CAPS_DEVICE_VIDEO_PRIMARY,
+            QEMU_CAPS_DEVICE_PCIE_PCI_BRIDGE,
+            QEMU_CAPS_DEVICE_PCIE_ROOT_PORT,
+            QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY);
+    DO_TEST("virtio-non-transitional",
+            QEMU_CAPS_DEVICE_VIDEO_PRIMARY,
+            QEMU_CAPS_DEVICE_PCIE_PCI_BRIDGE,
+            QEMU_CAPS_DEVICE_PCIE_ROOT_PORT,
+            QEMU_CAPS_VIRTIO_PCI_DISABLE_LEGACY);
+
     if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
         virFileDeleteTree(fakerootdir);