Implement a sub-test in qemuxmlconftest that mocks the scanning of sysfs to determine how many "nestedSmmuv3" devices to assign to the VM when "nestedSmmuv3" IOMMU model is parsed from the VM definition. Add a VM definition example with an associated qemu command line that exercises the detection of "nestedSmmuv3" IOMMU model and auto-creation of PXB controllers and "nestedSmmuv3" devices. Signed-off-by: Nathan Chen <nathanc@xxxxxxxxxx> --- src/conf/domain_conf.c | 2 +- src/conf/domain_conf.h | 2 + src/libvirt_private.syms | 2 + tests/meson.build | 1 + .../iommu-nestedsmmuv3.aarch64-latest.args | 38 ++++++++++++ .../iommu-nestedsmmuv3.aarch64-latest.xml | 61 +++++++++++++++++++ tests/qemuxmlconfdata/iommu-nestedsmmuv3.xml | 29 +++++++++ tests/qemuxmlconftest.c | 4 +- tests/virnestedsmmuv3mock.c | 57 +++++++++++++++++ 9 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 tests/qemuxmlconfdata/iommu-nestedsmmuv3.aarch64-latest.args create mode 100644 tests/qemuxmlconfdata/iommu-nestedsmmuv3.aarch64-latest.xml create mode 100644 tests/qemuxmlconfdata/iommu-nestedsmmuv3.xml create mode 100644 tests/virnestedsmmuv3mock.c diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 46f9b9b0cf..d8b473854e 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -22491,7 +22491,7 @@ virDomainDefAddImplicitVideo(virDomainDef *def, virDomainXMLOption *xmlopt) return 0; } -static int +int virDomainDefAddImplicitNestedSmmuv3(virDomainDef *def) { // Get the number of host-level SMMUv3 instances diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index edde9b63d6..8e7e8166e3 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -3873,6 +3873,8 @@ bool virDomainDefCheckABIStabilityFlags(virDomainDef *src, int virDomainDefAddImplicitDevices(virDomainDef *def, virDomainXMLOption *xmlopt); +int virDomainDefAddImplicitNestedSmmuv3(virDomainDef *def) G_NO_INLINE; + virDomainIOThreadIDDef *virDomainIOThreadIDFind(const virDomainDef *def, unsigned int iothread_id); virDomainIOThreadIDDef *virDomainIOThreadIDAdd(virDomainDef *def, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c931003fad..2527f0844a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -312,6 +312,7 @@ virDomainCryptoTypeTypeFromString; virDomainCryptoTypeTypeToString; virDomainDefAddController; virDomainDefAddImplicitDevices; +virDomainDefAddImplicitNestedSmmuv3; virDomainDefAddUSBController; virDomainDefCheckABIStability; virDomainDefCheckABIStabilityFlags; @@ -531,6 +532,7 @@ virDomainMemorySourceTypeFromString; virDomainMemorySourceTypeToString; virDomainMouseModeTypeFromString; virDomainMouseModeTypeToString; +virDomainNestedSmmuv3DefNew; virDomainNetAllocateActualDevice; virDomainNetAppendIPAddress; virDomainNetARPInterfaces; diff --git a/tests/meson.build b/tests/meson.build index 0d76d37959..d3b9d4612b 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -177,6 +177,7 @@ if conf.has('WITH_QEMU') { 'name': 'qemuhotplugmock', 'link_with': [ test_qemu_driver_lib, test_utils_qemu_lib, test_utils_lib ] }, { 'name': 'qemuxml2argvmock' }, { 'name': 'virhostidmock' }, + { 'name': 'virnestedsmmuv3mock' }, ] else test_qemu_driver_lib = [] diff --git a/tests/qemuxmlconfdata/iommu-nestedsmmuv3.aarch64-latest.args b/tests/qemuxmlconfdata/iommu-nestedsmmuv3.aarch64-latest.args new file mode 100644 index 0000000000..bf094dd20a --- /dev/null +++ b/tests/qemuxmlconfdata/iommu-nestedsmmuv3.aarch64-latest.args @@ -0,0 +1,38 @@ +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-aarch64 \ +-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,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=off \ +-accel tcg \ +-cpu cortex-a15 \ +-m size=1048576k \ +-object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \ +-overcommit mem-lock=off \ +-smp 1,sockets=1,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 \ +-device '{"driver":"pxb-pcie","bus_nr":254,"id":"pci.1","bus":"pcie.0","addr":"0x1"}' \ +-device '{"driver":"pxb-pcie","bus_nr":252,"id":"pci.2","bus":"pcie.0","addr":"0x2"}' \ +-device '{"driver":"pxb-pcie","bus_nr":250,"id":"pci.3","bus":"pcie.0","addr":"0x3"}' \ +-device '{"driver":"pcie-root-port","port":32,"chassis":4,"id":"pci.4","bus":"pcie.0","addr":"0x4"}' \ +-audiodev '{"id":"audio1","driver":"none"}' \ +-device '{"driver":"arm-smmuv3-nested","bus":"pci.1"}' \ +-device '{"driver":"arm-smmuv3-nested","bus":"pci.2"}' \ +-device '{"driver":"arm-smmuv3-nested","bus":"pci.3"}' \ +-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ +-msg timestamp=on diff --git a/tests/qemuxmlconfdata/iommu-nestedsmmuv3.aarch64-latest.xml b/tests/qemuxmlconfdata/iommu-nestedsmmuv3.aarch64-latest.xml new file mode 100644 index 0000000000..0aa9296eaa --- /dev/null +++ b/tests/qemuxmlconfdata/iommu-nestedsmmuv3.aarch64-latest.xml @@ -0,0 +1,61 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='aarch64' machine='virt'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <gic version='2'/> + </features> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>cortex-a15</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pcie-root'/> + <controller type='pci' index='1' model='pcie-expander-bus'> + <model name='pxb-pcie'/> + <target busNr='254'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/> + </controller> + <controller type='pci' index='2' model='pcie-expander-bus'> + <model name='pxb-pcie'/> + <target busNr='252'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/> + </controller> + <controller type='pci' index='3' model='pcie-expander-bus'> + <model name='pxb-pcie'/> + <target busNr='250'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/> + </controller> + <controller type='pci' index='4' model='pcie-root-port'> + <model name='pcie-root-port'/> + <target chassis='4' port='0x20'/> + <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/> + </controller> + <audio id='1' type='none'/> + <memballoon model='none'/> + <nestedSmmuv3> + <name>smmu3.0x0000000000000001</name> + <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/> + </nestedSmmuv3> + <nestedSmmuv3> + <name>smmu3.0x0000000000000002</name> + <address type='pci' domain='0x0000' bus='0x02' slot='0x00' function='0x0'/> + </nestedSmmuv3> + <nestedSmmuv3> + <name>smmu3.0x0000000000000003</name> + <address type='pci' domain='0x0000' bus='0x03' slot='0x00' function='0x0'/> + </nestedSmmuv3> + <iommu model='nestedSmmuv3'/> + </devices> +</domain> diff --git a/tests/qemuxmlconfdata/iommu-nestedsmmuv3.xml b/tests/qemuxmlconfdata/iommu-nestedsmmuv3.xml new file mode 100644 index 0000000000..c114a3675c --- /dev/null +++ b/tests/qemuxmlconfdata/iommu-nestedsmmuv3.xml @@ -0,0 +1,29 @@ +<domain type='qemu'> + <name>guest</name> + <uuid>1ccfd97d-5eb4-478a-bbe6-88d254c16db7</uuid> + <memory unit='KiB'>1048576</memory> + <currentMemory unit='KiB'>1048576</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='aarch64' machine='virt'>hvm</type> + <boot dev='hd'/> + </os> + <features> + <gic version='2'/> + </features> + <cpu mode='custom' match='exact' check='none'> + <model fallback='forbid'>cortex-a15</model> + </cpu> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu-system-aarch64</emulator> + <controller type='usb' index='0' model='none'/> + <controller type='pci' index='0' model='pcie-root'/> + <audio id='1' type='none'/> + <memballoon model='none'/> + <iommu model='nestedSmmuv3'/> + </devices> +</domain> diff --git a/tests/qemuxmlconftest.c b/tests/qemuxmlconftest.c index f3c8d0ae34..01176f42b7 100644 --- a/tests/qemuxmlconftest.c +++ b/tests/qemuxmlconftest.c @@ -2772,6 +2772,7 @@ mymain(void) DO_TEST_CAPS_LATEST_PARSE_ERROR("intel-iommu-wrong-machine"); DO_TEST_CAPS_LATEST_ABI_UPDATE("intel-iommu-eim-autoadd"); DO_TEST_CAPS_ARCH_LATEST("iommu-smmuv3", "aarch64"); + DO_TEST_CAPS_ARCH_LATEST("iommu-nestedsmmuv3", "aarch64"); DO_TEST_CAPS_LATEST("virtio-iommu-x86_64"); DO_TEST_CAPS_VER_PARSE_ERROR("virtio-iommu-x86_64", "6.1.0"); DO_TEST_CAPS_ARCH_LATEST("virtio-iommu-aarch64", "aarch64"); @@ -3030,7 +3031,8 @@ VIR_TEST_MAIN_PRELOAD(mymain, VIR_TEST_MOCK("virrandom"), VIR_TEST_MOCK("qemucpu"), VIR_TEST_MOCK("virpci"), - VIR_TEST_MOCK("virnuma")) + VIR_TEST_MOCK("virnuma"), + VIR_TEST_MOCK("virnestedsmmuv3")) #else diff --git a/tests/virnestedsmmuv3mock.c b/tests/virnestedsmmuv3mock.c new file mode 100644 index 0000000000..1f40ef46f4 --- /dev/null +++ b/tests/virnestedsmmuv3mock.c @@ -0,0 +1,57 @@ +/* + * virnestedsmmuv3mock.c: Mock sysfs nested SMMU paths + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "conf/domain_conf.h" +#include "viralloc.h" +#include "virstring.h" +#include "internal.h" +#include "virmock.h" + +int +virDomainDefAddImplicitNestedSmmuv3(virDomainDef *def) +{ + virDomainNestedSmmuv3Def* nestedsmmuv3 = NULL; + + if (!(nestedsmmuv3 = virDomainNestedSmmuv3DefNew())) + return -1; + VIR_REALLOC_N(nestedsmmuv3->name, strlen("smmu3.0x0000000000000001") + 1); + virStrcpy(nestedsmmuv3->name, "smmu3.0x0000000000000001", + strlen("smmu3.0x0000000000000001") + 1); + VIR_REALLOC_N(def->nestedsmmus, def->nnestedsmmus + 1); + def->nestedsmmus[def->nnestedsmmus++] = nestedsmmuv3; + + if (!(nestedsmmuv3 = virDomainNestedSmmuv3DefNew())) + return -1; + VIR_REALLOC_N(nestedsmmuv3->name, strlen("smmu3.0x0000000000000002") + 1); + virStrcpy(nestedsmmuv3->name, "smmu3.0x0000000000000002", + strlen("smmu3.0x0000000000000002") + 1); + VIR_REALLOC_N(def->nestedsmmus, def->nnestedsmmus + 1); + def->nestedsmmus[def->nnestedsmmus++] = nestedsmmuv3; + + if (!(nestedsmmuv3 = virDomainNestedSmmuv3DefNew())) + return -1; + VIR_REALLOC_N(nestedsmmuv3->name, strlen("smmu3.0x0000000000000003") + 1); + virStrcpy(nestedsmmuv3->name, "smmu3.0x0000000000000003", + strlen("smmu3.0x0000000000000003") + 1); + VIR_REALLOC_N(def->nestedsmmus, def->nnestedsmmus + 1); + def->nestedsmmus[def->nnestedsmmus++] = nestedsmmuv3; + + return 0; +} -- 2.34.1