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