xref: /openbmc/qemu/tests/functional/test_x86_cpu_model_versions.py (revision b92b39af4219df4250f121f64d215506909c7404)
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