qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] qtests: tpm: Add test cases for TPM TIS I2C device emulation
@ 2023-03-27 20:24 Stefan Berger
  2023-03-27 20:24 ` [PATCH 1/3] qtest: Add functions for accessing devices on Aspeed I2C controller Stefan Berger
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Stefan Berger @ 2023-03-27 20:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: marcandre.lureau, clg, ninad, joel, andrew, Stefan Berger

This series adds test cases exercising much of the TPM TIS I2C device model
assuming that the device is connected to the Aspeed I2C controller. Tests
are passing on little and big endian hosts.

This series of patches builds on the following series of patches
providing the TPM TIS I2C device emulation (v10):
https://lists.gnu.org/archive/html/qemu-devel/2023-03/msg06449.html

Note the additional comment here with a fix:
https://lists.gnu.org/archive/html/qemu-devel/2023-03/msg06464.html

Regards,
    Stefan

v2:
  - Split off Aspeed I2C controller library functions
  - Tweaking on test cases

Stefan Berger (3):
  qtest: Add functions for accessing devices on Aspeed I2C controller
  qtest: Move tpm_util_tis_transmit() into tpm-tis-utils.c and rename it
  qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C
    controller

 include/hw/i2c/aspeed_i2c.h             |   7 +
 tests/qtest/meson.build                 |   3 +
 tests/qtest/qtest_aspeed.c              | 109 ++++
 tests/qtest/qtest_aspeed.h              |  34 ++
 tests/qtest/tpm-crb-swtpm-test.c        |   3 -
 tests/qtest/tpm-crb-test.c              |   3 -
 tests/qtest/tpm-tis-device-swtpm-test.c |   5 +-
 tests/qtest/tpm-tis-i2c-test.c          | 637 ++++++++++++++++++++++++
 tests/qtest/tpm-tis-swtpm-test.c        |   5 +-
 tests/qtest/tpm-tis-util.c              |  47 +-
 tests/qtest/tpm-tis-util.h              |   4 +
 tests/qtest/tpm-util.c                  |  45 --
 tests/qtest/tpm-util.h                  |   3 -
 13 files changed, 846 insertions(+), 59 deletions(-)
 create mode 100644 tests/qtest/qtest_aspeed.c
 create mode 100644 tests/qtest/qtest_aspeed.h
 create mode 100644 tests/qtest/tpm-tis-i2c-test.c

-- 
2.39.2



^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/3] qtest: Add functions for accessing devices on Aspeed I2C controller
  2023-03-27 20:24 [PATCH 0/3] qtests: tpm: Add test cases for TPM TIS I2C device emulation Stefan Berger
@ 2023-03-27 20:24 ` Stefan Berger
  2023-03-28  6:39   ` Cédric Le Goater
  2023-03-28 13:26   ` Ninad Palsule
  2023-03-27 20:24 ` [PATCH 2/3] qtest: Move tpm_util_tis_transmit() into tpm-tis-utils.c and rename it Stefan Berger
  2023-03-27 20:24 ` [PATCH 3/3] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller Stefan Berger
  2 siblings, 2 replies; 14+ messages in thread
From: Stefan Berger @ 2023-03-27 20:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: marcandre.lureau, clg, ninad, joel, andrew, Stefan Berger

Add read and write functions for accessing registers of I2C devices
connected to the Aspeed I2C controller.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
 include/hw/i2c/aspeed_i2c.h |   7 +++
 tests/qtest/qtest_aspeed.c  | 109 ++++++++++++++++++++++++++++++++++++
 tests/qtest/qtest_aspeed.h  |  34 +++++++++++
 3 files changed, 150 insertions(+)
 create mode 100644 tests/qtest/qtest_aspeed.c
 create mode 100644 tests/qtest/qtest_aspeed.h

diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
index adc904d6c1..51c944efea 100644
--- a/include/hw/i2c/aspeed_i2c.h
+++ b/include/hw/i2c/aspeed_i2c.h
@@ -38,6 +38,13 @@ OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C)
 #define ASPEED_I2C_OLD_NUM_REG 11
 #define ASPEED_I2C_NEW_NUM_REG 22
 
+#define A_I2CD_M_STOP_CMD       BIT(5)
+#define A_I2CD_M_RX_CMD         BIT(3)
+#define A_I2CD_M_TX_CMD         BIT(1)
+#define A_I2CD_M_START_CMD      BIT(0)
+
+#define A_I2CD_MASTER_EN        BIT(0)
+
 /* Tx State Machine */
 #define   I2CD_TX_STATE_MASK                  0xf
 #define     I2CD_IDLE                         0x0
diff --git a/tests/qtest/qtest_aspeed.c b/tests/qtest/qtest_aspeed.c
new file mode 100644
index 0000000000..2fcafc22fc
--- /dev/null
+++ b/tests/qtest/qtest_aspeed.c
@@ -0,0 +1,109 @@
+/*
+ * Aspeed i2c bus interface for reading from and writing to i2c device registers
+ *
+ * Copyright (c) 2023 IBM Corporation
+ *
+ * Authors:
+ *   Stefan Berger <stefanb@linux.ibm.com>
+ *
+ * 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 "qtest_aspeed.h"
+#include "hw/i2c/aspeed_i2c.h"
+#include "libqtest-single.h"
+
+static void aspeed_i2c_startup(uint32_t baseaddr, uint8_t slave_addr,
+                               uint8_t reg)
+{
+    uint32_t v;
+    static int once;
+
+    if (!once) {
+        /* one time: enable master */
+       writel(baseaddr + A_I2CC_FUN_CTRL, 0);
+       v = readl(baseaddr + A_I2CC_FUN_CTRL) | A_I2CD_MASTER_EN;
+       writel(baseaddr + A_I2CC_FUN_CTRL, v);
+       once = 1;
+    }
+
+    /* select device */
+    writel(baseaddr + A_I2CD_BYTE_BUF, slave_addr << 1);
+    writel(baseaddr + A_I2CD_CMD, A_I2CD_M_START_CMD | A_I2CD_M_RX_CMD);
+
+    /* select the register to write to */
+    writel(baseaddr + A_I2CD_BYTE_BUF, reg);
+    writel(baseaddr + A_I2CD_CMD, A_I2CD_M_TX_CMD);
+}
+
+static uint32_t aspeed_i2c_read_n(uint32_t baseaddr, uint8_t slave_addr,
+                                  uint8_t reg, size_t nbytes)
+{
+    uint32_t res = 0;
+    uint32_t v;
+    size_t i;
+
+    aspeed_i2c_startup(baseaddr, slave_addr, reg);
+
+    for (i = 0; i < nbytes; i++) {
+        writel(baseaddr + A_I2CD_CMD, A_I2CD_M_RX_CMD);
+        v = readl(baseaddr + A_I2CD_BYTE_BUF) >> 8;
+        res |= (v & 0xff) << (i * 8);
+    }
+
+    writel(baseaddr + A_I2CD_CMD, A_I2CD_M_STOP_CMD);
+
+    return res;
+}
+
+uint32_t aspeed_i2c_readl(uint32_t baseaddr, uint8_t slave_addr, uint8_t reg)
+{
+    return aspeed_i2c_read_n(baseaddr, slave_addr, reg, sizeof(uint32_t));
+}
+
+uint16_t aspeed_i2c_readw(uint32_t baseaddr, uint8_t slave_addr, uint8_t reg)
+{
+    return aspeed_i2c_read_n(baseaddr, slave_addr, reg, sizeof(uint16_t));
+}
+
+uint8_t aspeed_i2c_readb(uint32_t baseaddr, uint8_t slave_addr, uint8_t reg)
+{
+    return aspeed_i2c_read_n(baseaddr, slave_addr, reg, sizeof(uint8_t));
+}
+
+static void aspeed_i2c_write_n(uint32_t baseaddr, uint8_t slave_addr,
+                               uint8_t reg, uint32_t v, size_t nbytes)
+{
+    size_t i;
+
+    aspeed_i2c_startup(baseaddr, slave_addr, reg);
+
+    for (i = 0; i < nbytes; i++) {
+        writel(baseaddr + A_I2CD_BYTE_BUF, v & 0xff);
+        v >>= 8;
+        writel(baseaddr + A_I2CD_CMD, A_I2CD_M_TX_CMD);
+    }
+
+    writel(baseaddr + A_I2CD_CMD, A_I2CD_M_STOP_CMD);
+}
+
+void aspeed_i2c_writel(uint32_t baseaddr, uint8_t slave_addr,
+                       uint8_t reg, uint32_t v)
+{
+    aspeed_i2c_write_n(baseaddr, slave_addr, reg, v, sizeof(v));
+}
+
+void aspeed_i2c_writew(uint32_t baseaddr, uint8_t slave_addr,
+                       uint8_t reg, uint16_t v)
+{
+    aspeed_i2c_write_n(baseaddr, slave_addr, reg, v, sizeof(v));
+}
+
+void aspeed_i2c_writeb(uint32_t baseaddr, uint8_t slave_addr,
+                       uint8_t reg, uint8_t v)
+{
+    aspeed_i2c_write_n(baseaddr, slave_addr, reg, v, sizeof(v));
+}
diff --git a/tests/qtest/qtest_aspeed.h b/tests/qtest/qtest_aspeed.h
new file mode 100644
index 0000000000..529061cf5b
--- /dev/null
+++ b/tests/qtest/qtest_aspeed.h
@@ -0,0 +1,34 @@
+/*
+ * Aspeed i2c bus interface to reading and writing to i2c device registers
+ *
+ * Copyright (c) 2023 IBM Corporation
+ *
+ * Authors:
+ *   Stefan Berger <stefanb@linux.ibm.com>
+ *
+ * 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 QTEST_ASPEED_H
+#define QTEST_ASPEED_H
+
+#include <stdint.h>
+
+#define AST2600_ASPEED_I2C_BASE_ADDR 0x1e78a000
+
+static inline uint32_t ast2600_aspeed_i2c_calc_dev_addr(uint8_t bus_num)
+{
+    return AST2600_ASPEED_I2C_BASE_ADDR + 0x80 + bus_num * 0x80;
+}
+
+uint8_t aspeed_i2c_readb(uint32_t baseaddr, uint8_t slave_addr, uint8_t reg);
+uint16_t aspeed_i2c_readw(uint32_t baseaddr, uint8_t slave_addr, uint8_t reg);
+uint32_t aspeed_i2c_readl(uint32_t baseaddr, uint8_t slave_addr, uint8_t reg);
+void aspeed_i2c_writeb(uint32_t baseaddr, uint8_t slave_addr,
+                       uint8_t reg, uint8_t v);
+void aspeed_i2c_writew(uint32_t baseaddr, uint8_t slave_addr,
+                       uint8_t reg, uint16_t v);
+void aspeed_i2c_writel(uint32_t baseaddr, uint8_t slave_addr,
+                       uint8_t reg, uint32_t v);
+
+#endif
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/3] qtest: Move tpm_util_tis_transmit() into tpm-tis-utils.c and rename it
  2023-03-27 20:24 [PATCH 0/3] qtests: tpm: Add test cases for TPM TIS I2C device emulation Stefan Berger
  2023-03-27 20:24 ` [PATCH 1/3] qtest: Add functions for accessing devices on Aspeed I2C controller Stefan Berger
@ 2023-03-27 20:24 ` Stefan Berger
  2023-03-28 13:31   ` Ninad Palsule
  2023-03-27 20:24 ` [PATCH 3/3] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller Stefan Berger
  2 siblings, 1 reply; 14+ messages in thread
From: Stefan Berger @ 2023-03-27 20:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: marcandre.lureau, clg, ninad, joel, andrew, Stefan Berger

To be able to remove tpm_tis_base_addr from test cases that do not really
need it move the tpm_util_tis_transmit() function into tpm-tis-utils.c and
rename it to tpm_tis_transmit().

Fix a locality parameter in a test case on the way.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
 tests/qtest/tpm-crb-swtpm-test.c        |  3 --
 tests/qtest/tpm-crb-test.c              |  3 --
 tests/qtest/tpm-tis-device-swtpm-test.c |  5 +--
 tests/qtest/tpm-tis-swtpm-test.c        |  5 +--
 tests/qtest/tpm-tis-util.c              | 47 ++++++++++++++++++++++++-
 tests/qtest/tpm-tis-util.h              |  4 +++
 tests/qtest/tpm-util.c                  | 45 -----------------------
 tests/qtest/tpm-util.h                  |  3 --
 8 files changed, 56 insertions(+), 59 deletions(-)

diff --git a/tests/qtest/tpm-crb-swtpm-test.c b/tests/qtest/tpm-crb-swtpm-test.c
index 40254f762f..ffeb1c396b 100644
--- a/tests/qtest/tpm-crb-swtpm-test.c
+++ b/tests/qtest/tpm-crb-swtpm-test.c
@@ -19,9 +19,6 @@
 #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;
     char *dst_tpm_path;
diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c
index 7b94453390..396ae3f91c 100644
--- a/tests/qtest/tpm-crb-test.c
+++ b/tests/qtest/tpm-crb-test.c
@@ -19,9 +19,6 @@
 #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-device-swtpm-test.c b/tests/qtest/tpm-tis-device-swtpm-test.c
index 8c067fddd4..517a077005 100644
--- a/tests/qtest/tpm-tis-device-swtpm-test.c
+++ b/tests/qtest/tpm-tis-device-swtpm-test.c
@@ -18,6 +18,7 @@
 #include "libqtest.h"
 #include "qemu/module.h"
 #include "tpm-tests.h"
+#include "tpm-tis-util.h"
 #include "hw/acpi/tpm.h"
 
 uint64_t tpm_tis_base_addr = 0xc000000;
@@ -33,7 +34,7 @@ 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_test_swtpm_test(ts->src_tpm_path, tpm_tis_transfer,
                         "tpm-tis-device", MACHINE_OPTIONS);
 }
 
@@ -42,7 +43,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-device",
+                                  tpm_tis_transfer, "tpm-tis-device",
                                   MACHINE_OPTIONS);
 }
 
diff --git a/tests/qtest/tpm-tis-swtpm-test.c b/tests/qtest/tpm-tis-swtpm-test.c
index 11539c0a52..105e42e21d 100644
--- a/tests/qtest/tpm-tis-swtpm-test.c
+++ b/tests/qtest/tpm-tis-swtpm-test.c
@@ -17,6 +17,7 @@
 #include "libqtest.h"
 #include "qemu/module.h"
 #include "tpm-tests.h"
+#include "tpm-tis-util.h"
 #include "hw/acpi/tpm.h"
 
 uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE;
@@ -31,7 +32,7 @@ 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_test_swtpm_test(ts->src_tpm_path, tpm_tis_transfer,
                         "tpm-tis", NULL);
 }
 
@@ -40,7 +41,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", NULL);
+                                  tpm_tis_transfer, "tpm-tis", NULL);
 }
 
 int main(int argc, char **argv)
diff --git a/tests/qtest/tpm-tis-util.c b/tests/qtest/tpm-tis-util.c
index 939893bf01..728cd3e065 100644
--- a/tests/qtest/tpm-tis-util.c
+++ b/tests/qtest/tpm-tis-util.c
@@ -52,7 +52,7 @@ void tpm_tis_test_check_localities(const void *data)
     uint32_t rid;
 
     for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) {
-        access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS));
+        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);
 
@@ -449,3 +449,48 @@ void tpm_tis_test_check_transmit(const void *data)
     writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_ACTIVE_LOCALITY);
     access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS));
 }
+
+void tpm_tis_transfer(QTestState *s,
+                      const unsigned char *req, size_t req_size,
+                      unsigned char *rsp, size_t rsp_size)
+{
+    uint32_t sts;
+    uint16_t bcount;
+    size_t i;
+
+    /* request use of locality 0 */
+    qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE);
+    qtest_writel(s, TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY);
+
+    sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS));
+    bcount = (sts >> 8) & 0xffff;
+    g_assert_cmpint(bcount, >=, req_size);
+
+    /* transmit command */
+    for (i = 0; i < req_size; i++) {
+        qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_DATA_FIFO), req[i]);
+    }
+
+    /* start processing */
+    qtest_writeb(s, 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 = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS));
+        if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) {
+            break;
+        }
+    } while (g_get_monotonic_time() < end_time);
+
+    sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS));
+    bcount = (sts >> 8) & 0xffff;
+
+    memset(rsp, 0, rsp_size);
+    for (i = 0; i < bcount; i++) {
+        rsp[i] = qtest_readb(s, TIS_REG(0, TPM_TIS_REG_DATA_FIFO));
+    }
+
+    /* relinquish use of locality 0 */
+    qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_ACCESS),
+                 TPM_TIS_ACCESS_ACTIVE_LOCALITY);
+}
diff --git a/tests/qtest/tpm-tis-util.h b/tests/qtest/tpm-tis-util.h
index d10efe86ae..03910a7ba7 100644
--- a/tests/qtest/tpm-tis-util.h
+++ b/tests/qtest/tpm-tis-util.h
@@ -20,4 +20,8 @@ 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);
 
