1*e2e9fd25SThomas Huth#!/usr/bin/env python3 2*e2e9fd25SThomas Huth# 3*e2e9fd25SThomas Huth# Functional test that boots a Linux kernel and checks the console 4*e2e9fd25SThomas Huth# 5*e2e9fd25SThomas Huth# Copyright IBM Corp. 2023 6*e2e9fd25SThomas Huth# 7*e2e9fd25SThomas Huth# Author: 8*e2e9fd25SThomas Huth# Pierre Morel <pmorel@linux.ibm.com> 9*e2e9fd25SThomas Huth# 10*e2e9fd25SThomas Huth# This work is licensed under the terms of the GNU GPL, version 2 or 11*e2e9fd25SThomas Huth# later. See the COPYING file in the top-level directory. 12*e2e9fd25SThomas Huth 13*e2e9fd25SThomas Huthimport os 14*e2e9fd25SThomas Huthimport time 15*e2e9fd25SThomas Huth 16*e2e9fd25SThomas Huthfrom qemu_test import QemuSystemTest, Asset 17*e2e9fd25SThomas Huthfrom qemu_test import exec_command 18*e2e9fd25SThomas Huthfrom qemu_test import exec_command_and_wait_for_pattern 19*e2e9fd25SThomas Huthfrom qemu_test import wait_for_console_pattern 20*e2e9fd25SThomas Huthfrom qemu_test.utils import lzma_uncompress 21*e2e9fd25SThomas Huth 22*e2e9fd25SThomas Huth 23*e2e9fd25SThomas Huthclass S390CPUTopology(QemuSystemTest): 24*e2e9fd25SThomas Huth """ 25*e2e9fd25SThomas Huth S390x CPU topology consists of 4 topology layers, from bottom to top, 26*e2e9fd25SThomas Huth the cores, sockets, books and drawers and 2 modifiers attributes, 27*e2e9fd25SThomas Huth the entitlement and the dedication. 28*e2e9fd25SThomas Huth See: docs/system/s390x/cpu-topology.rst. 29*e2e9fd25SThomas Huth 30*e2e9fd25SThomas Huth S390x CPU topology is setup in different ways: 31*e2e9fd25SThomas Huth - implicitly from the '-smp' argument by completing each topology 32*e2e9fd25SThomas Huth level one after the other beginning with drawer 0, book 0 and 33*e2e9fd25SThomas Huth socket 0. 34*e2e9fd25SThomas Huth - explicitly from the '-device' argument on the QEMU command line 35*e2e9fd25SThomas Huth - explicitly by hotplug of a new CPU using QMP or HMP 36*e2e9fd25SThomas Huth - it is modified by using QMP 'set-cpu-topology' 37*e2e9fd25SThomas Huth 38*e2e9fd25SThomas Huth The S390x modifier attribute entitlement depends on the machine 39*e2e9fd25SThomas Huth polarization, which can be horizontal or vertical. 40*e2e9fd25SThomas Huth The polarization is changed on a request from the guest. 41*e2e9fd25SThomas Huth """ 42*e2e9fd25SThomas Huth timeout = 90 43*e2e9fd25SThomas Huth event_timeout = 10 44*e2e9fd25SThomas Huth 45*e2e9fd25SThomas Huth KERNEL_COMMON_COMMAND_LINE = ('printk.time=0 ' 46*e2e9fd25SThomas Huth 'root=/dev/ram ' 47*e2e9fd25SThomas Huth 'selinux=0 ' 48*e2e9fd25SThomas Huth 'rdinit=/bin/sh') 49*e2e9fd25SThomas Huth ASSET_F35_KERNEL = Asset( 50*e2e9fd25SThomas Huth ('https://archives.fedoraproject.org/pub/archive' 51*e2e9fd25SThomas Huth '/fedora-secondary/releases/35/Server/s390x/os' 52*e2e9fd25SThomas Huth '/images/kernel.img'), 53*e2e9fd25SThomas Huth '1f2dddfd11bb1393dd2eb2e784036fbf6fc11057a6d7d27f9eb12d3edc67ef73') 54*e2e9fd25SThomas Huth 55*e2e9fd25SThomas Huth ASSET_F35_INITRD = Asset( 56*e2e9fd25SThomas Huth ('https://archives.fedoraproject.org/pub/archive' 57*e2e9fd25SThomas Huth '/fedora-secondary/releases/35/Server/s390x/os' 58*e2e9fd25SThomas Huth '/images/initrd.img'), 59*e2e9fd25SThomas Huth '1100145fbca00240c8c372ae4b89b48c99844bc189b3dfbc3f481dc60055ca46') 60*e2e9fd25SThomas Huth 61*e2e9fd25SThomas Huth def wait_until_booted(self): 62*e2e9fd25SThomas Huth wait_for_console_pattern(self, 'no job control', 63*e2e9fd25SThomas Huth failure_message='Kernel panic - not syncing', 64*e2e9fd25SThomas Huth vm=None) 65*e2e9fd25SThomas Huth 66*e2e9fd25SThomas Huth def check_topology(self, c, s, b, d, e, t): 67*e2e9fd25SThomas Huth res = self.vm.qmp('query-cpus-fast') 68*e2e9fd25SThomas Huth cpus = res['return'] 69*e2e9fd25SThomas Huth for cpu in cpus: 70*e2e9fd25SThomas Huth core = cpu['props']['core-id'] 71*e2e9fd25SThomas Huth socket = cpu['props']['socket-id'] 72*e2e9fd25SThomas Huth book = cpu['props']['book-id'] 73*e2e9fd25SThomas Huth drawer = cpu['props']['drawer-id'] 74*e2e9fd25SThomas Huth entitlement = cpu.get('entitlement') 75*e2e9fd25SThomas Huth dedicated = cpu.get('dedicated') 76*e2e9fd25SThomas Huth if core == c: 77*e2e9fd25SThomas Huth self.assertEqual(drawer, d) 78*e2e9fd25SThomas Huth self.assertEqual(book, b) 79*e2e9fd25SThomas Huth self.assertEqual(socket, s) 80*e2e9fd25SThomas Huth self.assertEqual(entitlement, e) 81*e2e9fd25SThomas Huth self.assertEqual(dedicated, t) 82*e2e9fd25SThomas Huth 83*e2e9fd25SThomas Huth def kernel_init(self): 84*e2e9fd25SThomas Huth """ 85*e2e9fd25SThomas Huth We need a VM that supports CPU topology, 86*e2e9fd25SThomas Huth currently this only the case when using KVM, not TCG. 87*e2e9fd25SThomas Huth We need a kernel supporting the CPU topology. 88*e2e9fd25SThomas Huth We need a minimal root filesystem with a shell. 89*e2e9fd25SThomas Huth """ 90*e2e9fd25SThomas Huth self.require_accelerator("kvm") 91*e2e9fd25SThomas Huth kernel_path = self.ASSET_F35_KERNEL.fetch() 92*e2e9fd25SThomas Huth initrd_path_xz = self.ASSET_F35_INITRD.fetch() 93*e2e9fd25SThomas Huth initrd_path = os.path.join(self.workdir, 'initrd-raw.img') 94*e2e9fd25SThomas Huth lzma_uncompress(initrd_path_xz, initrd_path) 95*e2e9fd25SThomas Huth 96*e2e9fd25SThomas Huth self.vm.set_console() 97*e2e9fd25SThomas Huth kernel_command_line = self.KERNEL_COMMON_COMMAND_LINE 98*e2e9fd25SThomas Huth self.vm.add_args('-nographic', 99*e2e9fd25SThomas Huth '-enable-kvm', 100*e2e9fd25SThomas Huth '-cpu', 'max,ctop=on', 101*e2e9fd25SThomas Huth '-m', '512', 102*e2e9fd25SThomas Huth '-kernel', kernel_path, 103*e2e9fd25SThomas Huth '-initrd', initrd_path, 104*e2e9fd25SThomas Huth '-append', kernel_command_line) 105*e2e9fd25SThomas Huth 106*e2e9fd25SThomas Huth def system_init(self): 107*e2e9fd25SThomas Huth self.log.info("System init") 108*e2e9fd25SThomas Huth exec_command_and_wait_for_pattern(self, 109*e2e9fd25SThomas Huth """ mount proc -t proc /proc; 110*e2e9fd25SThomas Huth mount sys -t sysfs /sys; 111*e2e9fd25SThomas Huth cat /sys/devices/system/cpu/dispatching """, 112*e2e9fd25SThomas Huth '0') 113*e2e9fd25SThomas Huth 114*e2e9fd25SThomas Huth def test_single(self): 115*e2e9fd25SThomas Huth """ 116*e2e9fd25SThomas Huth This test checks the simplest topology with a single CPU. 117*e2e9fd25SThomas Huth """ 118*e2e9fd25SThomas Huth self.set_machine('s390-ccw-virtio') 119*e2e9fd25SThomas Huth self.kernel_init() 120*e2e9fd25SThomas Huth self.vm.launch() 121*e2e9fd25SThomas Huth self.wait_until_booted() 122*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'medium', False) 123*e2e9fd25SThomas Huth 124*e2e9fd25SThomas Huth def test_default(self): 125*e2e9fd25SThomas Huth """ 126*e2e9fd25SThomas Huth This test checks the implicit topology. 127*e2e9fd25SThomas Huth """ 128*e2e9fd25SThomas Huth self.set_machine('s390-ccw-virtio') 129*e2e9fd25SThomas Huth self.kernel_init() 130*e2e9fd25SThomas Huth self.vm.add_args('-smp', 131*e2e9fd25SThomas Huth '13,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') 132*e2e9fd25SThomas Huth self.vm.launch() 133*e2e9fd25SThomas Huth self.wait_until_booted() 134*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'medium', False) 135*e2e9fd25SThomas Huth self.check_topology(1, 0, 0, 0, 'medium', False) 136*e2e9fd25SThomas Huth self.check_topology(2, 1, 0, 0, 'medium', False) 137*e2e9fd25SThomas Huth self.check_topology(3, 1, 0, 0, 'medium', False) 138*e2e9fd25SThomas Huth self.check_topology(4, 2, 0, 0, 'medium', False) 139*e2e9fd25SThomas Huth self.check_topology(5, 2, 0, 0, 'medium', False) 140*e2e9fd25SThomas Huth self.check_topology(6, 0, 1, 0, 'medium', False) 141*e2e9fd25SThomas Huth self.check_topology(7, 0, 1, 0, 'medium', False) 142*e2e9fd25SThomas Huth self.check_topology(8, 1, 1, 0, 'medium', False) 143*e2e9fd25SThomas Huth self.check_topology(9, 1, 1, 0, 'medium', False) 144*e2e9fd25SThomas Huth self.check_topology(10, 2, 1, 0, 'medium', False) 145*e2e9fd25SThomas Huth self.check_topology(11, 2, 1, 0, 'medium', False) 146*e2e9fd25SThomas Huth self.check_topology(12, 0, 0, 1, 'medium', False) 147*e2e9fd25SThomas Huth 148*e2e9fd25SThomas Huth def test_move(self): 149*e2e9fd25SThomas Huth """ 150*e2e9fd25SThomas Huth This test checks the topology modification by moving a CPU 151*e2e9fd25SThomas Huth to another socket: CPU 0 is moved from socket 0 to socket 2. 152*e2e9fd25SThomas Huth """ 153*e2e9fd25SThomas Huth self.set_machine('s390-ccw-virtio') 154*e2e9fd25SThomas Huth self.kernel_init() 155*e2e9fd25SThomas Huth self.vm.add_args('-smp', 156*e2e9fd25SThomas Huth '1,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') 157*e2e9fd25SThomas Huth self.vm.launch() 158*e2e9fd25SThomas Huth self.wait_until_booted() 159*e2e9fd25SThomas Huth 160*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'medium', False) 161*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 162*e2e9fd25SThomas Huth {'core-id': 0, 'socket-id': 2, 'entitlement': 'low'}) 163*e2e9fd25SThomas Huth self.assertEqual(res['return'], {}) 164*e2e9fd25SThomas Huth self.check_topology(0, 2, 0, 0, 'low', False) 165*e2e9fd25SThomas Huth 166*e2e9fd25SThomas Huth def test_dash_device(self): 167*e2e9fd25SThomas Huth """ 168*e2e9fd25SThomas Huth This test verifies that a CPU defined with the '-device' 169*e2e9fd25SThomas Huth command line option finds its right place inside the topology. 170*e2e9fd25SThomas Huth """ 171*e2e9fd25SThomas Huth self.set_machine('s390-ccw-virtio') 172*e2e9fd25SThomas Huth self.kernel_init() 173*e2e9fd25SThomas Huth self.vm.add_args('-smp', 174*e2e9fd25SThomas Huth '1,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') 175*e2e9fd25SThomas Huth self.vm.add_args('-device', 'max-s390x-cpu,core-id=10') 176*e2e9fd25SThomas Huth self.vm.add_args('-device', 177*e2e9fd25SThomas Huth 'max-s390x-cpu,' 178*e2e9fd25SThomas Huth 'core-id=1,socket-id=0,book-id=1,drawer-id=1,entitlement=low') 179*e2e9fd25SThomas Huth self.vm.add_args('-device', 180*e2e9fd25SThomas Huth 'max-s390x-cpu,' 181*e2e9fd25SThomas Huth 'core-id=2,socket-id=0,book-id=1,drawer-id=1,entitlement=medium') 182*e2e9fd25SThomas Huth self.vm.add_args('-device', 183*e2e9fd25SThomas Huth 'max-s390x-cpu,' 184*e2e9fd25SThomas Huth 'core-id=3,socket-id=1,book-id=1,drawer-id=1,entitlement=high') 185*e2e9fd25SThomas Huth self.vm.add_args('-device', 186*e2e9fd25SThomas Huth 'max-s390x-cpu,' 187*e2e9fd25SThomas Huth 'core-id=4,socket-id=1,book-id=1,drawer-id=1') 188*e2e9fd25SThomas Huth self.vm.add_args('-device', 189*e2e9fd25SThomas Huth 'max-s390x-cpu,' 190*e2e9fd25SThomas Huth 'core-id=5,socket-id=2,book-id=1,drawer-id=1,dedicated=true') 191*e2e9fd25SThomas Huth 192*e2e9fd25SThomas Huth self.vm.launch() 193*e2e9fd25SThomas Huth self.wait_until_booted() 194*e2e9fd25SThomas Huth 195*e2e9fd25SThomas Huth self.check_topology(10, 2, 1, 0, 'medium', False) 196*e2e9fd25SThomas Huth self.check_topology(1, 0, 1, 1, 'low', False) 197*e2e9fd25SThomas Huth self.check_topology(2, 0, 1, 1, 'medium', False) 198*e2e9fd25SThomas Huth self.check_topology(3, 1, 1, 1, 'high', False) 199*e2e9fd25SThomas Huth self.check_topology(4, 1, 1, 1, 'medium', False) 200*e2e9fd25SThomas Huth self.check_topology(5, 2, 1, 1, 'high', True) 201*e2e9fd25SThomas Huth 202*e2e9fd25SThomas Huth 203*e2e9fd25SThomas Huth def guest_set_dispatching(self, dispatching): 204*e2e9fd25SThomas Huth exec_command(self, 205*e2e9fd25SThomas Huth f'echo {dispatching} > /sys/devices/system/cpu/dispatching') 206*e2e9fd25SThomas Huth self.vm.event_wait('CPU_POLARIZATION_CHANGE', self.event_timeout) 207*e2e9fd25SThomas Huth exec_command_and_wait_for_pattern(self, 208*e2e9fd25SThomas Huth 'cat /sys/devices/system/cpu/dispatching', dispatching) 209*e2e9fd25SThomas Huth 210*e2e9fd25SThomas Huth 211*e2e9fd25SThomas Huth def test_polarization(self): 212*e2e9fd25SThomas Huth """ 213*e2e9fd25SThomas Huth This test verifies that QEMU modifies the entitlement change after 214*e2e9fd25SThomas Huth several guest polarization change requests. 215*e2e9fd25SThomas Huth """ 216*e2e9fd25SThomas Huth self.set_machine('s390-ccw-virtio') 217*e2e9fd25SThomas Huth self.kernel_init() 218*e2e9fd25SThomas Huth self.vm.launch() 219*e2e9fd25SThomas Huth self.wait_until_booted() 220*e2e9fd25SThomas Huth 221*e2e9fd25SThomas Huth self.system_init() 222*e2e9fd25SThomas Huth res = self.vm.qmp('query-s390x-cpu-polarization') 223*e2e9fd25SThomas Huth self.assertEqual(res['return']['polarization'], 'horizontal') 224*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'medium', False) 225*e2e9fd25SThomas Huth 226*e2e9fd25SThomas Huth self.guest_set_dispatching('1'); 227*e2e9fd25SThomas Huth res = self.vm.qmp('query-s390x-cpu-polarization') 228*e2e9fd25SThomas Huth self.assertEqual(res['return']['polarization'], 'vertical') 229*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'medium', False) 230*e2e9fd25SThomas Huth 231*e2e9fd25SThomas Huth self.guest_set_dispatching('0'); 232*e2e9fd25SThomas Huth res = self.vm.qmp('query-s390x-cpu-polarization') 233*e2e9fd25SThomas Huth self.assertEqual(res['return']['polarization'], 'horizontal') 234*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'medium', False) 235*e2e9fd25SThomas Huth 236*e2e9fd25SThomas Huth 237*e2e9fd25SThomas Huth def check_polarization(self, polarization): 238*e2e9fd25SThomas Huth #We need to wait for the change to have been propagated to the kernel 239*e2e9fd25SThomas Huth exec_command_and_wait_for_pattern(self, 240*e2e9fd25SThomas Huth "\n".join([ 241*e2e9fd25SThomas Huth "timeout 1 sh -c 'while true", 242*e2e9fd25SThomas Huth 'do', 243*e2e9fd25SThomas Huth ' syspath="/sys/devices/system/cpu/cpu0/polarization"', 244*e2e9fd25SThomas Huth ' polarization="$(cat "$syspath")" || exit', 245*e2e9fd25SThomas Huth f' if [ "$polarization" = "{polarization}" ]; then', 246*e2e9fd25SThomas Huth ' exit 0', 247*e2e9fd25SThomas Huth ' fi', 248*e2e9fd25SThomas Huth ' sleep 0.01', 249*e2e9fd25SThomas Huth #searched for strings mustn't show up in command, '' to obfuscate 250*e2e9fd25SThomas Huth "done' && echo succ''ess || echo fail''ure", 251*e2e9fd25SThomas Huth ]), 252*e2e9fd25SThomas Huth "success", "failure") 253*e2e9fd25SThomas Huth 254*e2e9fd25SThomas Huth 255*e2e9fd25SThomas Huth def test_entitlement(self): 256*e2e9fd25SThomas Huth """ 257*e2e9fd25SThomas Huth This test verifies that QEMU modifies the entitlement 258*e2e9fd25SThomas Huth after a guest request and that the guest sees the change. 259*e2e9fd25SThomas Huth """ 260*e2e9fd25SThomas Huth self.set_machine('s390-ccw-virtio') 261*e2e9fd25SThomas Huth self.kernel_init() 262*e2e9fd25SThomas Huth self.vm.launch() 263*e2e9fd25SThomas Huth self.wait_until_booted() 264*e2e9fd25SThomas Huth 265*e2e9fd25SThomas Huth self.system_init() 266*e2e9fd25SThomas Huth 267*e2e9fd25SThomas Huth self.check_polarization('horizontal') 268*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'medium', False) 269*e2e9fd25SThomas Huth 270*e2e9fd25SThomas Huth self.guest_set_dispatching('1') 271*e2e9fd25SThomas Huth self.check_polarization('vertical:medium') 272*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'medium', False) 273*e2e9fd25SThomas Huth 274*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 275*e2e9fd25SThomas Huth {'core-id': 0, 'entitlement': 'low'}) 276*e2e9fd25SThomas Huth self.assertEqual(res['return'], {}) 277*e2e9fd25SThomas Huth self.check_polarization('vertical:low') 278*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'low', False) 279*e2e9fd25SThomas Huth 280*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 281*e2e9fd25SThomas Huth {'core-id': 0, 'entitlement': 'medium'}) 282*e2e9fd25SThomas Huth self.assertEqual(res['return'], {}) 283*e2e9fd25SThomas Huth self.check_polarization('vertical:medium') 284*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'medium', False) 285*e2e9fd25SThomas Huth 286*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 287*e2e9fd25SThomas Huth {'core-id': 0, 'entitlement': 'high'}) 288*e2e9fd25SThomas Huth self.assertEqual(res['return'], {}) 289*e2e9fd25SThomas Huth self.check_polarization('vertical:high') 290*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'high', False) 291*e2e9fd25SThomas Huth 292*e2e9fd25SThomas Huth self.guest_set_dispatching('0'); 293*e2e9fd25SThomas Huth self.check_polarization("horizontal") 294*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'high', False) 295*e2e9fd25SThomas Huth 296*e2e9fd25SThomas Huth 297*e2e9fd25SThomas Huth def test_dedicated(self): 298*e2e9fd25SThomas Huth """ 299*e2e9fd25SThomas Huth This test verifies that QEMU adjusts the entitlement correctly when a 300*e2e9fd25SThomas Huth CPU is made dedicated. 301*e2e9fd25SThomas Huth QEMU retains the entitlement value when horizontal polarization is in effect. 302*e2e9fd25SThomas Huth For the guest, the field shows the effective value of the entitlement. 303*e2e9fd25SThomas Huth """ 304*e2e9fd25SThomas Huth self.set_machine('s390-ccw-virtio') 305*e2e9fd25SThomas Huth self.kernel_init() 306*e2e9fd25SThomas Huth self.vm.launch() 307*e2e9fd25SThomas Huth self.wait_until_booted() 308*e2e9fd25SThomas Huth 309*e2e9fd25SThomas Huth self.system_init() 310*e2e9fd25SThomas Huth 311*e2e9fd25SThomas Huth self.check_polarization("horizontal") 312*e2e9fd25SThomas Huth 313*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 314*e2e9fd25SThomas Huth {'core-id': 0, 'dedicated': True}) 315*e2e9fd25SThomas Huth self.assertEqual(res['return'], {}) 316*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'high', True) 317*e2e9fd25SThomas Huth self.check_polarization("horizontal") 318*e2e9fd25SThomas Huth 319*e2e9fd25SThomas Huth self.guest_set_dispatching('1'); 320*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'high', True) 321*e2e9fd25SThomas Huth self.check_polarization("vertical:high") 322*e2e9fd25SThomas Huth 323*e2e9fd25SThomas Huth self.guest_set_dispatching('0'); 324*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'high', True) 325*e2e9fd25SThomas Huth self.check_polarization("horizontal") 326*e2e9fd25SThomas Huth 327*e2e9fd25SThomas Huth 328*e2e9fd25SThomas Huth def test_socket_full(self): 329*e2e9fd25SThomas Huth """ 330*e2e9fd25SThomas Huth This test verifies that QEMU does not accept to overload a socket. 331*e2e9fd25SThomas Huth The socket-id 0 on book-id 0 already contains CPUs 0 and 1 and can 332*e2e9fd25SThomas Huth not accept any new CPU while socket-id 0 on book-id 1 is free. 333*e2e9fd25SThomas Huth """ 334*e2e9fd25SThomas Huth self.set_machine('s390-ccw-virtio') 335*e2e9fd25SThomas Huth self.kernel_init() 336*e2e9fd25SThomas Huth self.vm.add_args('-smp', 337*e2e9fd25SThomas Huth '3,drawers=2,books=2,sockets=3,cores=2,maxcpus=24') 338*e2e9fd25SThomas Huth self.vm.launch() 339*e2e9fd25SThomas Huth self.wait_until_booted() 340*e2e9fd25SThomas Huth 341*e2e9fd25SThomas Huth self.system_init() 342*e2e9fd25SThomas Huth 343*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 344*e2e9fd25SThomas Huth {'core-id': 2, 'socket-id': 0, 'book-id': 0}) 345*e2e9fd25SThomas Huth self.assertEqual(res['error']['class'], 'GenericError') 346*e2e9fd25SThomas Huth 347*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 348*e2e9fd25SThomas Huth {'core-id': 2, 'socket-id': 0, 'book-id': 1}) 349*e2e9fd25SThomas Huth self.assertEqual(res['return'], {}) 350*e2e9fd25SThomas Huth 351*e2e9fd25SThomas Huth def test_dedicated_error(self): 352*e2e9fd25SThomas Huth """ 353*e2e9fd25SThomas Huth This test verifies that QEMU refuses to lower the entitlement 354*e2e9fd25SThomas Huth of a dedicated CPU 355*e2e9fd25SThomas Huth """ 356*e2e9fd25SThomas Huth self.set_machine('s390-ccw-virtio') 357*e2e9fd25SThomas Huth self.kernel_init() 358*e2e9fd25SThomas Huth self.vm.launch() 359*e2e9fd25SThomas Huth self.wait_until_booted() 360*e2e9fd25SThomas Huth 361*e2e9fd25SThomas Huth self.system_init() 362*e2e9fd25SThomas Huth 363*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 364*e2e9fd25SThomas Huth {'core-id': 0, 'dedicated': True}) 365*e2e9fd25SThomas Huth self.assertEqual(res['return'], {}) 366*e2e9fd25SThomas Huth 367*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'high', True) 368*e2e9fd25SThomas Huth 369*e2e9fd25SThomas Huth self.guest_set_dispatching('1'); 370*e2e9fd25SThomas Huth 371*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'high', True) 372*e2e9fd25SThomas Huth 373*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 374*e2e9fd25SThomas Huth {'core-id': 0, 'entitlement': 'low', 'dedicated': True}) 375*e2e9fd25SThomas Huth self.assertEqual(res['error']['class'], 'GenericError') 376*e2e9fd25SThomas Huth 377*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 378*e2e9fd25SThomas Huth {'core-id': 0, 'entitlement': 'low'}) 379*e2e9fd25SThomas Huth self.assertEqual(res['error']['class'], 'GenericError') 380*e2e9fd25SThomas Huth 381*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 382*e2e9fd25SThomas Huth {'core-id': 0, 'entitlement': 'medium', 'dedicated': True}) 383*e2e9fd25SThomas Huth self.assertEqual(res['error']['class'], 'GenericError') 384*e2e9fd25SThomas Huth 385*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 386*e2e9fd25SThomas Huth {'core-id': 0, 'entitlement': 'medium'}) 387*e2e9fd25SThomas Huth self.assertEqual(res['error']['class'], 'GenericError') 388*e2e9fd25SThomas Huth 389*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 390*e2e9fd25SThomas Huth {'core-id': 0, 'entitlement': 'low', 'dedicated': False}) 391*e2e9fd25SThomas Huth self.assertEqual(res['return'], {}) 392*e2e9fd25SThomas Huth 393*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', 394*e2e9fd25SThomas Huth {'core-id': 0, 'entitlement': 'medium', 'dedicated': False}) 395*e2e9fd25SThomas Huth self.assertEqual(res['return'], {}) 396*e2e9fd25SThomas Huth 397*e2e9fd25SThomas Huth def test_move_error(self): 398*e2e9fd25SThomas Huth """ 399*e2e9fd25SThomas Huth This test verifies that QEMU refuses to move a CPU to an 400*e2e9fd25SThomas Huth nonexistent location 401*e2e9fd25SThomas Huth """ 402*e2e9fd25SThomas Huth self.set_machine('s390-ccw-virtio') 403*e2e9fd25SThomas Huth self.kernel_init() 404*e2e9fd25SThomas Huth self.vm.launch() 405*e2e9fd25SThomas Huth self.wait_until_booted() 406*e2e9fd25SThomas Huth 407*e2e9fd25SThomas Huth self.system_init() 408*e2e9fd25SThomas Huth 409*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', {'core-id': 0, 'drawer-id': 1}) 410*e2e9fd25SThomas Huth self.assertEqual(res['error']['class'], 'GenericError') 411*e2e9fd25SThomas Huth 412*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', {'core-id': 0, 'book-id': 1}) 413*e2e9fd25SThomas Huth self.assertEqual(res['error']['class'], 'GenericError') 414*e2e9fd25SThomas Huth 415*e2e9fd25SThomas Huth res = self.vm.qmp('set-cpu-topology', {'core-id': 0, 'socket-id': 1}) 416*e2e9fd25SThomas Huth self.assertEqual(res['error']['class'], 'GenericError') 417*e2e9fd25SThomas Huth 418*e2e9fd25SThomas Huth self.check_topology(0, 0, 0, 0, 'medium', False) 419*e2e9fd25SThomas Huth 420*e2e9fd25SThomas Huthif __name__ == '__main__': 421*e2e9fd25SThomas Huth QemuSystemTest.main() 422