1#!/usr/bin/env python3 2# 3# Basic validation of x86 versioned CPU models and CPU model aliases 4# 5# Copyright (c) 2019 Red Hat Inc 6# 7# Author: 8# Eduardo Habkost <ehabkost@redhat.com> 9# 10# This library is free software; you can redistribute it and/or 11# modify it under the terms of the GNU Lesser General Public 12# License as published by the Free Software Foundation; either 13# version 2.1 of the License, or (at your option) any later version. 14# 15# This library is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18# Lesser General Public License for more details. 19# 20# You should have received a copy of the GNU Lesser General Public 21# License along with this library; if not, see <http://www.gnu.org/licenses/>. 22# 23 24import re 25 26from qemu_test import QemuSystemTest 27 28class X86CPUModelAliases(QemuSystemTest): 29 """ 30 Validation of PC CPU model versions and CPU model aliases 31 """ 32 def validate_aliases(self, cpus): 33 for c in cpus.values(): 34 if 'alias-of' in c: 35 # all aliases must point to a valid CPU model name: 36 self.assertIn(c['alias-of'], cpus, 37 '%s.alias-of (%s) is not a valid CPU model name' % (c['name'], c['alias-of'])) 38 # aliases must not point to aliases 39 self.assertNotIn('alias-of', cpus[c['alias-of']], 40 '%s.alias-of (%s) points to another alias' % (c['name'], c['alias-of'])) 41 42 # aliases must not be static 43 self.assertFalse(c['static']) 44 45 def validate_variant_aliases(self, cpus): 46 # -noTSX, -IBRS and -IBPB variants of CPU models are special: 47 # they shouldn't have their own versions: 48 self.assertNotIn("Haswell-noTSX-v1", cpus, 49 "Haswell-noTSX shouldn't be versioned") 50 self.assertNotIn("Broadwell-noTSX-v1", cpus, 51 "Broadwell-noTSX shouldn't be versioned") 52 self.assertNotIn("Nehalem-IBRS-v1", cpus, 53 "Nehalem-IBRS shouldn't be versioned") 54 self.assertNotIn("Westmere-IBRS-v1", cpus, 55 "Westmere-IBRS shouldn't be versioned") 56 self.assertNotIn("SandyBridge-IBRS-v1", cpus, 57 "SandyBridge-IBRS shouldn't be versioned") 58 self.assertNotIn("IvyBridge-IBRS-v1", cpus, 59 "IvyBridge-IBRS shouldn't be versioned") 60 self.assertNotIn("Haswell-noTSX-IBRS-v1", cpus, 61 "Haswell-noTSX-IBRS shouldn't be versioned") 62 self.assertNotIn("Haswell-IBRS-v1", cpus, 63 "Haswell-IBRS shouldn't be versioned") 64 self.assertNotIn("Broadwell-noTSX-IBRS-v1", cpus, 65 "Broadwell-noTSX-IBRS shouldn't be versioned") 66 self.assertNotIn("Broadwell-IBRS-v1", cpus, 67 "Broadwell-IBRS shouldn't be versioned") 68 self.assertNotIn("Skylake-Client-IBRS-v1", cpus, 69 "Skylake-Client-IBRS shouldn't be versioned") 70 self.assertNotIn("Skylake-Server-IBRS-v1", cpus, 71 "Skylake-Server-IBRS shouldn't be versioned") 72 self.assertNotIn("EPYC-IBPB-v1", cpus, 73 "EPYC-IBPB shouldn't be versioned") 74 75 def test_unversioned_alias(self): 76 """ 77 Check if unversioned CPU model is an alias pointing to right version 78 """ 79 self.set_machine('pc') 80 self.vm.add_args('-S') 81 self.vm.launch() 82 83 cpus = dict((m['name'], m) for m in 84 self.vm.cmd('query-cpu-definitions')) 85 86 self.assertFalse(cpus['Cascadelake-Server']['static'], 87 'unversioned Cascadelake-Server CPU model must not be static') 88 self.assertEqual(cpus['Cascadelake-Server'].get('alias-of'), 89 'Cascadelake-Server-v1', 90 'Cascadelake-Server must be an alias of Cascadelake-Server-v1') 91 self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], 92 'Cascadelake-Server-v1 must not be an alias') 93 94 self.assertFalse(cpus['qemu64']['static'], 95 'unversioned qemu64 CPU model must not be static') 96 self.assertEqual(cpus['qemu64'].get('alias-of'), 'qemu64-v1', 97 'qemu64 must be an alias of qemu64-v1') 98 self.assertNotIn('alias-of', cpus['qemu64-v1'], 99 'qemu64-v1 must not be an alias') 100 101 self.validate_variant_aliases(cpus) 102 103 # On recent PC machines, -noTSX and -IBRS models should be aliases: 104 self.assertEqual(cpus["Haswell"].get('alias-of'), 105 "Haswell-v1", 106 "Haswell must be an alias") 107 self.assertEqual(cpus["Haswell-noTSX"].get('alias-of'), 108 "Haswell-v2", 109 "Haswell-noTSX must be an alias") 110 self.assertEqual(cpus["Haswell-IBRS"].get('alias-of'), 111 "Haswell-v3", 112 "Haswell-IBRS must be an alias") 113 self.assertEqual(cpus["Haswell-noTSX-IBRS"].get('alias-of'), 114 "Haswell-v4", 115 "Haswell-noTSX-IBRS must be an alias") 116 117 self.assertEqual(cpus["Broadwell"].get('alias-of'), 118 "Broadwell-v1", 119 "Broadwell must be an alias") 120 self.assertEqual(cpus["Broadwell-noTSX"].get('alias-of'), 121 "Broadwell-v2", 122 "Broadwell-noTSX must be an alias") 123 self.assertEqual(cpus["Broadwell-IBRS"].get('alias-of'), 124 "Broadwell-v3", 125 "Broadwell-IBRS must be an alias") 126 self.assertEqual(cpus["Broadwell-noTSX-IBRS"].get('alias-of'), 127 "Broadwell-v4", 128 "Broadwell-noTSX-IBRS must be an alias") 129 130 self.assertEqual(cpus["Nehalem"].get('alias-of'), 131 "Nehalem-v1", 132 "Nehalem must be an alias") 133 self.assertEqual(cpus["Nehalem-IBRS"].get('alias-of'), 134 "Nehalem-v2", 135 "Nehalem-IBRS must be an alias") 136 137 self.assertEqual(cpus["Westmere"].get('alias-of'), 138 "Westmere-v1", 139 "Westmere must be an alias") 140 self.assertEqual(cpus["Westmere-IBRS"].get('alias-of'), 141 "Westmere-v2", 142 "Westmere-IBRS must be an alias") 143 144 self.assertEqual(cpus["SandyBridge"].get('alias-of'), 145 "SandyBridge-v1", 146 "SandyBridge must be an alias") 147 self.assertEqual(cpus["SandyBridge-IBRS"].get('alias-of'), 148 "SandyBridge-v2", 149 "SandyBridge-IBRS must be an alias") 150 151 self.assertEqual(cpus["IvyBridge"].get('alias-of'), 152 "IvyBridge-v1", 153 "IvyBridge must be an alias") 154 self.assertEqual(cpus["IvyBridge-IBRS"].get('alias-of'), 155 "IvyBridge-v2", 156 "IvyBridge-IBRS must be an alias") 157 158 self.assertEqual(cpus["Skylake-Client"].get('alias-of'), 159 "Skylake-Client-v1", 160 "Skylake-Client must be an alias") 161 self.assertEqual(cpus["Skylake-Client-IBRS"].get('alias-of'), 162 "Skylake-Client-v2", 163 "Skylake-Client-IBRS must be an alias") 164 165 self.assertEqual(cpus["Skylake-Server"].get('alias-of'), 166 "Skylake-Server-v1", 167 "Skylake-Server must be an alias") 168 self.assertEqual(cpus["Skylake-Server-IBRS"].get('alias-of'), 169 "Skylake-Server-v2", 170 "Skylake-Server-IBRS must be an alias") 171 172 self.assertEqual(cpus["EPYC"].get('alias-of'), 173 "EPYC-v1", 174 "EPYC must be an alias") 175 self.assertEqual(cpus["EPYC-IBPB"].get('alias-of'), 176 "EPYC-v2", 177 "EPYC-IBPB must be an alias") 178 179 self.validate_aliases(cpus) 180 181 def test_none_alias(self): 182 """ 183 Check if unversioned CPU model is an alias pointing to some version 184 """ 185 self.set_machine('none') 186 self.vm.add_args('-S') 187 self.vm.launch() 188 189 cpus = dict((m['name'], m) for m in 190 self.vm.cmd('query-cpu-definitions')) 191 192 self.assertFalse(cpus['Cascadelake-Server']['static'], 193 'unversioned Cascadelake-Server CPU model must not be static') 194 self.assertTrue(re.match('Cascadelake-Server-v[0-9]+', cpus['Cascadelake-Server']['alias-of']), 195 'Cascadelake-Server must be an alias of versioned CPU model') 196 self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'], 197 'Cascadelake-Server-v1 must not be an alias') 198 199 self.assertFalse(cpus['qemu64']['static'], 200 'unversioned qemu64 CPU model must not be static') 201 self.assertTrue(re.match('qemu64-v[0-9]+', cpus['qemu64']['alias-of']), 202 'qemu64 must be an alias of versioned CPU model') 203 self.assertNotIn('alias-of', cpus['qemu64-v1'], 204 'qemu64-v1 must not be an alias') 205 206 self.validate_aliases(cpus) 207 208 209class CascadelakeArchCapabilities(QemuSystemTest): 210 """ 211 Validation of Cascadelake arch-capabilities 212 """ 213 def get_cpu_prop(self, prop): 214 cpu_path = self.vm.cmd('query-cpus-fast')[0].get('qom-path') 215 return self.vm.cmd('qom-get', path=cpu_path, property=prop) 216 217 def test(self): 218 self.set_machine('pc') 219 # machine-type only: 220 self.vm.add_args('-S') 221 self.set_vm_arg('-cpu', 222 'Cascadelake-Server,x-force-features=on,check=off,' 223 'enforce=off') 224 self.vm.launch() 225 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 226 'pc + Cascadelake-Server should not have arch-capabilities') 227 228 def test_unset(self): 229 self.set_machine('pc') 230 self.vm.add_args('-S') 231 self.set_vm_arg('-cpu', 232 'Cascadelake-Server,x-force-features=on,check=off,' 233 'enforce=off,-arch-capabilities') 234 self.vm.launch() 235 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 236 'pc + Cascadelake-Server,-arch-capabilities should not have arch-capabilities') 237 238 def test_v2_unset(self): 239 self.set_machine('pc') 240 self.vm.add_args('-S') 241 self.set_vm_arg('-cpu', 242 'Cascadelake-Server-v2,x-force-features=on,check=off,' 243 'enforce=off,-arch-capabilities') 244 self.vm.launch() 245 self.assertFalse(self.get_cpu_prop('arch-capabilities'), 246 'pc + Cascadelake-Server-v2,-arch-capabilities should not have arch-capabilities') 247 248if __name__ == '__main__': 249 QemuSystemTest.main() 250