]>
Commit | Line | Data |
---|---|---|
2d9ca5a3 CH |
1 | # Functional test that boots an s390x Linux guest with ccw and PCI devices |
2 | # attached and checks whether the devices are recognized by Linux | |
3 | # | |
4 | # Copyright (c) 2020 Red Hat, Inc. | |
5 | # | |
6 | # Author: | |
7 | # Cornelia Huck <cohuck@redhat.com> | |
8 | # | |
9 | # This work is licensed under the terms of the GNU GPL, version 2 or | |
10 | # later. See the COPYING file in the top-level directory. | |
11 | ||
24bfaae1 TH |
12 | import os |
13 | import tempfile | |
2d9ca5a3 CH |
14 | |
15 | from avocado_qemu import Test | |
16 | from avocado_qemu import exec_command_and_wait_for_pattern | |
17 | from avocado_qemu import wait_for_console_pattern | |
24bfaae1 | 18 | from avocado.utils import archive |
2d9ca5a3 CH |
19 | |
20 | class S390CCWVirtioMachine(Test): | |
21 | KERNEL_COMMON_COMMAND_LINE = 'printk.time=0 ' | |
22 | ||
09d4455e TH |
23 | timeout = 120 |
24 | ||
2d9ca5a3 CH |
25 | def wait_for_console_pattern(self, success_message, vm=None): |
26 | wait_for_console_pattern(self, success_message, | |
27 | failure_message='Kernel panic - not syncing', | |
28 | vm=vm) | |
29 | ||
09d4455e TH |
30 | def wait_for_crw_reports(self): |
31 | exec_command_and_wait_for_pattern(self, | |
32 | 'while ! (dmesg -c | grep CRW) ; do sleep 1 ; done', | |
33 | 'CRW reports') | |
34 | ||
35 | dmesg_clear_count = 1 | |
36 | def clear_guest_dmesg(self): | |
37 | exec_command_and_wait_for_pattern(self, 'dmesg -c > /dev/null; ' | |
38 | 'echo dm_clear\ ' + str(self.dmesg_clear_count), | |
39 | 'dm_clear ' + str(self.dmesg_clear_count)) | |
40 | self.dmesg_clear_count += 1 | |
2d9ca5a3 CH |
41 | |
42 | def test_s390x_devices(self): | |
43 | ||
44 | """ | |
45 | :avocado: tags=arch:s390x | |
46 | :avocado: tags=machine:s390-ccw-virtio | |
47 | """ | |
48 | ||
49 | kernel_url = ('https://snapshot.debian.org/archive/debian/' | |
50 | '20201126T092837Z/dists/buster/main/installer-s390x/' | |
51 | '20190702+deb10u6/images/generic/kernel.debian') | |
52 | kernel_hash = '5821fbee57d6220a067a8b967d24595621aa1eb6' | |
53 | kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) | |
54 | ||
55 | initrd_url = ('https://snapshot.debian.org/archive/debian/' | |
56 | '20201126T092837Z/dists/buster/main/installer-s390x/' | |
57 | '20190702+deb10u6/images/generic/initrd.debian') | |
58 | initrd_hash = '81ba09c97bef46e8f4660ac25b4ac0a5be3a94d6' | |
59 | initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) | |
60 | ||
61 | self.vm.set_console() | |
62 | kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + | |
63 | 'console=sclp0 root=/dev/ram0 BOOT_DEBUG=3') | |
64 | self.vm.add_args('-nographic', | |
65 | '-kernel', kernel_path, | |
66 | '-initrd', initrd_path, | |
67 | '-append', kernel_command_line, | |
68 | '-device', 'virtio-net-ccw,devno=fe.1.1111', | |
083470b5 | 69 | '-device', |
7e549424 | 70 | 'virtio-rng-ccw,devno=fe.2.0000,max_revision=0,id=rn1', |
083470b5 | 71 | '-device', |
7e549424 | 72 | 'virtio-rng-ccw,devno=fe.3.1234,max_revision=2,id=rn2', |
2d9ca5a3 | 73 | '-device', 'zpci,uid=5,target=zzz', |
085cec59 CH |
74 | '-device', 'virtio-net-pci,id=zzz', |
75 | '-device', 'zpci,uid=0xa,fid=12,target=serial', | |
d986bc4a TH |
76 | '-device', 'virtio-serial-pci,id=serial', |
77 | '-device', 'virtio-balloon-ccw') | |
2d9ca5a3 CH |
78 | self.vm.launch() |
79 | ||
80 | shell_ready = "sh: can't access tty; job control turned off" | |
81 | self.wait_for_console_pattern(shell_ready) | |
82 | # first debug shell is too early, we need to wait for device detection | |
83 | exec_command_and_wait_for_pattern(self, 'exit', shell_ready) | |
84 | ||
083470b5 | 85 | ccw_bus_ids="0.1.1111 0.2.0000 0.3.1234" |
085cec59 | 86 | pci_bus_ids="0005:00:00.0 000a:00:00.0" |
2d9ca5a3 | 87 | exec_command_and_wait_for_pattern(self, 'ls /sys/bus/ccw/devices/', |
083470b5 | 88 | ccw_bus_ids) |
2d9ca5a3 | 89 | exec_command_and_wait_for_pattern(self, 'ls /sys/bus/pci/devices/', |
085cec59 | 90 | pci_bus_ids) |
083470b5 CH |
91 | # check that the device at 0.2.0000 is in legacy mode, while the |
92 | # device at 0.3.1234 has the virtio-1 feature bit set | |
93 | virtio_rng_features="00000000000000000000000000001100" + \ | |
94 | "10000000000000000000000000000000" | |
95 | virtio_rng_features_legacy="00000000000000000000000000001100" + \ | |
96 | "00000000000000000000000000000000" | |
97 | exec_command_and_wait_for_pattern(self, | |
98 | 'cat /sys/bus/ccw/devices/0.2.0000/virtio?/features', | |
99 | virtio_rng_features_legacy) | |
100 | exec_command_and_wait_for_pattern(self, | |
101 | 'cat /sys/bus/ccw/devices/0.3.1234/virtio?/features', | |
102 | virtio_rng_features) | |
7e549424 TH |
103 | # check that /dev/hwrng works - and that it's gone after ejecting |
104 | exec_command_and_wait_for_pattern(self, | |
105 | 'dd if=/dev/hwrng of=/dev/null bs=1k count=10', | |
106 | '10+0 records out') | |
107 | self.clear_guest_dmesg() | |
108 | self.vm.command('device_del', id='rn1') | |
109 | self.wait_for_crw_reports() | |
110 | self.clear_guest_dmesg() | |
111 | self.vm.command('device_del', id='rn2') | |
112 | self.wait_for_crw_reports() | |
113 | exec_command_and_wait_for_pattern(self, | |
114 | 'dd if=/dev/hwrng of=/dev/null bs=1k count=10', | |
115 | 'dd: /dev/hwrng: No such device') | |
864852cc CH |
116 | # verify that we indeed have virtio-net devices (without having the |
117 | # virtio-net driver handy) | |
118 | exec_command_and_wait_for_pattern(self, | |
119 | 'cat /sys/bus/ccw/devices/0.1.1111/cutype', | |
120 | '3832/01') | |
121 | exec_command_and_wait_for_pattern(self, | |
122 | 'cat /sys/bus/pci/devices/0005\:00\:00.0/subsystem_vendor', | |
123 | '0x1af4') | |
124 | exec_command_and_wait_for_pattern(self, | |
125 | 'cat /sys/bus/pci/devices/0005\:00\:00.0/subsystem_device', | |
126 | '0x0001') | |
085cec59 CH |
127 | # check fid propagation |
128 | exec_command_and_wait_for_pattern(self, | |
129 | 'cat /sys/bus/pci/devices/000a\:00\:00.0/function_id', | |
130 | '0x0000000c') | |
44637c4b | 131 | # add another device |
09d4455e | 132 | self.clear_guest_dmesg() |
44637c4b CH |
133 | self.vm.command('device_add', driver='virtio-net-ccw', |
134 | devno='fe.0.4711', id='net_4711') | |
09d4455e | 135 | self.wait_for_crw_reports() |
44637c4b CH |
136 | exec_command_and_wait_for_pattern(self, 'ls /sys/bus/ccw/devices/', |
137 | '0.0.4711') | |
138 | # and detach it again | |
09d4455e | 139 | self.clear_guest_dmesg() |
44637c4b CH |
140 | self.vm.command('device_del', id='net_4711') |
141 | self.vm.event_wait(name='DEVICE_DELETED', | |
142 | match={'data': {'device': 'net_4711'}}) | |
09d4455e | 143 | self.wait_for_crw_reports() |
44637c4b CH |
144 | exec_command_and_wait_for_pattern(self, |
145 | 'ls /sys/bus/ccw/devices/0.0.4711', | |
146 | 'No such file or directory') | |
d986bc4a TH |
147 | # test the virtio-balloon device |
148 | exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', | |
149 | 'MemTotal: 115640 kB') | |
150 | self.vm.command('human-monitor-command', command_line='balloon 96') | |
151 | exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', | |
152 | 'MemTotal: 82872 kB') | |
153 | self.vm.command('human-monitor-command', command_line='balloon 128') | |
154 | exec_command_and_wait_for_pattern(self, 'head -n 1 /proc/meminfo', | |
155 | 'MemTotal: 115640 kB') | |
24bfaae1 TH |
156 | |
157 | ||
158 | def test_s390x_fedora(self): | |
159 | ||
160 | """ | |
161 | :avocado: tags=arch:s390x | |
162 | :avocado: tags=machine:s390-ccw-virtio | |
163 | :avocado: tags=device:virtio-gpu | |
164 | :avocado: tags=device:virtio-crypto | |
165 | :avocado: tags=device:virtio-net | |
166 | """ | |
167 | ||
168 | kernel_url = ('https://archives.fedoraproject.org/pub/archive' | |
169 | '/fedora-secondary/releases/31/Server/s390x/os' | |
170 | '/images/kernel.img') | |
171 | kernel_hash = 'b93d1efcafcf29c1673a4ce371a1f8b43941cfeb' | |
172 | kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) | |
173 | ||
174 | initrd_url = ('https://archives.fedoraproject.org/pub/archive' | |
175 | '/fedora-secondary/releases/31/Server/s390x/os' | |
176 | '/images/initrd.img') | |
177 | initrd_hash = '3de45d411df5624b8d8ef21cd0b44419ab59b12f' | |
178 | initrd_path_xz = self.fetch_asset(initrd_url, asset_hash=initrd_hash) | |
179 | initrd_path = os.path.join(self.workdir, 'initrd-raw.img') | |
180 | archive.lzma_uncompress(initrd_path_xz, initrd_path) | |
181 | ||
182 | self.vm.set_console() | |
183 | kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE + ' audit=0 ' | |
184 | 'rd.plymouth=0 plymouth.enable=0 rd.rescue') | |
185 | self.vm.add_args('-nographic', | |
186 | '-smp', '4', | |
187 | '-m', '512', | |
188 | '-name', 'Some Guest Name', | |
189 | '-uuid', '30de4fd9-b4d5-409e-86a5-09b387f70bfa', | |
190 | '-kernel', kernel_path, | |
191 | '-initrd', initrd_path, | |
192 | '-append', kernel_command_line, | |
193 | '-device', 'zpci,uid=7,target=n', | |
194 | '-device', 'virtio-net-pci,id=n,mac=02:ca:fe:fa:ce:12', | |
195 | '-device', 'virtio-rng-ccw,devno=fe.1.9876', | |
196 | '-device', 'virtio-gpu-ccw,devno=fe.2.5432') | |
197 | self.vm.launch() | |
198 | self.wait_for_console_pattern('Entering emergency mode') | |
199 | ||
200 | # Some tests to see whether the CLI options have been considered: | |
201 | self.log.info("Test whether QEMU CLI options have been considered") | |
202 | exec_command_and_wait_for_pattern(self, 'lspci', | |
203 | '0007:00:00.0 Class 0200: Device 1af4:1000') | |
204 | exec_command_and_wait_for_pattern(self, | |
205 | 'cat /sys/class/net/enP7p0s0/address', | |
206 | '02:ca:fe:fa:ce:12') | |
207 | exec_command_and_wait_for_pattern(self, 'lscss', '0.1.9876') | |
208 | exec_command_and_wait_for_pattern(self, 'lscss', '0.2.5432') | |
209 | exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', | |
210 | 'processors : 4') | |
211 | exec_command_and_wait_for_pattern(self, 'grep MemTotal /proc/meminfo', | |
212 | 'MemTotal: 499848 kB') | |
213 | exec_command_and_wait_for_pattern(self, 'grep Name /proc/sysinfo', | |
214 | 'Extended Name: Some Guest Name') | |
215 | exec_command_and_wait_for_pattern(self, 'grep UUID /proc/sysinfo', | |
216 | '30de4fd9-b4d5-409e-86a5-09b387f70bfa') | |
217 | ||
218 | # Disable blinking cursor, then write some stuff into the framebuffer. | |
219 | # QEMU's PPM screendumps contain uncompressed 24-bit values, while the | |
220 | # framebuffer uses 32-bit, so we pad our text with some spaces when | |
221 | # writing to the framebuffer. Since the PPM is uncompressed, we then | |
222 | # can simply read the written "magic bytes" back from the PPM file to | |
223 | # check whether the framebuffer is working as expected. | |
224 | self.log.info("Test screendump of virtio-gpu device") | |
225 | exec_command_and_wait_for_pattern(self, | |
226 | 'echo -e "\e[?25l" > /dev/tty0', ':/#') | |
227 | exec_command_and_wait_for_pattern(self, 'for ((i=0;i<250;i++)); do ' | |
228 | 'echo " The qu ick fo x j ump s o ver a laz y d og" >> fox.txt;' | |
229 | 'done', | |
230 | ':/#') | |
231 | exec_command_and_wait_for_pattern(self, | |
232 | 'dd if=fox.txt of=/dev/fb0 bs=1000 oflag=sync,nocache ; rm fox.txt', | |
233 | '12+0 records out') | |
234 | with tempfile.NamedTemporaryFile(suffix='.ppm', | |
235 | prefix='qemu-scrdump-') as ppmfile: | |
236 | self.vm.command('screendump', filename=ppmfile.name) | |
237 | ppmfile.seek(0) | |
238 | line = ppmfile.readline() | |
239 | self.assertEqual(line, b"P6\n") | |
240 | line = ppmfile.readline() | |
241 | self.assertEqual(line, b"1024 768\n") | |
242 | line = ppmfile.readline() | |
243 | self.assertEqual(line, b"255\n") | |
244 | line = ppmfile.readline() | |
245 | self.assertEqual(line, b"The quick fox jumps over a lazy dog\n") | |
246 | ||
247 | # Hot-plug a virtio-crypto device and see whether it gets accepted | |
248 | self.log.info("Test hot-plug virtio-crypto device") | |
249 | self.clear_guest_dmesg() | |
250 | self.vm.command('object-add', qom_type='cryptodev-backend-builtin', | |
251 | id='cbe0') | |
252 | self.vm.command('device_add', driver='virtio-crypto-ccw', id='crypdev0', | |
253 | cryptodev='cbe0', devno='fe.0.2342') | |
254 | exec_command_and_wait_for_pattern(self, | |
255 | 'while ! (dmesg -c | grep Accelerator.device) ; do' | |
256 | ' sleep 1 ; done', 'Accelerator device is ready') | |
257 | exec_command_and_wait_for_pattern(self, 'lscss', '0.0.2342') | |
258 | self.vm.command('device_del', id='crypdev0') | |
259 | self.vm.command('object-del', id='cbe0') | |
260 | exec_command_and_wait_for_pattern(self, | |
261 | 'while ! (dmesg -c | grep Start.virtcrypto_remove) ; do' | |
262 | ' sleep 1 ; done', 'Start virtcrypto_remove.') |