+void tpm_tis_transfer(QTestState *s,
+                      const unsigned char *req, size_t req_size,
+                      unsigned char *rsp, size_t rsp_size);
+
 #endif /* TESTS_TPM_TIS_UTIL_H */
diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c
index a7efe2d0d2..1c0319e6e7 100644
--- a/tests/qtest/tpm-util.c
+++ b/tests/qtest/tpm-util.c
@@ -51,51 +51,6 @@ void tpm_util_crb_transfer(QTestState *s,
     qtest_memread(s, raddr, rsp, rsp_size);
 }
 
-void tpm_util_tis_transfer(QTestState *s,
-                           const unsigned char *req, size_t req_size,
-                           unsigned char *rsp, size_t rsp_size)
-{
-    uint32_t sts;
-    uint16_t bcount;
-    size_t i;
-
-    /* request use of locality 0 */
-    qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE);
-    qtest_writel(s, TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY);
-
-    sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS));
-    bcount = (sts >> 8) & 0xffff;
-    g_assert_cmpint(bcount, >=, req_size);
-
-    /* transmit command */
-    for (i = 0; i < req_size; i++) {
-        qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_DATA_FIFO), req[i]);
-    }
-
-    /* start processing */
-    qtest_writeb(s, 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 = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS));
-        if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) {
-            break;
-        }
-    } while (g_get_monotonic_time() < end_time);
-
-    sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS));
-    bcount = (sts >> 8) & 0xffff;
-
-    memset(rsp, 0, rsp_size);
-    for (i = 0; i < bcount; i++) {
-        rsp[i] = qtest_readb(s, TIS_REG(0, TPM_TIS_REG_DATA_FIFO));
-    }
-
-    /* relinquish use of locality 0 */
-    qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_ACCESS),
-                 TPM_TIS_ACCESS_ACTIVE_LOCALITY);
-}
-
 void tpm_util_startup(QTestState *s, tx_func *tx)
 {
     unsigned char buffer[1024];
diff --git a/tests/qtest/tpm-util.h b/tests/qtest/tpm-util.h
index 80720afac0..0cb28dd6e5 100644
--- a/tests/qtest/tpm-util.h
+++ b/tests/qtest/tpm-util.h
@@ -27,9 +27,6 @@ typedef void (tx_func)(QTestState *s,
 void tpm_util_crb_transfer(QTestState *s,
                            const unsigned char *req, size_t req_size,
                            unsigned char *rsp, size_t rsp_size);
-void tpm_util_tis_transfer(QTestState *s,
-                           const unsigned char *req, size_t req_size,
-                           unsigned char *rsp, size_t rsp_size);
 
 void tpm_util_startup(QTestState *s, tx_func *tx);
 void tpm_util_pcrextend(QTestState *s, tx_func *tx);
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/3] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller
  2023-03-27 20:24 [PATCH 0/3] qtests: tpm: Add test cases for TPM TIS I2C device emulation Stefan Berger
  2023-03-27 20:24 ` [PATCH 1/3] qtest: Add functions for accessing devices on Aspeed I2C controller Stefan Berger
  2023-03-27 20:24 ` [PATCH 2/3] qtest: Move tpm_util_tis_transmit() into tpm-tis-utils.c and rename it Stefan Berger
@ 2023-03-27 20:24 ` Stefan Berger
  2023-03-28  6:44   ` Cédric Le Goater
                     ` (2 more replies)
  2 siblings, 3 replies; 14+ messages in thread
From: Stefan Berger @ 2023-03-27 20:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: marcandre.lureau, clg, ninad, joel, andrew, Stefan Berger

Add a test case for the TPM TIS I2C device exercising most of its
functionality, including localities.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
---
 tests/qtest/meson.build        |   3 +
 tests/qtest/tpm-tis-i2c-test.c | 637 +++++++++++++++++++++++++++++++++
 2 files changed, 640 insertions(+)
 create mode 100644 tests/qtest/tpm-tis-i2c-test.c

diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 29a4efb4c2..065a00d34d 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -200,6 +200,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'] : []) + \
   ['arm-cpu-features',
    'microbit-test',
    'test-arm-mptimer',
@@ -212,6 +213,7 @@ qtests_aarch64 = \
     ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) +                                         \
   (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \
   (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) +  \
+  (config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
   ['arm-cpu-features',
    'numa-test',
    'boot-serial-test',
@@ -303,6 +305,7 @@ qtests = {
   'tpm-crb-test': [io, tpmemu_files],
   '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, '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'],
   'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'),
diff --git a/tests/qtest/tpm-tis-i2c-test.c b/tests/qtest/tpm-tis-i2c-test.c
new file mode 100644
index 0000000000..94ec423845
--- /dev/null
+++ b/tests/qtest/tpm-tis-i2c-test.c
@@ -0,0 +1,637 @@
+/*
+ * QTest testcases for TPM TIS on I2C (derived from TPM TIS test)
+ *
+ * Copyright (c) 2023 IBM Corporation
+ * Copyright (c) 2023 Red Hat, Inc.
+ *
+ * Authors:
+ *   Stefan Berger <stefanb@linux.ibm.com>
+ *   Marc-André Lureau <marcandre.lureau@redhat.com>
+ *
+ * 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 <glib/gstdio.h>
+
+#include "libqtest-single.h"
+#include "hw/acpi/tpm.h"
+#include "hw/pci/pci_ids.h"
+#include "qtest_aspeed.h"
+#include "tpm-emu.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)
+
+#define I2C_SLAVE_ADDR   0x2e
+#define I2C_DEV_BUS_NUM  10
+
+static const uint8_t TPM_CMD[12] =
+    "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00";
+
+uint32_t aspeed_dev_addr;
+
+uint8_t cur_locty = 0xff;
+
+static void tpm_tis_i2c_set_locty(uint8_t locty)
+{
+    if (cur_locty != locty) {
+        cur_locty = locty;
+        aspeed_i2c_writeb(aspeed_dev_addr, I2C_SLAVE_ADDR,
+                          TPM_I2C_REG_LOC_SEL, locty);
+    }
+}
+
+static uint8_t tpm_tis_i2c_readb(uint8_t locty, uint8_t reg)
+{
+    tpm_tis_i2c_set_locty(locty);
+    return aspeed_i2c_readb(aspeed_dev_addr, I2C_SLAVE_ADDR, reg);
+}
+
+static uint16_t tpm_tis_i2c_readw(uint8_t locty, uint8_t reg)
+{
+    tpm_tis_i2c_set_locty(locty);
+    return aspeed_i2c_readw(aspeed_dev_addr, I2C_SLAVE_ADDR, reg);
+}
+
+static uint32_t tpm_tis_i2c_readl(uint8_t locty, uint8_t reg)
+{
+    tpm_tis_i2c_set_locty(locty);
+    return aspeed_i2c_readl(aspeed_dev_addr, I2C_SLAVE_ADDR, reg);
+}
+
+static void tpm_tis_i2c_writeb(uint8_t locty, uint8_t reg, uint8_t v)
+{
+    if (reg != TPM_I2C_REG_LOC_SEL) {
+        tpm_tis_i2c_set_locty(locty);
+    }
+    aspeed_i2c_writeb(aspeed_dev_addr, I2C_SLAVE_ADDR, reg, v);
+}
+
+static void tpm_tis_i2c_writel(uint8_t locty, uint8_t reg, uint32_t v)
+{
+    if (reg != TPM_I2C_REG_LOC_SEL) {
+        tpm_tis_i2c_set_locty(locty);
+    }
+    aspeed_i2c_writel(aspeed_dev_addr, I2C_SLAVE_ADDR, reg, v);
+}
+
+static void tpm_tis_i2c_test_basic(const void *data)
+{
+    uint8_t access;
+    uint32_t v;
+
+    /*
+     * All register accesses below must work without locality 0 being the
+     * active locality. Therefore, ensure access is released.
+     */
+    tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS,
+                       TPM_TIS_ACCESS_ACTIVE_LOCALITY);
+    access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS);
+    g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
+                                TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
+
+    /* read interrupt capability -- none are supported */
+    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_CAPABILITY);
+    g_assert_cmpint(v, ==, 0);
+
+    /* try to enable all interrupts */
+    tpm_tis_i2c_writel(0, TPM_I2C_REG_INT_ENABLE, 0xffffffff);
+    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_ENABLE);
+    /* none could be enabled */
+    g_assert_cmpint(v, ==, 0);
+
+    /* enable csum */
+    tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, TPM_DATA_CSUM_ENABLED);
+    /* check csum enable register has bit 0 set */
+    v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
+    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
+    /* reading it as 32bit register returns same result */
+    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
+    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
+
+    /* disable csum */
+    tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, 0);
+    /* check csum enable register has bit 0 clear */
+    v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
+    g_assert_cmpint(v, ==, 0);
+
+    /* write to unsupported register '1' */
+    tpm_tis_i2c_writel(0, 1, 0x12345678);
+    v = tpm_tis_i2c_readl(0, 1);
+    g_assert_cmpint(v, ==, 0xffffffff);
+}
+
+static void tpm_tis_i2c_test_check_localities(const void *data)
+{
+    uint8_t locty, l;
+    uint8_t access;
+    uint32_t capability, i2c_cap;
+    uint32_t didvid;
+    uint32_t rid;
+
+    for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) {
+        access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
+        g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
+                                    TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
+
+        capability = tpm_tis_i2c_readl(locty, TPM_I2C_REG_INTF_CAPABILITY);
+        i2c_cap = (TPM_I2C_CAP_INTERFACE_TYPE |
+                   TPM_I2C_CAP_INTERFACE_VER  |
+                   TPM_I2C_CAP_TPM2_FAMILY    |
+                   TPM_I2C_CAP_LOCALITY_CAP   |
+                   TPM_I2C_CAP_BUS_SPEED      |
+                   TPM_I2C_CAP_DEV_ADDR_CHANGE);
+        g_assert_cmpint(capability, ==, i2c_cap);
+
+        didvid = tpm_tis_i2c_readl(locty, TPM_I2C_REG_DID_VID);
+        g_assert_cmpint(didvid, ==, (1 << 16) | PCI_VENDOR_ID_IBM);
+
+        rid = tpm_tis_i2c_readl(locty, TPM_I2C_REG_RID);
+        g_assert_cmpint(rid, !=, 0);
+        g_assert_cmpint(rid, !=, 0xffffffff);
+
+        /* locality selection must be at locty */
+        l = tpm_tis_i2c_readb(locty, TPM_I2C_REG_LOC_SEL);
+        g_assert_cmpint(l, ==, locty);
+    }
+}
+
+static void tpm_tis_i2c_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 = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
+        g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
+                                    TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
+
+        /* request use of locality */
+        tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS,
+                           TPM_TIS_ACCESS_REQUEST_USE);
+
+        access = tpm_tis_i2c_readb(locty, TPM_I2C_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 */
+        tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS,
+                           TPM_TIS_ACCESS_ACTIVE_LOCALITY);
+        access = tpm_tis_i2c_readb(locty, TPM_I2C_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_i2c_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 = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
+        g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
+                                    TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
+
+        /* request use of locality */
+        tpm_tis_i2c_writeb(locty,
+                           TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE);
+        access = tpm_tis_i2c_readb(locty, TPM_I2C_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 = tpm_tis_i2c_readb(l, TPM_I2C_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' */
+            tpm_tis_i2c_writeb(l,
+                               TPM_I2C_REG_ACCESS,
+                               TPM_TIS_ACCESS_REQUEST_USE);
+
+            /*
+             * requesting use from 'l' was not possible;
+             * we must see REQUEST_USE and possibly PENDING_REQUEST
+             */
+            access = tpm_tis_i2c_readb(l, TPM_I2C_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 = tpm_tis_i2c_readb(locty, TPM_I2C_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' */
+            tpm_tis_i2c_writeb(l,
+                               TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_SEIZE);
+            /* seize from 'l' was not possible */
+            access = tpm_tis_i2c_readb(l, TPM_I2C_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 = tpm_tis_i2c_readb(locty, TPM_I2C_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' */
+            tpm_tis_i2c_writeb(l, TPM_I2C_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 = tpm_tis_i2c_readb(l, TPM_I2C_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 = tpm_tis_i2c_readb(l - 1, TPM_I2C_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' */
+            tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_SEIZE);
+
+            /* seize from 'l' was possible */
+            access = tpm_tis_i2c_readb(l, TPM_I2C_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 = tpm_tis_i2c_readb(l - 1, TPM_I2C_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 */
+            tpm_tis_i2c_writeb(l - 1, TPM_I2C_REG_ACCESS,
+                               TPM_TIS_ACCESS_BEEN_SEIZED);
+
+            access = tpm_tis_i2c_readb(l - 1, TPM_I2C_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 = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
+        DPRINTF_ACCESS;
+
+        DPRINTF("%s: %d: relinquishing control on l = %d\n",
+                __func__, __LINE__, l);
+        tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS,
+                           TPM_TIS_ACCESS_ACTIVE_LOCALITY);
+
+        access = tpm_tis_i2c_readb(l, TPM_I2C_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 = tpm_tis_i2c_readb(l, TPM_I2C_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 */
+            tpm_tis_i2c_writeb(l, TPM_I2C_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 = tpm_tis_i2c_readb(l, TPM_I2C_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_i2c_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 = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
+        g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
+                                    TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
+
+        /* request use of locality */
+        tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS,
+                           TPM_TIS_ACCESS_REQUEST_USE);
+        access = tpm_tis_i2c_readb(locty, TPM_I2C_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
+             */
+            tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS,
+                               TPM_TIS_ACCESS_REQUEST_USE);
+            access = tpm_tis_i2c_readb(l, TPM_I2C_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' */
+        tpm_tis_i2c_writeb(locty, TPM_I2C_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 = tpm_tis_i2c_readb(l, TPM_I2C_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 */
+            tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS,
+                               TPM_TIS_ACCESS_ACTIVE_LOCALITY);
+            access = tpm_tis_i2c_readb(l, TPM_I2C_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_i2c_test_check_transmit(const void *data)
+{
+    const TPMTestState *s = data;
+    uint8_t access;
+    uint32_t sts, v;
+    uint16_t bcount, csum;
+    size_t i;
+
+    /* enable csum */
+    tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, TPM_DATA_CSUM_ENABLED);
+    /* check csum enable register has bit 0 set */
+    v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
+    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
+    /* reading it as 32bit register returns same result */
+    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
+    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
+
+    /* request use of locality 0 */
+    tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE);
+    access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS);
+    g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
+                                TPM_TIS_ACCESS_ACTIVE_LOCALITY |
+                                TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
+
+    sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS);
+    DPRINTF_STS;
+
+    g_assert_cmpint(sts & 0xff, ==, 0);
+
+    bcount = (sts >> 8) & 0xffff;
+    g_assert_cmpint(bcount, >=, 128);
+
+    /* ic2 must have bits 26-31 zero */
+    g_assert_cmpint(sts & (0x1f << 26), ==, 0);
+
+    tpm_tis_i2c_writel(0, TPM_I2C_REG_STS, TPM_TIS_STS_COMMAND_READY);
+    sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS);
+    DPRINTF_STS;
+    g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY);
+
+    /* transmit command */
+    for (i = 0; i < sizeof(TPM_CMD); i++) {
+        tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_FIFO, TPM_CMD[i]);
+        sts = tpm_tis_i2c_readl(0, TPM_I2C_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);
+    }
+    /* read the checksum */
+    csum = tpm_tis_i2c_readw(0, TPM_I2C_REG_DATA_CSUM_GET);
+    g_assert_cmpint(csum, ==, 0x6733);
+
+    /* start processing */
+    tpm_tis_i2c_writeb(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(0, TPM_I2C_REG_STS);
+        if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) {
+            break;
+        }
+    } while (g_get_monotonic_time() < end_time);
+
+    sts = tpm_tis_i2c_readl(0, TPM_I2C_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] = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_FIFO);
+        sts = tpm_tis_i2c_readl(0, TPM_I2C_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 */
+    tpm_tis_i2c_writeb(0,
+                       TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_ACTIVE_LOCALITY);
+    access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS);
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+    char *args;
+    char *tmp_path = g_dir_make_tmp("qemu-tpm-tis-i2c-test.XXXXXX", NULL);
+    GThread *thread;
+    TPMTestState test;
+
+    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;
+    test.tpm_version = TPM_VERSION_2_0;
+
+    thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
+    tpm_emu_test_wait_cond(&test);
+
+    aspeed_dev_addr = ast2600_aspeed_i2c_calc_dev_addr(I2C_DEV_BUS_NUM);
+
+    args = g_strdup_printf(
+        "-machine rainier-bmc -accel tcg "
+        "-chardev socket,id=chr,path=%s "
+        "-tpmdev emulator,id=tpm0,chardev=chr "
+        "-device tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.%d,address=0x%x",
+        test.addr->u.q_unix.path,
+        I2C_DEV_BUS_NUM,
+        I2C_SLAVE_ADDR);
+    qtest_start(args);
+
+    qtest_add_data_func("/tpm-tis-i2c/test_basic", &test,
+                        tpm_tis_i2c_test_basic);
+
+    qtest_add_data_func("/tpm-tis-i2c/test_check_localities", &test,
+                        tpm_tis_i2c_test_check_localities);
+
+    qtest_add_data_func("/tpm-tis-i2c/check_access_reg", &test,
+                        tpm_tis_i2c_test_check_access_reg);
+
+    qtest_add_data_func("/tpm-tis-i2c/check_access_reg_seize", &test,
+                        tpm_tis_i2c_test_check_access_reg_seize);
+
+    qtest_add_data_func("/tpm-tis-i2c/check_access_reg_release", &test,
+                        tpm_tis_i2c_test_check_access_reg_release);
+
+    qtest_add_data_func("/tpm-tis-i2c/test_check_transmit", &test,
+                        tpm_tis_i2c_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;
+}
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] qtest: Add functions for accessing devices on Aspeed I2C controller
  2023-03-27 20:24 ` [PATCH 1/3] qtest: Add functions for accessing devices on Aspeed I2C controller Stefan Berger
@ 2023-03-28  6:39   ` Cédric Le Goater
  2023-03-28 12:26     ` Stefan Berger
  2023-03-28 13:26   ` Ninad Palsule
  1 sibling, 1 reply; 14+ messages in thread
From: Cédric Le Goater @ 2023-03-28  6:39 UTC (permalink / raw)
  To: Stefan Berger, qemu-devel; +Cc: marcandre.lureau, ninad, joel, andrew

On 3/27/23 22:24, Stefan Berger wrote:
> Add read and write functions for accessing registers of I2C devices
> connected to the Aspeed I2C controller.
> 
> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>

Reviewed-by: Cédric Le Goater <clg@kaod.org>

[... ]

> +#ifndef QTEST_ASPEED_H
> +#define QTEST_ASPEED_H
> +
> +#include <stdint.h>
> +
> +#define AST2600_ASPEED_I2C_BASE_ADDR 0x1e78a000
> +
> +static inline uint32_t ast2600_aspeed_i2c_calc_dev_addr(uint8_t bus_num)

I think you could simplify the name ast2600_aspeed_i2c_calc_dev_addr()
to aspeed_i2c_calc_bus_addr() and add a comment saying it implements only
the AST2600 I2C controller. I don't think we will need the others.

> +{
> +    return AST2600_ASPEED_I2C_BASE_ADDR + 0x80 + bus_num * 0x80;
> +}

The formula is :

    return soc_base + (soc_i2c_offset + bus_num) * soc_i2c_reg_size;

May be turn it that way in case you respin. This is minor.

Thanks,

C.



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/3] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller
  2023-03-27 20:24 ` [PATCH 3/3] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller Stefan Berger
@ 2023-03-28  6:44   ` Cédric Le Goater
  2023-03-28  9:17   ` Cédric Le Goater
  2023-03-28 14:10   ` Ninad Palsule
  2 siblings, 0 replies; 14+ messages in thread
From: Cédric Le Goater @ 2023-03-28  6:44 UTC (permalink / raw)
  To: Stefan Berger, qemu-devel; +Cc: marcandre.lureau, ninad, joel, andrew

On 3/27/23 22:24, Stefan Berger wrote:
> Add a test case for the TPM TIS I2C device exercising most of its
> functionality, including localities.
> 
> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
> ---
>   tests/qtest/meson.build        |   3 +
>   tests/qtest/tpm-tis-i2c-test.c | 637 +++++++++++++++++++++++++++++++++
>   2 files changed, 640 insertions(+)
>   create mode 100644 tests/qtest/tpm-tis-i2c-test.c
> 
> diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
> index 29a4efb4c2..065a00d34d 100644
> --- a/tests/qtest/meson.build
> +++ b/tests/qtest/meson.build
> @@ -200,6 +200,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'] : []) + \
>     ['arm-cpu-features',
>      'microbit-test',
>      'test-arm-mptimer',
> @@ -212,6 +213,7 @@ qtests_aarch64 = \
>       ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) +                                         \
>     (config_all_devices.has_key('CONFIG_XLNX_ZYNQMP_ARM') ? ['xlnx-can-test', 'fuzz-xlnx-dp-test'] : []) + \
>     (config_all_devices.has_key('CONFIG_RASPI') ? ['bcm2835-dma-test'] : []) +  \
> +  (config_all_devices.has_key('CONFIG_TPM_TIS_I2C') ? ['tpm-tis-i2c-test'] : []) + \
>     ['arm-cpu-features',
>      'numa-test',
>      'boot-serial-test',
> @@ -303,6 +305,7 @@ qtests = {
>     'tpm-crb-test': [io, tpmemu_files],
>     '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, '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'],
>     'vmgenid-test': files('boot-sector.c', 'acpi-utils.c'),
> diff --git a/tests/qtest/tpm-tis-i2c-test.c b/tests/qtest/tpm-tis-i2c-test.c
> new file mode 100644
> index 0000000000..94ec423845
> --- /dev/null
> +++ b/tests/qtest/tpm-tis-i2c-test.c
> @@ -0,0 +1,637 @@
> +/*
> + * QTest testcases for TPM TIS on I2C (derived from TPM TIS test)
> + *
> + * Copyright (c) 2023 IBM Corporation
> + * Copyright (c) 2023 Red Hat, Inc.
> + *
> + * Authors:
> + *   Stefan Berger <stefanb@linux.ibm.com>
> + *   Marc-André Lureau <marcandre.lureau@redhat.com>
> + *
> + * 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 <glib/gstdio.h>
> +
> +#include "libqtest-single.h"
> +#include "hw/acpi/tpm.h"
> +#include "hw/pci/pci_ids.h"
> +#include "qtest_aspeed.h"
> +#include "tpm-emu.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)
> +
> +#define I2C_SLAVE_ADDR   0x2e
> +#define I2C_DEV_BUS_NUM  10
> +
> +static const uint8_t TPM_CMD[12] =
> +    "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00";
> +
> +uint32_t aspeed_dev_addr;

aspeed_bus_addr may be. It should be a static.

> +
> +uint8_t cur_locty = 0xff;

ditto.


> +
> +static void tpm_tis_i2c_set_locty(uint8_t locty)
> +{
> +    if (cur_locty != locty) {
> +        cur_locty = locty;
> +        aspeed_i2c_writeb(aspeed_dev_addr, I2C_SLAVE_ADDR,
> +                          TPM_I2C_REG_LOC_SEL, locty);
> +    }
> +}
> +
> +static uint8_t tpm_tis_i2c_readb(uint8_t locty, uint8_t reg)
> +{
> +    tpm_tis_i2c_set_locty(locty);
> +    return aspeed_i2c_readb(aspeed_dev_addr, I2C_SLAVE_ADDR, reg);
> +}
> +
> +static uint16_t tpm_tis_i2c_readw(uint8_t locty, uint8_t reg)
> +{
> +    tpm_tis_i2c_set_locty(locty);
> +    return aspeed_i2c_readw(aspeed_dev_addr, I2C_SLAVE_ADDR, reg);
> +}
> +
> +static uint32_t tpm_tis_i2c_readl(uint8_t locty, uint8_t reg)
> +{
> +    tpm_tis_i2c_set_locty(locty);
> +    return aspeed_i2c_readl(aspeed_dev_addr, I2C_SLAVE_ADDR, reg);
> +}
> +
> +static void tpm_tis_i2c_writeb(uint8_t locty, uint8_t reg, uint8_t v)
> +{
> +    if (reg != TPM_I2C_REG_LOC_SEL) {
> +        tpm_tis_i2c_set_locty(locty);
> +    }
> +    aspeed_i2c_writeb(aspeed_dev_addr, I2C_SLAVE_ADDR, reg, v);
> +}
> +
> +static void tpm_tis_i2c_writel(uint8_t locty, uint8_t reg, uint32_t v)
> +{
> +    if (reg != TPM_I2C_REG_LOC_SEL) {
> +        tpm_tis_i2c_set_locty(locty);
> +    }
> +    aspeed_i2c_writel(aspeed_dev_addr, I2C_SLAVE_ADDR, reg, v);
> +}
> +
> +static void tpm_tis_i2c_test_basic(const void *data)
> +{
> +    uint8_t access;
> +    uint32_t v;
> +
> +    /*
> +     * All register accesses below must work without locality 0 being the
> +     * active locality. Therefore, ensure access is released.
> +     */
> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS,
> +                       TPM_TIS_ACCESS_ACTIVE_LOCALITY);
> +    access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS);
> +    g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
> +                                TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
> +
> +    /* read interrupt capability -- none are supported */
> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_CAPABILITY);
> +    g_assert_cmpint(v, ==, 0);
> +
> +    /* try to enable all interrupts */
> +    tpm_tis_i2c_writel(0, TPM_I2C_REG_INT_ENABLE, 0xffffffff);
> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_ENABLE);
> +    /* none could be enabled */
> +    g_assert_cmpint(v, ==, 0);
> +
> +    /* enable csum */
> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, TPM_DATA_CSUM_ENABLED);
> +    /* check csum enable register has bit 0 set */
> +    v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
> +    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
> +    /* reading it as 32bit register returns same result */
> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
> +    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
> +
> +    /* disable csum */
> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, 0);
> +    /* check csum enable register has bit 0 clear */
> +    v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
> +    g_assert_cmpint(v, ==, 0);
> +
> +    /* write to unsupported register '1' */
> +    tpm_tis_i2c_writel(0, 1, 0x12345678);
> +    v = tpm_tis_i2c_readl(0, 1);
> +    g_assert_cmpint(v, ==, 0xffffffff);
> +}
> +
> +static void tpm_tis_i2c_test_check_localities(const void *data)
> +{
> +    uint8_t locty, l;
> +    uint8_t access;
> +    uint32_t capability, i2c_cap;
> +    uint32_t didvid;
> +    uint32_t rid;
> +
> +    for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) {
> +        access = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
> +        g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
> +                                    TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
> +
> +        capability = tpm_tis_i2c_readl(locty, TPM_I2C_REG_INTF_CAPABILITY);
> +        i2c_cap = (TPM_I2C_CAP_INTERFACE_TYPE |
> +                   TPM_I2C_CAP_INTERFACE_VER  |
> +                   TPM_I2C_CAP_TPM2_FAMILY    |
> +                   TPM_I2C_CAP_LOCALITY_CAP   |
> +                   TPM_I2C_CAP_BUS_SPEED      |
> +                   TPM_I2C_CAP_DEV_ADDR_CHANGE);
> +        g_assert_cmpint(capability, ==, i2c_cap);
> +
> +        didvid = tpm_tis_i2c_readl(locty, TPM_I2C_REG_DID_VID);
> +        g_assert_cmpint(didvid, ==, (1 << 16) | PCI_VENDOR_ID_IBM);
> +
> +        rid = tpm_tis_i2c_readl(locty, TPM_I2C_REG_RID);
> +        g_assert_cmpint(rid, !=, 0);
> +        g_assert_cmpint(rid, !=, 0xffffffff);
> +
> +        /* locality selection must be at locty */
> +        l = tpm_tis_i2c_readb(locty, TPM_I2C_REG_LOC_SEL);
> +        g_assert_cmpint(l, ==, locty);
> +    }
> +}
> +
> +static void tpm_tis_i2c_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 = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
> +        g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
> +                                    TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
> +
> +        /* request use of locality */
> +        tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS,
> +                           TPM_TIS_ACCESS_REQUEST_USE);
> +
> +        access = tpm_tis_i2c_readb(locty, TPM_I2C_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 */
> +        tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS,
> +                           TPM_TIS_ACCESS_ACTIVE_LOCALITY);
> +        access = tpm_tis_i2c_readb(locty, TPM_I2C_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_i2c_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 = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
> +        g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
> +                                    TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
> +
> +        /* request use of locality */
> +        tpm_tis_i2c_writeb(locty,
> +                           TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE);
> +        access = tpm_tis_i2c_readb(locty, TPM_I2C_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 = tpm_tis_i2c_readb(l, TPM_I2C_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' */
> +            tpm_tis_i2c_writeb(l,
> +                               TPM_I2C_REG_ACCESS,
> +                               TPM_TIS_ACCESS_REQUEST_USE);
> +
> +            /*
> +             * requesting use from 'l' was not possible;
> +             * we must see REQUEST_USE and possibly PENDING_REQUEST
> +             */
> +            access = tpm_tis_i2c_readb(l, TPM_I2C_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 = tpm_tis_i2c_readb(locty, TPM_I2C_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' */
> +            tpm_tis_i2c_writeb(l,
> +                               TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_SEIZE);
> +            /* seize from 'l' was not possible */
> +            access = tpm_tis_i2c_readb(l, TPM_I2C_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 = tpm_tis_i2c_readb(locty, TPM_I2C_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' */
> +            tpm_tis_i2c_writeb(l, TPM_I2C_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 = tpm_tis_i2c_readb(l, TPM_I2C_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 = tpm_tis_i2c_readb(l - 1, TPM_I2C_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' */
> +            tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_SEIZE);
> +
> +            /* seize from 'l' was possible */
> +            access = tpm_tis_i2c_readb(l, TPM_I2C_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 = tpm_tis_i2c_readb(l - 1, TPM_I2C_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 */
> +            tpm_tis_i2c_writeb(l - 1, TPM_I2C_REG_ACCESS,
> +                               TPM_TIS_ACCESS_BEEN_SEIZED);
> +
> +            access = tpm_tis_i2c_readb(l - 1, TPM_I2C_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 = tpm_tis_i2c_readb(l, TPM_I2C_REG_ACCESS);
> +        DPRINTF_ACCESS;
> +
> +        DPRINTF("%s: %d: relinquishing control on l = %d\n",
> +                __func__, __LINE__, l);
> +        tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS,
> +                           TPM_TIS_ACCESS_ACTIVE_LOCALITY);
> +
> +        access = tpm_tis_i2c_readb(l, TPM_I2C_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 = tpm_tis_i2c_readb(l, TPM_I2C_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 */
> +            tpm_tis_i2c_writeb(l, TPM_I2C_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 = tpm_tis_i2c_readb(l, TPM_I2C_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_i2c_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 = tpm_tis_i2c_readb(locty, TPM_I2C_REG_ACCESS);
> +        g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
> +                                    TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
> +
> +        /* request use of locality */
> +        tpm_tis_i2c_writeb(locty, TPM_I2C_REG_ACCESS,
> +                           TPM_TIS_ACCESS_REQUEST_USE);
> +        access = tpm_tis_i2c_readb(locty, TPM_I2C_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
> +             */
> +            tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS,
> +                               TPM_TIS_ACCESS_REQUEST_USE);
> +            access = tpm_tis_i2c_readb(l, TPM_I2C_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' */
> +        tpm_tis_i2c_writeb(locty, TPM_I2C_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 = tpm_tis_i2c_readb(l, TPM_I2C_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 */
> +            tpm_tis_i2c_writeb(l, TPM_I2C_REG_ACCESS,
> +                               TPM_TIS_ACCESS_ACTIVE_LOCALITY);
> +            access = tpm_tis_i2c_readb(l, TPM_I2C_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_i2c_test_check_transmit(const void *data)
> +{
> +    const TPMTestState *s = data;
> +    uint8_t access;
> +    uint32_t sts, v;
> +    uint16_t bcount, csum;
> +    size_t i;
> +
> +    /* enable csum */
> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, TPM_DATA_CSUM_ENABLED);
> +    /* check csum enable register has bit 0 set */
> +    v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
> +    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
> +    /* reading it as 32bit register returns same result */
> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
> +    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
> +
> +    /* request use of locality 0 */
> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_REQUEST_USE);
> +    access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS);
> +    g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
> +                                TPM_TIS_ACCESS_ACTIVE_LOCALITY |
> +                                TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
> +
> +    sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS);
> +    DPRINTF_STS;
> +
> +    g_assert_cmpint(sts & 0xff, ==, 0);
> +
> +    bcount = (sts >> 8) & 0xffff;
> +    g_assert_cmpint(bcount, >=, 128);
> +
> +    /* ic2 must have bits 26-31 zero */
> +    g_assert_cmpint(sts & (0x1f << 26), ==, 0);
> +
> +    tpm_tis_i2c_writel(0, TPM_I2C_REG_STS, TPM_TIS_STS_COMMAND_READY);
> +    sts = tpm_tis_i2c_readl(0, TPM_I2C_REG_STS);
> +    DPRINTF_STS;
> +    g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY);
> +
> +    /* transmit command */
> +    for (i = 0; i < sizeof(TPM_CMD); i++) {
> +        tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_FIFO, TPM_CMD[i]);
> +        sts = tpm_tis_i2c_readl(0, TPM_I2C_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);
> +    }
> +    /* read the checksum */
> +    csum = tpm_tis_i2c_readw(0, TPM_I2C_REG_DATA_CSUM_GET);
> +    g_assert_cmpint(csum, ==, 0x6733);
> +
> +    /* start processing */
> +    tpm_tis_i2c_writeb(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(0, TPM_I2C_REG_STS);
> +        if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) {
> +            break;
> +        }
> +    } while (g_get_monotonic_time() < end_time);
> +
> +    sts = tpm_tis_i2c_readl(0, TPM_I2C_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] = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_FIFO);
> +        sts = tpm_tis_i2c_readl(0, TPM_I2C_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 */
> +    tpm_tis_i2c_writeb(0,
> +                       TPM_I2C_REG_ACCESS, TPM_TIS_ACCESS_ACTIVE_LOCALITY);
> +    access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS);
> +}
> +
> +int main(int argc, char **argv)
> +{
> +    int ret;
> +    char *args;
> +    char *tmp_path = g_dir_make_tmp("qemu-tpm-tis-i2c-test.XXXXXX", NULL);
> +    GThread *thread;
> +    TPMTestState test;
> +
> +    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;
> +    test.tpm_version = TPM_VERSION_2_0;
> +
> +    thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
> +    tpm_emu_test_wait_cond(&test);
> +
> +    aspeed_dev_addr = ast2600_aspeed_i2c_calc_dev_addr(I2C_DEV_BUS_NUM);
> +
> +    args = g_strdup_printf(
> +        "-machine rainier-bmc -accel tcg "
> +        "-chardev socket,id=chr,path=%s "
> +        "-tpmdev emulator,id=tpm0,chardev=chr "
> +        "-device tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.%d,address=0x%x",
> +        test.addr->u.q_unix.path,
> +        I2C_DEV_BUS_NUM,
> +        I2C_SLAVE_ADDR);
> +    qtest_start(args);
> +
> +    qtest_add_data_func("/tpm-tis-i2c/test_basic", &test,
> +                        tpm_tis_i2c_test_basic);
> +
> +    qtest_add_data_func("/tpm-tis-i2c/test_check_localities", &test,
> +                        tpm_tis_i2c_test_check_localities);
> +
> +    qtest_add_data_func("/tpm-tis-i2c/check_access_reg", &test,
> +                        tpm_tis_i2c_test_check_access_reg);
> +
> +    qtest_add_data_func("/tpm-tis-i2c/check_access_reg_seize", &test,
> +                        tpm_tis_i2c_test_check_access_reg_seize);
> +
> +    qtest_add_data_func("/tpm-tis-i2c/check_access_reg_release", &test,
> +                        tpm_tis_i2c_test_check_access_reg_release);
> +
> +    qtest_add_data_func("/tpm-tis-i2c/test_check_transmit", &test,
> +                        tpm_tis_i2c_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;
> +}



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/3] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller
  2023-03-27 20:24 ` [PATCH 3/3] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller Stefan Berger
  2023-03-28  6:44   ` Cédric Le Goater
@ 2023-03-28  9:17   ` Cédric Le Goater
  2023-03-28 11:31     ` Stefan Berger
  2023-03-28 14:10   ` Ninad Palsule
  2 siblings, 1 reply; 14+ messages in thread
From: Cédric Le Goater @ 2023-03-28  9:17 UTC (permalink / raw)
  To: Stefan Berger, qemu-devel; +Cc: marcandre.lureau, ninad, joel, andrew

> +static void tpm_tis_i2c_test_basic(const void *data)
> +{
> +    uint8_t access;
> +    uint32_t v;
> +
> +    /*
> +     * All register accesses below must work without locality 0 being the
> +     * active locality. Therefore, ensure access is released.
> +     */
> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS,
> +                       TPM_TIS_ACCESS_ACTIVE_LOCALITY);
> +    access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS);
> +    g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
> +                                TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
> +
> +    /* read interrupt capability -- none are supported */
> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_CAPABILITY);
> +    g_assert_cmpint(v, ==, 0);
> +
> +    /* try to enable all interrupts */
> +    tpm_tis_i2c_writel(0, TPM_I2C_REG_INT_ENABLE, 0xffffffff);
> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_ENABLE);
> +    /* none could be enabled */
> +    g_assert_cmpint(v, ==, 0);
> +
> +    /* enable csum */
> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, TPM_DATA_CSUM_ENABLED);
> +    /* check csum enable register has bit 0 set */
> +    v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
> +    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
> +    /* reading it as 32bit register returns same result */
> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
> +    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
> +
> +    /* disable csum */
> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, 0);
> +    /* check csum enable register has bit 0 clear */
> +    v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
> +    g_assert_cmpint(v, ==, 0);
> +
> +    /* write to unsupported register '1' */
> +    tpm_tis_i2c_writel(0, 1, 0x12345678);
> +    v = tpm_tis_i2c_readl(0, 1);
> +    g_assert_cmpint(v, ==, 0xffffffff);
> +}

