<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(a)redhat.com>
---
docs/formatdomain.html.in | 45 +++++++++++++++++++
docs/schemas/domaincommon.rng | 9 ++++
src/conf/domain_conf.c | 40 +++++++++++++++++
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 | 17 +++++++
.../virtio-transitional.x86_64-3.1.0.args | 34 ++++++++++++++
.../virtio-transitional.x86_64-latest.args | 34 ++++++++++++++
.../qemuxml2argvdata/virtio-transitional.xml | 17 +++++++
tests/qemuxml2argvtest.c | 6 +++
.../virtio-non-transitional.xml | 42 +++++++++++++++++
.../virtio-transitional.xml | 42 +++++++++++++++++
tests/qemuxml2xmltest.c | 11 +++++
15 files changed, 378 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
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 2ae5006849..85bc6a9d0b 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -2922,6 +2922,17 @@
<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", see
+ <a href="#elementsVirtioTransitional">Virtio transitional
devices</a>
+ for more details.
+ <span class="since">Since 5.1.0</span>
+ </dd>
<dt><code>rawio</code></dt>
<dd>
Indicates whether the disk needs rawio capability. Valid
@@ -4074,6 +4085,40 @@
<span class="since">Since 3.5.0</span>
</p>
+ <h4><a id="elementsVirtioTransitional">Virtio transitional
devices</a></h4>
+
+ <p>
+ <span class="since">Since 5.1.0</span>, some of QEMU's
virtio devices,
+ when used with PCI/PCIe machine types, accept the following
+ <code>model</code> values:
+ </p>
+
+ <dl>
+ <dt><code>virtio-transitional</code></dt>
+ <dd>This instructs libvirt to always place the device in a conventional
+ PCI slot. The device can work with a virtio 0.9 or virtio 1.0
+ guest driver.
+ </dd>
+ <dt><code>virtio-non-transitional</code></dt>
+ <dd>
+ The device can only work with a virtio 1.0 guest driver.
+ </dd>
+ <dt><code>virtio</code></dt>
+ <dd> If the device is plugged into a PCIe slot, it acts as a
+ virtio-non-transitional device. If plugged into a conventional PCI slot,
+ it will function as a virtio-transitional device. This logic only
+ applies to devices that support the transitional models; for other
+ devices, <code>virtio</code> behavior will be different.
+ </dd>
+ </dl>
+
+ <p>
+ For more details see the
+ <a
href="https://lists.gnu.org/archive/html/qemu-devel/2018-12/msg00923...
patch posting</a> and the
+ <a
href="http://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html...
spec</a>.
+ </p>
+
+
<h4><a
id="elementsControllers">Controllers</a></h4>
<p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index ba80440c72..8811cf7e45 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1509,6 +1509,15 @@
</interleave>
</group>
</choice>
+ <optional>
+ <attribute name="model">
+ <choice>
+ <value>virtio</value>
+ <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 6772c327ed..3768143b2c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -985,6 +985,13 @@ VIR_ENUM_IMPL(virDomainDiskDetectZeroes,
VIR_DOMAIN_DISK_DETECT_ZEROES_LAST,
"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",
@@ -5633,6 +5640,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;
}
@@ -9719,6 +9737,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");
@@ -21960,6 +21986,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;
@@ -24517,6 +24551,12 @@ 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 2bc3f879f7..ecf8b06c2e 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;
};
@@ -3416,6 +3426,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 67579742fd..aeedb1834c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -344,6 +344,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..115ae48737
--- /dev/null
+++ b/tests/qemuxml2argvdata/virtio-non-transitional.xml
@@ -0,0 +1,17 @@
+<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>
+ </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..8febfc8423
--- /dev/null
+++ b/tests/qemuxml2argvdata/virtio-transitional.xml
@@ -0,0 +1,17 @@
+<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>
+ </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 dd4f73a5fb..de9eb6abdb 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -2996,6 +2996,12 @@ mymain(void)
DO_TEST("riscv64-virt-pci",
QEMU_CAPS_OBJECT_GPEX);
+ /* 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 b38cbd6994..15f0ccffb1 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1254,6 +1254,17 @@ mymain(void)
DO_TEST("riscv64-virt-pci",
QEMU_CAPS_OBJECT_GPEX);
+ 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);
--
2.20.1