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