I am seeing some errors :

$ QTEST_QEMU_BINARY=arm-softmmu/qemu-system-arm  tests/qtest/tpm-tis-i2c-test
# random seed: R02S68cdeb5a9a7b97eed594a7792b6aa7ff
# starting QEMU: exec arm-softmmu/qemu-system-arm -qtest unix:/tmp/qtest-1981218.sock -qtest-log /dev/null -chardev socket,path=/tmp/qtest-1981218.qmp,id=char0 -mon chardev=char0,mode=control -display none -machine rainier-bmc -accel tcg -chardev socket,id=chr,path=/tmp/qemu-tpm-tis-i2c-test.DFGN21/sock -tpmdev emulator,id=tpm0,chardev=chr -device tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.10,address=0x2e -accel qtest
# GLib-DEBUG: setenv()/putenv() are not thread-safe and should not be used after threads are created
qemu-system-arm: warning: Aspeed iBT has no chardev backend
1..6
# Start of arm tests
# Start of tpm-tis-i2c tests
**
ERROR:../tests/qtest/tpm-tis-i2c-test.c:130:tpm_tis_i2c_test_basic: assertion failed (v == 0): (1 == 0)
Bail out! ERROR:../tests/qtest/tpm-tis-i2c-test.c:130:tpm_tis_i2c_test_basic: assertion failed (v == 0): (1 == 0)
Unexpected error in qio_channel_socket_writev() at ../io/channel-socket.c:621:
qemu-system-arm: tests/qtest/tpm-tis-i2c-test:tpm-emulator: Could not cleanly shutdown the TPM: Interrupted system call
Unable to write to socket: Bad file descriptor
Aborted (core dumped)



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/3] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller
  2023-03-28  9:17   ` Cédric Le Goater
@ 2023-03-28 11:31     ` Stefan Berger
  2023-03-28 11:52       ` Cédric Le Goater
  0 siblings, 1 reply; 14+ messages in thread
From: Stefan Berger @ 2023-03-28 11:31 UTC (permalink / raw)
  To: Cédric Le Goater, qemu-devel; +Cc: marcandre.lureau, ninad, joel, andrew



On 3/28/23 05:17, Cédric Le Goater wrote:
>> +static void tpm_tis_i2c_test_basic(const void *data)
>> +{
>> +    uint8_t access;
>> +    uint32_t v;
>> +
>> +    /*
>> +     * All register accesses below must work without locality 0 being the
>> +     * active locality. Therefore, ensure access is released.
>> +     */
>> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS,
>> +                       TPM_TIS_ACCESS_ACTIVE_LOCALITY);
>> +    access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS);
>> +    g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
>> +                                TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
>> +
>> +    /* read interrupt capability -- none are supported */
>> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_CAPABILITY);
>> +    g_assert_cmpint(v, ==, 0);
>> +
>> +    /* try to enable all interrupts */
>> +    tpm_tis_i2c_writel(0, TPM_I2C_REG_INT_ENABLE, 0xffffffff);
>> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_ENABLE);
>> +    /* none could be enabled */
>> +    g_assert_cmpint(v, ==, 0);
>> +
>> +    /* enable csum */
>> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, TPM_DATA_CSUM_ENABLED);
>> +    /* check csum enable register has bit 0 set */
>> +    v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
>> +    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
>> +    /* reading it as 32bit register returns same result */
>> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
>> +    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
>> +
>> +    /* disable csum */
>> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, 0);
>> +    /* check csum enable register has bit 0 clear */
>> +    v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
>> +    g_assert_cmpint(v, ==, 0);
>> +
>> +    /* write to unsupported register '1' */
>> +    tpm_tis_i2c_writel(0, 1, 0x12345678);
>> +    v = tpm_tis_i2c_readl(0, 1);
>> +    g_assert_cmpint(v, ==, 0xffffffff);
>> +}
> 
> I am seeing some errors :


There's a small fix to apply to 3/3 of Ninad's patches. See my comment here:


https://lists.nongnu.org/archive/html/qemu-devel/2023-03/msg06464.html

     Stefan
> 
> $ QTEST_QEMU_BINARY=arm-softmmu/qemu-system-arm  tests/qtest/tpm-tis-i2c-test
> # random seed: R02S68cdeb5a9a7b97eed594a7792b6aa7ff
> # starting QEMU: exec arm-softmmu/qemu-system-arm -qtest unix:/tmp/qtest-1981218.sock -qtest-log /dev/null -chardev socket,path=/tmp/qtest-1981218.qmp,id=char0 -mon chardev=char0,mode=control -display none -machine rainier-bmc -accel tcg -chardev socket,id=chr,path=/tmp/qemu-tpm-tis-i2c-test.DFGN21/sock -tpmdev emulator,id=tpm0,chardev=chr -device tpm-tis-i2c,tpmdev=tpm0,bus=aspeed.i2c.bus.10,address=0x2e -accel qtest
> # GLib-DEBUG: setenv()/putenv() are not thread-safe and should not be used after threads are created
> qemu-system-arm: warning: Aspeed iBT has no chardev backend
> 1..6
> # Start of arm tests
> # Start of tpm-tis-i2c tests
> **
> ERROR:../tests/qtest/tpm-tis-i2c-test.c:130:tpm_tis_i2c_test_basic: assertion failed (v == 0): (1 == 0)
> Bail out! ERROR:../tests/qtest/tpm-tis-i2c-test.c:130:tpm_tis_i2c_test_basic: assertion failed (v == 0): (1 == 0)
> Unexpected error in qio_channel_socket_writev() at ../io/channel-socket.c:621:
> qemu-system-arm: tests/qtest/tpm-tis-i2c-test:tpm-emulator: Could not cleanly shutdown the TPM: Interrupted system call
> Unable to write to socket: Bad file descriptor
> Aborted (core dumped)
> 


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/3] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller
  2023-03-28 11:31     ` Stefan Berger
