1# 2# Basic validation of x86 versioned CPU models and CPU model aliases 3# 4# Copyright (c) 2019 Red Hat Inc 5# 6# Author: 7# Eduardo Habkost <ehabkost@redhat.com> 8# 9# This library is free software; you can redistribute it and/or 10# modify it under the terms of the GNU Lesser General Public 11# License as published by the Free Software Foundation; either 12# version 2.1 of the License, or (at your option) any later version. 13# 14# This library is distributed in the hope that it will be useful, 15# but WITHOUT ANY WARRANTY; without even the implied warranty of 16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17# Lesser General Public License for more details. 18# 19# You should have received a copy of the GNU Lesser General Public 20# License along with this library; if not, see <http://www.gnu.org/licenses/>. 21# 22 23 24import avocado_qemu 25import re 26 27class X86CPUModelAliases(avocado_qemu.QemuSystemTest): 28 """ 29 Validation of PC CPU model versions and CPU model aliases 30 31 :avocado: tags=arch:x86_64 32 """ 33 def validate_aliases(self, cpus): 34 for c in cpus.values(): 35 if 'alias-of' in c: 36 # all aliases must point to a valid CPU model name: 37 self.assertIn(c['alias-of'], cpus, 38 '%s.alias-of (%s) is not a valid CPU model name' % (c['name'], c['alias-of'])) 39 # aliases must not point to aliases 40 self.assertNotIn('alias-of', cpus[c['alias-of']], 41 '%s.alias-of (%s) points to another alias' % (c['name'], c['alias-of'])) 42 43 # aliases must not be static 44 self.assertFalse(c['static']) 45 46 def validate_variant_aliases(self, cpus): 47 # -noTSX, -IBRS and -IBPB variants of CPU models are special: 48 # they shouldn't have their own versions: 49 self.assertNotIn("Haswell-noTSX-v1", cpus, 50 "Haswell-noTSX shouldn't be versioned") 51 self.assertNotIn("Broadwell-noTSX-v1", cpus, 52 "Broadwell-noTSX shouldn't be versioned") 53 self.assertNotIn("Nehalem-IBRS-v1", cpus, 54 "Nehalem-IBRS shouldn't be versioned") 55 self.assertNotIn("Westmere-IBRS-v1", cpus, 56 "Westmere-IBRS shouldn't be versioned") 57 self.assertNotIn("SandyBridge-IBRS-v1", cpus, 58 "SandyBridge-IBRS shouldn't be versioned") 59 self.assertNotIn("IvyBridge-IBRS-v1", cpus, 60 "IvyBridge-IBRS shouldn't be versioned") 61 self.assertNotIn("Haswell-noTSX-IBRS-v1", cpus, 62 "Haswell-noTSX-IBRS shouldn't be versioned") 63 self.assertNotIn("Haswell-IBRS-v1", cpus, 64 "Haswell-IBRS shouldn't be versioned") 65 self.assertNotIn("Broadwell-noTSX-IBRS-v1", cpus, 66 "Broadwell-noTSX-IBRS shouldn't be versioned") 67 self.assertNotIn("Broadwell-IBRS-v1", cpus, 68 "Broadwell-IBRS shouldn't be versioned") 69 self.assertNotIn("Skylake-Client-IBRS-v1", cpus, 70 "Skylake-Client-IBRS shouldn't be versioned") 71 self.assertNotIn("Skylake-Server-IBRS-v1", cpus, 72 "Skylake-Server-IBRS shouldn't be versioned") 73 self.assertNotIn("EPYC-IBPB-v1", cpus, 74 "EPYC-IBPB shouldn't be versioned") 75 76 def test_4_0_alias_compatibility(self): 77 """ 78 Check if pc-*-4.0 unversioned CPU model won't be reported as aliases 79 80 :avocado: tags=machine:pc-i440fx-4.0 81 """ 82 # pc-*-4.0 won't expose non-versioned CPU models as aliases 83 # We do this to help management software to keep compatibility 84 # with older QEMU versions that didn't have the versioned CPU model 85 self.vm.add_args('-S') 86 self.vm.launch() 87 cpus = dict((m['name'], m) for m in 88 self.vm.cmd('query-cpu-definitions')) 89 90 self.assertFalse(cpus['Cascadelake-Server']['static'], 91 'unversioned Cascadelake-Server CPU model must not be static') 92 self.assertNotIn('alias-of', cpus['Cascadelake-Server'], 93 'Cascadelake-Server must not be an alias') 94 self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], 95 'Cascadelake-Server-v1 must not be an alias') 96 97 self.assertFalse(cpus['qemu64']['static'], 98 'unversioned qemu64 CPU model must not be static') 99 self.assertNotIn('alias-of', cpus['qemu64'], 100 'qemu64 must not be an alias') 101 self.assertNotIn('alias-of', cpus['qemu64-v1'], 102 'qemu64-v1 must not be an alias') 103 104 self.validate_variant_aliases(cpus) 105 106 # On pc-*-4.0, no CPU model should be reported as an alias: 107 for name,c in cpus.items(): 108 self.assertNotIn('alias-of', c, "%s shouldn't be an alias" % (name)) 109 110 def test_4_1_alias(self): 111 """ 112 Check if unversioned CPU model is an alias pointing to right version 113 114 :avocado: tags=machine:pc-i440fx-4.1 115 """ 116 self.vm.add_args('-S') 117 self.vm.launch() 118 119 cpus = dict((m['name'], m) for m in 120 self.vm.cmd('query-cpu-definitions')) 121 122 self.assertFalse(cpus['Cascadelake-Server']['static'], 123 'unversioned Cascadelake-Server CPU model must not be static') 124 self.assertEqual(cpus['Cascadelake-Server'].get('alias-of'), 125 'Cascadelake-Server-v1', 126 'Cascadelake-Server must be an alias of Cascadelake-Server-v1') 127 self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], 128 'Cascadelake-Server-v1 must not be an alias') 129 130 self.assertFalse(cpus['qemu64']['static'], 131 'unversioned qemu64 CPU model must not be static') 132 self.assertEqual(cpus['qemu64'].get('alias-of'), 'qemu64-v1', 133 'qemu64 must be an alias of qemu64-v1') 134 self.assertNotIn('alias-of', cpus['qemu64-v1'], 135 'qemu64-v1 must not be an alias') 136 137 self.validate_variant_aliases(cpus) 138 139 # On pc-*-4.1, -noTSX and -IBRS models should be aliases: 140 self.assertEqual(cpus["Haswell"].get('alias-of'), 141 "Haswell-v1", 142 "Haswell must be an alias") 143 self.assertEqual(cpus["Haswell-noTSX"].get('alias-of'), 144 "Haswell-v2", 145 "Haswell-noTSX must be an alias") 146 self.assertEqual(cpus["Haswell-IBRS"].get('alias-of'), 147 "Haswell-v3", 148 "Haswell-IBRS must be an alias") 149 self.assertEqual(cpus["Haswell-noTSX-IBRS"].get('alias-of'), 150 "Haswell-v4", 151 "Haswell-noTSX-IBRS must be an alias") 152 153 self.assertEqual(cpus["Broadwell"].get('alias-of'), 154 "Broadwell-v1", 155 "Broadwell must be an alias") 156 self.assertEqual(cpus["Broadwell-noTSX"].get('alias-of'), 157 "Broadwell-v2", 158 "Broadwell-noTSX must be an alias") 159 self.assertEqual(cpus["Broadwell-IBRS"].get('alias-of'), 160 "Broadwell-v3", 161 "Broadwell-IBRS must be an alias") 162 self.assertEqual(cpus["Broadwell-noTSX-IBRS"].get('alias-of'), 163 "Broadwell-v4", 164 "Broadwell-noTSX-IBRS must be an alias") 165 166 self.assertEqual(cpus["Nehalem"].get('alias-of'), 167 "Nehalem-v1", 168 "Nehalem must be an alias") 169 self.assertEqual(cpus["Nehalem-IBRS"].get('alias-of'), 170 "Nehalem-v2", 171 "Nehalem-IBRS must be an alias") 172 173 self.assertEqual(cpus["Westmere"].get('alias-of'), 174 "Westmere-v1", 175 "Westmere must be an alias") 176 self.assertEqual(cpus["Westmere-IBRS"].get('alias-of'), 177 "Westmere-v2", 178 "Westmere-IBRS must be an alias") 179 180 self.assertEqual(cpus["SandyBridge"].get('alias-of'), 181 "SandyBridge-v1", 182 "SandyBridge must be an alias") 183 self.assertEqual(cpus["SandyBridge-IBRS"].get('alias-of'), 184 "SandyBridge-v2", 185 "SandyBridge-IBRS must be an alias") 186 187 self.assertEqual(cpus["IvyBridge"].get('alias-of'), 188 "IvyBridge-v1", 189 "IvyBridge must be an alias") 190 self.assertEqual(cpus["IvyBridge-IBRS"].get('alias-of'), 191 "IvyBridge-v2", 192 "IvyBridge-IBRS must be an alias") 193 194 self.assertEqual(cpus["Skylake-Client"].get('alias-of'), 195 "Skylake-Client-v1", 196 "Skylake-Client must be an alias") 197 self.assertEqual(cpus["Skylake-Client-IBRS"].get('alias-of'), 198 "Skylake-Client-v2", 199 "Skylake-Client-IBRS must be an alias") 200 201 self.assertEqual(cpus["Skylake-Server"].get('alias-of'), 202 "Skylake-Server-v1", 203 "Skylake-Server must be an alias") 204 self.assertEqual(cpus["Skylake-Server-IBRS"].get('alias-of'), 205 "Skylake-Server-v2", 206 "Skylake-Server-IBRS must be an alias") 207 208 self.assertEqual(cpus["EPYC"].get('alias-of'), 209 "EPYC-v1", 210 "EPYC must be an alias") 211 self.assertEqual(cpus["EPYC-IBPB"].get('alias-of'), 212 "EPYC-v2", 213 "EPYC-IBPB must be an alias") 214 215 self.validate_aliases(cpus) 216 217 def test_none_alias(self): 218 """ 219 Check if unversioned CPU model is an alias pointing to some version 220 221 :avocado: tags=machine:none 222 """ 223 self.vm.add_args('-S') 224 self.vm.launch() 225 226 cpus = dict((m['name'], m) for m in 227 self.vm.cmd('query-cpu-definitions')) 228 229 self.assertFalse(cpus['Cascadelake-Server']['static'], 230 'unversioned Cascadelake-Server CPU model must not be static') 231 self.assertTrue(re.match('Cascadelake-Server-v[0-9]+', cpus['Cascadelake-Server']['alias-of']), 232 'Cascadelake-Server must be an alias of versioned CPU model') 233 self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], 234 'Cascadelake-Server-v1 must not be an alias') 235 236 self.assertFalse(cpus['qemu64']['static'], 237 'unversioned qemu64 CPU model must not be static') 238 self.assertTrue(re.match('qemu64-v[0-9]+', cpus['qemu64']['alias-of']), 239 'qemu64 must be an alias of versioned CPU model') 240 self.assertNotIn('alias-of', cpus['qemu64-v1'], 241 'qemu64-v1 must not be an alias') 242 243 self.validate_aliases(cpus) 244 245 246class CascadelakeArchCapabilities(avocado_qemu.QemuSystemTest): 247 """ 248 Validation of Cascadelake arch-capabilities 249 250 :avocado: tags=arch:x86_64 251 """ 252 def get_cpu_prop(self, prop): 253 cpu_path = self.vm.cmd('query-cpus-fast')[0].get('qom-path') 254 return self.vm.cmd('qom-get', path=cpu_path, property=prop) 255 256 def test_4_1(self): 257 """ 258 :avocado: tags=machine:pc-i440fx-4.1 259 :avocado: tags=cpu:Cascadelake-Server 260 """ 261 # machine-type only: 262 self.vm.add_args('-S') 263 self.set_vm_arg('-cpu', 264 'Cascadelake-Server,x-force-features=on,check=off,' 265 'enforce=off') 266 self.vm.launch() 267 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 268 'pc-i440fx-4.1 + Cascadelake-Server should not have arch-capabilities') 269 270 def test_4_0(self): 271 """ 272 :avocado: tags=machine:pc-i440fx-4.0 273 :avocado: tags=cpu:Cascadelake-Server 274 """ 275 self.vm.add_args('-S') 276 self.set_vm_arg('-cpu', 277 'Cascadelake-Server,x-force-features=on,check=off,' 278 'enforce=off') 279 self.vm.launch() 280 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 281 'pc-i440fx-4.0 + Cascadelake-Server should not have arch-capabilities') 282 283 def test_set_4_0(self): 284 """ 285 :avocado: tags=machine:pc-i440fx-4.0 286 :avocado: tags=cpu:Cascadelake-Server 287 """ 288 # command line must override machine-type if CPU model is not versioned: 289 self.vm.add_args('-S') 290 self.set_vm_arg('-cpu', 291 'Cascadelake-Server,x-force-features=on,check=off,' 292 'enforce=off,+arch-capabilities') 293 self.vm.launch() 294 self.assertTrue(self.get_cpu_prop('arch-capabilities'), 295 'pc-i440fx-4.0 + Cascadelake-Server,+arch-capabilities should have arch-capabilities') 296 297 def test_unset_4_1(self): 298 """ 299 :avocado: tags=machine:pc-i440fx-4.1 300 :avocado: tags=cpu:Cascadelake-Server 301 """ 302 self.vm.add_args('-S') 303 self.set_vm_arg('-cpu', 304 'Cascadelake-Server,x-force-features=on,check=off,' 305 'enforce=off,-arch-capabilities') 306 self.vm.launch() 307 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 308 'pc-i440fx-4.1 + Cascadelake-Server,-arch-capabilities should not have arch-capabilities') 309 310 def test_v1_4_0(self): 311 """ 312 :avocado: tags=machine:pc-i440fx-4.0 313 :avocado: tags=cpu:Cascadelake-Server 314 """ 315 # versioned CPU model overrides machine-type: 316 self.vm.add_args('-S') 317 self.set_vm_arg('-cpu', 318 'Cascadelake-Server-v1,x-force-features=on,check=off,' 319 'enforce=off') 320 self.vm.launch() 321 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 322 'pc-i440fx-4.0 + Cascadelake-Server-v1 should not have arch-capabilities') 323 324 def test_v2_4_0(self): 325 """ 326 :avocado: tags=machine:pc-i440fx-4.0 327 :avocado: tags=cpu:Cascadelake-Server 328 """ 329 self.vm.add_args('-S') 330 self.set_vm_arg('-cpu', 331 'Cascadelake-Server-v2,x-force-features=on,check=off,' 332 'enforce=off') 333 self.vm.launch() 334 self.assertTrue(self.get_cpu_prop('arch-capabilities'), 335 'pc-i440fx-4.0 + Cascadelake-Server-v2 should have arch-capabilities') 336 337 def test_v1_set_4_0(self): 338 """ 339 :avocado: tags=machine:pc-i440fx-4.0 340 :avocado: tags=cpu:Cascadelake-Server 341 """ 342 # command line must override machine-type and versioned CPU model: 343 self.vm.add_args('-S') 344 self.set_vm_arg('-cpu', 345 'Cascadelake-Server-v1,x-force-features=on,check=off,' 346 'enforce=off,+arch-capabilities') 347 self.vm.launch() 348 self.assertTrue(self.get_cpu_prop('arch-capabilities'), 349 'pc-i440fx-4.0 + Cascadelake-Server-v1,+arch-capabilities should have arch-capabilities') 350 351 def test_v2_unset_4_1(self): 352 """ 353 :avocado: tags=machine:pc-i440fx-4.1 354 :avocado: tags=cpu:Cascadelake-Server 355 """ 356 self.vm.add_args('-S') 357 self.set_vm_arg('-cpu', 358 'Cascadelake-Server-v2,x-force-features=on,check=off,' 359 'enforce=off,-arch-capabilities') 360 self.vm.launch() 361 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 362 'pc-i440fx-4.1 + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities') 363