From 2e8f7675b59f9cf448ff3cf2ec1671350ad60a67 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 5 Mar 2020 17:51:43 +0100 Subject: tpm: Separate TPM_TIS and TPM_TIS_ISA configs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's separate the compilation of tpm_tis_common.c from the compilation of tpm_tis_isa.c The common part will be also compiled along with the tpm_tis_sysbus device. Signed-off-by: Eric Auger Reviewed-by: Philippe Mathieu-Daudé Tested-by: Ard Biesheuvel Acked-by: Ard Biesheuvel Message-id: 20200305165149.618-5-eric.auger@redhat.com Signed-off-by: Stefan Berger --- tests/qtest/Makefile.include | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tests') diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include index e769c1ad70..028af5b782 100644 --- a/tests/qtest/Makefile.include +++ b/tests/qtest/Makefile.include @@ -54,8 +54,8 @@ check-qtest-i386-y += q35-test check-qtest-i386-y += vmgenid-test check-qtest-i386-$(CONFIG_TPM_CRB) += tpm-crb-swtpm-test check-qtest-i386-$(CONFIG_TPM_CRB) += tpm-crb-test -check-qtest-i386-$(CONFIG_TPM_TIS) += tpm-tis-swtpm-test -check-qtest-i386-$(CONFIG_TPM_TIS) += tpm-tis-test +check-qtest-i386-$(CONFIG_TPM_TIS_ISA) += tpm-tis-swtpm-test +check-qtest-i386-$(CONFIG_TPM_TIS_ISA) += tpm-tis-test check-qtest-i386-$(CONFIG_SLIRP) += test-netfilter check-qtest-i386-$(CONFIG_POSIX) += test-filter-mirror check-qtest-i386-$(CONFIG_RTL8139_PCI) += test-filter-redirector -- cgit v1.2.3 From 551cabdfa9acaf6bb245a5c01d3fa4a15fc714de Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 5 Mar 2020 17:51:47 +0100 Subject: test: tpm: pass optional machine options to swtpm test functions We plan to use swtpm test functions on ARM for testing the sysbus TPM-TIS device. However on ARM there is no default machine type. So we need to explictly pass some machine options on startup. Let's allow this by adding a new parameter to both swtpm test functions and update all call sites. Signed-off-by: Eric Auger Reviewed-by: Stefan Berger Message-id: 20200305165149.618-9-eric.auger@redhat.com Signed-off-by: Stefan Berger --- tests/qtest/tpm-crb-swtpm-test.c | 5 +++-- tests/qtest/tpm-tests.c | 10 ++++++---- tests/qtest/tpm-tests.h | 5 +++-- tests/qtest/tpm-tis-swtpm-test.c | 5 +++-- tests/qtest/tpm-util.c | 8 ++++++-- tests/qtest/tpm-util.h | 3 ++- 6 files changed, 23 insertions(+), 13 deletions(-) (limited to 'tests') diff --git a/tests/qtest/tpm-crb-swtpm-test.c b/tests/qtest/tpm-crb-swtpm-test.c index 2c4fb8ae29..5228cb7af4 100644 --- a/tests/qtest/tpm-crb-swtpm-test.c +++ b/tests/qtest/tpm-crb-swtpm-test.c @@ -29,7 +29,8 @@ static void tpm_crb_swtpm_test(const void *data) { const TestState *ts = data; - tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_crb_transfer, "tpm-crb"); + tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_crb_transfer, + "tpm-crb", NULL); } static void tpm_crb_swtpm_migration_test(const void *data) @@ -37,7 +38,7 @@ static void tpm_crb_swtpm_migration_test(const void *data) const TestState *ts = data; tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri, - tpm_util_crb_transfer, "tpm-crb"); + tpm_util_crb_transfer, "tpm-crb", NULL); } int main(int argc, char **argv) diff --git a/tests/qtest/tpm-tests.c b/tests/qtest/tpm-tests.c index 6e45a0ba85..a2f2838e15 100644 --- a/tests/qtest/tpm-tests.c +++ b/tests/qtest/tpm-tests.c @@ -30,7 +30,7 @@ tpm_test_swtpm_skip(void) } void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, - const char *ifmodel) + const char *ifmodel, const char *machine_options) { char *args = NULL; QTestState *s; @@ -47,10 +47,11 @@ void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, g_assert_true(succ); args = g_strdup_printf( + "%s " "-chardev socket,id=chr,path=%s " "-tpmdev emulator,id=dev,chardev=chr " "-device %s,tpmdev=dev", - addr->u.q_unix.path, ifmodel); + machine_options ? : "", addr->u.q_unix.path, ifmodel); s = qtest_start(args); g_free(args); @@ -78,7 +79,8 @@ void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, void tpm_test_swtpm_migration_test(const char *src_tpm_path, const char *dst_tpm_path, const char *uri, tx_func *tx, - const char *ifmodel) + const char *ifmodel, + const char *machine_options) { gboolean succ; GPid src_tpm_pid, dst_tpm_pid; @@ -100,7 +102,7 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path, tpm_util_migration_start_qemu(&src_qemu, &dst_qemu, src_tpm_addr, dst_tpm_addr, uri, - ifmodel); + ifmodel, machine_options); tpm_util_startup(src_qemu, tx); tpm_util_pcrextend(src_qemu, tx); diff --git a/tests/qtest/tpm-tests.h b/tests/qtest/tpm-tests.h index b97688fe75..a5df35ab5b 100644 --- a/tests/qtest/tpm-tests.h +++ b/tests/qtest/tpm-tests.h @@ -16,11 +16,12 @@ #include "tpm-util.h" void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, - const char *ifmodel); + const char *ifmodel, const char *machine_options); void tpm_test_swtpm_migration_test(const char *src_tpm_path, const char *dst_tpm_path, const char *uri, tx_func *tx, - const char *ifmodel); + const char *ifmodel, + const char *machine_options); #endif /* TESTS_TPM_TESTS_H */ diff --git a/tests/qtest/tpm-tis-swtpm-test.c b/tests/qtest/tpm-tis-swtpm-test.c index 9f58a3a92b..9470f15751 100644 --- a/tests/qtest/tpm-tis-swtpm-test.c +++ b/tests/qtest/tpm-tis-swtpm-test.c @@ -29,7 +29,8 @@ static void tpm_tis_swtpm_test(const void *data) { const TestState *ts = data; - tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer, "tpm-tis"); + tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer, + "tpm-tis", NULL); } static void tpm_tis_swtpm_migration_test(const void *data) @@ -37,7 +38,7 @@ static void tpm_tis_swtpm_migration_test(const void *data) const TestState *ts = data; tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri, - tpm_util_tis_transfer, "tpm-tis"); + tpm_util_tis_transfer, "tpm-tis", NULL); } int main(int argc, char **argv) diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c index e08b137651..7ecdae2fc6 100644 --- a/tests/qtest/tpm-util.c +++ b/tests/qtest/tpm-util.c @@ -258,23 +258,27 @@ void tpm_util_migration_start_qemu(QTestState **src_qemu, SocketAddress *src_tpm_addr, SocketAddress *dst_tpm_addr, const char *miguri, - const char *ifmodel) + const char *ifmodel, + const char *machine_options) { char *src_qemu_args, *dst_qemu_args; src_qemu_args = g_strdup_printf( + "%s " "-chardev socket,id=chr,path=%s " "-tpmdev emulator,id=dev,chardev=chr " "-device %s,tpmdev=dev ", - src_tpm_addr->u.q_unix.path, ifmodel); + machine_options ? : "", src_tpm_addr->u.q_unix.path, ifmodel); *src_qemu = qtest_init(src_qemu_args); dst_qemu_args = g_strdup_printf( + "%s " "-chardev socket,id=chr,path=%s " "-tpmdev emulator,id=dev,chardev=chr " "-device %s,tpmdev=dev " "-incoming %s", + machine_options ? : "", dst_tpm_addr->u.q_unix.path, ifmodel, miguri); diff --git a/tests/qtest/tpm-util.h b/tests/qtest/tpm-util.h index 5755698ad2..15e3924942 100644 --- a/tests/qtest/tpm-util.h +++ b/tests/qtest/tpm-util.h @@ -44,7 +44,8 @@ void tpm_util_migration_start_qemu(QTestState **src_qemu, SocketAddress *src_tpm_addr, SocketAddress *dst_tpm_addr, const char *miguri, - const char *ifmodel); + const char *ifmodel, + const char *machine_options); void tpm_util_wait_for_migration_complete(QTestState *who); -- cgit v1.2.3 From 5166c32617065a66e3f95e49381f15bf29ce6799 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 5 Mar 2020 17:51:48 +0100 Subject: test: tpm-tis: Get prepared to share tests between ISA and sysbus devices ISA and sysbus TPM-TIS devices will share their tests. Only the main() will change (instantiation option is different). Also the base address of the TPM-TIS device is going to be different. on x86 it is located at 0xFED40000 while on ARM it can be located at any location, discovered through the device tree description. So we put shared test functions in a new object module. Each test needs to set tpm_tis_base_addr global variable. Also take benefit of this move to fix "block comments using a leading */ on a separate line" checkpatch warnings. Signed-off-by: Eric Auger Reviewed-by: Stefan Berger Message-id: 20200305165149.618-10-eric.auger@redhat.com Signed-off-by: Stefan Berger --- tests/qtest/Makefile.include | 2 +- tests/qtest/tpm-crb-swtpm-test.c | 4 + tests/qtest/tpm-crb-test.c | 3 + tests/qtest/tpm-tis-swtpm-test.c | 3 + tests/qtest/tpm-tis-test.c | 414 +---------------------------------- tests/qtest/tpm-tis-util.c | 451 +++++++++++++++++++++++++++++++++++++++ tests/qtest/tpm-tis-util.h | 23 ++ tests/qtest/tpm-util.c | 3 - tests/qtest/tpm-util.h | 5 + 9 files changed, 493 insertions(+), 415 deletions(-) create mode 100644 tests/qtest/tpm-tis-util.c create mode 100644 tests/qtest/tpm-tis-util.h (limited to 'tests') diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include index 028af5b782..44aac68b25 100644 --- a/tests/qtest/Makefile.include +++ b/tests/qtest/Makefile.include @@ -302,7 +302,7 @@ tests/qtest/tpm-crb-swtpm-test$(EXESUF): tests/qtest/tpm-crb-swtpm-test.o tests/ tests/qtest/tpm-crb-test$(EXESUF): tests/qtest/tpm-crb-test.o tests/qtest/tpm-emu.o $(test-io-obj-y) tests/qtest/tpm-tis-swtpm-test$(EXESUF): tests/qtest/tpm-tis-swtpm-test.o tests/qtest/tpm-emu.o \ tests/qtest/tpm-util.o tests/qtest/tpm-tests.o $(test-io-obj-y) -tests/qtest/tpm-tis-test$(EXESUF): tests/qtest/tpm-tis-test.o tests/qtest/tpm-emu.o $(test-io-obj-y) +tests/qtest/tpm-tis-test$(EXESUF): tests/qtest/tpm-tis-test.o tests/qtest/tpm-tis-util.o tests/qtest/tpm-emu.o $(test-io-obj-y) # QTest rules diff --git a/tests/qtest/tpm-crb-swtpm-test.c b/tests/qtest/tpm-crb-swtpm-test.c index 5228cb7af4..55fdb5657d 100644 --- a/tests/qtest/tpm-crb-swtpm-test.c +++ b/tests/qtest/tpm-crb-swtpm-test.c @@ -18,6 +18,10 @@ #include "libqtest.h" #include "qemu/module.h" #include "tpm-tests.h" +#include "hw/acpi/tpm.h" + +/* Not used but needed for linking */ +uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; typedef struct TestState { char *src_tpm_path; diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c index 632fb7fbd8..ed533900d1 100644 --- a/tests/qtest/tpm-crb-test.c +++ b/tests/qtest/tpm-crb-test.c @@ -19,6 +19,9 @@ #include "qemu/module.h" #include "tpm-emu.h" +/* Not used but needed for linking */ +uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; + #define TPM_CMD "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00" static void tpm_crb_test(const void *data) diff --git a/tests/qtest/tpm-tis-swtpm-test.c b/tests/qtest/tpm-tis-swtpm-test.c index 9470f15751..90131cb3c4 100644 --- a/tests/qtest/tpm-tis-swtpm-test.c +++ b/tests/qtest/tpm-tis-swtpm-test.c @@ -18,6 +18,9 @@ #include "libqtest.h" #include "qemu/module.h" #include "tpm-tests.h" +#include "hw/acpi/tpm.h" + +uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; typedef struct TestState { char *src_tpm_path; diff --git a/tests/qtest/tpm-tis-test.c b/tests/qtest/tpm-tis-test.c index dcf30e05b7..79ffbc943e 100644 --- a/tests/qtest/tpm-tis-test.c +++ b/tests/qtest/tpm-tis-test.c @@ -1,5 +1,5 @@ /* - * QTest testcase for TPM TIS + * QTest testcase for ISA TPM TIS * * Copyright (c) 2018 Red Hat, Inc. * Copyright (c) 2018 IBM Corporation @@ -20,417 +20,9 @@ #include "libqtest-single.h" #include "qemu/module.h" #include "tpm-emu.h" +#include "tpm-tis-util.h" -#define TIS_REG(LOCTY, REG) \ - (TPM_TIS_ADDR_BASE + ((LOCTY) << 12) + REG) - -#define DEBUG_TIS_TEST 0 - -#define DPRINTF(fmt, ...) do { \ - if (DEBUG_TIS_TEST) { \ - printf(fmt, ## __VA_ARGS__); \ - } \ -} while (0) - -#define DPRINTF_ACCESS \ - DPRINTF("%s: %d: locty=%d l=%d access=0x%02x pending_request_flag=0x%x\n", \ - __func__, __LINE__, locty, l, access, pending_request_flag) - -#define DPRINTF_STS \ - DPRINTF("%s: %d: sts = 0x%08x\n", __func__, __LINE__, sts) - -static const uint8_t TPM_CMD[12] = - "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00"; - -static void tpm_tis_test_check_localities(const void *data) -{ - uint8_t locty; - uint8_t access; - uint32_t ifaceid; - uint32_t capability; - uint32_t didvid; - uint32_t rid; - - for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) { - access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - capability = readl(TIS_REG(locty, TPM_TIS_REG_INTF_CAPABILITY)); - g_assert_cmpint(capability, ==, TPM_TIS_CAPABILITIES_SUPPORTED2_0); - - ifaceid = readl(TIS_REG(locty, TPM_TIS_REG_INTERFACE_ID)); - g_assert_cmpint(ifaceid, ==, TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0); - - didvid = readl(TIS_REG(locty, TPM_TIS_REG_DID_VID)); - g_assert_cmpint(didvid, !=, 0); - g_assert_cmpint(didvid, !=, 0xffffffff); - - rid = readl(TIS_REG(locty, TPM_TIS_REG_RID)); - g_assert_cmpint(rid, !=, 0); - g_assert_cmpint(rid, !=, 0xffffffff); - } -} - -static void tpm_tis_test_check_access_reg(const void *data) -{ - uint8_t locty; - uint8_t access; - - /* do not test locality 4 (hw only) */ - for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* request use of locality */ - writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); - - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_ACTIVE_LOCALITY | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* release access */ - writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), - TPM_TIS_ACCESS_ACTIVE_LOCALITY); - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - } -} - -/* - * Test case for seizing access by a higher number locality - */ -static void tpm_tis_test_check_access_reg_seize(const void *data) -{ - int locty, l; - uint8_t access; - uint8_t pending_request_flag; - - /* do not test locality 4 (hw only) */ - for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { - pending_request_flag = 0; - - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* request use of locality */ - writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_ACTIVE_LOCALITY | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* lower localities cannot seize access */ - for (l = 0; l < locty; l++) { - /* lower locality is not active */ - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - pending_request_flag | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* try to request use from 'l' */ - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); - - /* requesting use from 'l' was not possible; - we must see REQUEST_USE and possibly PENDING_REQUEST */ - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_REQUEST_USE | - pending_request_flag | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* locality 'locty' must be unchanged; - we must see PENDING_REQUEST */ - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_ACTIVE_LOCALITY | - TPM_TIS_ACCESS_PENDING_REQUEST | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* try to seize from 'l' */ - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); - /* seize from 'l' was not possible */ - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_REQUEST_USE | - pending_request_flag | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* locality 'locty' must be unchanged */ - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_ACTIVE_LOCALITY | - TPM_TIS_ACCESS_PENDING_REQUEST | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* on the next loop we will have a PENDING_REQUEST flag - set for locality 'l' */ - pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; - } - - /* higher localities can 'seize' access but not 'request use'; - note: this will activate first l+1, then l+2 etc. */ - for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { - /* try to 'request use' from 'l' */ - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); - - /* requesting use from 'l' was not possible; we should see - REQUEST_USE and may see PENDING_REQUEST */ - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_REQUEST_USE | - pending_request_flag | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* locality 'l-1' must be unchanged; we should always - see PENDING_REQUEST from 'l' requesting access */ - access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_ACTIVE_LOCALITY | - TPM_TIS_ACCESS_PENDING_REQUEST | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* try to seize from 'l' */ - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); - - /* seize from 'l' was possible */ - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_ACTIVE_LOCALITY | - pending_request_flag | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* l - 1 should show that it has BEEN_SEIZED */ - access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_BEEN_SEIZED | - pending_request_flag | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* clear the BEEN_SEIZED flag and make sure it's gone */ - writeb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS), - TPM_TIS_ACCESS_BEEN_SEIZED); - - access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - pending_request_flag | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - } - - /* PENDING_REQUEST will not be set if locty = 0 since all localities - were active; in case of locty = 1, locality 0 will be active - but no PENDING_REQUEST anywhere */ - if (locty <= 1) { - pending_request_flag = 0; - } - - /* release access from l - 1; this activates locty - 1 */ - l--; - - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - - DPRINTF("%s: %d: relinquishing control on l = %d\n", - __func__, __LINE__, l); - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), - TPM_TIS_ACCESS_ACTIVE_LOCALITY); - - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - pending_request_flag | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - for (l = locty - 1; l >= 0; l--) { - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_ACTIVE_LOCALITY | - pending_request_flag | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* release this locality */ - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), - TPM_TIS_ACCESS_ACTIVE_LOCALITY); - - if (l == 1) { - pending_request_flag = 0; - } - } - - /* no locality may be active now */ - for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - } - } -} - -/* - * Test case for getting access when higher number locality relinquishes access - */ -static void tpm_tis_test_check_access_reg_release(const void *data) -{ - int locty, l; - uint8_t access; - uint8_t pending_request_flag; - - /* do not test locality 4 (hw only) */ - for (locty = TPM_TIS_NUM_LOCALITIES - 2; locty >= 0; locty--) { - pending_request_flag = 0; - - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* request use of locality */ - writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_ACTIVE_LOCALITY | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - /* request use of all other localities */ - for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { - if (l == locty) { - continue; - } - /* request use of locality 'l' -- we MUST see REQUEST USE and - may see PENDING_REQUEST */ - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_REQUEST_USE | - pending_request_flag | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; - } - /* release locality 'locty' */ - writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), - TPM_TIS_ACCESS_ACTIVE_LOCALITY); - /* highest locality should now be active; release it and make sure the - next higest locality is active afterwards */ - for (l = TPM_TIS_NUM_LOCALITIES - 2; l >= 0; l--) { - if (l == locty) { - continue; - } - /* 'l' should be active now */ - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_ACTIVE_LOCALITY | - pending_request_flag | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - /* 'l' relinquishes access */ - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), - TPM_TIS_ACCESS_ACTIVE_LOCALITY); - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); - DPRINTF_ACCESS; - if (l == 1 || (locty <= 1 && l == 2)) { - pending_request_flag = 0; - } - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - pending_request_flag | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - } - } -} - -/* - * Test case for transmitting packets - */ -static void tpm_tis_test_check_transmit(const void *data) -{ - const TestState *s = data; - uint8_t access; - uint32_t sts; - uint16_t bcount; - size_t i; - - /* request use of locality 0 */ - writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); - access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | - TPM_TIS_ACCESS_ACTIVE_LOCALITY | - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); - - sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); - DPRINTF_STS; - - g_assert_cmpint(sts & 0xff, ==, 0); - g_assert_cmpint(sts & TPM_TIS_STS_TPM_FAMILY_MASK, ==, - TPM_TIS_STS_TPM_FAMILY2_0); - - bcount = (sts >> 8) & 0xffff; - g_assert_cmpint(bcount, >=, 128); - - writel(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY); - sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); - DPRINTF_STS; - g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY); - - /* transmit command */ - for (i = 0; i < sizeof(TPM_CMD); i++) { - writeb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO), TPM_CMD[i]); - sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); - DPRINTF_STS; - if (i < sizeof(TPM_CMD) - 1) { - g_assert_cmpint(sts & 0xff, ==, - TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); - } else { - g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_VALID); - } - g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); - } - /* start processing */ - writeb(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_TPM_GO); - - uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND; - do { - sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); - if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) { - break; - } - } while (g_get_monotonic_time() < end_time); - - sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); - DPRINTF_STS; - g_assert_cmpint(sts & 0xff, == , - TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); - bcount = (sts >> 8) & 0xffff; - - /* read response */ - uint8_t tpm_msg[sizeof(struct tpm_hdr)]; - g_assert_cmpint(sizeof(tpm_msg), ==, bcount); - - for (i = 0; i < sizeof(tpm_msg); i++) { - tpm_msg[i] = readb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO)); - sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); - DPRINTF_STS; - if (sts & TPM_TIS_STS_DATA_AVAILABLE) { - g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); - } - } - g_assert_cmpmem(tpm_msg, sizeof(tpm_msg), s->tpm_msg, sizeof(*s->tpm_msg)); - - /* relinquish use of locality 0 */ - writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_ACTIVE_LOCALITY); - access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); -} +uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; int main(int argc, char **argv) { diff --git a/tests/qtest/tpm-tis-util.c b/tests/qtest/tpm-tis-util.c new file mode 100644 index 0000000000..9aff503fd8 --- /dev/null +++ b/tests/qtest/tpm-tis-util.c @@ -0,0 +1,451 @@ +/* + * QTest testcase for TPM TIS: common test functions used for both + * the ISA and SYSBUS devices + * + * Copyright (c) 2018 Red Hat, Inc. + * Copyright (c) 2018 IBM Corporation + * + * Authors: + * Marc-André Lureau + * Stefan Berger + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include + +#include "hw/acpi/tpm.h" +#include "io/channel-socket.h" +#include "libqtest-single.h" +#include "qemu/module.h" +#include "tpm-emu.h" +#include "tpm-util.h" +#include "tpm-tis-util.h" + +#define DEBUG_TIS_TEST 0 + +#define DPRINTF(fmt, ...) do { \ + if (DEBUG_TIS_TEST) { \ + printf(fmt, ## __VA_ARGS__); \ + } \ +} while (0) + +#define DPRINTF_ACCESS \ + DPRINTF("%s: %d: locty=%d l=%d access=0x%02x pending_request_flag=0x%x\n", \ + __func__, __LINE__, locty, l, access, pending_request_flag) + +#define DPRINTF_STS \ + DPRINTF("%s: %d: sts = 0x%08x\n", __func__, __LINE__, sts) + +static const uint8_t TPM_CMD[12] = + "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00"; + +void tpm_tis_test_check_localities(const void *data) +{ + uint8_t locty; + uint8_t access; + uint32_t ifaceid; + uint32_t capability; + uint32_t didvid; + uint32_t rid; + + for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) { + access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + capability = readl(TIS_REG(locty, TPM_TIS_REG_INTF_CAPABILITY)); + g_assert_cmpint(capability, ==, TPM_TIS_CAPABILITIES_SUPPORTED2_0); + + ifaceid = readl(TIS_REG(locty, TPM_TIS_REG_INTERFACE_ID)); + g_assert_cmpint(ifaceid, ==, TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0); + + didvid = readl(TIS_REG(locty, TPM_TIS_REG_DID_VID)); + g_assert_cmpint(didvid, !=, 0); + g_assert_cmpint(didvid, !=, 0xffffffff); + + rid = readl(TIS_REG(locty, TPM_TIS_REG_RID)); + g_assert_cmpint(rid, !=, 0); + g_assert_cmpint(rid, !=, 0xffffffff); + } +} + +void tpm_tis_test_check_access_reg(const void *data) +{ + uint8_t locty; + uint8_t access; + + /* do not test locality 4 (hw only) */ + for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* request use of locality */ + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); + + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* release access */ + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), + TPM_TIS_ACCESS_ACTIVE_LOCALITY); + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + } +} + +/* + * Test case for seizing access by a higher number locality + */ +void tpm_tis_test_check_access_reg_seize(const void *data) +{ + int locty, l; + uint8_t access; + uint8_t pending_request_flag; + + /* do not test locality 4 (hw only) */ + for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { + pending_request_flag = 0; + + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* request use of locality */ + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* lower localities cannot seize access */ + for (l = 0; l < locty; l++) { + /* lower locality is not active */ + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* try to request use from 'l' */ + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); + + /* + * requesting use from 'l' was not possible; + * we must see REQUEST_USE and possibly PENDING_REQUEST + */ + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_REQUEST_USE | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* + * locality 'locty' must be unchanged; + * we must see PENDING_REQUEST + */ + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_PENDING_REQUEST | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* try to seize from 'l' */ + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); + /* seize from 'l' was not possible */ + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_REQUEST_USE | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* locality 'locty' must be unchanged */ + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_PENDING_REQUEST | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* + * on the next loop we will have a PENDING_REQUEST flag + * set for locality 'l' + */ + pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; + } + + /* + * higher localities can 'seize' access but not 'request use'; + * note: this will activate first l+1, then l+2 etc. + */ + for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { + /* try to 'request use' from 'l' */ + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); + + /* + * requesting use from 'l' was not possible; we should see + * REQUEST_USE and may see PENDING_REQUEST + */ + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_REQUEST_USE | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* + * locality 'l-1' must be unchanged; we should always + * see PENDING_REQUEST from 'l' requesting access + */ + access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_PENDING_REQUEST | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* try to seize from 'l' */ + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); + + /* seize from 'l' was possible */ + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* l - 1 should show that it has BEEN_SEIZED */ + access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_BEEN_SEIZED | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* clear the BEEN_SEIZED flag and make sure it's gone */ + writeb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS), + TPM_TIS_ACCESS_BEEN_SEIZED); + + access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + } + + /* + * PENDING_REQUEST will not be set if locty = 0 since all localities + * were active; in case of locty = 1, locality 0 will be active + * but no PENDING_REQUEST anywhere + */ + if (locty <= 1) { + pending_request_flag = 0; + } + + /* release access from l - 1; this activates locty - 1 */ + l--; + + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + + DPRINTF("%s: %d: relinquishing control on l = %d\n", + __func__, __LINE__, l); + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), + TPM_TIS_ACCESS_ACTIVE_LOCALITY); + + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + for (l = locty - 1; l >= 0; l--) { + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* release this locality */ + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), + TPM_TIS_ACCESS_ACTIVE_LOCALITY); + + if (l == 1) { + pending_request_flag = 0; + } + } + + /* no locality may be active now */ + for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + } + } +} + +/* + * Test case for getting access when higher number locality relinquishes access + */ +void tpm_tis_test_check_access_reg_release(const void *data) +{ + int locty, l; + uint8_t access; + uint8_t pending_request_flag; + + /* do not test locality 4 (hw only) */ + for (locty = TPM_TIS_NUM_LOCALITIES - 2; locty >= 0; locty--) { + pending_request_flag = 0; + + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* request use of locality */ + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + /* request use of all other localities */ + for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { + if (l == locty) { + continue; + } + /* + * request use of locality 'l' -- we MUST see REQUEST USE and + * may see PENDING_REQUEST + */ + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_REQUEST_USE | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; + } + /* release locality 'locty' */ + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), + TPM_TIS_ACCESS_ACTIVE_LOCALITY); + /* + * highest locality should now be active; release it and make sure the + * next higest locality is active afterwards + */ + for (l = TPM_TIS_NUM_LOCALITIES - 2; l >= 0; l--) { + if (l == locty) { + continue; + } + /* 'l' should be active now */ + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + /* 'l' relinquishes access */ + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), + TPM_TIS_ACCESS_ACTIVE_LOCALITY); + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); + DPRINTF_ACCESS; + if (l == 1 || (locty <= 1 && l == 2)) { + pending_request_flag = 0; + } + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + pending_request_flag | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + } + } +} + +/* + * Test case for transmitting packets + */ +void tpm_tis_test_check_transmit(const void *data) +{ + const TestState *s = data; + uint8_t access; + uint32_t sts; + uint16_t bcount; + size_t i; + + /* request use of locality 0 */ + writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); + access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | + TPM_TIS_ACCESS_ACTIVE_LOCALITY | + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); + + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); + DPRINTF_STS; + + g_assert_cmpint(sts & 0xff, ==, 0); + g_assert_cmpint(sts & TPM_TIS_STS_TPM_FAMILY_MASK, ==, + TPM_TIS_STS_TPM_FAMILY2_0); + + bcount = (sts >> 8) & 0xffff; + g_assert_cmpint(bcount, >=, 128); + + writel(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY); + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); + DPRINTF_STS; + g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY); + + /* transmit command */ + for (i = 0; i < sizeof(TPM_CMD); i++) { + writeb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO), TPM_CMD[i]); + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); + DPRINTF_STS; + if (i < sizeof(TPM_CMD) - 1) { + g_assert_cmpint(sts & 0xff, ==, + TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); + } else { + g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_VALID); + } + g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); + } + /* start processing */ + writeb(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_TPM_GO); + + uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND; + do { + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); + if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) { + break; + } + } while (g_get_monotonic_time() < end_time); + + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); + DPRINTF_STS; + g_assert_cmpint(sts & 0xff, == , + TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); + bcount = (sts >> 8) & 0xffff; + + /* read response */ + uint8_t tpm_msg[sizeof(struct tpm_hdr)]; + g_assert_cmpint(sizeof(tpm_msg), ==, bcount); + + for (i = 0; i < sizeof(tpm_msg); i++) { + tpm_msg[i] = readb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO)); + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); + DPRINTF_STS; + if (sts & TPM_TIS_STS_DATA_AVAILABLE) { + g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); + } + } + g_assert_cmpmem(tpm_msg, sizeof(tpm_msg), s->tpm_msg, sizeof(*s->tpm_msg)); + + /* relinquish use of locality 0 */ + writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_ACTIVE_LOCALITY); + access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); +} diff --git a/tests/qtest/tpm-tis-util.h b/tests/qtest/tpm-tis-util.h new file mode 100644 index 0000000000..d10efe86ae --- /dev/null +++ b/tests/qtest/tpm-tis-util.h @@ -0,0 +1,23 @@ +/* + * QTest TPM TIS: Common test functions used for both the + * ISA and SYSBUS devices + * + * Copyright (c) 2018 IBM Corporation + * + * Authors: + * Stefan Berger + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef TESTS_TPM_TIS_UTIL_H +#define TESTS_TPM_TIS_UTIL_H + +void tpm_tis_test_check_localities(const void *data); +void tpm_tis_test_check_access_reg(const void *data); +void tpm_tis_test_check_access_reg_seize(const void *data); +void tpm_tis_test_check_access_reg_release(const void *data); +void tpm_tis_test_check_transmit(const void *data); + +#endif /* TESTS_TPM_TIS_UTIL_H */ diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c index 7ecdae2fc6..34efae8f18 100644 --- a/tests/qtest/tpm-util.c +++ b/tests/qtest/tpm-util.c @@ -19,9 +19,6 @@ #include "tpm-util.h" #include "qapi/qmp/qdict.h" -#define TIS_REG(LOCTY, REG) \ - (TPM_TIS_ADDR_BASE + ((LOCTY) << 12) + REG) - void tpm_util_crb_transfer(QTestState *s, const unsigned char *req, size_t req_size, unsigned char *rsp, size_t rsp_size) diff --git a/tests/qtest/tpm-util.h b/tests/qtest/tpm-util.h index 15e3924942..3b97d69017 100644 --- a/tests/qtest/tpm-util.h +++ b/tests/qtest/tpm-util.h @@ -15,6 +15,11 @@ #include "io/channel-socket.h" +extern uint64_t tpm_tis_base_addr; + +#define TIS_REG(LOCTY, REG) \ + (tpm_tis_base_addr + ((LOCTY) << 12) + REG) + typedef void (tx_func)(QTestState *s, const unsigned char *req, size_t req_size, unsigned char *rsp, size_t rsp_size); -- cgit v1.2.3 From fe985ed6837ac6169ab9673547115df2897bcf6d Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 5 Mar 2020 17:51:49 +0100 Subject: test: tpm-tis: Add Sysbus TPM-TIS device test The tests themselves are the same as the ISA device ones. Only the main() changes as the "tpm-tis-device" device gets instantiated. Also the base address of the device is not 0xFED40000 anymore but matches the base address of the ARM virt platform bus. Signed-off-by: Eric Auger Reviewed-by: Stefan Berger Message-id: 20200305165149.618-11-eric.auger@redhat.com Signed-off-by: Stefan Berger --- tests/qtest/Makefile.include | 5 ++ tests/qtest/tpm-tis-device-swtpm-test.c | 76 ++++++++++++++++++++++++++++ tests/qtest/tpm-tis-device-test.c | 87 +++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 tests/qtest/tpm-tis-device-swtpm-test.c create mode 100644 tests/qtest/tpm-tis-device-test.c (limited to 'tests') diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include index 44aac68b25..383b0ab217 100644 --- a/tests/qtest/Makefile.include +++ b/tests/qtest/Makefile.include @@ -130,6 +130,8 @@ check-qtest-arm-y += hexloader-test check-qtest-arm-$(CONFIG_PFLASH_CFI02) += pflash-cfi02-test check-qtest-aarch64-y += arm-cpu-features +check-qtest-aarch64-$(CONFIG_TPM_TIS_SYSBUS) += tpm-tis-device-test +check-qtest-aarch64-$(CONFIG_TPM_TIS_SYSBUS) += tpm-tis-device-swtpm-test check-qtest-aarch64-y += numa-test check-qtest-aarch64-y += boot-serial-test check-qtest-aarch64-y += migration-test @@ -302,7 +304,10 @@ tests/qtest/tpm-crb-swtpm-test$(EXESUF): tests/qtest/tpm-crb-swtpm-test.o tests/ tests/qtest/tpm-crb-test$(EXESUF): tests/qtest/tpm-crb-test.o tests/qtest/tpm-emu.o $(test-io-obj-y) tests/qtest/tpm-tis-swtpm-test$(EXESUF): tests/qtest/tpm-tis-swtpm-test.o tests/qtest/tpm-emu.o \ tests/qtest/tpm-util.o tests/qtest/tpm-tests.o $(test-io-obj-y) +tests/qtest/tpm-tis-device-swtpm-test$(EXESUF): tests/qtest/tpm-tis-device-swtpm-test.o tests/qtest/tpm-emu.o \ + tests/qtest/tpm-util.o tests/qtest/tpm-tests.o $(test-io-obj-y) tests/qtest/tpm-tis-test$(EXESUF): tests/qtest/tpm-tis-test.o tests/qtest/tpm-tis-util.o tests/qtest/tpm-emu.o $(test-io-obj-y) +tests/qtest/tpm-tis-device-test$(EXESUF): tests/qtest/tpm-tis-device-test.o tests/qtest/tpm-tis-util.o tests/qtest/tpm-emu.o $(test-io-obj-y) # QTest rules diff --git a/tests/qtest/tpm-tis-device-swtpm-test.c b/tests/qtest/tpm-tis-device-swtpm-test.c new file mode 100644 index 0000000000..7b20035142 --- /dev/null +++ b/tests/qtest/tpm-tis-device-swtpm-test.c @@ -0,0 +1,76 @@ +/* + * QTest testcase for Sysbus TPM TIS talking to external swtpm and swtpm + * migration + * + * Copyright (c) 2018 IBM Corporation + * with parts borrowed from migration-test.c that is: + * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates + * + * Authors: + * Stefan Berger + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include + +#include "libqtest.h" +#include "qemu/module.h" +#include "tpm-tests.h" +#include "hw/acpi/tpm.h" + +uint64_t tpm_tis_base_addr = 0xc000000; +#define MACHINE_OPTIONS "-machine virt,gic-version=max -accel tcg" + +typedef struct TestState { + char *src_tpm_path; + char *dst_tpm_path; + char *uri; +} TestState; + +static void tpm_tis_swtpm_test(const void *data) +{ + const TestState *ts = data; + + tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer, + "tpm-tis-device", MACHINE_OPTIONS); +} + +static void tpm_tis_swtpm_migration_test(const void *data) +{ + const TestState *ts = data; + + tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri, + tpm_util_tis_transfer, "tpm-tis-device", + MACHINE_OPTIONS); +} + +int main(int argc, char **argv) +{ + int ret; + TestState ts = { 0 }; + + ts.src_tpm_path = g_dir_make_tmp("qemu-tpm-tis-device-swtpm-test.XXXXXX", + NULL); + ts.dst_tpm_path = g_dir_make_tmp("qemu-tpm-tis-device-swtpm-test.XXXXXX", + NULL); + ts.uri = g_strdup_printf("unix:%s/migsocket", ts.src_tpm_path); + + module_call_init(MODULE_INIT_QOM); + g_test_init(&argc, &argv, NULL); + + qtest_add_data_func("/tpm/tis-swtpm/test", &ts, tpm_tis_swtpm_test); + qtest_add_data_func("/tpm/tis-swtpm-migration/test", &ts, + tpm_tis_swtpm_migration_test); + ret = g_test_run(); + + g_rmdir(ts.dst_tpm_path); + g_free(ts.dst_tpm_path); + g_rmdir(ts.src_tpm_path); + g_free(ts.src_tpm_path); + g_free(ts.uri); + + return ret; +} diff --git a/tests/qtest/tpm-tis-device-test.c b/tests/qtest/tpm-tis-device-test.c new file mode 100644 index 0000000000..63ed36440f --- /dev/null +++ b/tests/qtest/tpm-tis-device-test.c @@ -0,0 +1,87 @@ +/* + * QTest testcase for SYSBUS TPM TIS + * + * Copyright (c) 2018 Red Hat, Inc. + * Copyright (c) 2018 IBM Corporation + * + * Authors: + * Marc-André Lureau + * Stefan Berger + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include + +#include "io/channel-socket.h" +#include "libqtest-single.h" +#include "qemu/module.h" +#include "tpm-emu.h" +#include "tpm-util.h" +#include "tpm-tis-util.h" + +/* + * As the Sysbus tpm-tis-device is instantiated on the ARM virt + * platform bus and it is the only sysbus device dynamically + * instantiated, it gets plugged at its base address + */ +uint64_t tpm_tis_base_addr = 0xc000000; + +int main(int argc, char **argv) +{ + char *tmp_path = g_dir_make_tmp("qemu-tpm-tis-device-test.XXXXXX", NULL); + GThread *thread; + TestState test; + char *args; + int ret; + + module_call_init(MODULE_INIT_QOM); + g_test_init(&argc, &argv, NULL); + + test.addr = g_new0(SocketAddress, 1); + test.addr->type = SOCKET_ADDRESS_TYPE_UNIX; + test.addr->u.q_unix.path = g_build_filename(tmp_path, "sock", NULL); + g_mutex_init(&test.data_mutex); + g_cond_init(&test.data_cond); + test.data_cond_signal = false; + + thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test); + tpm_emu_test_wait_cond(&test); + + args = g_strdup_printf( + "-machine virt,gic-version=max -accel tcg " + "-chardev socket,id=chr,path=%s " + "-tpmdev emulator,id=dev,chardev=chr " + "-device tpm-tis-device,tpmdev=dev", + test.addr->u.q_unix.path); + qtest_start(args); + + qtest_add_data_func("/tpm-tis/test_check_localities", &test, + tpm_tis_test_check_localities); + + qtest_add_data_func("/tpm-tis/test_check_access_reg", &test, + tpm_tis_test_check_access_reg); + + qtest_add_data_func("/tpm-tis/test_check_access_reg_seize", &test, + tpm_tis_test_check_access_reg_seize); + + qtest_add_data_func("/tpm-tis/test_check_access_reg_release", &test, + tpm_tis_test_check_access_reg_release); + + qtest_add_data_func("/tpm-tis/test_check_transmit", &test, + tpm_tis_test_check_transmit); + + ret = g_test_run(); + + qtest_end(); + + g_thread_join(thread); + g_unlink(test.addr->u.q_unix.path); + qapi_free_SocketAddress(test.addr); + g_rmdir(tmp_path); + g_free(tmp_path); + g_free(args); + return ret; +} -- cgit v1.2.3