@ 2023-03-28 11:52       ` Cédric Le Goater
  0 siblings, 0 replies; 14+ messages in thread
From: Cédric Le Goater @ 2023-03-28 11:52 UTC (permalink / raw)
  To: Stefan Berger, qemu-devel; +Cc: marcandre.lureau, ninad, joel, andrew

On 3/28/23 13:31, Stefan Berger wrote:
> 
> 
> On 3/28/23 05:17, Cédric Le Goater wrote:
>>> +static void tpm_tis_i2c_test_basic(const void *data)
>>> +{
>>> +    uint8_t access;
>>> +    uint32_t v;
>>> +
>>> +    /*
>>> +     * All register accesses below must work without locality 0 being the
>>> +     * active locality. Therefore, ensure access is released.
>>> +     */
>>> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_ACCESS,
>>> +                       TPM_TIS_ACCESS_ACTIVE_LOCALITY);
>>> +    access = tpm_tis_i2c_readb(0, TPM_I2C_REG_ACCESS);
>>> +    g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS |
>>> +                                TPM_TIS_ACCESS_TPM_ESTABLISHMENT);
>>> +
>>> +    /* read interrupt capability -- none are supported */
>>> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_CAPABILITY);
>>> +    g_assert_cmpint(v, ==, 0);
>>> +
>>> +    /* try to enable all interrupts */
>>> +    tpm_tis_i2c_writel(0, TPM_I2C_REG_INT_ENABLE, 0xffffffff);
>>> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_INT_ENABLE);
>>> +    /* none could be enabled */
>>> +    g_assert_cmpint(v, ==, 0);
>>> +
>>> +    /* enable csum */
>>> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, TPM_DATA_CSUM_ENABLED);
>>> +    /* check csum enable register has bit 0 set */
>>> +    v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
>>> +    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
>>> +    /* reading it as 32bit register returns same result */
>>> +    v = tpm_tis_i2c_readl(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
>>> +    g_assert_cmpint(v, ==, TPM_DATA_CSUM_ENABLED);
>>> +
>>> +    /* disable csum */
>>> +    tpm_tis_i2c_writeb(0, TPM_I2C_REG_DATA_CSUM_ENABLE, 0);
>>> +    /* check csum enable register has bit 0 clear */
>>> +    v = tpm_tis_i2c_readb(0, TPM_I2C_REG_DATA_CSUM_ENABLE);
>>> +    g_assert_cmpint(v, ==, 0);
>>> +
>>> +    /* write to unsupported register '1' */
>>> +    tpm_tis_i2c_writel(0, 1, 0x12345678);
>>> +    v = tpm_tis_i2c_readl(0, 1);
>>> +    g_assert_cmpint(v, ==, 0xffffffff);
>>> +}
>>
>> I am seeing some errors :
> 
> 
> There's a small fix to apply to 3/3 of Ninad's patches. See my comment here:
> 
> 
> https://lists.nongnu.org/archive/html/qemu-devel/2023-03/msg06464.html


That was it.

Tested-by: Cédric Le Goater <clg@kaod.org>

Thanks,

C.



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] qtest: Add functions for accessing devices on Aspeed I2C controller
  2023-03-28  6:39   ` Cédric Le Goater
