OSDN Git Service

be949222a4ed806dd8ae188e53ba810d8df4bf0b
[qmiga/qemu.git] / tests / avocado / mem-addr-space-check.py
1 # Check for crash when using memory beyond the available guest processor
2 # address space.
3 #
4 # Copyright (c) 2023 Red Hat, Inc.
5 #
6 # Author:
7 #  Ani Sinha <anisinha@redhat.com>
8 #
9 # SPDX-License-Identifier: GPL-2.0-or-later
10
11 from avocado_qemu import QemuSystemTest
12 import signal
13 import time
14
15 class MemAddrCheck(QemuSystemTest):
16     # after launch, in order to generate the logs from QEMU we need to
17     # wait for some time. Launching and then immediately shutting down
18     # the VM generates empty logs. A delay of 1 second is added for
19     # this reason.
20     DELAY_Q35_BOOT_SEQUENCE = 1
21
22     # first, lets test some 32-bit processors.
23     # for all 32-bit cases, pci64_hole_size is 0.
24     def test_phybits_low_pse36(self):
25         """
26         :avocado: tags=machine:q35
27         :avocado: tags=arch:x86_64
28
29         With pse36 feature ON, a processor has 36 bits of addressing. So it can
30         access up to a maximum of 64GiB of memory. Memory hotplug region begins
31         at 4 GiB boundary when "above_4g_mem_size" is 0 (this would be true when
32         we have 0.5 GiB of VM memory, see pc_q35_init()). This means total
33         hotpluggable memory size is 60 GiB. Per slot, we reserve 1 GiB of memory
34         for dimm alignment for all newer machines (see enforce_aligned_dimm
35         property for pc machines and pc_get_device_memory_range()). That leaves
36         total hotpluggable actual memory size of 59 GiB. If the VM is started
37         with 0.5 GiB of memory, maxmem should be set to a maximum value of
38         59.5 GiB to ensure that the processor can address all memory directly.
39         Note that 64-bit pci hole size is 0 in this case. If maxmem is set to
40         59.6G, QEMU should fail to start with a message "phy-bits are too low".
41         If maxmem is set to 59.5G with all other QEMU parameters identical, QEMU
42         should start fine.
43         """
44         self.vm.add_args('-S', '-machine', 'q35', '-m',
45                          '512,slots=1,maxmem=59.6G',
46                          '-cpu', 'pentium,pse36=on', '-display', 'none',
47                          '-object', 'memory-backend-ram,id=mem1,size=1G',
48                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
49         self.vm.set_qmp_monitor(enabled=False)
50         self.vm.launch()
51         self.vm.wait()
52         self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1")
53         self.assertRegex(self.vm.get_log(), r'phys-bits too low')
54
55     def test_phybits_low_pae(self):
56         """
57         :avocado: tags=machine:q35
58         :avocado: tags=arch:x86_64
59
60         With pae feature ON, a processor has 36 bits of addressing. So it can
61         access up to a maximum of 64GiB of memory. Rest is the same as the case
62         with pse36 above.
63         """
64         self.vm.add_args('-S', '-machine', 'q35', '-m',
65                          '512,slots=1,maxmem=59.6G',
66                          '-cpu', 'pentium,pae=on', '-display', 'none',
67                          '-object', 'memory-backend-ram,id=mem1,size=1G',
68                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
69         self.vm.set_qmp_monitor(enabled=False)
70         self.vm.launch()
71         self.vm.wait()
72         self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1")
73         self.assertRegex(self.vm.get_log(), r'phys-bits too low')
74
75     def test_phybits_ok_pentium_pse36(self):
76         """
77         :avocado: tags=machine:q35
78         :avocado: tags=arch:x86_64
79
80         Setting maxmem to 59.5G and making sure that QEMU can start with the
81         same options as the failing case above with pse36 cpu feature.
82         """
83         self.vm.add_args('-machine', 'q35', '-m',
84                          '512,slots=1,maxmem=59.5G',
85                          '-cpu', 'pentium,pse36=on', '-display', 'none',
86                          '-object', 'memory-backend-ram,id=mem1,size=1G',
87                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
88         self.vm.set_qmp_monitor(enabled=False)
89         self.vm.launch()
90         time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
91         self.vm.shutdown()
92         self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
93
94     def test_phybits_ok_pentium_pae(self):
95         """
96         :avocado: tags=machine:q35
97         :avocado: tags=arch:x86_64
98
99         Test is same as above but now with pae cpu feature turned on.
100         Setting maxmem to 59.5G and making sure that QEMU can start fine
101         with the same options as the case above.
102         """
103         self.vm.add_args('-machine', 'q35', '-m',
104                          '512,slots=1,maxmem=59.5G',
105                          '-cpu', 'pentium,pae=on', '-display', 'none',
106                          '-object', 'memory-backend-ram,id=mem1,size=1G',
107                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
108         self.vm.set_qmp_monitor(enabled=False)
109         self.vm.launch()
110         time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
111         self.vm.shutdown()
112         self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
113
114     def test_phybits_ok_pentium2(self):
115         """
116         :avocado: tags=machine:q35
117         :avocado: tags=arch:x86_64
118
119         Pentium2 has 36 bits of addressing, so its same as pentium
120         with pse36 ON.
121         """
122         self.vm.add_args('-machine', 'q35', '-m',
123                          '512,slots=1,maxmem=59.5G',
124                          '-cpu', 'pentium2', '-display', 'none',
125                          '-object', 'memory-backend-ram,id=mem1,size=1G',
126                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
127         self.vm.set_qmp_monitor(enabled=False)
128         self.vm.launch()
129         time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
130         self.vm.shutdown()
131         self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
132
133     def test_phybits_low_nonpse36(self):
134         """
135         :avocado: tags=machine:q35
136         :avocado: tags=arch:x86_64
137
138         Pentium processor has 32 bits of addressing without pse36 or pae
139         so it can access physical address up to 4 GiB. Setting maxmem to
140         4 GiB should make QEMU fail to start with "phys-bits too low"
141         message because the region for memory hotplug is always placed
142         above 4 GiB due to the PCI hole and simplicity.
143         """
144         self.vm.add_args('-S', '-machine', 'q35', '-m',
145                          '512,slots=1,maxmem=4G',
146                          '-cpu', 'pentium', '-display', 'none',
147                          '-object', 'memory-backend-ram,id=mem1,size=1G',
148                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
149         self.vm.set_qmp_monitor(enabled=False)
150         self.vm.launch()
151         self.vm.wait()
152         self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1")
153         self.assertRegex(self.vm.get_log(), r'phys-bits too low')
154
155     # now lets test some 64-bit CPU cases.
156     def test_phybits_low_tcg_q35_70_amd(self):
157         """
158         :avocado: tags=machine:q35
159         :avocado: tags=arch:x86_64
160
161         For q35 7.1 machines and above, there is a HT window that starts at
162         1024 GiB and ends at 1 TiB - 1. If the max GPA falls in this range,
163         "above_4G" memory is adjusted to start at 1 TiB boundary for AMD cpus
164         in the default case. Lets test without that case for machines 7.0.
165         For q35-7.0 machines, "above 4G" memory starts are 4G.
166         pci64_hole size is 32 GiB. Since TCG_PHYS_ADDR_BITS is defined to
167         be 40, TCG emulated CPUs have maximum of 1 TiB (1024 GiB) of
168         directly addressible memory.
169         Hence, maxmem value at most can be
170         1024 GiB - 4 GiB - 1 GiB per slot for alignment - 32 GiB + 0.5 GiB
171         which is equal to 987.5 GiB. Setting the value to 988 GiB should
172         make QEMU fail with the error message.
173         """
174         self.vm.add_args('-S', '-machine', 'pc-q35-7.0', '-m',
175                          '512,slots=1,maxmem=988G',
176                          '-display', 'none',
177                          '-object', 'memory-backend-ram,id=mem1,size=1G',
178                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
179         self.vm.set_qmp_monitor(enabled=False)
180         self.vm.launch()
181         self.vm.wait()
182         self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1")
183         self.assertRegex(self.vm.get_log(), r'phys-bits too low')
184
185     def test_phybits_low_tcg_q35_71_amd(self):
186         """
187         :avocado: tags=machine:q35
188         :avocado: tags=arch:x86_64
189
190         AMD_HT_START is defined to be at 1012 GiB. So for q35 machines
191         version > 7.0 and AMD cpus, instead of 1024 GiB limit for 40 bit
192         processor address space, it has to be 1012 GiB , that is 12 GiB
193         less than the case above in order to accomodate HT hole.
194         Make sure QEMU fails when maxmem size is 976 GiB (12 GiB less
195         than 988 GiB).
196         """
197         self.vm.add_args('-S', '-machine', 'pc-q35-7.1', '-m',
198                          '512,slots=1,maxmem=976G',
199                          '-display', 'none',
200                          '-object', 'memory-backend-ram,id=mem1,size=1G',
201                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
202         self.vm.set_qmp_monitor(enabled=False)
203         self.vm.launch()
204         self.vm.wait()
205         self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1")
206         self.assertRegex(self.vm.get_log(), r'phys-bits too low')
207
208     def test_phybits_ok_tcg_q35_70_amd(self):
209         """
210         :avocado: tags=machine:q35
211         :avocado: tags=arch:x86_64
212
213         Same as q35-7.0 AMD case except that here we check that QEMU can
214         successfully start when maxmem is < 988G.
215         """
216         self.vm.add_args('-S', '-machine', 'pc-q35-7.0', '-m',
217                          '512,slots=1,maxmem=987.5G',
218                          '-display', 'none',
219                          '-object', 'memory-backend-ram,id=mem1,size=1G',
220                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
221         self.vm.set_qmp_monitor(enabled=False)
222         self.vm.launch()
223         time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
224         self.vm.shutdown()
225         self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
226
227     def test_phybits_ok_tcg_q35_71_amd(self):
228         """
229         :avocado: tags=machine:q35
230         :avocado: tags=arch:x86_64
231
232         Same as q35-7.1 AMD case except that here we check that QEMU can
233         successfully start when maxmem is < 976G.
234         """
235         self.vm.add_args('-S', '-machine', 'pc-q35-7.1', '-m',
236                          '512,slots=1,maxmem=975.5G',
237                          '-display', 'none',
238                          '-object', 'memory-backend-ram,id=mem1,size=1G',
239                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
240         self.vm.set_qmp_monitor(enabled=False)
241         self.vm.launch()
242         time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
243         self.vm.shutdown()
244         self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
245
246     def test_phybits_ok_tcg_q35_71_intel(self):
247         """
248         :avocado: tags=machine:q35
249         :avocado: tags=arch:x86_64
250
251         Same parameters as test_phybits_low_tcg_q35_71_amd() but use
252         Intel cpu instead. QEMU should start fine in this case as
253         "above_4G" memory starts at 4G.
254         """
255         self.vm.add_args('-S', '-cpu', 'Skylake-Server',
256                          '-machine', 'pc-q35-7.1', '-m',
257                          '512,slots=1,maxmem=976G',
258                          '-display', 'none',
259                          '-object', 'memory-backend-ram,id=mem1,size=1G',
260                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
261         self.vm.set_qmp_monitor(enabled=False)
262         self.vm.launch()
263         time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
264         self.vm.shutdown()
265         self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
266
267     def test_phybits_low_tcg_q35_71_amd_41bits(self):
268         """
269         :avocado: tags=machine:q35
270         :avocado: tags=arch:x86_64
271
272         AMD processor with 41 bits. Max cpu hw address = 2 TiB.
273         By setting maxram above 1012 GiB  - 32 GiB - 4 GiB = 976 GiB, we can
274         force "above_4G" memory to start at 1 TiB for q35-7.1 machines
275         (max GPA will be above AMD_HT_START which is defined as 1012 GiB).
276
277         With pci_64_hole size at 32 GiB, in this case, maxmem should be 991.5
278         GiB with 1 GiB per slot for alignment and 0.5 GiB as non-hotplug
279         memory for the VM (1024 - 32 - 1 + 0.5). With 992 GiB, QEMU should
280         fail to start.
281         """
282         self.vm.add_args('-S', '-cpu', 'EPYC-v4,phys-bits=41',
283                          '-machine', 'pc-q35-7.1', '-m',
284                          '512,slots=1,maxmem=992G',
285                          '-display', 'none',
286                          '-object', 'memory-backend-ram,id=mem1,size=1G',
287                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
288         self.vm.set_qmp_monitor(enabled=False)
289         self.vm.launch()
290         self.vm.wait()
291         self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1")
292         self.assertRegex(self.vm.get_log(), r'phys-bits too low')
293
294     def test_phybits_ok_tcg_q35_71_amd_41bits(self):
295         """
296         :avocado: tags=machine:q35
297         :avocado: tags=arch:x86_64
298
299         AMD processor with 41 bits. Max cpu hw address = 2 TiB.
300         Same as above but by setting maxram beween 976 GiB and 992 Gib,
301         QEMU should start fine.
302         """
303         self.vm.add_args('-S', '-cpu', 'EPYC-v4,phys-bits=41',
304                          '-machine', 'pc-q35-7.1', '-m',
305                          '512,slots=1,maxmem=990G',
306                          '-display', 'none',
307                          '-object', 'memory-backend-ram,id=mem1,size=1G',
308                          '-device', 'pc-dimm,id=vm0,memdev=mem1')
309         self.vm.set_qmp_monitor(enabled=False)
310         self.vm.launch()
311         time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
312         self.vm.shutdown()
313         self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')
314
315     def test_phybits_low_tcg_q35_intel_cxl(self):
316         """
317         :avocado: tags=machine:q35
318         :avocado: tags=arch:x86_64
319
320         cxl memory window starts after memory device range. Here, we use 1 GiB
321         of cxl window memory. 4G_mem end aligns at 4G. pci64_hole is 32 GiB and
322         starts after the cxl memory window.
323         So maxmem here should be at most 986 GiB considering all memory boundary
324         alignment constraints with 40 bits (1 TiB) of processor physical bits.
325         """
326         self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40',
327                          '-machine', 'q35,cxl=on', '-m',
328                          '512,slots=1,maxmem=987G',
329                          '-display', 'none',
330                          '-device', 'pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1',
331                          '-M', 'cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=1G')
332         self.vm.set_qmp_monitor(enabled=False)
333         self.vm.launch()
334         self.vm.wait()
335         self.assertEquals(self.vm.exitcode(), 1, "QEMU exit code should be 1")
336         self.assertRegex(self.vm.get_log(), r'phys-bits too low')
337
338     def test_phybits_ok_tcg_q35_intel_cxl(self):
339         """
340         :avocado: tags=machine:q35
341         :avocado: tags=arch:x86_64
342
343         Same as above but here we do not reserve any cxl memory window. Hence,
344         with the exact same parameters as above, QEMU should start fine even
345         with cxl enabled.
346         """
347         self.vm.add_args('-S', '-cpu', 'Skylake-Server,phys-bits=40',
348                          '-machine', 'q35,cxl=on', '-m',
349                          '512,slots=1,maxmem=987G',
350                          '-display', 'none',
351                          '-device', 'pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1')
352         self.vm.set_qmp_monitor(enabled=False)
353         self.vm.launch()
354         time.sleep(self.DELAY_Q35_BOOT_SEQUENCE)
355         self.vm.shutdown()
356         self.assertNotRegex(self.vm.get_log(), r'phys-bits too low')