diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 0cbf570a13..eb619a1656 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -7011,7 +7011,8 @@ qemu-kvm -net nic,model=? /dev/null
is available) and pci-serial
(usable whenever PCI support
is available); since 3.10.0,
spapr-vio-serial
(usable with ppc64/pseries guests),
- system-serial
(usable with aarch64/virt guests) and
+ system-serial
(usable with aarch64/virt and,
+ since 4.7.0, riscv/virt guests) and
sclp-serial
(usable with s390 and s390x guests) are
available as well.
@@ -7025,10 +7026,11 @@ qemu-kvm -net nic,model=? /dev/null
target type); pci-serial
(usable with the pci-serial
target type);
spapr-vty
(usable with the spapr-vio-serial
- target type); pl011
(usable with the
- system-serial
target type); sclpconsole
and
- sclplmconsole
(usable with the sclp-serial
- target type).
+ target type); pl011
and,
+ since 4.7.0, 16550a
(usable
+ with the system-serial
target type);
+ sclpconsole
and sclplmconsole
(usable with
+ the sclp-serial
target type).
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index f176538195..3796eb4b5e 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3733,6 +3733,7 @@
pci-serial
spapr-vty
pl011
+ 16550a
sclpconsole
sclplmconsole
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 8cb28a0880..38cac07913 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -493,6 +493,7 @@ VIR_ENUM_IMPL(virDomainChrSerialTargetModel,
"pl011",
"sclpconsole",
"sclplmconsole",
+ "16550a",
);
VIR_ENUM_IMPL(virDomainChrDevice, VIR_DOMAIN_CHR_DEVICE_TYPE_LAST,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c0ad072db5..8a3673361a 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1133,6 +1133,7 @@ typedef enum {
VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011,
VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE,
VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE,
+ VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A,
VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST
} virDomainChrSerialTargetModel;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2c3d5f08a9..8aa20496bc 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -9151,6 +9151,7 @@ qemuChrSerialTargetModelToCaps(virDomainChrSerialTargetModel targetModel)
return QEMU_CAPS_DEVICE_SCLPLMCONSOLE;
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
return QEMU_CAPS_DEVICE_PL011;
+ case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE:
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST:
break;
@@ -9191,6 +9192,16 @@ qemuChrIsPlatformDevice(const virDomainDef *def,
}
}
+ if (ARCH_IS_RISCV(def->os.arch)) {
+
+ /* 16550a (used by riscv/virt guests) is a platform device */
+ if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL &&
+ chr->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM &&
+ chr->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A) {
+ return true;
+ }
+ }
+
/* If we got all the way here and we're still stuck with the default
* target type for a serial device, it means we have no clue what kind of
* device we're talking about and we must treat it as a platform device. */
@@ -10581,6 +10592,7 @@ qemuBuildSerialChrDeviceStr(char **deviceStr,
break;
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
+ case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_NONE:
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_LAST:
/* Except from _LAST, which is just a guard value and will never
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 22c6d8f090..d7d145b9d4 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -4186,6 +4186,7 @@ qemuDomainChrSerialTargetModelToTargetType(int targetModel)
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY:
return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO;
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
+ case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
return VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM;
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE:
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE:
@@ -4251,6 +4252,7 @@ qemuDomainChrTargetDefValidate(const virDomainChrDef *chr)
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011:
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE:
case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPLMCONSOLE:
+ case VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A:
expected = qemuDomainChrSerialTargetModelToTargetType(chr->targetModel);
@@ -4301,18 +4303,23 @@ qemuDomainChrDefValidate(const virDomainChrDef *dev,
if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL) {
bool isCompatible = true;
+ if (dev->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM) {
+ if (dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011 &&
+ !qemuDomainIsARMVirt(def)) {
+ isCompatible = false;
+ }
+ if (dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A &&
+ !qemuDomainIsRISCVVirt(def)) {
+ isCompatible = false;
+ }
+ }
+
if (!qemuDomainIsPSeries(def) &&
(dev->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO ||
dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY)) {
isCompatible = false;
}
- if (!qemuDomainIsARMVirt(def) &&
- (dev->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM ||
- dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011)) {
- isCompatible = false;
- }
-
if (!ARCH_IS_S390(def->os.arch) &&
(dev->targetType == VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP ||
dev->targetModel == VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE ||
@@ -6132,7 +6139,7 @@ qemuDomainChrDefPostParse(virDomainChrDefPtr chr,
chr->targetType = VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_ISA;
} else if (qemuDomainIsPSeries(def)) {
chr->targetType = VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SPAPR_VIO;
- } else if (qemuDomainIsARMVirt(def)) {
+ } else if (qemuDomainIsARMVirt(def) || qemuDomainIsRISCVVirt(def)) {
chr->targetType = VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM;
} else if (ARCH_IS_S390(def->os.arch)) {
chr->targetType = VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP;
@@ -6156,7 +6163,11 @@ qemuDomainChrDefPostParse(virDomainChrDefPtr chr,
chr->targetModel = VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SPAPR_VTY;
break;
case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SYSTEM:
- chr->targetModel = VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011;
+ if (qemuDomainIsARMVirt(def)) {
+ chr->targetModel = VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_PL011;
+ } else if (qemuDomainIsRISCVVirt(def)) {
+ chr->targetModel = VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_16550A;
+ }
break;
case VIR_DOMAIN_CHR_SERIAL_TARGET_TYPE_SCLP:
chr->targetModel = VIR_DOMAIN_CHR_SERIAL_TARGET_MODEL_SCLPCONSOLE;
diff --git a/tests/qemuxml2xmloutdata/riscv64-virt.xml b/tests/qemuxml2xmloutdata/riscv64-virt.xml
index 5e0d7caacf..ec41f211c2 100644
--- a/tests/qemuxml2xmloutdata/riscv64-virt.xml
+++ b/tests/qemuxml2xmloutdata/riscv64-virt.xml
@@ -23,7 +23,9 @@
-
+
+
+