@ 2023-03-28 12:26     ` Stefan Berger
  2023-03-28 13:10       ` Cédric Le Goater
  0 siblings, 1 reply; 14+ messages in thread
From: Stefan Berger @ 2023-03-28 12:26 UTC (permalink / raw)
  To: Cédric Le Goater, qemu-devel; +Cc: marcandre.lureau, ninad, joel, andrew



On 3/28/23 02:39, Cédric Le Goater wrote:
> On 3/27/23 22:24, Stefan Berger wrote:
>> Add read and write functions for accessing registers of I2C devices
>> connected to the Aspeed I2C controller.
>>
>> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
> 
> Reviewed-by: Cédric Le Goater <clg@kaod.org>
> 
> [... ]
> 
>> +#ifndef QTEST_ASPEED_H
>> +#define QTEST_ASPEED_H
>> +
>> +#include <stdint.h>
>> +
>> +#define AST2600_ASPEED_I2C_BASE_ADDR 0x1e78a000
>> +
>> +static inline uint32_t ast2600_aspeed_i2c_calc_dev_addr(uint8_t bus_num)
> 
> I think you could simplify the name ast2600_aspeed_i2c_calc_dev_addr()
> to aspeed_i2c_calc_bus_addr() and add a comment saying it implements only
> the AST2600 I2C controller. I don't think we will need the others.


