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