qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

tpm-tis-util.c (17841B)


      1 /*
      2  * QTest testcase for TPM TIS: common test functions used for both
      3  * the ISA and SYSBUS devices
      4  *
      5  * Copyright (c) 2018 Red Hat, Inc.
      6  * Copyright (c) 2018 IBM Corporation
      7  *
      8  * Authors:
      9  *   Marc-André Lureau <marcandre.lureau@redhat.com>
     10  *   Stefan Berger <stefanb@linux.vnet.ibm.com>
     11  *
     12  * This work is licensed under the terms of the GNU GPL, version 2 or later.
     13  * See the COPYING file in the top-level directory.
     14  */
     15 
     16 #include "qemu/osdep.h"
     17 #include <glib/gstdio.h>
     18 
     19 #include "hw/acpi/tpm.h"
     20 #include "io/channel-socket.h"
     21 #include "libqtest-single.h"
     22 #include "qemu/module.h"
     23 #include "tpm-emu.h"
     24 #include "tpm-util.h"
     25 #include "tpm-tis-util.h"
     26 
     27 #define DEBUG_TIS_TEST 0
     28 
     29 #define DPRINTF(fmt, ...) do { \
     30     if (DEBUG_TIS_TEST) { \
     31         printf(fmt, ## __VA_ARGS__); \
     32     } \
     33 } while (0)
     34 
     35 #define DPRINTF_ACCESS \
     36     DPRINTF("%s: %d: locty=%d l=%d access=0x%02x pending_request_flag=0x%x\n", \
     37             __func__, __LINE__, locty, l, access, pending_request_flag)
     38 
     39 #define DPRINTF_STS \
     40     DPRINTF("%s: %d: sts = 0x%08x\n", __func__, __LINE__, sts)
     41 
     42 static const uint8_t TPM_CMD[12] =
     43     "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00";
     44 
     45 void tpm_tis_test_check_localities(const void *data)
     46 {
     47     uint8_t locty;
     48     uint8_t access;
     49     uint32_t ifaceid;
     50     uint32_t capability;
     51     uint32_t didvid;
     52     uint32_t rid;
     53 
     54     for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) {
     55         access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS));
     56         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
     57                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
     58 
     59         capability = readl(TIS_REG(locty, TPM_TIS_REG_INTF_CAPABILITY));
     60         g_assert_cmpint(capability, ==, TPM_TIS_CAPABILITIES_SUPPORTED2_0);
     61 
     62         ifaceid = readl(TIS_REG(locty, TPM_TIS_REG_INTERFACE_ID));
     63         g_assert_cmpint(ifaceid, ==, TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0);
     64 
     65         didvid = readl(TIS_REG(locty, TPM_TIS_REG_DID_VID));
     66         g_assert_cmpint(didvid, !=, 0);
     67         g_assert_cmpint(didvid, !=, 0xffffffff);
     68 
     69         rid = readl(TIS_REG(locty, TPM_TIS_REG_RID));
     70         g_assert_cmpint(rid, !=, 0);
     71         g_assert_cmpint(rid, !=, 0xffffffff);
     72     }
     73 }
     74 
     75 void tpm_tis_test_check_access_reg(const void *data)
     76 {
     77     uint8_t locty;
     78     uint8_t access;
     79 
     80     /* do not test locality 4 (hw only) */
     81     for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) {
     82         access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS));
     83         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
     84                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
     85 
     86         /* request use of locality */
     87         writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE);
     88 
     89         access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS));
     90         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
     91                                     TPM_TIS_ACCESS_ACTIVE_LOCALITY |
     92                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
     93 
     94         /* release access */
     95         writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS),
     96                TPM_TIS_ACCESS_ACTIVE_LOCALITY);
     97         access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS));
     98         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
     99                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    100     }
    101 }
    102 
    103 /*
    104  * Test case for seizing access by a higher number locality
    105  */
    106 void tpm_tis_test_check_access_reg_seize(const void *data)
    107 {
    108     int locty, l;
    109     uint8_t access;
    110     uint8_t pending_request_flag;
    111 
    112     /* do not test locality 4 (hw only) */
    113     for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) {
    114         pending_request_flag = 0;
    115 
    116         access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS));
    117         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    118                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    119 
    120         /* request use of locality */
    121         writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE);
    122         access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS));
    123         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    124                                     TPM_TIS_ACCESS_ACTIVE_LOCALITY |
    125                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    126 
    127         /* lower localities cannot seize access */
    128         for (l = 0; l < locty; l++) {
    129             /* lower locality is not active */
    130             access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS));
    131             DPRINTF_ACCESS;
    132             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    133                                         pending_request_flag |
    134                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    135 
    136             /* try to request use from 'l' */
    137             writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE);
    138 
    139             /*
    140              * requesting use from 'l' was not possible;
    141              * we must see REQUEST_USE and possibly PENDING_REQUEST
    142              */
    143             access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS));
    144             DPRINTF_ACCESS;
    145             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    146                                         TPM_TIS_ACCESS_REQUEST_USE |
    147                                         pending_request_flag |
    148                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    149 
    150             /*
    151              * locality 'locty' must be unchanged;
    152              * we must see PENDING_REQUEST
    153              */
    154             access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS));
    155             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    156                                         TPM_TIS_ACCESS_ACTIVE_LOCALITY |
    157                                         TPM_TIS_ACCESS_PENDING_REQUEST |
    158                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    159 
    160             /* try to seize from 'l' */
    161             writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE);
    162             /* seize from 'l' was not possible */
    163             access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS));
    164             DPRINTF_ACCESS;
    165             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    166                                         TPM_TIS_ACCESS_REQUEST_USE |
    167                                         pending_request_flag |
    168                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    169 
    170             /* locality 'locty' must be unchanged */
    171             access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS));
    172             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    173                                         TPM_TIS_ACCESS_ACTIVE_LOCALITY |
    174                                         TPM_TIS_ACCESS_PENDING_REQUEST |
    175                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    176 
    177             /*
    178              * on the next loop we will have a PENDING_REQUEST flag
    179              * set for locality 'l'
    180              */
    181             pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST;
    182         }
    183 
    184         /*
    185          * higher localities can 'seize' access but not 'request use';
    186          * note: this will activate first l+1, then l+2 etc.
    187          */
    188         for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES - 1; l++) {
    189             /* try to 'request use' from 'l' */
    190             writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE);
    191 
    192             /*
    193              * requesting use from 'l' was not possible; we should see
    194              * REQUEST_USE and may see PENDING_REQUEST
    195              */
    196             access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS));
    197             DPRINTF_ACCESS;
    198             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    199                                         TPM_TIS_ACCESS_REQUEST_USE |
    200                                         pending_request_flag |
    201                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    202 
    203             /*
    204              * locality 'l-1' must be unchanged; we should always
    205              * see PENDING_REQUEST from 'l' requesting access
    206              */
    207             access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS));
    208             DPRINTF_ACCESS;
    209             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    210                                         TPM_TIS_ACCESS_ACTIVE_LOCALITY |
    211                                         TPM_TIS_ACCESS_PENDING_REQUEST |
    212                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    213 
    214             /* try to seize from 'l' */
    215             writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE);
    216 
    217             /* seize from 'l' was possible */
    218             access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS));
    219             DPRINTF_ACCESS;
    220             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    221                                         TPM_TIS_ACCESS_ACTIVE_LOCALITY |
    222                                         pending_request_flag |
    223                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    224 
    225             /* l - 1 should show that it has BEEN_SEIZED */
    226             access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS));
    227             DPRINTF_ACCESS;
    228             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    229                                         TPM_TIS_ACCESS_BEEN_SEIZED |
    230                                         pending_request_flag |
    231                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    232 
    233             /* clear the BEEN_SEIZED flag and make sure it's gone */
    234             writeb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS),
    235                    TPM_TIS_ACCESS_BEEN_SEIZED);
    236 
    237             access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS));
    238             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    239                                         pending_request_flag |
    240                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    241         }
    242 
    243         /*
    244          * PENDING_REQUEST will not be set if locty = 0 since all localities
    245          * were active; in case of locty = 1, locality 0 will be active
    246          * but no PENDING_REQUEST anywhere
    247          */
    248         if (locty <= 1) {
    249             pending_request_flag = 0;
    250         }
    251 
    252         /* release access from l - 1; this activates locty - 1 */
    253         l--;
    254 
    255         access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS));
    256         DPRINTF_ACCESS;
    257 
    258         DPRINTF("%s: %d: relinquishing control on l = %d\n",
    259                 __func__, __LINE__, l);
    260         writeb(TIS_REG(l, TPM_TIS_REG_ACCESS),
    261                TPM_TIS_ACCESS_ACTIVE_LOCALITY);
    262 
    263         access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS));
    264         DPRINTF_ACCESS;
    265         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    266                                     pending_request_flag |
    267                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    268 
    269         for (l = locty - 1; l >= 0; l--) {
    270             access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS));
    271             DPRINTF_ACCESS;
    272             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    273                                         TPM_TIS_ACCESS_ACTIVE_LOCALITY |
    274                                         pending_request_flag |
    275                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    276 
    277             /* release this locality */
    278             writeb(TIS_REG(l, TPM_TIS_REG_ACCESS),
    279                    TPM_TIS_ACCESS_ACTIVE_LOCALITY);
    280 
    281             if (l == 1) {
    282                 pending_request_flag = 0;
    283             }
    284         }
    285 
    286         /* no locality may be active now */
    287         for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) {
    288             access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS));
    289             DPRINTF_ACCESS;
    290             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    291                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    292         }
    293     }
    294 }
    295 
    296 /*
    297  * Test case for getting access when higher number locality relinquishes access
    298  */
    299 void tpm_tis_test_check_access_reg_release(const void *data)
    300 {
    301     int locty, l;
    302     uint8_t access;
    303     uint8_t pending_request_flag;
    304 
    305     /* do not test locality 4 (hw only) */
    306     for (locty = TPM_TIS_NUM_LOCALITIES - 2; locty >= 0; locty--) {
    307         pending_request_flag = 0;
    308 
    309         access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS));
    310         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    311                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    312 
    313         /* request use of locality */
    314         writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE);
    315         access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS));
    316         g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    317                                     TPM_TIS_ACCESS_ACTIVE_LOCALITY |
    318                                     TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    319 
    320         /* request use of all other localities */
    321         for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) {
    322             if (l == locty) {
    323                 continue;
    324             }
    325             /*
    326              * request use of locality 'l' -- we MUST see REQUEST USE and
    327              * may see PENDING_REQUEST
    328              */
    329             writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE);
    330             access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS));
    331             DPRINTF_ACCESS;
    332             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    333                                         TPM_TIS_ACCESS_REQUEST_USE |
    334                                         pending_request_flag |
    335                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    336             pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST;
    337         }
    338         /* release locality 'locty' */
    339         writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS),
    340                TPM_TIS_ACCESS_ACTIVE_LOCALITY);
    341         /*
    342          * highest locality should now be active; release it and make sure the
    343          * next higest locality is active afterwards
    344          */
    345         for (l = TPM_TIS_NUM_LOCALITIES - 2; l >= 0; l--) {
    346             if (l == locty) {
    347                 continue;
    348             }
    349             /* 'l' should be active now */
    350             access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS));
    351             DPRINTF_ACCESS;
    352             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    353                                         TPM_TIS_ACCESS_ACTIVE_LOCALITY |
    354                                         pending_request_flag |
    355                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    356             /* 'l' relinquishes access */
    357             writeb(TIS_REG(l, TPM_TIS_REG_ACCESS),
    358                    TPM_TIS_ACCESS_ACTIVE_LOCALITY);
    359             access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS));
    360             DPRINTF_ACCESS;
    361             if (l == 1 || (locty <= 1 && l == 2)) {
    362                 pending_request_flag = 0;
    363             }
    364             g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    365                                         pending_request_flag |
    366                                         TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    367         }
    368     }
    369 }
    370 
    371 /*
    372  * Test case for transmitting packets
    373  */
    374 void tpm_tis_test_check_transmit(const void *data)
    375 {
    376     const TPMTestState *s = data;
    377     uint8_t access;
    378     uint32_t sts;
    379     uint16_t bcount;
    380     size_t i;
    381 
    382     /* request use of locality 0 */
    383     writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE);
    384     access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS));
    385     g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
    386                                 TPM_TIS_ACCESS_ACTIVE_LOCALITY |
    387                                 TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
    388 
    389     sts = readl(TIS_REG(0, TPM_TIS_REG_STS));
    390     DPRINTF_STS;
    391 
    392     g_assert_cmpint(sts & 0xff, ==, 0);
    393     g_assert_cmpint(sts & TPM_TIS_STS_TPM_FAMILY_MASK, ==,
    394                     TPM_TIS_STS_TPM_FAMILY2_0);
    395 
    396     bcount = (sts >> 8) & 0xffff;
    397     g_assert_cmpint(bcount, >=, 128);
    398 
    399     writel(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY);
    400     sts = readl(TIS_REG(0, TPM_TIS_REG_STS));
    401     DPRINTF_STS;
    402     g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY);
    403 
    404     /* transmit command */
    405     for (i = 0; i < sizeof(TPM_CMD); i++) {
    406         writeb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO), TPM_CMD[i]);
    407         sts = readl(TIS_REG(0, TPM_TIS_REG_STS));
    408         DPRINTF_STS;
    409         if (i < sizeof(TPM_CMD) - 1) {
    410             g_assert_cmpint(sts & 0xff, ==,
    411                             TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
    412         } else {
    413             g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_VALID);
    414         }
    415         g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount);
    416     }
    417     /* start processing */
    418     writeb(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_TPM_GO);
    419 
    420     uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND;
    421     do {
    422         sts = readl(TIS_REG(0, TPM_TIS_REG_STS));
    423         if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) {
    424             break;
    425         }
    426     } while (g_get_monotonic_time() < end_time);
    427 
    428     sts = readl(TIS_REG(0, TPM_TIS_REG_STS));
    429     DPRINTF_STS;
    430     g_assert_cmpint(sts & 0xff, == ,
    431                     TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE);
    432     bcount = (sts >> 8) & 0xffff;
    433 
    434     /* read response */
    435     uint8_t tpm_msg[sizeof(struct tpm_hdr)];
    436     g_assert_cmpint(sizeof(tpm_msg), ==, bcount);
    437 
    438     for (i = 0; i < sizeof(tpm_msg); i++) {
    439         tpm_msg[i] = readb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO));
    440         sts = readl(TIS_REG(0, TPM_TIS_REG_STS));
    441         DPRINTF_STS;
    442         if (sts & TPM_TIS_STS_DATA_AVAILABLE) {
    443             g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount);
    444         }
    445     }
    446     g_assert_cmpmem(tpm_msg, sizeof(tpm_msg), s->tpm_msg, sizeof(*s->tpm_msg));
    447 
    448     /* relinquish use of locality 0 */
    449     writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_ACTIVE_LOCALITY);
    450     access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS));
    451 }