What are 'the others'?

> 
>> +{
>> +    return AST2600_ASPEED_I2C_BASE_ADDR + 0x80 + bus_num * 0x80;
>> +}
> 
> The formula is :
> 
>     return soc_base + (soc_i2c_offset + bus_num) * soc_i2c_reg_size;

That's what I thought:

return soc_base + soc_i2c_offset + (bus_num * soc_i2c_reg_size);

I will keep it as it is, though.

     Stefan

> 
> May be turn it that way in case you respin. This is minor.
> 
> Thanks,
> 
> C.
> 


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] qtest: Add functions for accessing devices on Aspeed I2C controller
  2023-03-28 12:26     ` Stefan Berger
@ 2023-03-28 13:10       ` Cédric Le Goater
  0 siblings, 0 replies; 14+ messages in thread
From: Cédric Le Goater @ 2023-03-28 13:10 UTC (permalink / raw)
  To: Stefan Berger, qemu-devel; +Cc: marcandre.lureau, ninad, joel, andrew

On 3/28/23 14:26, Stefan Berger wrote:
> 
> 
> On 3/28/23 02:39, Cédric Le Goater wrote:
>> On 3/27/23 22:24, Stefan Berger wrote:
>>> Add read and write functions for accessing registers of I2C devices
>>> connected to the Aspeed I2C controller.
>>>
>>> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
>>
>> Reviewed-by: Cédric Le Goater <clg@kaod.org>
>>
>> [... ]
>>
>>> +#ifndef QTEST_ASPEED_H
>>> +#define QTEST_ASPEED_H
>>> +
>>> +#include <stdint.h>
>>> +
>>> +#define AST2600_ASPEED_I2C_BASE_ADDR 0x1e78a000
>>> +
>>> +static inline uint32_t ast2600_aspeed_i2c_calc_dev_addr(uint8_t bus_num)
>>
>> I think you could simplify the name ast2600_aspeed_i2c_calc_dev_addr()
>> to aspeed_i2c_calc_bus_addr() and add a comment saying it implements only
>> the AST2600 I2C controller. I don't think we will need the others.
> 
> 
> What are 'the others'?

AST2400 and AST2500 SoC.

>>> +{
>>> +    return AST2600_ASPEED_I2C_BASE_ADDR + 0x80 + bus_num * 0x80;
>>> +}
>>
>> The formula is :
>>
>>     return soc_base + (soc_i2c_offset + bus_num) * soc_i2c_reg_size;
> 
> That's what I thought:
> 
> return soc_base + soc_i2c_offset + (bus_num * soc_i2c_reg_size);
>
> I will keep it as it is, though.

It should work also for the AST2600

FYI, see the layouts below,

Thanks,

C.


AST2400

     000000001e78a000-000000001e78afff (prio 0, i/o): aspeed.i2c
       000000001e78a040-000000001e78a07f (prio 0, i/o): aspeed.i2c.bus.0
       000000001e78a080-000000001e78a0bf (prio 0, i/o): aspeed.i2c.bus.1
       000000001e78a0c0-000000001e78a0ff (prio 0, i/o): aspeed.i2c.bus.2
       000000001e78a100-000000001e78a13f (prio 0, i/o): aspeed.i2c.bus.3
       000000001e78a140-000000001e78a17f (prio 0, i/o): aspeed.i2c.bus.4
       000000001e78a180-000000001e78a1bf (prio 0, i/o): aspeed.i2c.bus.5
       000000001e78a1c0-000000001e78a1ff (prio 0, i/o): aspeed.i2c.bus.6
       000000001e78a300-000000001e78a33f (prio 0, i/o): aspeed.i2c.bus.7
       000000001e78a340-000000001e78a37f (prio 0, i/o): aspeed.i2c.bus.8
       000000001e78a380-000000001e78a3bf (prio 0, i/o): aspeed.i2c.bus.9
       000000001e78a3c0-000000001e78a3ff (prio 0, i/o): aspeed.i2c.bus.10
       000000001e78a400-000000001e78a43f (prio 0, i/o): aspeed.i2c.bus.11
       000000001e78a440-000000001e78a47f (prio 0, i/o): aspeed.i2c.bus.12
       000000001e78a480-000000001e78a4bf (prio 0, i/o): aspeed.i2c.bus.13
       000000001e78a800-000000001e78afff (prio 0, i/o): aspeed.i2c-pool

