master
py 212 lines 9.14 KB
Raw
1 #!/usr/bin/env python3
2 #
3 # SPDX-License-Identifier: GPL-2.0-or-later
4 #
5 # SMMUv3 Functional tests
6 #
7 # Copyright (c) 2021 Red Hat, Inc.
8 #
9 # Author:
10 # Eric Auger <eric.auger@redhat.com>
11 #
12 # This work is licensed under the terms of the GNU GPL, version 2 or
13 # later. See the COPYING file in the top-level directory.
14
15 import os
16 import time
17
18 from qemu_test import LinuxKernelTest, Asset, exec_command_and_wait_for_pattern
19 from qemu_test import BUILD_DIR
20 from qemu.utils import kvm_available, hvf_available
21
22
23 class SMMU(LinuxKernelTest):
24
25 default_kernel_params = ('earlyprintk=pl011,0x9000000 no_timer_check '
26 'printk.time=1 rd_NO_PLYMOUTH net.ifnames=0 '
27 'console=ttyAMA0 rd.rescue')
28 IOMMU_ADDON = ',iommu_platform=on,disable-modern=off,disable-legacy=on'
29 kernel_path = None
30 initrd_path = None
31 kernel_params = None
32
33 GUEST_PORT = 8080
34
35 def set_up_boot(self, path):
36 self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,' +
37 'drive=drv0,id=virtio-disk0,bootindex=1,'
38 'werror=stop,rerror=stop' + self.IOMMU_ADDON)
39 self.vm.add_args('-drive',
40 f'file={path},if=none,cache=writethrough,id=drv0,snapshot=on')
41
42 self.vm.add_args('-netdev',
43 'user,id=n1,hostfwd=tcp:127.0.0.1:0-:%d' %
44 self.GUEST_PORT)
45 self.vm.add_args('-device', 'virtio-net,netdev=n1' + self.IOMMU_ADDON)
46
47 def common_vm_setup(self, kernel, initrd, disk):
48 if hvf_available(self.qemu_bin):
49 accel = "hvf"
50 elif kvm_available(self.qemu_bin):
51 accel = "kvm"
52 else:
53 accel = None # for keeping pylint happy
54 self.skipTest("Neither HVF nor KVM accelerator is available")
55 self.require_accelerator(accel)
56 self.require_netdev('user')
57 self.set_machine("virt")
58 self.vm.add_args('-m', '1G')
59 self.vm.add_args("-accel", accel)
60 self.vm.add_args("-cpu", "host")
61 self.vm.add_args("-machine", "iommu=smmuv3")
62 self.vm.add_args("-d", "guest_errors")
63 self.vm.add_args('-bios', os.path.join(BUILD_DIR, 'pc-bios',
64 'edk2-aarch64-code.fd'))
65 self.vm.add_args('-device', 'virtio-rng-pci,rng=rng0')
66 self.vm.add_args('-object',
67 'rng-random,id=rng0,filename=/dev/urandom')
68
69 self.kernel_path = kernel.fetch()
70 self.initrd_path = initrd.fetch()
71 self.set_up_boot(disk.fetch())
72
73 def run_and_check(self, filename, hashsum):
74 self.vm.add_args('-initrd', self.initrd_path)
75 self.vm.add_args('-append', self.kernel_params)
76 self.launch_kernel(self.kernel_path, initrd=self.initrd_path,
77 wait_for='attach it to a bug report.')
78 prompt = '# '
79 # Fedora 33 requires 'return' to be pressed to enter the shell.
80 # There seems to be a small race between detecting the previous ':'
81 # and sending the newline, so we need to add a small delay here.
82 self.wait_for_console_pattern(':')
83 time.sleep(0.2)
84 exec_command_and_wait_for_pattern(self, '\n', prompt)
85 exec_command_and_wait_for_pattern(self, 'cat /proc/cmdline',
86 self.kernel_params)
87
88 # Checking for SMMU enablement:
89 self.log.info("Checking whether SMMU has been enabled...")
90 exec_command_and_wait_for_pattern(self, 'dmesg | grep smmu',
91 'arm-smmu-v3')
92 self.wait_for_console_pattern(prompt)
93 exec_command_and_wait_for_pattern(self,
94 'find /sys/kernel/iommu_groups/ -type l',
95 'devices/0000:00:')
96 self.wait_for_console_pattern(prompt)
97
98 # Copy a file (checked later), umount afterwards to drop disk cache:
99 self.log.info("Checking hard disk...")
100 exec_command_and_wait_for_pattern(self,
101 "while ! (dmesg -c | grep vda:) ; do sleep 1 ; done",
102 "vda2")
103 exec_command_and_wait_for_pattern(self, 'mount /dev/vda2 /sysroot',
104 'mounted filesystem')
105 exec_command_and_wait_for_pattern(self, 'cp /bin/vi /sysroot/root/vi',
106 prompt)
107 exec_command_and_wait_for_pattern(self, 'umount /sysroot', prompt)
108 # Switch from initrd to the cloud image filesystem:
109 exec_command_and_wait_for_pattern(self, 'mount /dev/vda2 /sysroot',
110 prompt)
111 exec_command_and_wait_for_pattern(self,
112 ('for d in dev proc sys run ; do '
113 'mount -o bind /$d /sysroot/$d ; done'), prompt)
114 exec_command_and_wait_for_pattern(self, 'chroot /sysroot', prompt)
115 # Check files on the hard disk:
116 exec_command_and_wait_for_pattern(self,
117 ('if diff -q /root/vi /usr/bin/vi ; then echo "file" "ok" ; '
118 'else echo "files differ"; fi'), 'file ok')
119 self.wait_for_console_pattern(prompt)
120 exec_command_and_wait_for_pattern(self, f'sha256sum {filename}',
121 hashsum)
122
123 # Check virtio-net via HTTP:
124 exec_command_and_wait_for_pattern(self, 'dhclient eth0', prompt)
125 self.check_http_download(filename, hashsum, self.GUEST_PORT)
126
127
128 # 5.3 kernel without RIL #
129
130 ASSET_KERNEL_F31 = Asset(
131 ('https://archives.fedoraproject.org/pub/archive/fedora/linux/'
132 'releases/31/Server/aarch64/os/images/pxeboot/vmlinuz'),
133 '3ae07fcafbfc8e4abeb693035a74fe10698faae15e9ccd48882a9167800c1527')
134
135 ASSET_INITRD_F31 = Asset(
136 ('https://archives.fedoraproject.org/pub/archive/fedora/linux/'
137 'releases/31/Server/aarch64/os/images/pxeboot/initrd.img'),
138 '9f3146b28bc531c689f3c5f114cb74e4bd7bd548e0ba19fa77921d8bd256755a')
139
140 ASSET_DISK_F31 = Asset(
141 ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases'
142 '/31/Cloud/aarch64/images/Fedora-Cloud-Base-31-1.9.aarch64.qcow2'),
143 '1e18d9c0cf734940c4b5d5ec592facaed2af0ad0329383d5639c997fdf16fe49')
144
145 F31_FILENAME = '/boot/initramfs-5.3.7-301.fc31.aarch64.img'
146 F31_HSUM = '1a4beec6607d94df73d9dd1b4985c9c23dd0fdcf4e6ca1351d477f190df7bef9'
147
148 def test_smmu_noril(self):
149 self.common_vm_setup(self.ASSET_KERNEL_F31, self.ASSET_INITRD_F31,
150 self.ASSET_DISK_F31)
151 self.kernel_params = self.default_kernel_params
152 self.run_and_check(self.F31_FILENAME, self.F31_HSUM)
153
154 def test_smmu_noril_passthrough(self):
155 self.common_vm_setup(self.ASSET_KERNEL_F31, self.ASSET_INITRD_F31,
156 self.ASSET_DISK_F31)
157 self.kernel_params = (self.default_kernel_params +
158 ' iommu.passthrough=on')
159 self.run_and_check(self.F31_FILENAME, self.F31_HSUM)
160
161 def test_smmu_noril_nostrict(self):
162 self.common_vm_setup(self.ASSET_KERNEL_F31, self.ASSET_INITRD_F31,
163 self.ASSET_DISK_F31)
164 self.kernel_params = (self.default_kernel_params +
165 ' iommu.strict=0')
166 self.run_and_check(self.F31_FILENAME, self.F31_HSUM)
167
168
169 # 5.8 kernel featuring range invalidation
170 # >= v5.7 kernel
171
172 ASSET_KERNEL_F33 = Asset(
173 ('https://archives.fedoraproject.org/pub/archive/fedora/linux/'
174 'releases/33/Server/aarch64/os/images/pxeboot/vmlinuz'),
175 'd8b1e6f7241f339d8e7609c456cf0461ffa4583ed07e0b55c7d1d8a0c154aa89')
176
177 ASSET_INITRD_F33 = Asset(
178 ('https://archives.fedoraproject.org/pub/archive/fedora/linux/'
179 'releases/33/Server/aarch64/os/images/pxeboot/initrd.img'),
180 '92513f55295c2c16a777f7b6c35ccd70a438e9e1e40b6ba39e0e60900615b3df')
181
182 ASSET_DISK_F33 = Asset(
183 ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases'
184 '/33/Cloud/aarch64/images/Fedora-Cloud-Base-33-1.2.aarch64.qcow2'),
185 'e7f75cdfd523fe5ac2ca9eeece68edc1a81f386a17f969c1d1c7c87031008a6b')
186
187 F33_FILENAME = '/boot/initramfs-5.8.15-301.fc33.aarch64.img'
188 F33_HSUM = '079cfad0caa82e84c8ca1fb0897a4999dd769f262216099f518619e807a550d9'
189
190 def test_smmu_ril(self):
191 self.common_vm_setup(self.ASSET_KERNEL_F33, self.ASSET_INITRD_F33,
192 self.ASSET_DISK_F33)
193 self.kernel_params = self.default_kernel_params
194 self.run_and_check(self.F33_FILENAME, self.F33_HSUM)
195
196 def test_smmu_ril_passthrough(self):
197 self.common_vm_setup(self.ASSET_KERNEL_F33, self.ASSET_INITRD_F33,
198 self.ASSET_DISK_F33)
199 self.kernel_params = (self.default_kernel_params +
200 ' iommu.passthrough=on')
201 self.run_and_check(self.F33_FILENAME, self.F33_HSUM)
202
203 def test_smmu_ril_nostrict(self):
204 self.common_vm_setup(self.ASSET_KERNEL_F33, self.ASSET_INITRD_F33,
205 self.ASSET_DISK_F33)
206 self.kernel_params = (self.default_kernel_params +
207 ' iommu.strict=0')
208 self.run_and_check(self.F33_FILENAME, self.F33_HSUM)
209
210
211 if __name__ == '__main__':
212 LinuxKernelTest.main()