Commit a94f1c2eff for qemu.org
commit a94f1c2eff993a5cafd666eed89e59775cde28b0
Author: Stefan Berger <stefanb@linux.vnet.ibm.com>
Date: Wed Apr 29 12:17:43 2026 +0000
tests: Add a TPM TIS I2C swtpm test
Add a test case testing the TPM TIS over I2C with swtpm.
Reviewed-by: Arun Menon <armenon@redhat.com>
Link: https://lore.kernel.org/qemu-devel/20260429121743.1346635-7-stefanb@linux.ibm.com
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 57512c6e56..45ea497fa5 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -244,7 +244,7 @@ qtests_arm = \
(config_all_devices.has_key('CONFIG_ASPEED_SOC') ? qtests_aspeed : []) + \
(config_all_devices.has_key('CONFIG_NPCM7XX') ? qtests_npcm7xx : []) + \
(config_all_devices.has_key('CONFIG_GENERIC_LOADER') ? ['hexloader-test'] : []) + \
- (config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
+ (config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test', 'tpm-tis-i2c-swtpm-test'] : []) + \
(config_all_devices.has_key('CONFIG_VEXPRESS') ? ['test-arm-mptimer'] : []) + \
(config_all_devices.has_key('CONFIG_MICROBIT') ? ['microbit-test'] : []) + \
(config_all_devices.has_key('CONFIG_STM32L4X5_SOC') ? qtests_stm32l4x5 : []) + \
@@ -263,7 +263,7 @@ qtests_aarch64 = \
(config_all_devices.has_key('CONFIG_XLNX_VERSAL') ? ['xlnx-canfd-test', 'xlnx-versal-trng-test'] : []) + \
(config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test', 'bcm2835-i2c-test'] : []) + \
(config_all_accel.has_key('CONFIG_TCG') and \
- config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
+ config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test', 'tpm-tis-i2c-swtpm-test'] : []) + \
(config_all_devices.has_key('CONFIG_ASPEED_SOC') ? qtests_aspeed64 : []) + \
(config_all_devices.has_key('CONFIG_NPCM8XX') ? qtests_npcm8xx : []) + \
(config_all_devices.has_key('CONFIG_IOMMU_TESTDEV') and
@@ -402,6 +402,7 @@ qtests = {
'tpm-tis-swtpm-test': [io, tpmemu_files, 'tpm-tis-util.c'],
'tpm-tis-test': [io, tpmemu_files, 'tpm-tis-util.c'],
'tpm-tis-i2c-test': [io, tpmemu_files, 'tpm-tis-i2c-util.c', 'qtest_aspeed.c'],
+ 'tpm-tis-i2c-swtpm-test': [io, tpmemu_files, 'tpm-tis-i2c-util.c', 'qtest_aspeed.c'],
'tpm-tis-device-swtpm-test': [io, tpmemu_files, 'tpm-tis-util.c'],
'tpm-tis-device-test': [io, tpmemu_files, 'tpm-tis-util.c'],
'virtio-net-failover': test_migration_files,
diff --git a/tests/qtest/tpm-tis-i2c-swtpm-test.c b/tests/qtest/tpm-tis-i2c-swtpm-test.c
new file mode 100644
index 0000000000..50d32a960b
--- /dev/null
+++ b/tests/qtest/tpm-tis-i2c-swtpm-test.c
@@ -0,0 +1,82 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * QTest testcase for TPM TIS over I2C talking to external swtpm
+ *
+ * Copyright (c) 2018, 2026 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 <stefanb@linux.ibm.com>
+ *
+ */
+
+#include "qemu/osdep.h"
+
+#include "libqtest.h"
+#include "qemu/module.h"
+#include "tpm-tests.h"
+#include "tpm-tis-i2c-util.h"
+#include "qtest_aspeed.h"
+
+typedef struct TestState {
+ char *src_tpm_path;
+ char *dst_tpm_path;
+ char *uri;
+ const char *machine_options;
+ char *ifmodel;
+} TestState;
+
+static void tpm_tis_i2c_swtpm_test(const void *data)
+{
+ const TestState *ts = data;
+
+ tpm_test_swtpm_test(ts->src_tpm_path, tpm_tis_i2c_transfer,
+ ts->ifmodel, ts->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_tis_i2c_transfer,
+ ts->ifmodel, ts->machine_options);
+}
+
+
+int main(int argc, char **argv)
+{
+ int ret;
+ TestState ts;
+
+ ts.src_tpm_path = g_dir_make_tmp("qemu-tpm-tis-i2c-swtpm-test.XXXXXX",
+ NULL);
+ ts.dst_tpm_path = g_dir_make_tmp("qemu-tpm-tis-i2c-swtpm-test.XXXXXX",
+ NULL);
+ ts.uri = g_strdup_printf("unix:%s/migsocket", ts.src_tpm_path);
+ ts.machine_options = "-machine rainier-bmc -accel tcg";
+ ts.ifmodel = g_strdup_printf(
+ "tpm-tis-i2c,bus=aspeed.i2c.bus.%d,address=0x%x",
+ I2C_DEV_BUS_NUM, I2C_SLAVE_ADDR);
+
+ module_call_init(MODULE_INIT_QOM);
+ g_test_init(&argc, &argv, NULL);
+
+ aspeed_bus_addr = ast2600_i2c_calc_bus_addr(I2C_DEV_BUS_NUM);
+
+ qtest_add_data_func("/tpm/tis-i2c-swtpm/test", &ts, tpm_tis_i2c_swtpm_test);
+ qtest_add_data_func("/tpm/tis-i2c-swtpm-migration/test", &ts,
+ tpm_tis_swtpm_migration_test);
+ ret = g_test_run();
+
+ tpm_util_rmdir(ts.dst_tpm_path);
+ g_free(ts.dst_tpm_path);
+ tpm_util_rmdir(ts.src_tpm_path);
+ g_free(ts.src_tpm_path);
+ g_free(ts.uri);
+ g_free(ts.ifmodel);
+
+ return ret;
+}
diff --git a/tests/qtest/tpm-tis-i2c-util.c b/tests/qtest/tpm-tis-i2c-util.c
index 6e724a4a47..c73420ec5b 100644
--- a/tests/qtest/tpm-tis-i2c-util.c
+++ b/tests/qtest/tpm-tis-i2c-util.c
@@ -15,6 +15,7 @@
#include "libqtest-single.h"
#include "qtest_aspeed.h"
#include "tpm-tis-i2c-util.h"
+#include "tpm-emu.h"
uint32_t aspeed_bus_addr;
@@ -62,3 +63,40 @@ void tpm_tis_i2c_writel(QTestState *s, uint8_t locty, uint8_t reg, uint32_t v)
}
aspeed_i2c_writel(s, aspeed_bus_addr, I2C_SLAVE_ADDR, reg, v);
}
+
+void tpm_tis_i2c_transfer(QTestState *s,
+ const unsigned char *req, size_t req_size,
+ unsigned char *rsp, size_t rsp_size)
+{
+ uint32_t sts;
+ size_t i;
+
+ /* request use of locality 0 */
+ tpm_tis_i2c_writeb(s, 0, TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE);
+
+ tpm_tis_i2c_writel(s, 0, TPM_I2C_REG_STS, TPM_TIS_STS_COMMAND_READY);
+
+ /* transmit command */
+ for (i = 0; i < req_size; i++) {
+ tpm_tis_i2c_writeb(s, 0, TPM_I2C_REG_DATA_FIFO, req[i]);
+ }
+
+ /* start processing */
+ tpm_tis_i2c_writeb(s, 0, TPM_I2C_REG_STS, TPM_TIS_STS_TPM_GO);
+
+ uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND;
+ do {
+ sts = tpm_tis_i2c_readl(s, 0, TPM_I2C_REG_STS);
+ if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) {
+ break;
+ }
+ } while (g_get_monotonic_time() < end_time);
+
+ /* read response */
+ for (i = 0; i < rsp_size; i++) {
+ rsp[i] = tpm_tis_i2c_readb(s, 0, TPM_I2C_REG_DATA_FIFO);
+ }
+ /* relinquish use of locality 0 */
+ tpm_tis_i2c_writeb(s, 0,
+ TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_ACTIVE_LOCALITY);
+}
diff --git a/tests/qtest/tpm-tis-i2c-util.h b/tests/qtest/tpm-tis-i2c-util.h
index 3289545f61..499bf4964a 100644
--- a/tests/qtest/tpm-tis-i2c-util.h
+++ b/tests/qtest/tpm-tis-i2c-util.h
@@ -27,4 +27,8 @@ uint32_t tpm_tis_i2c_readl(QTestState *s, uint8_t locty, uint8_t reg);
void tpm_tis_i2c_writeb(QTestState *s, uint8_t locty, uint8_t reg, uint8_t v);
void tpm_tis_i2c_writel(QTestState *s, uint8_t locty, uint8_t reg, uint32_t v);
+void tpm_tis_i2c_transfer(QTestState *s,
+ const unsigned char *req, size_t req_size,
+ unsigned char *rsp, size_t rsp_size);
+
#endif /* TESTS_TPM_TIS_I2C_UTIL_H */