diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 310d2bc4275b76b86e0ce26b66daf6a7f946af94..c5c069e6df720c0a90b06cc86a94315061570289 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -2014,6 +2014,7 @@ Hypervisors may allow certain CPU / machine features to be toggled on/off.
128
+
...
@@ -2248,6 +2249,13 @@ are:
Depending on the ``enabled`` attribute (values ``yes``, ``no``) enable or
disable QEMU asynchronous teardown to improve memory reclaiming on a guest.
:since:`Since 9.6.0` (QEMU only)
+``aia``
+ Configure aia (Advanced Interrupt Architecture) for RISC-V 'virt'
+ guests. Possible values for the ``value`` attribute are ``aplic`` (one
+ emulated APLIC device present per socket), ``aplic-imsic`` (one APLIC and
+ one IMSIC device present per core), or ``none`` (no support for AIA).
+ If the attribute is not defined, the hypervisor default
+ will be used. :since:`Since 11.1.0` (QEMU/KVM and RISC-V guests only)
Time keeping
------------
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index dd0cb9d548b682ac6fa68c147ac4a1debf49fed6..dd0a8d87a1a4a0541cf0e35d9c3185bc29205610 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -184,6 +184,7 @@ VIR_ENUM_IMPL(virDomainFeature,
"ibs",
"tcg",
"async-teardown",
+ "aia",
);
VIR_ENUM_IMPL(virDomainCapabilitiesPolicy,
@@ -1516,6 +1517,14 @@ VIR_ENUM_IMPL(virDomainLaunchSecurity,
"s390-pv",
);
+VIR_ENUM_IMPL(virDomainAIA,
+ VIR_DOMAIN_AIA_LAST,
+ "default",
+ "none",
+ "aplic",
+ "aplic-imsic",
+);
+
typedef enum {
VIR_DOMAIN_NET_VHOSTUSER_MODE_NONE,
VIR_DOMAIN_NET_VHOSTUSER_MODE_CLIENT,
@@ -16744,6 +16753,19 @@ virDomainFeaturesDefParse(virDomainDef *def,
break;
}
+ case VIR_DOMAIN_FEATURE_AIA: {
+ virDomainAIA value;
+
+ if (virXMLPropEnumDefault(nodes[i], "value", virDomainAIATypeFromString,
+ VIR_XML_PROP_NONZERO, &value,
+ VIR_DOMAIN_AIA_DEFAULT) < 0)
+ return -1;
+
+ def->features[val] = value;
+ break;
+
+ }
+
case VIR_DOMAIN_FEATURE_TCG:
if (virDomainFeaturesTCGDefParse(def, ctxt, nodes[i]) < 0)
return -1;
@@ -20734,6 +20756,17 @@ virDomainDefFeaturesCheckABIStability(virDomainDef *src,
}
break;
+ case VIR_DOMAIN_FEATURE_AIA:
+ if (src->features[i] != dst->features[i]) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("State of feature '%1$s' differs: source: '%2$s=%3$s', destination: '%4$s=%5$s'"),
+ featureName,
+ "value", virDomainAIATypeToString(src->features[i]),
+ "value", virDomainAIATypeToString(dst->features[i]));
+ return false;
+ }
+ break;
+
case VIR_DOMAIN_FEATURE_MSRS:
case VIR_DOMAIN_FEATURE_TCG:
case VIR_DOMAIN_FEATURE_ASYNC_TEARDOWN:
@@ -27565,6 +27598,14 @@ virDomainDefFormatFeatures(virBuffer *buf,
virTristateBoolTypeToString(def->features[i]));
break;
+ case VIR_DOMAIN_FEATURE_AIA:
+ if (def->features[i] == VIR_DOMAIN_AIA_DEFAULT)
+ break;
+
+ virBufferAsprintf(&childBuf, "\n",
+ virDomainAIATypeToString(def->features[i]));
+ break;
+
case VIR_DOMAIN_FEATURE_LAST:
break;
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 6681eb37b4f1d2ce7230c6980550e78b0fb08467..fbc224e1ee005cb23fcd30104a41ee06d04070a8 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2148,6 +2148,7 @@ typedef enum {
VIR_DOMAIN_FEATURE_IBS,
VIR_DOMAIN_FEATURE_TCG,
VIR_DOMAIN_FEATURE_ASYNC_TEARDOWN,
+ VIR_DOMAIN_FEATURE_AIA,
VIR_DOMAIN_FEATURE_LAST
} virDomainFeature;
@@ -2362,6 +2363,17 @@ typedef enum {
VIR_ENUM_DECL(virDomainIBS);
+typedef enum {
+ VIR_DOMAIN_AIA_DEFAULT = 0,
+ VIR_DOMAIN_AIA_NONE,
+ VIR_DOMAIN_AIA_APLIC,
+ VIR_DOMAIN_AIA_APLIC_IMSIC,
+
+ VIR_DOMAIN_AIA_LAST
+} virDomainAIA;
+
+VIR_ENUM_DECL(virDomainAIA);
+
typedef struct _virDomainFeatureKVM virDomainFeatureKVM;
struct _virDomainFeatureKVM {
int features[VIR_DOMAIN_KVM_LAST];
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index b98a2ae60230a5860447d8bc94e271c51b6730df..8d2213416f0d38cf1dd973dc5e1df2b9b521d3aa 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6769,6 +6769,9 @@
+
+
+
@@ -7067,6 +7070,18 @@
+
+
+
+
+ none
+ aplic
+ aplic-imsic
+
+
+
+
+
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 553b01b8c0fa788ab3700ee32b8d3113098f6161..9aade3b31d762ce7777963f701ac9f7a4837dadc 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -226,6 +226,8 @@ virDiskNameParse;
virDiskNameToBusDeviceIndex;
virDiskNameToIndex;
virDomainActualNetDefFree;
+virDomainAIATypeFromString;
+virDomainAIATypeToString;
virDomainAudioDefFree;
virDomainAudioFormatTypeFromString;
virDomainAudioFormatTypeToString;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index c21f0e55dc6f834eb059400de99043c493dc5e5d..c69625e49beb56579753f532bab6be02daaadb41 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -698,6 +698,7 @@ VIR_ENUM_IMPL(virQEMUCaps,
/* 450 */
"run-with.async-teardown", /* QEMU_CAPS_RUN_WITH_ASYNC_TEARDOWN */
"virtio-blk-vhost-vdpa", /* QEMU_CAPS_DEVICE_VIRTIO_BLK_VHOST_VDPA */
+ "machine.virt.aia", /* QEMU_CAPS_MACHINE_VIRT_AIA */
);
@@ -1721,6 +1722,7 @@ static struct virQEMUCapsStringFlags virQEMUCapsMachinePropsPSeries[] = {
static struct virQEMUCapsStringFlags virQEMUCapsMachinePropsVirt[] = {
{ "iommu", QEMU_CAPS_MACHINE_VIRT_IOMMU },
+ { "aia", QEMU_CAPS_MACHINE_VIRT_AIA },
};
static struct virQEMUCapsStringFlags virQEMUCapsMachinePropsGeneric[] = {
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 3c4f7f625b45c51318b9b9dad292d49142590330..e6d4aef2a70d7a203f9c96af338e875862bebdff 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -677,6 +677,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
/* 450 */
QEMU_CAPS_RUN_WITH_ASYNC_TEARDOWN, /* asynchronous teardown -run-with async-teardown=on|off */
QEMU_CAPS_DEVICE_VIRTIO_BLK_VHOST_VDPA, /* virtio-blk-vhost-vdpa block driver */
+ QEMU_CAPS_MACHINE_VIRT_AIA, /* -machine virt,aia=(none|aplic|aplic-imsic), RISC-V only */
QEMU_CAPS_LAST /* this must always be the last item */
} virQEMUCapsFlags;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 579774a8c0649c30f734a11b52703de20e92b62a..8360cdb52f96ac69bf24eac4f8f5a38a8d53ae3a 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6822,6 +6822,11 @@ qemuAppendDomainFeaturesMachineParam(virBuffer *buf,
virBufferAsprintf(buf, ",cap-ibs=%s", str);
}
+ if (def->features[VIR_DOMAIN_FEATURE_AIA] != VIR_DOMAIN_AIA_DEFAULT) {
+ const char *str = virDomainAIATypeToString(def->features[VIR_DOMAIN_FEATURE_AIA]);
+ virBufferAsprintf(buf, ",aia=%s", str);
+ }
+
return 0;
}
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index d32b20a423f17a81b1db261822b9fa2b5dbc7ac2..1c6b4aa1c134be0cef7860fb1a31b7ad949eae72 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -226,6 +226,21 @@ qemuValidateDomainDefFeatures(const virDomainDef *def,
}
break;
+ case VIR_DOMAIN_FEATURE_AIA:
+ if (def->features[i] != VIR_DOMAIN_AIA_DEFAULT &&
+ !qemuDomainIsRISCVVirt(def)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("aia feature is only supported with RISC-V Virt machines"));
+
+ return -1;
+ }
+ if (def->features[i] != VIR_DOMAIN_AIA_DEFAULT &&
+ !virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_VIRT_AIA)) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("aia feature is not available with this QEMU binary"));
+ return -1;
+ }
+
case VIR_DOMAIN_FEATURE_SMM:
case VIR_DOMAIN_FEATURE_KVM:
case VIR_DOMAIN_FEATURE_XEN:
diff --git a/tests/qemucapabilitiesdata/caps_8.0.0_riscv64.xml b/tests/qemucapabilitiesdata/caps_8.0.0_riscv64.xml
index 31300d3d31ce910cffb01ea8d2cf698b065d09d8..13f85eb447dc54c60e0be87c11af3fb7d07e8ac8 100644
--- a/tests/qemucapabilitiesdata/caps_8.0.0_riscv64.xml
+++ b/tests/qemucapabilitiesdata/caps_8.0.0_riscv64.xml
@@ -138,6 +138,7 @@
+
7002050
0
v7.2.0-333-g222059a0fc
diff --git a/tests/qemuxml2argvdata/riscv64-virt-features-aia.riscv64-latest.args b/tests/qemuxml2argvdata/riscv64-virt-features-aia.riscv64-latest.args
new file mode 100644
index 0000000000000000000000000000000000000000..61f92d475a1a57187e28c9514b4e54c5eba7ddd0
--- /dev/null
+++ b/tests/qemuxml2argvdata/riscv64-virt-features-aia.riscv64-latest.args
@@ -0,0 +1,30 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/var/lib/libvirt/qemu/domain--1-guest \
+USER=test \
+LOGNAME=test \
+XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \
+XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \
+XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \
+/usr/bin/qemu-system-riscv64 \
+-name guest=guest,debug-threads=on \
+-S \
+-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \
+-machine virt,usb=off,aia=none,dump-guest-core=off,memory-backend=riscv_virt_board.ram \
+-accel tcg \
+-m size=4194304k \
+-object '{"qom-type":"memory-backend-ram","id":"riscv_virt_board.ram","size":4294967296}' \
+-overcommit mem-lock=off \
+-smp 4,sockets=4,cores=1,threads=1 \
+-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \
+-display none \
+-no-user-config \
+-nodefaults \
+-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \
+-mon chardev=charmonitor,id=monitor,mode=control \
+-rtc base=utc \
+-no-shutdown \
+-boot strict=on \
+-audiodev '{"id":"audio1","driver":"none"}' \
+-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
+-msg timestamp=on
diff --git a/tests/qemuxml2argvdata/riscv64-virt-features-aia.xml b/tests/qemuxml2argvdata/riscv64-virt-features-aia.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2303f937c2669f3cac79f5e0209a302a9161c2a9
--- /dev/null
+++ b/tests/qemuxml2argvdata/riscv64-virt-features-aia.xml
@@ -0,0 +1,24 @@
+
+ guest
+ 1ccfd97d-5eb4-478a-bbe6-88d254c16db7
+ 4194304
+ 4194304
+ 4
+
+ hvm
+
+
+
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-riscv64
+
+
+
+
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 68e2ef3bf6fb7da70785325004066f053dfb019d..67a282331781bb0386e6df0f86ae87538dd5d912 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -2384,6 +2384,8 @@ mymain(void)
DO_TEST_CAPS_ARCH_LATEST("x86_64-default-cpu-tcg-q35-4.2", "x86_64");
DO_TEST_CAPS_ARCH_LATEST("x86_64-default-cpu-tcg-features", "x86_64");
+ DO_TEST_CAPS_ARCH_LATEST("riscv64-virt-features-aia", "riscv64");
+
DO_TEST_CAPS_LATEST("virtio-9p-multidevs");
DO_TEST_CAPS_LATEST("virtio-9p-createmode");
diff --git a/tests/qemuxml2xmloutdata/riscv64-virt-features-aia.riscv64-latest.xml b/tests/qemuxml2xmloutdata/riscv64-virt-features-aia.riscv64-latest.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2303f937c2669f3cac79f5e0209a302a9161c2a9
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/riscv64-virt-features-aia.riscv64-latest.xml
@@ -0,0 +1,24 @@
+
+ guest
+ 1ccfd97d-5eb4-478a-bbe6-88d254c16db7
+ 4194304
+ 4194304
+ 4
+
+ hvm
+
+
+
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-riscv64
+
+
+
+
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 49722322acdc75a307a56add726ba4004753a628..f48ca7c2697334b930d682e81d8bce7334f9f8a8 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -950,6 +950,8 @@ mymain(void)
DO_TEST_CAPS_ARCH_LATEST("x86_64-default-cpu-tcg-q35-4.2", "x86_64");
DO_TEST_CAPS_ARCH_LATEST("x86_64-default-cpu-tcg-features", "x86_64");
+ DO_TEST_CAPS_ARCH_LATEST("riscv64-virt-features-aia", "riscv64");
+
DO_TEST_CAPS_LATEST("virtio-9p-multidevs");
DO_TEST_CAPS_LATEST("virtio-9p-createmode");
DO_TEST_CAPS_LATEST("downscript");