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");