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