Hi Thomas,
On 3/11/25 11:49 AM, Thomas Huth wrote: > This test was using cloudinit and a "dnf install" command in the guest > to exercise the NIC with SMMU enabled. Since we don't have the cloudinit > stuff in the functional framework and we should not rely on having access > to external networks (once our ASSETs have been cached), we rather boot > into the initrd first, manually mount the root disk and then use the > check_http_download() function from the functional framework here instead > for testing whether the network works as expected. > > Unfortunately, there seems to be a small race when using the files > from Fedora 33: To enter the initrd shell, we have to send a "return" > once. But it does not seem to work if we send it too early. Using a > sleep(0.2) makes it work reliably for me, but to make it even more > unlikely to trigger this situation, let's better limit the Fedora 33 > tests to only run with KVM. > > Finally, while we're at it, we also add some lines for testing writes > to the hard disk, as we already do it in the test_intel_iommu test. for your info it does not apply anymore on mainline after latest appied functional test additions. > > Signed-off-by: Thomas Huth <th...@redhat.com> > --- > MAINTAINERS | 2 +- > tests/functional/meson.build | 2 + > .../test_aarch64_smmu.py} | 243 +++++++++++------- > 3 files changed, 159 insertions(+), 88 deletions(-) > rename tests/{avocado/smmu.py => functional/test_aarch64_smmu.py} (17%) > mode change 100644 => 100755 > > diff --git a/MAINTAINERS b/MAINTAINERS > index 90e48b26715..211e70c6942 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -218,7 +218,7 @@ L: qemu-...@nongnu.org > S: Maintained > F: hw/arm/smmu* > F: include/hw/arm/smmu* > -F: tests/avocado/smmu.py > +F: tests/functional/test_aarch64_smmu.py > > AVR TCG CPUs > M: Michael Rolnik <mrol...@gmail.com> > diff --git a/tests/functional/meson.build b/tests/functional/meson.build > index 43a34c6447e..e8bf0e4a6bc 100644 > --- a/tests/functional/meson.build > +++ b/tests/functional/meson.build > @@ -18,6 +18,7 @@ test_timeouts = { > 'aarch64_rme_sbsaref' : 1200, > 'aarch64_sbsaref_alpine' : 1200, > 'aarch64_sbsaref_freebsd' : 720, > + 'aarch64_smmu' : 720, > 'aarch64_tuxrun' : 240, > 'aarch64_virt' : 720, > 'acpi_bits' : 420, > @@ -84,6 +85,7 @@ tests_aarch64_system_thorough = [ > 'aarch64_sbsaref', > 'aarch64_sbsaref_alpine', > 'aarch64_sbsaref_freebsd', > + 'aarch64_smmu', > 'aarch64_tcg_plugins', > 'aarch64_tuxrun', > 'aarch64_virt', > diff --git a/tests/avocado/smmu.py b/tests/functional/test_aarch64_smmu.py > old mode 100644 > new mode 100755 > similarity index 17% > rename from tests/avocado/smmu.py > rename to tests/functional/test_aarch64_smmu.py > index 83fd79e922e..bba8599401c > --- a/tests/avocado/smmu.py > +++ b/tests/functional/test_aarch64_smmu.py > @@ -1,3 +1,5 @@ > +#!/usr/bin/env python3 > +# > # SMMUv3 Functional tests > # > # Copyright (c) 2021 Red Hat, Inc. > @@ -7,44 +9,48 @@ > # > # This work is licensed under the terms of the GNU GPL, version 2 or > # later. See the COPYING file in the top-level directory. > + > import os > +import time > + > +from qemu_test import LinuxKernelTest, Asset, > exec_command_and_wait_for_pattern > +from qemu_test import BUILD_DIR > +from qemu.utils import kvm_available > > -from avocado import skipUnless > -from avocado_qemu import BUILD_DIR > -from avocado_qemu.linuxtest import LinuxTest > - > -@skipUnless(os.getenv('QEMU_TEST_FLAKY_TESTS'), 'Test is unstable on GitLab') > -class SMMU(LinuxTest): > - """ > - :avocado: tags=accel:kvm > - :avocado: tags=cpu:host > - :avocado: tags=arch:aarch64 > - :avocado: tags=machine:virt > - :avocado: tags=distro:fedora > - :avocado: tags=smmu > - :avocado: tags=flaky > - """ > > +class SMMU(LinuxKernelTest): > + > + default_kernel_params = ('earlyprintk=pl011,0x9000000 no_timer_check ' > + 'printk.time=1 rd_NO_PLYMOUTH net.ifnames=0 ' > + 'console=ttyAMA0 rd.rescue') > IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on' > kernel_path = None > initrd_path = None > kernel_params = None > > - def set_up_boot(self): > - path = self.download_boot() > + GUEST_PORT = 8080 > + > + def set_up_boot(self, path): > self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,' + > 'drive=drv0,id=virtio-disk0,bootindex=1,' > 'werror=stop,rerror=stop' + self.IOMMU_ADDON) > self.vm.add_args('-drive', > - 'file=%s,if=none,cache=writethrough,id=drv0' % path) > - > - def setUp(self): > - super(SMMU, self).setUp(None, 'virtio-net-pci' + self.IOMMU_ADDON) > - > - def common_vm_setup(self, custom_kernel=False): > - self.require_accelerator("kvm") > - self.vm.add_args("-accel", "kvm") > - self.vm.add_args("-cpu", "host") > + > f'file={path},if=none,cache=writethrough,id=drv0,snapshot=on') > + > + self.vm.add_args('-netdev', > + 'user,id=n1,hostfwd=tcp:127.0.0.1:0-:%d' % > + self.GUEST_PORT) > + self.vm.add_args('-device', 'virtio-net,netdev=n1' + > self.IOMMU_ADDON) > + > + def common_vm_setup(self, kernel, initrd, disk): > + self.set_machine("virt") > + self.require_netdev('user') > + if kvm_available(qemu_bin=self.qemu_bin): > + self.vm.add_args("-accel", "kvm") > + self.vm.add_args("-cpu", "host") > + else: > + self.vm.add_args("-cpu", "cortex-a57") > + self.vm.add_args('-m', '1G') > self.vm.add_args("-machine", "iommu=smmuv3") > self.vm.add_args("-d", "guest_errors") > self.vm.add_args('-bios', os.path.join(BUILD_DIR, 'pc-bios', > @@ -53,87 +59,150 @@ def common_vm_setup(self, custom_kernel=False): > self.vm.add_args('-object', > 'rng-random,id=rng0,filename=/dev/urandom') > > - if custom_kernel is False: > - return > + self.kernel_path = kernel.fetch() > + self.initrd_path = initrd.fetch() > + self.set_up_boot(disk.fetch()) > + > + def run_and_check(self, filename, hashsum): > + self.vm.add_args('-initrd', self.initrd_path) > + self.vm.add_args('-append', self.kernel_params) > + self.launch_kernel(self.kernel_path, initrd=self.initrd_path, > + wait_for='attach it to a bug report.') > + prompt = '# ' > + # Fedora 33 requires 'return' to be pressed to enter the shell. > + # There seems to be a small race between detecting the previous ':' > + # and sending the newline, so we need to add a small delay here. > + self.wait_for_console_pattern(':') > + time.sleep(0.2) > + exec_command_and_wait_for_pattern(self, '\n', prompt) > + exec_command_and_wait_for_pattern(self, 'cat /proc/cmdline', > + self.kernel_params) > + > + # Checking for SMMU enablement: > + self.log.info("Checking whether SMMU has been enabled...") > + exec_command_and_wait_for_pattern(self, 'dmesg | grep smmu', > + 'arm-smmu-v3') > + self.wait_for_console_pattern(prompt) > + exec_command_and_wait_for_pattern(self, > + 'find /sys/kernel/iommu_groups/ -type l', > + 'devices/0000:00:') > + self.wait_for_console_pattern(prompt) > + > + # Copy a file (checked later), umount afterwards to drop disk cache: > + self.log.info("Checking hard disk...") > + exec_command_and_wait_for_pattern(self, > + "while ! (dmesg -c | grep vda:) ; do sleep 1 ; done", > + "vda2") > + exec_command_and_wait_for_pattern(self, 'mount /dev/vda2 /sysroot', > + 'mounted filesystem') > + exec_command_and_wait_for_pattern(self, 'cp /bin/vi > /sysroot/root/vi', > + prompt) > + exec_command_and_wait_for_pattern(self, 'umount /sysroot', prompt) > + # Switch from initrd to the cloud image filesystem: > + exec_command_and_wait_for_pattern(self, 'mount /dev/vda2 /sysroot', > + prompt) > + exec_command_and_wait_for_pattern(self, > + ('for d in dev proc sys run ; do ' > + 'mount -o bind /$d /sysroot/$d ; done'), prompt) > + exec_command_and_wait_for_pattern(self, 'chroot /sysroot', prompt) > + # Check files on the hard disk: > + exec_command_and_wait_for_pattern(self, > + ('if diff -q /root/vi /usr/bin/vi ; then echo "file" "ok" ; ' > + 'else echo "files differ"; fi'), 'file ok') > + self.wait_for_console_pattern(prompt) > + exec_command_and_wait_for_pattern(self, f'sha256sum {filename}', > + hashsum) > + > + # Check virtio-net via HTTP: > + exec_command_and_wait_for_pattern(self, 'dhclient eth0', prompt) > + self.check_http_download(filename, hashsum, self.GUEST_PORT) > > - kernel_url = self.distro.pxeboot_url + 'vmlinuz' > - initrd_url = self.distro.pxeboot_url + 'initrd.img' > - self.kernel_path = self.fetch_asset(kernel_url) > - self.initrd_path = self.fetch_asset(initrd_url) > > - def run_and_check(self): > - if self.kernel_path: > - self.vm.add_args('-kernel', self.kernel_path, > - '-append', self.kernel_params, > - '-initrd', self.initrd_path) > - self.launch_and_wait() > - self.ssh_command('cat /proc/cmdline') > - self.ssh_command('dnf -y install numactl-devel') > + # 5.3 kernel without RIL # > > + ASSET_KERNEL_F31 = Asset( > + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' > + 'releases/31/Server/aarch64/os/images/pxeboot/vmlinuz'), > + '413c7f95e7f40cfa3e73290ffae855c88fae54cccc46123a4b4ed2db7d5c2120') the hash seems wrong for the vmlinuz. I get Exception: Hash of https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/31/Server/aarch64/os/images/pxeboot/vmlinuz does not match 413c7f95e7f40cfa3e73290ffae855c88fae54cccc46123a4b4ed2db7d5c2120 > > - # 5.3 kernel without RIL # > + ASSET_INITRD_F31 = Asset( > + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' > + 'releases/31/Server/aarch64/os/images/pxeboot/initrd.img'), > + '9f3146b28bc531c689f3c5f114cb74e4bd7bd548e0ba19fa77921d8bd256755a') > + > + ASSET_DISK_F31 = Asset( > + > ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' > + '/31/Cloud/aarch64/images/Fedora-Cloud-Base-31-1.9.aarch64.qcow2'), > + '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49') > + > + F31_FILENAME = '/boot/initramfs-5.3.7-301.fc31.aarch64.img' > + F31_HSUM = > '1a4beec6607d94df73d9dd1b4985c9c23dd0fdcf4e6ca1351d477f190df7bef9' > > def test_smmu_noril(self): > - """ > - :avocado: tags=smmu_noril > - :avocado: tags=smmu_noril_tests > - :avocado: tags=distro_version:31 > - """ > - self.common_vm_setup() > - self.run_and_check() > + self.common_vm_setup(self.ASSET_KERNEL_F31, self.ASSET_INITRD_F31, > + self.ASSET_DISK_F31) > + self.kernel_params = self.default_kernel_params > + self.run_and_check(self.F31_FILENAME, self.F31_HSUM) > > def test_smmu_noril_passthrough(self): > - """ > - :avocado: tags=smmu_noril_passthrough > - :avocado: tags=smmu_noril_tests > - :avocado: tags=distro_version:31 > - """ > - self.common_vm_setup(True) > - self.kernel_params = (self.distro.default_kernel_params + > + self.common_vm_setup(self.ASSET_KERNEL_F31, self.ASSET_INITRD_F31, > + self.ASSET_DISK_F31) > + self.kernel_params = (self.default_kernel_params + > ' iommu.passthrough=on') > - self.run_and_check() > + self.run_and_check(self.F31_FILENAME, self.F31_HSUM) > > def test_smmu_noril_nostrict(self): > - """ > - :avocado: tags=smmu_noril_nostrict > - :avocado: tags=smmu_noril_tests > - :avocado: tags=distro_version:31 > - """ > - self.common_vm_setup(True) > - self.kernel_params = (self.distro.default_kernel_params + > + self.common_vm_setup(self.ASSET_KERNEL_F31, self.ASSET_INITRD_F31, > + self.ASSET_DISK_F31) > + self.kernel_params = (self.default_kernel_params + > ' iommu.strict=0') > - self.run_and_check() > + self.run_and_check(self.F31_FILENAME, self.F31_HSUM) > + > > # 5.8 kernel featuring range invalidation > # >= v5.7 kernel > > + ASSET_KERNEL_F33 = Asset( > + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' > + 'releases/33/Server/aarch64/os/images/pxeboot/vmlinuz'), > + '0ef9e34f80b49fa2ac098899b27075e95c11d5b646f6ca4df2e89237a40f9e4f') same here I get Exception: Hash of https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/33/Server/aarch64/os/images/pxeboot/vmlinuz does not match 0ef9e34f80b49fa2ac098899b27075e95c11d5b646f6ca4df2e89237a40f9e4f > + > + ASSET_INITRD_F33 = Asset( > + ('https://archives.fedoraproject.org/pub/archive/fedora/linux/' > + 'releases/33/Server/aarch64/os/images/pxeboot/initrd.img'), > + '92513f55295c2c16a777f7b6c35ccd70a438e9e1e40b6ba39e0e60900615b3df') > + > + ASSET_DISK_F33 = Asset( > + > ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases' > + '/33/Cloud/aarch64/images/Fedora-Cloud-Base-33-1.2.aarch64.qcow2'), > + 'e7f75cdfd523fe5ac2ca9eeece68edc1a81f386a17f969c1d1c7c87031008a6b') > + > + F33_FILENAME = '/boot/initramfs-5.8.15-301.fc33.aarch64.img' > + F33_HSUM = > '079cfad0caa82e84c8ca1fb0897a4999dd769f262216099f518619e807a550d9' > + > def test_smmu_ril(self): > - """ > - :avocado: tags=smmu_ril > - :avocado: tags=smmu_ril_tests > - :avocado: tags=distro_version:33 > - """ > - self.common_vm_setup() > - self.run_and_check() > + self.require_accelerator("kvm") > + self.common_vm_setup(self.ASSET_KERNEL_F33, self.ASSET_INITRD_F33, > + self.ASSET_DISK_F33) > + self.kernel_params = self.default_kernel_params > + self.run_and_check(self.F33_FILENAME, self.F33_HSUM) > > def test_smmu_ril_passthrough(self): > - """ > - :avocado: tags=smmu_ril_passthrough > - :avocado: tags=smmu_ril_tests > - :avocado: tags=distro_version:33 > - """ > - self.common_vm_setup(True) > - self.kernel_params = (self.distro.default_kernel_params + > + self.require_accelerator("kvm") > + self.common_vm_setup(self.ASSET_KERNEL_F33, self.ASSET_INITRD_F33, > + self.ASSET_DISK_F33) > + self.kernel_params = (self.default_kernel_params + > ' iommu.passthrough=on') > - self.run_and_check() > + self.run_and_check(self.F33_FILENAME, self.F33_HSUM) > > def test_smmu_ril_nostrict(self): > - """ > - :avocado: tags=smmu_ril_nostrict > - :avocado: tags=smmu_ril_tests > - :avocado: tags=distro_version:33 > - """ > - self.common_vm_setup(True) > - self.kernel_params = (self.distro.default_kernel_params + > + self.require_accelerator("kvm") > + self.common_vm_setup(self.ASSET_KERNEL_F33, self.ASSET_INITRD_F33, > + self.ASSET_DISK_F33) > + self.kernel_params = (self.default_kernel_params + > ' iommu.strict=0') > - self.run_and_check() > + self.run_and_check(self.F33_FILENAME, self.F33_HSUM) > + > + > +if __name__ == '__main__': > + LinuxKernelTest.main() Thanks Eric