cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

x86_cpu_model_versions.py (15930B)


      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.Test):
     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.Test):
    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')