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.assertEquals(cpus['Cascadelake-Server'].get('alias-of'), 'Cascadelake-Server-v1', 125 'Cascadelake-Server must be an alias of Cascadelake-Server-v1') 126 self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], 127 'Cascadelake-Server-v1 must not be an alias') 128 129 self.assertFalse(cpus['qemu64']['static'], 130 'unversioned qemu64 CPU model must not be static') 131 self.assertEquals(cpus['qemu64'].get('alias-of'), 'qemu64-v1', 132 'qemu64 must be an alias of qemu64-v1') 133 self.assertNotIn('alias-of', cpus['qemu64-v1'], 134 'qemu64-v1 must not be an alias') 135 136 self.validate_variant_aliases(cpus) 137 138 # On pc-*-4.1, -noTSX and -IBRS models should be aliases: 139 self.assertEquals(cpus["Haswell"].get('alias-of'), 140 "Haswell-v1", 141 "Haswell must be an alias") 142 self.assertEquals(cpus["Haswell-noTSX"].get('alias-of'), 143 "Haswell-v2", 144 "Haswell-noTSX must be an alias") 145 self.assertEquals(cpus["Haswell-IBRS"].get('alias-of'), 146 "Haswell-v3", 147 "Haswell-IBRS must be an alias") 148 self.assertEquals(cpus["Haswell-noTSX-IBRS"].get('alias-of'), 149 "Haswell-v4", 150 "Haswell-noTSX-IBRS must be an alias") 151 152 self.assertEquals(cpus["Broadwell"].get('alias-of'), 153 "Broadwell-v1", 154 "Broadwell must be an alias") 155 self.assertEquals(cpus["Broadwell-noTSX"].get('alias-of'), 156 "Broadwell-v2", 157 "Broadwell-noTSX must be an alias") 158 self.assertEquals(cpus["Broadwell-IBRS"].get('alias-of'), 159 "Broadwell-v3", 160 "Broadwell-IBRS must be an alias") 161 self.assertEquals(cpus["Broadwell-noTSX-IBRS"].get('alias-of'), 162 "Broadwell-v4", 163 "Broadwell-noTSX-IBRS must be an alias") 164 165 self.assertEquals(cpus["Nehalem"].get('alias-of'), 166 "Nehalem-v1", 167 "Nehalem must be an alias") 168 self.assertEquals(cpus["Nehalem-IBRS"].get('alias-of'), 169 "Nehalem-v2", 170 "Nehalem-IBRS must be an alias") 171 172 self.assertEquals(cpus["Westmere"].get('alias-of'), 173 "Westmere-v1", 174 "Westmere must be an alias") 175 self.assertEquals(cpus["Westmere-IBRS"].get('alias-of'), 176 "Westmere-v2", 177 "Westmere-IBRS must be an alias") 178 179 self.assertEquals(cpus["SandyBridge"].get('alias-of'), 180 "SandyBridge-v1", 181 "SandyBridge must be an alias") 182 self.assertEquals(cpus["SandyBridge-IBRS"].get('alias-of'), 183 "SandyBridge-v2", 184 "SandyBridge-IBRS must be an alias") 185 186 self.assertEquals(cpus["IvyBridge"].get('alias-of'), 187 "IvyBridge-v1", 188 "IvyBridge must be an alias") 189 self.assertEquals(cpus["IvyBridge-IBRS"].get('alias-of'), 190 "IvyBridge-v2", 191 "IvyBridge-IBRS must be an alias") 192 193 self.assertEquals(cpus["Skylake-Client"].get('alias-of'), 194 "Skylake-Client-v1", 195 "Skylake-Client must be an alias") 196 self.assertEquals(cpus["Skylake-Client-IBRS"].get('alias-of'), 197 "Skylake-Client-v2", 198 "Skylake-Client-IBRS must be an alias") 199 200 self.assertEquals(cpus["Skylake-Server"].get('alias-of'), 201 "Skylake-Server-v1", 202 "Skylake-Server must be an alias") 203 self.assertEquals(cpus["Skylake-Server-IBRS"].get('alias-of'), 204 "Skylake-Server-v2", 205 "Skylake-Server-IBRS must be an alias") 206 207 self.assertEquals(cpus["EPYC"].get('alias-of'), 208 "EPYC-v1", 209 "EPYC must be an alias") 210 self.assertEquals(cpus["EPYC-IBPB"].get('alias-of'), 211 "EPYC-v2", 212 "EPYC-IBPB must be an alias") 213 214 self.validate_aliases(cpus) 215 216 def test_none_alias(self): 217 """ 218 Check if unversioned CPU model is an alias pointing to some version 219 220 :avocado: tags=machine:none 221 """ 222 self.vm.add_args('-S') 223 self.vm.launch() 224 225 cpus = dict((m['name'], m) for m in 226 self.vm.cmd('query-cpu-definitions')) 227 228 self.assertFalse(cpus['Cascadelake-Server']['static'], 229 'unversioned Cascadelake-Server CPU model must not be static') 230 self.assertTrue(re.match('Cascadelake-Server-v[0-9]+', cpus['Cascadelake-Server']['alias-of']), 231 'Cascadelake-Server must be an alias of versioned CPU model') 232 self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], 233 'Cascadelake-Server-v1 must not be an alias') 234 235 self.assertFalse(cpus['qemu64']['static'], 236 'unversioned qemu64 CPU model must not be static') 237 self.assertTrue(re.match('qemu64-v[0-9]+', cpus['qemu64']['alias-of']), 238 'qemu64 must be an alias of versioned CPU model') 239 self.assertNotIn('alias-of', cpus['qemu64-v1'], 240 'qemu64-v1 must not be an alias') 241 242 self.validate_aliases(cpus) 243 244 245class CascadelakeArchCapabilities(avocado_qemu.QemuSystemTest): 246 """ 247 Validation of Cascadelake arch-capabilities 248 249 :avocado: tags=arch:x86_64 250 """ 251 def get_cpu_prop(self, prop): 252 cpu_path = self.vm.cmd('query-cpus-fast')[0].get('qom-path') 253 return self.vm.cmd('qom-get', path=cpu_path, property=prop) 254 255 def test_4_1(self): 256 """ 257 :avocado: tags=machine:pc-i440fx-4.1 258 :avocado: tags=cpu:Cascadelake-Server 259 """ 260 # machine-type only: 261 self.vm.add_args('-S') 262 self.set_vm_arg('-cpu', 263 'Cascadelake-Server,x-force-features=on,check=off,' 264 'enforce=off') 265 self.vm.launch() 266 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 267 'pc-i440fx-4.1 + Cascadelake-Server should not have arch-capabilities') 268 269 def test_4_0(self): 270 """ 271 :avocado: tags=machine:pc-i440fx-4.0 272 :avocado: tags=cpu:Cascadelake-Server 273 """ 274 self.vm.add_args('-S') 275 self.set_vm_arg('-cpu', 276 'Cascadelake-Server,x-force-features=on,check=off,' 277 'enforce=off') 278 self.vm.launch() 279 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 280 'pc-i440fx-4.0 + Cascadelake-Server should not have arch-capabilities') 281 282 def test_set_4_0(self): 283 """ 284 :avocado: tags=machine:pc-i440fx-4.0 285 :avocado: tags=cpu:Cascadelake-Server 286 """ 287 # command line must override machine-type if CPU model is not versioned: 288 self.vm.add_args('-S') 289 self.set_vm_arg('-cpu', 290 'Cascadelake-Server,x-force-features=on,check=off,' 291 'enforce=off,+arch-capabilities') 292 self.vm.launch() 293 self.assertTrue(self.get_cpu_prop('arch-capabilities'), 294 'pc-i440fx-4.0 + Cascadelake-Server,+arch-capabilities should have arch-capabilities') 295 296 def test_unset_4_1(self): 297 """ 298 :avocado: tags=machine:pc-i440fx-4.1 299 :avocado: tags=cpu:Cascadelake-Server 300 """ 301 self.vm.add_args('-S') 302 self.set_vm_arg('-cpu', 303 'Cascadelake-Server,x-force-features=on,check=off,' 304 'enforce=off,-arch-capabilities') 305 self.vm.launch() 306 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 307 'pc-i440fx-4.1 + Cascadelake-Server,-arch-capabilities should not have arch-capabilities') 308 309 def test_v1_4_0(self): 310 """ 311 :avocado: tags=machine:pc-i440fx-4.0 312 :avocado: tags=cpu:Cascadelake-Server 313 """ 314 # versioned CPU model overrides machine-type: 315 self.vm.add_args('-S') 316 self.set_vm_arg('-cpu', 317 'Cascadelake-Server-v1,x-force-features=on,check=off,' 318 'enforce=off') 319 self.vm.launch() 320 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 321 'pc-i440fx-4.0 + Cascadelake-Server-v1 should not have arch-capabilities') 322 323 def test_v2_4_0(self): 324 """ 325 :avocado: tags=machine:pc-i440fx-4.0 326 :avocado: tags=cpu:Cascadelake-Server 327 """ 328 self.vm.add_args('-S') 329 self.set_vm_arg('-cpu', 330 'Cascadelake-Server-v2,x-force-features=on,check=off,' 331 'enforce=off') 332 self.vm.launch() 333 self.assertTrue(self.get_cpu_prop('arch-capabilities'), 334 'pc-i440fx-4.0 + Cascadelake-Server-v2 should have arch-capabilities') 335 336 def test_v1_set_4_0(self): 337 """ 338 :avocado: tags=machine:pc-i440fx-4.0 339 :avocado: tags=cpu:Cascadelake-Server 340 """ 341 # command line must override machine-type and versioned CPU model: 342 self.vm.add_args('-S') 343 self.set_vm_arg('-cpu', 344 'Cascadelake-Server-v1,x-force-features=on,check=off,' 345 'enforce=off,+arch-capabilities') 346 self.vm.launch() 347 self.assertTrue(self.get_cpu_prop('arch-capabilities'), 348 'pc-i440fx-4.0 + Cascadelake-Server-v1,+arch-capabilities should have arch-capabilities') 349 350 def test_v2_unset_4_1(self): 351 """ 352 :avocado: tags=machine:pc-i440fx-4.1 353 :avocado: tags=cpu:Cascadelake-Server 354 """ 355 self.vm.add_args('-S') 356 self.set_vm_arg('-cpu', 357 'Cascadelake-Server-v2,x-force-features=on,check=off,' 358 'enforce=off,-arch-capabilities') 359 self.vm.launch() 360 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 361 'pc-i440fx-4.1 + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities') 362