diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 56d94bb1bae288c58fe5b824b9e64632c97b9db1..c002505e12cde18d79741fb1c6e1d2d0114088ec 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -2020,6 +2020,7 @@ Hypervisors may allow certain CPU / machine features to be toggled on/off.
128
+
...
@@ -2254,6 +2255,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 e30ec0dca4c788669edf682c284337884a6c7aa1..ee001dc4a1ff4fc42130b86f0b6429cd2338d3ed 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,
@@ -1520,6 +1521,14 @@ VIR_ENUM_IMPL(virDomainLaunchSecurity,
"cca",
);
+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,
@@ -16873,6 +16882,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;
@@ -20945,6 +20967,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:
@@ -27830,6 +27863,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 cadca3324651092a3ef70101248c5afb272dde4e..2c1efd5fa2703eb4e7c667d4d0e822ec28a24898 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2162,6 +2162,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;
@@ -2376,6 +2377,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 78773f744b35127b18cee430ff8e69ede2cd5e1b..93892740f0abde04e05e6cddc63b0081e29bef53 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6820,6 +6820,9 @@
+
+
+
@@ -7118,6 +7121,18 @@
+
+
+
+
+ none
+ aplic
+ aplic-imsic
+
+
+
+
+
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4cd5f0b2f38b684f6aeb374237c2f1a54d92af0b..72191961888d64f774ea2e734ed6e2d6fc5b6a43 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -228,6 +228,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 90fb603adf003bf7d0370d2aed10ccfeea1cf2b9..d2f7a87b19f7d98bb9f8b2920aa27b979ec48223 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -701,6 +701,9 @@ VIR_ENUM_IMPL(virQEMUCaps,
"smp-clusters", /* QEMU_CAPS_SMP_CLUSTERS */
"tmm-guest", /* QEMU_CAPS_VIRTCCA */
"rme-guest", /* QEMU_CAPS_CCA_GUEST */
+
+ /* 455 */
+ "machine.virt.aia", /* QEMU_CAPS_MACHINE_VIRT_AIA */
);
@@ -1731,6 +1734,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 e4a97bc49113415504b1551a8b1b31ff417491a2..b5f75edd18d1b3431566df6e2e868bd8b71c132e 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -681,6 +681,9 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
QEMU_CAPS_VIRTCCA, /* tmm-guest */
QEMU_CAPS_CCA_GUEST, /* -object rme-guest */
+ /* 455 */
+ 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 cc8ecfa9fb741575a26bd550204effaa2b38ecfe..cc3489784ff20bca3019aba712a079041bb216df 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6885,6 +6885,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 e3ed00d9b02af12fbd27351c9122cac4cba36463..ca2c97ddde0eadb3f01f4c2dd59be459b0a4bf9c 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -226,6 +226,22 @@ 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;
+ }
+ break;
+
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 3f2acb50187e3c758db7aeced6423091db9e419e..2c909f5e0cc82dfa7865aed9c1e426d706f0f8a0 100644
--- a/tests/qemucapabilitiesdata/caps_8.0.0_riscv64.xml
+++ b/tests/qemucapabilitiesdata/caps_8.0.0_riscv64.xml
@@ -139,6 +139,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 b2ea2191dca69d689aaf4f4440dd4811b01702d1..0cdc9beb3e2e128f26d27d10145a3ee5fb527301 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -2381,6 +2381,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 1010b68ebcf1090583851ef6cc3700dc1915e707..9b2d1a6736c94f4e358da20a2d61be62831f6b98 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -947,6 +947,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");