AST2500

     000000001e78a000-000000001e78afff (prio 0, i/o): aspeed.i2c
       000000001e78a040-000000001e78a07f (prio 0, i/o): aspeed.i2c.bus.0
       000000001e78a080-000000001e78a0bf (prio 0, i/o): aspeed.i2c.bus.1
       000000001e78a0c0-000000001e78a0ff (prio 0, i/o): aspeed.i2c.bus.2
       000000001e78a100-000000001e78a13f (prio 0, i/o): aspeed.i2c.bus.3
       000000001e78a140-000000001e78a17f (prio 0, i/o): aspeed.i2c.bus.4
       000000001e78a180-000000001e78a1bf (prio 0, i/o): aspeed.i2c.bus.5
       000000001e78a1c0-000000001e78a1ff (prio 0, i/o): aspeed.i2c.bus.6
       000000001e78a200-000000001e78a2ff (prio 0, i/o): aspeed.i2c-pool
       000000001e78a300-000000001e78a33f (prio 0, i/o): aspeed.i2c.bus.7
       000000001e78a340-000000001e78a37f (prio 0, i/o): aspeed.i2c.bus.8
       000000001e78a380-000000001e78a3bf (prio 0, i/o): aspeed.i2c.bus.9
       000000001e78a3c0-000000001e78a3ff (prio 0, i/o): aspeed.i2c.bus.10
       000000001e78a400-000000001e78a43f (prio 0, i/o): aspeed.i2c.bus.11
       000000001e78a440-000000001e78a47f (prio 0, i/o): aspeed.i2c.bus.12
       000000001e78a480-000000001e78a4bf (prio 0, i/o): aspeed.i2c.bus.13

AST2600

     000000001e78a000-000000001e78afff (prio 0, i/o): aspeed.i2c
       000000001e78a080-000000001e78a0ff (prio 0, i/o): aspeed.i2c.bus.0
       000000001e78a100-000000001e78a17f (prio 0, i/o): aspeed.i2c.bus.1
       000000001e78a180-000000001e78a1ff (prio 0, i/o): aspeed.i2c.bus.2
       000000001e78a200-000000001e78a27f (prio 0, i/o): aspeed.i2c.bus.3
       000000001e78a280-000000001e78a2ff (prio 0, i/o): aspeed.i2c.bus.4
       000000001e78a300-000000001e78a37f (prio 0, i/o): aspeed.i2c.bus.5
       000000001e78a380-000000001e78a3ff (prio 0, i/o): aspeed.i2c.bus.6
       000000001e78a400-000000001e78a47f (prio 0, i/o): aspeed.i2c.bus.7
       000000001e78a480-000000001e78a4ff (prio 0, i/o): aspeed.i2c.bus.8
       000000001e78a500-000000001e78a57f (prio 0, i/o): aspeed.i2c.bus.9
       000000001e78a580-000000001e78a5ff (prio 0, i/o): aspeed.i2c.bus.10
       000000001e78a600-000000001e78a67f (prio 0, i/o): aspeed.i2c.bus.11
       000000001e78a680-000000001e78a6ff (prio 0, i/o): aspeed.i2c.bus.12
       000000001e78a700-000000001e78a77f (prio 0, i/o): aspeed.i2c.bus.13
       000000001e78a780-000000001e78a7ff (prio 0, i/o): aspeed.i2c.bus.14
       000000001e78a800-000000001e78a87f (prio 0, i/o): aspeed.i2c.bus.15
       000000001e78ac00-000000001e78adff (prio 0, i/o): aspeed.i2c-pool



^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] qtest: Add functions for accessing devices on Aspeed I2C controller
  2023-03-27 20:24 ` [PATCH 1/3] qtest: Add functions for accessing devices on Aspeed I2C controller Stefan Berger
  2023-03-28  6:39   ` Cédric Le Goater
@ 2023-03-28 13:26   ` Ninad Palsule
  1 sibling, 0 replies; 14+ messages in thread
From: Ninad Palsule @ 2023-03-28 13:26 UTC (permalink / raw)
  To: Stefan Berger, qemu-devel; +Cc: marcandre.lureau, clg, ninad, joel, andrew


On 3/27/23 3:24 PM, Stefan Berger wrote:
> Add read and write functions for accessing registers of I2C devices
> connected to the Aspeed I2C controller.
>
> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Ninad Palsule <ninad@linux.ibm.com>

> ---
>   include/hw/i2c/aspeed_i2c.h |   7 +++
>   tests/qtest/qtest_aspeed.c  | 109 ++++++++++++++++++++++++++++++++++++
>   tests/qtest/qtest_aspeed.h  |  34 +++++++++++
>   3 files changed, 150 insertions(+)
>   create mode 100644 tests/qtest/qtest_aspeed.c
>   create mode 100644 tests/qtest/qtest_aspeed.h
>
> diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
> index adc904d6c1..51c944efea 100644
> --- a/include/hw/i2c/aspeed_i2c.h
> +++ b/include/hw/i2c/aspeed_i2c.h
> @@ -38,6 +38,13 @@ OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C)
>   #define ASPEED_I2C_OLD_NUM_REG 11
>   #define ASPEED_I2C_NEW_NUM_REG 22
>   
> +#define A_I2CD_M_STOP_CMD       BIT(5)
> +#define A_I2CD_M_RX_CMD         BIT(3)
> +#define A_I2CD_M_TX_CMD         BIT(1)
> +#define A_I2CD_M_START_CMD      BIT(0)
> +
> +#define A_I2CD_MASTER_EN        BIT(0)
> +
>   /* Tx State Machine */
>   #define   I2CD_TX_STATE_MASK                  0xf
>   #define     I2CD_IDLE                         0x0
> diff --git a/tests/qtest/qtest_aspeed.c b/tests/qtest/qtest_aspeed.c
> new file mode 100644
> index 0000000000..2fcafc22fc
> --- /dev/null
> +++ b/tests/qtest/qtest_aspeed.c
> @@ -0,0 +1,109 @@
> +/*
> + * Aspeed i2c bus interface for reading from and writing to i2c device registers
> + *
> + * Copyright (c) 2023 IBM Corporation
> + *
> + * Authors:
> + *   Stefan Berger <stefanb@linux.ibm.com>
> + *
> + * 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 "qtest_aspeed.h"
> +#include "hw/i2c/aspeed_i2c.h"
> +#include "libqtest-single.h"
> +
> +static void aspeed_i2c_startup(uint32_t baseaddr, uint8_t slave_addr,
> +                               uint8_t reg)
> +{
> +    uint32_t v;
> +    static int once;
> +
> +    if (!once) {
> +        /* one time: enable master */
> +       writel(baseaddr + A_I2CC_FUN_CTRL, 0);
> +       v = readl(baseaddr + A_I2CC_FUN_CTRL) | A_I2CD_MASTER_EN;
> +       writel(baseaddr + A_I2CC_FUN_CTRL, v);
> +       once = 1;
> +    }
> +
> +    /* select device */
> +    writel(baseaddr + A_I2CD_BYTE_BUF, slave_addr << 1);
> +    writel(baseaddr + A_I2CD_CMD, A_I2CD_M_START_CMD | A_I2CD_M_RX_CMD);
> +
> +    /* select the register to write to */
> +    writel(baseaddr + A_I2CD_BYTE_BUF, reg);
> +    writel(baseaddr + A_I2CD_CMD, A_I2CD_M_TX_CMD);
> +}
> +
> +static uint32_t aspeed_i2c_read_n(uint32_t baseaddr, uint8_t slave_addr,
> +                                  uint8_t reg, size_t nbytes)
> +{
> +    uint32_t res = 0;
> +    uint32_t v;
> +    size_t i;
> +
> +    aspeed_i2c_startup(baseaddr, slave_addr, reg);
> +
> +    for (i = 0; i < nbytes; i++) {
> +        writel(baseaddr + A_I2CD_CMD, A_I2CD_M_RX_CMD);
> +        v = readl(baseaddr + A_I2CD_BYTE_BUF) >> 8;
> +        res |= (v & 0xff) << (i * 8);
> +    }
> +
> +    writel(baseaddr + A_I2CD_CMD, A_I2CD_M_STOP_CMD);
> +
> +    return res;
> +}
> +
> +uint32_t aspeed_i2c_readl(uint32_t baseaddr, uint8_t slave_addr, uint8_t reg)
> +{
> +    return aspeed_i2c_read_n(baseaddr, slave_addr, reg, sizeof(uint32_t));
> +}
> +
> +uint16_t aspeed_i2c_readw(uint32_t baseaddr, uint8_t slave_addr, uint8_t reg)
> +{
> +    return aspeed_i2c_read_n(baseaddr, slave_addr, reg, sizeof(uint16_t));
> +}
> +
> +uint8_t aspeed_i2c_readb(uint32_t baseaddr, uint8_t slave_addr, uint8_t reg)
> +{
> +    return aspeed_i2c_read_n(baseaddr, slave_addr, reg, sizeof(uint8_t));
> +}
> +
> +static void aspeed_i2c_write_n(uint32_t baseaddr, uint8_t slave_addr,
> +                               uint8_t reg, uint32_t v, size_t nbytes)
> +{
> +    size_t i;
> +
> +    aspeed_i2c_startup(baseaddr, slave_addr, reg);
> +
> +    for (i = 0; i < nbytes; i++) {
> +        writel(baseaddr + A_I2CD_BYTE_BUF, v & 0xff);
> +        v >>= 8;
> +        writel(baseaddr + A_I2CD_CMD, A_I2CD_M_TX_CMD);
> +    }
> +
> +    writel(baseaddr + A_I2CD_CMD, A_I2CD_M_STOP_CMD);
> +}
> +
> +void aspeed_i2c_writel(uint32_t baseaddr, uint8_t slave_addr,
> +                       uint8_t reg, uint32_t v)
> +{
> +    aspeed_i2c_write_n(baseaddr, slave_addr, reg, v, sizeof(v));
> +}
> +
> +void aspeed_i2c_writew(uint32_t baseaddr, uint8_t slave_addr,
> +                       uint8_t reg, uint16_t v)
> +{
> +    aspeed_i2c_write_n(baseaddr, slave_addr, reg, v, sizeof(v));
> +}
> +
> +void aspeed_i2c_writeb(uint32_t baseaddr, uint8_t slave_addr,
> +                       uint8_t reg, uint8_t v)
> +{
> +    aspeed_i2c_write_n(baseaddr, slave_addr, reg, v, sizeof(v));
> +}
> diff --git a/tests/qtest/qtest_aspeed.h b/tests/qtest/qtest_aspeed.h
> new file mode 100644
> index 0000000000..529061cf5b
> --- /dev/null
> +++ b/tests/qtest/qtest_aspeed.h
> @@ -0,0 +1,34 @@
> +/*
> + * Aspeed i2c bus interface to reading and writing to i2c device registers
> + *
> + * Copyright (c) 2023 IBM Corporation
> + *
> + * Authors:
> + *   Stefan Berger <stefanb@linux.ibm.com>
> + *
> + * 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 QTEST_ASPEED_H
> +#define QTEST_ASPEED_H
> +
> +#include <stdint.h>
> +
> +#define AST2600_ASPEED_I2C_BASE_ADDR 0x1e78a000
> +
> +static inline uint32_t ast2600_aspeed_i2c_calc_dev_addr(uint8_t bus_num)
> +{
> +    return AST2600_ASPEED_I2C_BASE_ADDR + 0x80 + bus_num * 0x80;
> +}
> +
> +uint8_t aspeed_i2c_readb(uint32_t baseaddr, uint8_t slave_addr, uint8_t reg);
> +uint16_t aspeed_i2c_readw(uint32_t baseaddr, uint8_t slave_addr, uint8_t reg);
> +uint32_t aspeed_i2c_readl(uint32_t baseaddr, uint8_t slave_addr, uint8_t reg);
> +void aspeed_i2c_writeb(uint32_t baseaddr, uint8_t slave_addr,
> +                       uint8_t reg, uint8_t v);
> +void aspeed_i2c_writew(uint32_t baseaddr, uint8_t slave_addr,
> +                       uint8_t reg, uint16_t v);
> +void aspeed_i2c_writel(uint32_t baseaddr, uint8_t slave_addr,
> +                       uint8_t reg, uint32_t v);
> +
> +#endif


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/3] qtest: Move tpm_util_tis_transmit() into tpm-tis-utils.c and rename it
  2023-03-27 20:24 ` [PATCH 2/3] qtest: Move tpm_util_tis_transmit() into tpm-tis-utils.c and rename it Stefan Berger
@ 2023-03-28 13:31   ` Ninad Palsule
  0 siblings, 0 replies; 14+ messages in thread
From: Ninad Palsule @ 2023-03-28 13:31 UTC (permalink / raw)
  To: Stefan Berger, qemu-devel; +Cc: marcandre.lureau, clg, ninad, joel, andrew


On 3/27/23 3:24 PM, Stefan Berger wrote:
> To be able to remove tpm_tis_base_addr from test cases that do not really
> need it move the tpm_util_tis_transmit() function into tpm-tis-utils.c and
> rename it to tpm_tis_transmit().
>
> Fix a locality parameter in a test case on the way.
>
> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Ninad Palsule <ninad@linux.ibm.com>
> ---
>   tests/qtest/tpm-crb-swtpm-test.c        |  3 --
>   tests/qtest/tpm-crb-test.c              |  3 --
>   tests/qtest/tpm-tis-device-swtpm-test.c |  5 +--
>   tests/qtest/tpm-tis-swtpm-test.c        |  5 +--
>   tests/qtest/tpm-tis-util.c              | 47 ++++++++++++++++++++++++-
>   tests/qtest/tpm-tis-util.h              |  4 +++
>   tests/qtest/tpm-util.c                  | 45 -----------------------
>   tests/qtest/tpm-util.h                  |  3 --
>   8 files changed, 56 insertions(+), 59 deletions(-)
>
> diff --git a/tests/qtest/tpm-crb-swtpm-test.c b/tests/qtest/tpm-crb-swtpm-test.c
> index 40254f762f..ffeb1c396b 100644
> --- a/tests/qtest/tpm-crb-swtpm-test.c
> +++ b/tests/qtest/tpm-crb-swtpm-test.c
> @@ -19,9 +19,6 @@
>   #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;
>       char *dst_tpm_path;
> diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c
> index 7b94453390..396ae3f91c 100644
> --- a/tests/qtest/tpm-crb-test.c
> +++ b/tests/qtest/tpm-crb-test.c
> @@ -19,9 +19,6 @@
>   #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-device-swtpm-test.c b/tests/qtest/tpm-tis-device-swtpm-test.c
> index 8c067fddd4..517a077005 100644
> --- a/tests/qtest/tpm-tis-device-swtpm-test.c
> +++ b/tests/qtest/tpm-tis-device-swtpm-test.c
> @@ -18,6 +18,7 @@
>   #include "libqtest.h"
>   #include "qemu/module.h"
>   #include "tpm-tests.h"
> +#include "tpm-tis-util.h"
>   #include "hw/acpi/tpm.h"
>   
>   uint64_t tpm_tis_base_addr = 0xc000000;
> @@ -33,7 +34,7 @@ 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_test_swtpm_test(ts->src_tpm_path, tpm_tis_transfer,
>                           "tpm-tis-device", MACHINE_OPTIONS);
>   }
>   
> @@ -42,7 +43,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-device",
> +                                  tpm_tis_transfer, "tpm-tis-device",
>                                     MACHINE_OPTIONS);
>   }
>   
> diff --git a/tests/qtest/tpm-tis-swtpm-test.c b/tests/qtest/tpm-tis-swtpm-test.c
> index 11539c0a52..105e42e21d 100644
> --- a/tests/qtest/tpm-tis-swtpm-test.c
> +++ b/tests/qtest/tpm-tis-swtpm-test.c
> @@ -17,6 +17,7 @@
>   #include "libqtest.h"
>   #include "qemu/module.h"
>   #include "tpm-tests.h"
> +#include "tpm-tis-util.h"
>   #include "hw/acpi/tpm.h"
>   
>   uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE;
> @@ -31,7 +32,7 @@ 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_test_swtpm_test(ts->src_tpm_path, tpm_tis_transfer,
>                           "tpm-tis", NULL);
>   }
>   
> @@ -40,7 +41,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", NULL);
> +                                  tpm_tis_transfer, "tpm-tis", NULL);
>   }
>   
>   int main(int argc, char **argv)
> diff --git a/tests/qtest/tpm-tis-util.c b/tests/qtest/tpm-tis-util.c
> index 939893bf01..728cd3e065 100644
> --- a/tests/qtest/tpm-tis-util.c
> +++ b/tests/qtest/tpm-tis-util.c
> @@ -52,7 +52,7 @@ void tpm_tis_test_check_localities(const void *data)
>       uint32_t rid;
>   
>       for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) {
> -        access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS));
> +        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);
>   
> @@ -449,3 +449,48 @@ void tpm_tis_test_check_transmit(const void *data)
>       writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_ACTIVE_LOCALITY);
>       access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS));
>   }
> +
> +void tpm_tis_transfer(QTestState *s,
> +                      const unsigned char *req, size_t req_size,
> +                      unsigned char *rsp, size_t rsp_size)
> +{
> +    uint32_t sts;
> +    uint16_t bcount;
> +    size_t i;
> +
> +    /* request use of locality 0 */
> +    qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE);
> +    qtest_writel(s, TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY);
> +
> +    sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS));
> +    bcount = (sts >> 8) & 0xffff;
> +    g_assert_cmpint(bcount, >=, req_size);
> +
> +    /* transmit command */
> +    for (i = 0; i < req_size; i++) {
> +        qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_DATA_FIFO), req[i]);
> +    }
> +
> +    /* start processing */
> +    qtest_writeb(s, 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 = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS));
> +        if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) {
> +            break;
> +        }
> +    } while (g_get_monotonic_time() < end_time);
> +
> +    sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS));
> +    bcount = (sts >> 8) & 0xffff;
> +
> +    memset(rsp, 0, rsp_size);
> +    for (i = 0; i < bcount; i++) {
> +        rsp[i] = qtest_readb(s, TIS_REG(0, TPM_TIS_REG_DATA_FIFO));
> +    }
> +
> +    /* relinquish use of locality 0 */
> +    qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_ACCESS),
> +                 TPM_TIS_ACCESS_ACTIVE_LOCALITY);
> +}
> diff --git a/tests/qtest/tpm-tis-util.h b/tests/qtest/tpm-tis-util.h
> index d10efe86ae..03910a7ba7 100644
> --- a/tests/qtest/tpm-tis-util.h
> +++ b/tests/qtest/tpm-tis-util.h
> @@ -20,4 +20,8 @@ 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);
>   
> +void tpm_tis_transfer(QTestState *s,
> +                      const unsigned char *req, size_t req_size,
> +                      unsigned char *rsp, size_t rsp_size);
> +
>   #endif /* TESTS_TPM_TIS_UTIL_H */
> diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c
> index a7efe2d0d2..1c0319e6e7 100644
> --- a/tests/qtest/tpm-util.c
> +++ b/tests/qtest/tpm-util.c
> @@ -51,51 +51,6 @@ void tpm_util_crb_transfer(QTestState *s,
>       qtest_memread(s, raddr, rsp, rsp_size);
>   }
>   
> -void tpm_util_tis_transfer(QTestState *s,
> -                           const unsigned char *req, size_t req_size,
> -                           unsigned char *rsp, size_t rsp_size)
> -{
> -    uint32_t sts;
> -    uint16_t bcount;
> -    size_t i;
> -
> -    /* request use of locality 0 */
> -    qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE);
> -    qtest_writel(s, TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY);
> -
> -    sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS));
> -    bcount = (sts >> 8) & 0xffff;
> -    g_assert_cmpint(bcount, >=, req_size);
> -
> -    /* transmit command */
> -    for (i = 0; i < req_size; i++) {
> -        qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_DATA_FIFO), req[i]);
> -    }
> -
> -    /* start processing */
> -    qtest_writeb(s, 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 = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS));
> -        if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) {
> -            break;
> -        }
> -    } while (g_get_monotonic_time() < end_time);
> -
> -    sts = qtest_readl(s, TIS_REG(0, TPM_TIS_REG_STS));
> -    bcount = (sts >> 8) & 0xffff;
> -
> -    memset(rsp, 0, rsp_size);
> -    for (i = 0; i < bcount; i++) {
> -        rsp[i] = qtest_readb(s, TIS_REG(0, TPM_TIS_REG_DATA_FIFO));
> -    }
> -
> -    /* relinquish use of locality 0 */
> -    qtest_writeb(s, TIS_REG(0, TPM_TIS_REG_ACCESS),
> -                 TPM_TIS_ACCESS_ACTIVE_LOCALITY);
> -}
> -
>   void tpm_util_startup(QTestState *s, tx_func *tx)
>   {
>       unsigned char buffer[1024];
> diff --git a/tests/qtest/tpm-util.h b/tests/qtest/tpm-util.h
> index 80720afac0..0cb28dd6e5 100644
> --- a/tests/qtest/tpm-util.h
> +++ b/tests/qtest/tpm-util.h
> @@ -27,9 +27,6 @@ typedef void (tx_func)(QTestState *s,
>   void tpm_util_crb_transfer(QTestState *s,
>                              const unsigned char *req, size_t req_size,
>                              unsigned char *rsp, size_t rsp_size);
> -void tpm_util_tis_transfer(QTestState *s,
> -                           const unsigned char *req, size_t req_size,
> -                           unsigned char *rsp, size_t rsp_size);
>   
>   void tpm_util_startup(QTestState *s, tx_func *tx);
>   void tpm_util_pcrextend(QTestState *s, tx_func *tx);


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/3] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller
  2023-03-27 20:24 ` [PATCH 3/3] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller Stefan Berger
  2023-03-28  6:44   ` Cédric Le Goater
  2023-03-28  9:17   ` Cédric Le Goater
@ 2023-03-28 14:10   ` Ninad Palsule
  2 siblings, 0 replies; 14+ messages in thread
From: Ninad Palsule @ 2023-03-28 14:10 UTC (permalink / raw)
  To: Stefan Berger, qemu-devel; +Cc: marcandre.lureau, clg, ninad, joel, andrew


On 3/27/23 3:24 PM, Stefan Berger wrote:
> Add a test case for the TPM TIS I2C device exercising most of its
> functionality, including localities.
>
> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>

Reviewed-by: Ninad Palsule <ninad@linux.ibm.com>
Tested-by: Ninad Palsule <ninad@linux.ibm.com>




^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2023-03-28 14:11 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-27 20:24 [PATCH 0/3] qtests: tpm: Add test cases for TPM TIS I2C device emulation Stefan Berger
2023-03-27 20:24 ` [PATCH 1/3] qtest: Add functions for accessing devices on Aspeed I2C controller Stefan Berger
2023-03-28  6:39   ` Cédric Le Goater
2023-03-28 12:26     ` Stefan Berger
2023-03-28 13:10       ` Cédric Le Goater
2023-03-28 13:26   ` Ninad Palsule
2023-03-27 20:24 ` [PATCH 2/3] qtest: Move tpm_util_tis_transmit() into tpm-tis-utils.c and rename it Stefan Berger
2023-03-28 13:31   ` Ninad Palsule
2023-03-27 20:24 ` [PATCH 3/3] qtest: Add a test case for TPM TIS I2C connected to Aspeed I2C controller Stefan Berger
2023-03-28  6:44   ` Cédric Le Goater
2023-03-28  9:17   ` Cédric Le Goater
2023-03-28 11:31     ` Stefan Berger
2023-03-28 11:52       ` Cédric Le Goater
2023-03-28 14:10   ` Ninad Palsule

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).