All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device
@ 2023-07-14  7:09 Joelle van Dyne
  2023-07-14  7:09 ` [PATCH v2 01/11] tpm_crb: refactor common code Joelle van Dyne
                   ` (10 more replies)
  0 siblings, 11 replies; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14  7:09 UTC (permalink / raw)
  To: qemu-devel

The impetus for this patch set is to get TPM 2.0 working on Windows 11 ARM64.
Windows' tpm.sys does not seem to work on a TPM TIS device (as verified with
VMWare's implementation). However, the current TPM CRB device uses a fixed
system bus address that is reserved for RAM in ARM64 Virt machines.

In the process of adding the TPM CRB SysBus device, we also went ahead and
cleaned up some of the existing TPM hardware code and fixed some bugs. We used
the TPM TIS devices as a template for the TPM CRB devices and refactored out
common code. We moved the ACPI DSDT generation to the device in order to handle
dynamic base address requirements as well as reduce redundent code in different
machine ACPI generation. We also changed the tpm_crb device to use the ISA bus
instead of depending on the default system bus as the device only was built for
the PC configuration.

Another change is that the TPM CRB registers are now mapped in the same way that
the pflash ROM devices are mapped. It is a memory region whose writes are
trapped as MMIO accesses. This was needed because Apple Silicon does not decode
LDP (AARCH64 load pair of registers) caused page faults. @agraf suggested that
we do this to avoid having to do AARCH64 decoding in the HVF backend's fault
handler.

Unfortunately, it seems like the LDP fault still happens on HVF but the issue
seems to be in the HVF backend which needs to be fixed in a separate patch.

One last thing that's needed to get Windows 11 to recognize the TPM 2.0 device
is for the OVMF firmware to setup the TPM device. Currently, OVMF for ARM64 Virt
only recognizes the TPM TIS device through a FDT entry. A workaround is to
falsely identify the TPM CRB device as a TPM TIS device in the FDT node but this
causes issues for Linux. A proper fix would involve adding an ACPI device driver
in OVMF.

v2:
- Fixed an issue where VMstate restore from an older version failed due to name
  collision of the memory block.
- In the ACPI table generation for CRB devices, the check for TPM 2.0 backend is
  moved to the device realize as CRB does not support TPM 1.0. It will error in
  that case.
- Dropped the patch to fix crash when PPI is enabled on TIS SysBus device since
  a separate patch submitted by Stefan Berger disables such an option.
- Fixed an issue where we default tpmEstablished=0 when it should be 1.
- In TPM CRB SysBus's ACPI entry, we accidently changed _UID from 0 to 1. This
  shouldn't be an issue but we changed it back just in case.
- Added a patch to migrate saved VMstate from an older version with the regs
  saved separately instead of as a RAM block.

Joelle van Dyne (11):
  tpm_crb: refactor common code
  tpm_crb: CTRL_RSP_ADDR is 64-bits wide
  tpm_ppi: refactor memory space initialization
  tpm_crb: use a single read-as-mem/write-as-mmio mapping
  tpm_crb: use the ISA bus
  tpm_crb: move ACPI table building to device interface
  hw/arm/virt: add plug handler for TPM on SysBus
  hw/loongarch/virt: add plug handler for TPM on SysBus
  tpm_tis_sysbus: move DSDT AML generation to device
  tpm_crb_sysbus: introduce TPM CRB SysBus device
  tpm_crb: support restoring older vmstate

 docs/specs/tpm.rst          |   2 +
 hw/tpm/tpm_crb.h            |  75 +++++++++
 hw/tpm/tpm_ppi.h            |  10 +-
 include/hw/acpi/aml-build.h |   1 +
 include/hw/acpi/tpm.h       |   3 +-
 include/sysemu/tpm.h        |   3 +
 hw/acpi/aml-build.c         |   7 +-
 hw/arm/virt-acpi-build.c    |  38 +----
 hw/arm/virt.c               |  38 +++++
 hw/core/sysbus-fdt.c        |   1 +
 hw/i386/acpi-build.c        |  23 ---
 hw/loongarch/acpi-build.c   |  38 +----
 hw/loongarch/virt.c         |  38 +++++
 hw/riscv/virt.c             |   1 +
 hw/tpm/tpm_crb.c            | 314 +++++++++---------------------------
 hw/tpm/tpm_crb_common.c     | 233 ++++++++++++++++++++++++++
 hw/tpm/tpm_crb_sysbus.c     | 170 +++++++++++++++++++
 hw/tpm/tpm_ppi.c            |   5 +-
 hw/tpm/tpm_tis_isa.c        |   5 +-
 hw/tpm/tpm_tis_sysbus.c     |  35 ++++
 tests/qtest/tpm-crb-test.c  |   2 +-
 tests/qtest/tpm-util.c      |   2 +-
 hw/arm/Kconfig              |   1 +
 hw/riscv/Kconfig            |   1 +
 hw/tpm/Kconfig              |   7 +-
 hw/tpm/meson.build          |   3 +
 hw/tpm/trace-events         |   2 +-
 27 files changed, 708 insertions(+), 350 deletions(-)
 create mode 100644 hw/tpm/tpm_crb.h
 create mode 100644 hw/tpm/tpm_crb_common.c
 create mode 100644 hw/tpm/tpm_crb_sysbus.c

-- 
2.39.2 (Apple Git-143)



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

* [PATCH v2 01/11] tpm_crb: refactor common code
  2023-07-14  7:09 [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device Joelle van Dyne
@ 2023-07-14  7:09 ` Joelle van Dyne
  2023-07-14  7:09 ` [PATCH v2 02/11] tpm_crb: CTRL_RSP_ADDR is 64-bits wide Joelle van Dyne
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14  7:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Joelle van Dyne, Stefan Berger, Stefan Berger

In preparation for the SysBus variant, we move common code styled
after the TPM TIS devices.

To maintain compatibility, we do not rename the existing tpm-crb
device.

Signed-off-by: Joelle van Dyne <j@getutm.app>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
 docs/specs/tpm.rst      |   1 +
 hw/tpm/tpm_crb.h        |  76 +++++++++++
 hw/tpm/tpm_crb.c        | 270 ++++++----------------------------------
 hw/tpm/tpm_crb_common.c | 218 ++++++++++++++++++++++++++++++++
 hw/tpm/meson.build      |   1 +
 hw/tpm/trace-events     |   2 +-
 6 files changed, 333 insertions(+), 235 deletions(-)
 create mode 100644 hw/tpm/tpm_crb.h
 create mode 100644 hw/tpm/tpm_crb_common.c

diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index efe124a148..2bc29c9804 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -45,6 +45,7 @@ operating system.
 
 QEMU files related to TPM CRB interface:
  - ``hw/tpm/tpm_crb.c``
+ - ``hw/tpm/tpm_crb_common.c``
 
 SPAPR interface
 ---------------
diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
new file mode 100644
index 0000000000..da3a0cf256
--- /dev/null
+++ b/hw/tpm/tpm_crb.h
@@ -0,0 +1,76 @@
+/*
+ * tpm_crb.h - QEMU's TPM CRB interface emulator
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * Authors:
+ *   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.
+ *
+ * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
+ * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
+ * Family “2.0” Level 00 Revision 01.03 v22
+ */
+#ifndef TPM_TPM_CRB_H
+#define TPM_TPM_CRB_H
+
+#include "exec/memory.h"
+#include "hw/acpi/tpm.h"
+#include "sysemu/tpm_backend.h"
+#include "tpm_ppi.h"
+
+#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - A_CRB_DATA_BUFFER)
+
+typedef struct TPMCRBState {
+    TPMBackend *tpmbe;
+    TPMBackendCmd cmd;
+    uint32_t regs[TPM_CRB_R_MAX];
+    MemoryRegion mmio;
+    MemoryRegion cmdmem;
+
+    size_t be_buffer_size;
+
+    bool ppi_enabled;
+    TPMPPI ppi;
+} TPMCRBState;
+
+#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
+#define CRB_INTF_VERSION_CRB 0b1
+#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
+#define CRB_INTF_CAP_IDLE_FAST 0b0
+#define CRB_INTF_CAP_XFER_SIZE_64 0b11
+#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
+#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
+#define CRB_INTF_IF_SELECTOR_CRB 0b1
+
+enum crb_loc_ctrl {
+    CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
+    CRB_LOC_CTRL_RELINQUISH = BIT(1),
+    CRB_LOC_CTRL_SEIZE = BIT(2),
+    CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
+};
+
+enum crb_ctrl_req {
+    CRB_CTRL_REQ_CMD_READY = BIT(0),
+    CRB_CTRL_REQ_GO_IDLE = BIT(1),
+};
+
+enum crb_start {
+    CRB_START_INVOKE = BIT(0),
+};
+
+enum crb_cancel {
+    CRB_CANCEL_INVOKE = BIT(0),
+};
+
+#define TPM_CRB_NO_LOCALITY 0xff
+
+void tpm_crb_request_completed(TPMCRBState *s, int ret);
+enum TPMVersion tpm_crb_get_version(TPMCRBState *s);
+int tpm_crb_pre_save(TPMCRBState *s);
+void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr);
+void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp);
+
+#endif /* TPM_TPM_CRB_H */
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index ea930da545..3ef4977fb5 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -31,257 +31,62 @@
 #include "tpm_ppi.h"
 #include "trace.h"
 #include "qom/object.h"
+#include "tpm_crb.h"
 
 struct CRBState {
     DeviceState parent_obj;
 
-    TPMBackend *tpmbe;
-    TPMBackendCmd cmd;
-    uint32_t regs[TPM_CRB_R_MAX];
-    MemoryRegion mmio;
-    MemoryRegion cmdmem;
-
-    size_t be_buffer_size;
-
-    bool ppi_enabled;
-    TPMPPI ppi;
+    TPMCRBState state;
 };
 typedef struct CRBState CRBState;
 
 DECLARE_INSTANCE_CHECKER(CRBState, CRB,
                          TYPE_TPM_CRB)
 
-#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
-#define CRB_INTF_VERSION_CRB 0b1
-#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
-#define CRB_INTF_CAP_IDLE_FAST 0b0
-#define CRB_INTF_CAP_XFER_SIZE_64 0b11
-#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
-#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
-#define CRB_INTF_IF_SELECTOR_CRB 0b1
-
-#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - A_CRB_DATA_BUFFER)
-
-enum crb_loc_ctrl {
-    CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
-    CRB_LOC_CTRL_RELINQUISH = BIT(1),
-    CRB_LOC_CTRL_SEIZE = BIT(2),
-    CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
-};
-
-enum crb_ctrl_req {
-    CRB_CTRL_REQ_CMD_READY = BIT(0),
-    CRB_CTRL_REQ_GO_IDLE = BIT(1),
-};
-
-enum crb_start {
-    CRB_START_INVOKE = BIT(0),
-};
-
-enum crb_cancel {
-    CRB_CANCEL_INVOKE = BIT(0),
-};
-
-#define TPM_CRB_NO_LOCALITY 0xff
-
-static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
-                                  unsigned size)
-{
-    CRBState *s = CRB(opaque);
-    void *regs = (void *)&s->regs + (addr & ~3);
-    unsigned offset = addr & 3;
-    uint32_t val = *(uint32_t *)regs >> (8 * offset);
-
-    switch (addr) {
-    case A_CRB_LOC_STATE:
-        val |= !tpm_backend_get_tpm_established_flag(s->tpmbe);
-        break;
-    }
-
-    trace_tpm_crb_mmio_read(addr, size, val);
-
-    return val;
-}
-
-static uint8_t tpm_crb_get_active_locty(CRBState *s)
-{
-    if (!ARRAY_FIELD_EX32(s->regs, CRB_LOC_STATE, locAssigned)) {
-        return TPM_CRB_NO_LOCALITY;
-    }
-    return ARRAY_FIELD_EX32(s->regs, CRB_LOC_STATE, activeLocality);
-}
-
-static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
-                               uint64_t val, unsigned size)
-{
-    CRBState *s = CRB(opaque);
-    uint8_t locty =  addr >> 12;
-
-    trace_tpm_crb_mmio_write(addr, size, val);
-
-    switch (addr) {
-    case A_CRB_CTRL_REQ:
-        switch (val) {
-        case CRB_CTRL_REQ_CMD_READY:
-            ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
-                             tpmIdle, 0);
-            break;
-        case CRB_CTRL_REQ_GO_IDLE:
-            ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
-                             tpmIdle, 1);
-            break;
-        }
-        break;
-    case A_CRB_CTRL_CANCEL:
-        if (val == CRB_CANCEL_INVOKE &&
-            s->regs[R_CRB_CTRL_START] & CRB_START_INVOKE) {
-            tpm_backend_cancel_cmd(s->tpmbe);
-        }
-        break;
-    case A_CRB_CTRL_START:
-        if (val == CRB_START_INVOKE &&
-            !(s->regs[R_CRB_CTRL_START] & CRB_START_INVOKE) &&
-            tpm_crb_get_active_locty(s) == locty) {
-            void *mem = memory_region_get_ram_ptr(&s->cmdmem);
-
-            s->regs[R_CRB_CTRL_START] |= CRB_START_INVOKE;
-            s->cmd = (TPMBackendCmd) {
-                .in = mem,
-                .in_len = MIN(tpm_cmd_get_size(mem), s->be_buffer_size),
-                .out = mem,
-                .out_len = s->be_buffer_size,
-            };
-
-            tpm_backend_deliver_request(s->tpmbe, &s->cmd);
-        }
-        break;
-    case A_CRB_LOC_CTRL:
-        switch (val) {
-        case CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT:
-            /* not loc 3 or 4 */
-            break;
-        case CRB_LOC_CTRL_RELINQUISH:
-            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STATE,
-                             locAssigned, 0);
-            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STS,
-                             Granted, 0);
-            break;
-        case CRB_LOC_CTRL_REQUEST_ACCESS:
-            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STS,
-                             Granted, 1);
-            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STS,
-                             beenSeized, 0);
-            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STATE,
-                             locAssigned, 1);
-            break;
-        }
-        break;
-    }
-}
-
-static const MemoryRegionOps tpm_crb_memory_ops = {
-    .read = tpm_crb_mmio_read,
-    .write = tpm_crb_mmio_write,
-    .endianness = DEVICE_LITTLE_ENDIAN,
-    .valid = {
-        .min_access_size = 1,
-        .max_access_size = 4,
-    },
-};
-
-static void tpm_crb_request_completed(TPMIf *ti, int ret)
+static void tpm_crb_none_request_completed(TPMIf *ti, int ret)
 {
     CRBState *s = CRB(ti);
 
-    s->regs[R_CRB_CTRL_START] &= ~CRB_START_INVOKE;
-    if (ret != 0) {
-        ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
-                         tpmSts, 1); /* fatal error */
-    }
-    memory_region_set_dirty(&s->cmdmem, 0, CRB_CTRL_CMD_SIZE);
+    tpm_crb_request_completed(&s->state, ret);
 }
 
-static enum TPMVersion tpm_crb_get_version(TPMIf *ti)
+static enum TPMVersion tpm_crb_none_get_version(TPMIf *ti)
 {
     CRBState *s = CRB(ti);
 
-    return tpm_backend_get_tpm_version(s->tpmbe);
+    return tpm_crb_get_version(&s->state);
 }
 
-static int tpm_crb_pre_save(void *opaque)
+static int tpm_crb_none_pre_save(void *opaque)
 {
     CRBState *s = opaque;
 
-    tpm_backend_finish_sync(s->tpmbe);
-
-    return 0;
+    return tpm_crb_pre_save(&s->state);
 }
 
-static const VMStateDescription vmstate_tpm_crb = {
+static const VMStateDescription vmstate_tpm_crb_none = {
     .name = "tpm-crb",
-    .pre_save = tpm_crb_pre_save,
+    .pre_save = tpm_crb_none_pre_save,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(regs, CRBState, TPM_CRB_R_MAX),
+        VMSTATE_UINT32_ARRAY(state.regs, CRBState, TPM_CRB_R_MAX),
         VMSTATE_END_OF_LIST(),
     }
 };
 
-static Property tpm_crb_properties[] = {
-    DEFINE_PROP_TPMBE("tpmdev", CRBState, tpmbe),
-    DEFINE_PROP_BOOL("ppi", CRBState, ppi_enabled, true),
+static Property tpm_crb_none_properties[] = {
+    DEFINE_PROP_TPMBE("tpmdev", CRBState, state.tpmbe),
+    DEFINE_PROP_BOOL("ppi", CRBState, state.ppi_enabled, true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void tpm_crb_reset(void *dev)
+static void tpm_crb_none_reset(void *dev)
 {
     CRBState *s = CRB(dev);
 
-    if (s->ppi_enabled) {
-        tpm_ppi_reset(&s->ppi);
-    }
-    tpm_backend_reset(s->tpmbe);
-
-    memset(s->regs, 0, sizeof(s->regs));
-
-    ARRAY_FIELD_DP32(s->regs, CRB_LOC_STATE,
-                     tpmRegValidSts, 1);
-    ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
-                     tpmIdle, 1);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
-                     InterfaceType, CRB_INTF_TYPE_CRB_ACTIVE);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
-                     InterfaceVersion, CRB_INTF_VERSION_CRB);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
-                     CapLocality, CRB_INTF_CAP_LOCALITY_0_ONLY);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
-                     CapCRBIdleBypass, CRB_INTF_CAP_IDLE_FAST);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
-                     CapDataXferSizeSupport, CRB_INTF_CAP_XFER_SIZE_64);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
-                     CapFIFO, CRB_INTF_CAP_FIFO_NOT_SUPPORTED);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
-                     CapCRB, CRB_INTF_CAP_CRB_SUPPORTED);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
-                     InterfaceSelector, CRB_INTF_IF_SELECTOR_CRB);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
-                     RID, 0b0000);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID2,
-                     VID, PCI_VENDOR_ID_IBM);
-
-    s->regs[R_CRB_CTRL_CMD_SIZE] = CRB_CTRL_CMD_SIZE;
-    s->regs[R_CRB_CTRL_CMD_LADDR] = TPM_CRB_ADDR_BASE + A_CRB_DATA_BUFFER;
-    s->regs[R_CRB_CTRL_RSP_SIZE] = CRB_CTRL_CMD_SIZE;
-    s->regs[R_CRB_CTRL_RSP_ADDR] = TPM_CRB_ADDR_BASE + A_CRB_DATA_BUFFER;
-
-    s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
-                            CRB_CTRL_CMD_SIZE);
-
-    if (tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size) < 0) {
-        exit(1);
-    }
+    return tpm_crb_reset(&s->state, TPM_CRB_ADDR_BASE);
 }
 
-static void tpm_crb_realize(DeviceState *dev, Error **errp)
+static void tpm_crb_none_realize(DeviceState *dev, Error **errp)
 {
     CRBState *s = CRB(dev);
 
@@ -289,64 +94,61 @@ static void tpm_crb_realize(DeviceState *dev, Error **errp)
         error_setg(errp, "at most one TPM device is permitted");
         return;
     }
-    if (!s->tpmbe) {
+    if (!s->state.tpmbe) {
         error_setg(errp, "'tpmdev' property is required");
         return;
     }
 
-    memory_region_init_io(&s->mmio, OBJECT(s), &tpm_crb_memory_ops, s,
-        "tpm-crb-mmio", sizeof(s->regs));
-    memory_region_init_ram(&s->cmdmem, OBJECT(s),
-        "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+    tpm_crb_init_memory(OBJECT(s), &s->state, errp);
 
     memory_region_add_subregion(get_system_memory(),
-        TPM_CRB_ADDR_BASE, &s->mmio);
+        TPM_CRB_ADDR_BASE, &s->state.mmio);
     memory_region_add_subregion(get_system_memory(),
-        TPM_CRB_ADDR_BASE + sizeof(s->regs), &s->cmdmem);
+        TPM_CRB_ADDR_BASE + sizeof(s->state.regs), &s->state.cmdmem);
 
-    if (s->ppi_enabled) {
-        tpm_ppi_init(&s->ppi, get_system_memory(),
+    if (s->state.ppi_enabled) {
+        tpm_ppi_init(&s->state.ppi, get_system_memory(),
                      TPM_PPI_ADDR_BASE, OBJECT(s));
     }
 
     if (xen_enabled()) {
-        tpm_crb_reset(dev);
+        tpm_crb_none_reset(dev);
     } else {
-        qemu_register_reset(tpm_crb_reset, dev);
+        qemu_register_reset(tpm_crb_none_reset, dev);
     }
 }
 
-static void tpm_crb_class_init(ObjectClass *klass, void *data)
+static void tpm_crb_none_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     TPMIfClass *tc = TPM_IF_CLASS(klass);
 
-    dc->realize = tpm_crb_realize;
-    device_class_set_props(dc, tpm_crb_properties);
-    dc->vmsd  = &vmstate_tpm_crb;
+    dc->realize = tpm_crb_none_realize;
+    device_class_set_props(dc, tpm_crb_none_properties);
+    dc->vmsd  = &vmstate_tpm_crb_none;
     dc->user_creatable = true;
     tc->model = TPM_MODEL_TPM_CRB;
-    tc->get_version = tpm_crb_get_version;
-    tc->request_completed = tpm_crb_request_completed;
+    tc->get_version = tpm_crb_none_get_version;
+    tc->request_completed = tpm_crb_none_request_completed;
 
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
-static const TypeInfo tpm_crb_info = {
+static const TypeInfo tpm_crb_none_info = {
     .name = TYPE_TPM_CRB,
     /* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */
     .parent = TYPE_DEVICE,
     .instance_size = sizeof(CRBState),
-    .class_init  = tpm_crb_class_init,
+    .class_init  = tpm_crb_none_class_init,
     .interfaces = (InterfaceInfo[]) {
         { TYPE_TPM_IF },
         { }
     }
 };
 
-static void tpm_crb_register(void)
+static void tpm_crb_none_register(void)
 {
-    type_register_static(&tpm_crb_info);
+    type_register_static(&tpm_crb_none_info);
 }
 
-type_init(tpm_crb_register)
+type_init(tpm_crb_none_register)
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
new file mode 100644
index 0000000000..4c173affb6
--- /dev/null
+++ b/hw/tpm/tpm_crb_common.c
@@ -0,0 +1,218 @@
+/*
+ * tpm_crb.c - QEMU's TPM CRB interface emulator
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * Authors:
+ *   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.
+ *
+ * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
+ * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
+ * Family “2.0” Level 00 Revision 01.03 v22
+ */
+
+#include "qemu/osdep.h"
+
+#include "qemu/module.h"
+#include "qapi/error.h"
+#include "exec/address-spaces.h"
+#include "hw/qdev-properties.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/acpi/tpm.h"
+#include "migration/vmstate.h"
+#include "sysemu/tpm_backend.h"
+#include "sysemu/tpm_util.h"
+#include "sysemu/reset.h"
+#include "sysemu/xen.h"
+#include "tpm_prop.h"
+#include "tpm_ppi.h"
+#include "trace.h"
+#include "qom/object.h"
+#include "tpm_crb.h"
+
+static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    TPMCRBState *s = opaque;
+    void *regs = (void *)&s->regs + (addr & ~3);
+    unsigned offset = addr & 3;
+    uint32_t val = *(uint32_t *)regs >> (8 * offset);
+
+    switch (addr) {
+    case A_CRB_LOC_STATE:
+        val |= !tpm_backend_get_tpm_established_flag(s->tpmbe);
+        break;
+    }
+
+    trace_tpm_crb_mmio_read(addr, size, val);
+
+    return val;
+}
+
+static uint8_t tpm_crb_get_active_locty(TPMCRBState *s)
+{
+    if (!ARRAY_FIELD_EX32(s->regs, CRB_LOC_STATE, locAssigned)) {
+        return TPM_CRB_NO_LOCALITY;
+    }
+    return ARRAY_FIELD_EX32(s->regs, CRB_LOC_STATE, activeLocality);
+}
+
+static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
+                               uint64_t val, unsigned size)
+{
+    TPMCRBState *s = opaque;
+    uint8_t locty =  addr >> 12;
+
+    trace_tpm_crb_mmio_write(addr, size, val);
+
+    switch (addr) {
+    case A_CRB_CTRL_REQ:
+        switch (val) {
+        case CRB_CTRL_REQ_CMD_READY:
+            ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
+                             tpmIdle, 0);
+            break;
+        case CRB_CTRL_REQ_GO_IDLE:
+            ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
+                             tpmIdle, 1);
+            break;
+        }
+        break;
+    case A_CRB_CTRL_CANCEL:
+        if (val == CRB_CANCEL_INVOKE &&
+            s->regs[R_CRB_CTRL_START] & CRB_START_INVOKE) {
+            tpm_backend_cancel_cmd(s->tpmbe);
+        }
+        break;
+    case A_CRB_CTRL_START:
+        if (val == CRB_START_INVOKE &&
+            !(s->regs[R_CRB_CTRL_START] & CRB_START_INVOKE) &&
+            tpm_crb_get_active_locty(s) == locty) {
+            void *mem = memory_region_get_ram_ptr(&s->cmdmem);
+
+            s->regs[R_CRB_CTRL_START] |= CRB_START_INVOKE;
+            s->cmd = (TPMBackendCmd) {
+                .in = mem,
+                .in_len = MIN(tpm_cmd_get_size(mem), s->be_buffer_size),
+                .out = mem,
+                .out_len = s->be_buffer_size,
+            };
+
+            tpm_backend_deliver_request(s->tpmbe, &s->cmd);
+        }
+        break;
+    case A_CRB_LOC_CTRL:
+        switch (val) {
+        case CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT:
+            /* not loc 3 or 4 */
+            break;
+        case CRB_LOC_CTRL_RELINQUISH:
+            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STATE,
+                             locAssigned, 0);
+            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STS,
+                             Granted, 0);
+            break;
+        case CRB_LOC_CTRL_REQUEST_ACCESS:
+            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STS,
+                             Granted, 1);
+            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STS,
+                             beenSeized, 0);
+            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STATE,
+                             locAssigned, 1);
+            break;
+        }
+        break;
+    }
+}
+
+const MemoryRegionOps tpm_crb_memory_ops = {
+    .read = tpm_crb_mmio_read,
+    .write = tpm_crb_mmio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+void tpm_crb_request_completed(TPMCRBState *s, int ret)
+{
+    s->regs[R_CRB_CTRL_START] &= ~CRB_START_INVOKE;
+    if (ret != 0) {
+        ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
+                         tpmSts, 1); /* fatal error */
+    }
+    memory_region_set_dirty(&s->cmdmem, 0, CRB_CTRL_CMD_SIZE);
+}
+
+enum TPMVersion tpm_crb_get_version(TPMCRBState *s)
+{
+    return tpm_backend_get_tpm_version(s->tpmbe);
+}
+
+int tpm_crb_pre_save(TPMCRBState *s)
+{
+    tpm_backend_finish_sync(s->tpmbe);
+
+    return 0;
+}
+
+void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr)
+{
+    if (s->ppi_enabled) {
+        tpm_ppi_reset(&s->ppi);
+    }
+    tpm_backend_reset(s->tpmbe);
+
+    memset(s->regs, 0, sizeof(s->regs));
+
+    ARRAY_FIELD_DP32(s->regs, CRB_LOC_STATE,
+                     tpmRegValidSts, 1);
+    ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
+                     tpmIdle, 1);
+    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+                     InterfaceType, CRB_INTF_TYPE_CRB_ACTIVE);
+    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+                     InterfaceVersion, CRB_INTF_VERSION_CRB);
+    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+                     CapLocality, CRB_INTF_CAP_LOCALITY_0_ONLY);
+    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+                     CapCRBIdleBypass, CRB_INTF_CAP_IDLE_FAST);
+    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+                     CapDataXferSizeSupport, CRB_INTF_CAP_XFER_SIZE_64);
+    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+                     CapFIFO, CRB_INTF_CAP_FIFO_NOT_SUPPORTED);
+    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+                     CapCRB, CRB_INTF_CAP_CRB_SUPPORTED);
+    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+                     InterfaceSelector, CRB_INTF_IF_SELECTOR_CRB);
+    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+                     RID, 0b0000);
+    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID2,
+                     VID, PCI_VENDOR_ID_IBM);
+
+    baseaddr += A_CRB_DATA_BUFFER;
+    s->regs[R_CRB_CTRL_CMD_SIZE] = CRB_CTRL_CMD_SIZE;
+    s->regs[R_CRB_CTRL_CMD_LADDR] = (uint32_t)baseaddr;
+    s->regs[R_CRB_CTRL_CMD_HADDR] = (uint32_t)(baseaddr >> 32);
+    s->regs[R_CRB_CTRL_RSP_SIZE] = CRB_CTRL_CMD_SIZE;
+    s->regs[R_CRB_CTRL_RSP_ADDR] = (uint32_t)baseaddr;
+
+    s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
+                            CRB_CTRL_CMD_SIZE);
+
+    if (tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size) < 0) {
+        exit(1);
+    }
+}
+
+void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp)
+{
+    memory_region_init_io(&s->mmio, obj, &tpm_crb_memory_ops, s,
+        "tpm-crb-mmio", sizeof(s->regs));
+    memory_region_init_ram(&s->cmdmem, obj,
+        "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+}
diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build
index 6968e60b3f..cb8204d5bc 100644
--- a/hw/tpm/meson.build
+++ b/hw/tpm/meson.build
@@ -3,6 +3,7 @@ system_ss.add(when: 'CONFIG_TPM_TIS_ISA', if_true: files('tpm_tis_isa.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: files('tpm_tis_sysbus.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS_I2C', if_true: files('tpm_tis_i2c.c'))
 system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
+system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb_common.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_ppi.c'))
 system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_ppi.c'))
 
diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events
index fa882dfefe..3ab1bdb97b 100644
--- a/hw/tpm/trace-events
+++ b/hw/tpm/trace-events
@@ -1,6 +1,6 @@
 # See docs/devel/tracing.rst for syntax documentation.
 
-# tpm_crb.c
+# tpm_crb_common.c
 tpm_crb_mmio_read(uint64_t addr, unsigned size, uint32_t val) "CRB read 0x%016" PRIx64 " len:%u val: 0x%" PRIx32
 tpm_crb_mmio_write(uint64_t addr, unsigned size, uint32_t val) "CRB write 0x%016" PRIx64 " len:%u val: 0x%" PRIx32
 
-- 
2.39.2 (Apple Git-143)



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

* [PATCH v2 02/11] tpm_crb: CTRL_RSP_ADDR is 64-bits wide
  2023-07-14  7:09 [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device Joelle van Dyne
  2023-07-14  7:09 ` [PATCH v2 01/11] tpm_crb: refactor common code Joelle van Dyne
@ 2023-07-14  7:09 ` Joelle van Dyne
  2023-07-14  7:09 ` [PATCH v2 03/11] tpm_ppi: refactor memory space initialization Joelle van Dyne
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14  7:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Joelle van Dyne, Stefan Berger, Stefan Berger,
	Michael S. Tsirkin, Igor Mammedov, Ani Sinha, Thomas Huth,
	Laurent Vivier, Paolo Bonzini

The register is actually 64-bits but in order to make this more clear
than the specification, we define two 32-bit registers:
CTRL_RSP_LADDR and CTRL_RSP_HADDR to match the CTRL_CMD_* naming. This
deviates from the specs but is way more clear.

Previously, the only CRB device uses a fixed system address so this
was not an issue. However, once we support SysBus CRB device, the
address can be anywhere in 64-bit space.

Signed-off-by: Joelle van Dyne <j@getutm.app>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
 include/hw/acpi/tpm.h      | 3 ++-
 hw/tpm/tpm_crb_common.c    | 3 ++-
 tests/qtest/tpm-crb-test.c | 2 +-
 tests/qtest/tpm-util.c     | 2 +-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
index 579c45f5ba..f60bfe2789 100644
--- a/include/hw/acpi/tpm.h
+++ b/include/hw/acpi/tpm.h
@@ -174,7 +174,8 @@ REG32(CRB_CTRL_CMD_SIZE, 0x58)
 REG32(CRB_CTRL_CMD_LADDR, 0x5C)
 REG32(CRB_CTRL_CMD_HADDR, 0x60)
 REG32(CRB_CTRL_RSP_SIZE, 0x64)
-REG32(CRB_CTRL_RSP_ADDR, 0x68)
+REG32(CRB_CTRL_RSP_LADDR, 0x68)
+REG32(CRB_CTRL_RSP_HADDR, 0x6C)
 REG32(CRB_DATA_BUFFER, 0x80)
 
 #define TPM_CRB_ADDR_BASE           0xFED40000
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 4c173affb6..228e2d0faf 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -199,7 +199,8 @@ void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr)
     s->regs[R_CRB_CTRL_CMD_LADDR] = (uint32_t)baseaddr;
     s->regs[R_CRB_CTRL_CMD_HADDR] = (uint32_t)(baseaddr >> 32);
     s->regs[R_CRB_CTRL_RSP_SIZE] = CRB_CTRL_CMD_SIZE;
-    s->regs[R_CRB_CTRL_RSP_ADDR] = (uint32_t)baseaddr;
+    s->regs[R_CRB_CTRL_RSP_LADDR] = (uint32_t)baseaddr;
+    s->regs[R_CRB_CTRL_RSP_HADDR] = (uint32_t)(baseaddr >> 32);
 
     s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
                             CRB_CTRL_CMD_SIZE);
diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c
index 396ae3f91c..9d30fe8293 100644
--- a/tests/qtest/tpm-crb-test.c
+++ b/tests/qtest/tpm-crb-test.c
@@ -28,7 +28,7 @@ static void tpm_crb_test(const void *data)
     uint32_t csize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_SIZE);
     uint64_t caddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
     uint32_t rsize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_SIZE);
-    uint64_t raddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
+    uint64_t raddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_LADDR);
     uint8_t locstate = readb(TPM_CRB_ADDR_BASE + A_CRB_LOC_STATE);
     uint32_t locctrl = readl(TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL);
     uint32_t locsts = readl(TPM_CRB_ADDR_BASE + A_CRB_LOC_STS);
diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c
index 1c0319e6e7..dd02057fc0 100644
--- a/tests/qtest/tpm-util.c
+++ b/tests/qtest/tpm-util.c
@@ -25,7 +25,7 @@ void tpm_util_crb_transfer(QTestState *s,
                            unsigned char *rsp, size_t rsp_size)
 {
     uint64_t caddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
-    uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
+    uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_LADDR);
 
     qtest_writeb(s, TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL, 1);
 
-- 
2.39.2 (Apple Git-143)



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

* [PATCH v2 03/11] tpm_ppi: refactor memory space initialization
  2023-07-14  7:09 [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device Joelle van Dyne
  2023-07-14  7:09 ` [PATCH v2 01/11] tpm_crb: refactor common code Joelle van Dyne
  2023-07-14  7:09 ` [PATCH v2 02/11] tpm_crb: CTRL_RSP_ADDR is 64-bits wide Joelle van Dyne
@ 2023-07-14  7:09 ` Joelle van Dyne
  2023-07-14  7:09 ` [PATCH v2 04/11] tpm_crb: use a single read-as-mem/write-as-mmio mapping Joelle van Dyne
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14  7:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Joelle van Dyne, Stefan Berger, Stefan Berger

Instead of calling `memory_region_add_subregion` directly, we defer to
the caller to do it. This allows us to re-use the code for a SysBus
device.

Signed-off-by: Joelle van Dyne <j@getutm.app>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
---
 hw/tpm/tpm_ppi.h        | 10 +++-------
 hw/tpm/tpm_crb.c        |  4 ++--
 hw/tpm/tpm_crb_common.c |  3 +++
 hw/tpm/tpm_ppi.c        |  5 +----
 hw/tpm/tpm_tis_isa.c    |  5 +++--
 5 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/hw/tpm/tpm_ppi.h b/hw/tpm/tpm_ppi.h
index bf5d4a300f..30863c6438 100644
--- a/hw/tpm/tpm_ppi.h
+++ b/hw/tpm/tpm_ppi.h
@@ -20,17 +20,13 @@ typedef struct TPMPPI {
 } TPMPPI;
 
 /**
- * tpm_ppi_init:
+ * tpm_ppi_init_memory:
  * @tpmppi: a TPMPPI
- * @m: the address-space / MemoryRegion to use
- * @addr: the address of the PPI region
  * @obj: the owner object
  *
- * Register the TPM PPI memory region at @addr on the given address
- * space for the object @obj.
+ * Creates the TPM PPI memory region.
  **/
-void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
-                  hwaddr addr, Object *obj);
+void tpm_ppi_init_memory(TPMPPI *tpmppi, Object *obj);
 
 /**
  * tpm_ppi_reset:
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 3ef4977fb5..598c3e0161 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -107,8 +107,8 @@ static void tpm_crb_none_realize(DeviceState *dev, Error **errp)
         TPM_CRB_ADDR_BASE + sizeof(s->state.regs), &s->state.cmdmem);
 
     if (s->state.ppi_enabled) {
-        tpm_ppi_init(&s->state.ppi, get_system_memory(),
-                     TPM_PPI_ADDR_BASE, OBJECT(s));
+        memory_region_add_subregion(get_system_memory(),
+            TPM_PPI_ADDR_BASE, &s->state.ppi.ram);
     }
 
     if (xen_enabled()) {
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 228e2d0faf..e56e910670 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -216,4 +216,7 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp)
         "tpm-crb-mmio", sizeof(s->regs));
     memory_region_init_ram(&s->cmdmem, obj,
         "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+    if (s->ppi_enabled) {
+        tpm_ppi_init_memory(&s->ppi, obj);
+    }
 }
diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c
index 7f74e26ec6..40cab59afa 100644
--- a/hw/tpm/tpm_ppi.c
+++ b/hw/tpm/tpm_ppi.c
@@ -44,14 +44,11 @@ void tpm_ppi_reset(TPMPPI *tpmppi)
     }
 }
 
-void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
-                  hwaddr addr, Object *obj)
+void tpm_ppi_init_memory(TPMPPI *tpmppi, Object *obj)
 {
     tpmppi->buf = qemu_memalign(qemu_real_host_page_size(),
                                 HOST_PAGE_ALIGN(TPM_PPI_ADDR_SIZE));
     memory_region_init_ram_device_ptr(&tpmppi->ram, obj, "tpm-ppi",
                                       TPM_PPI_ADDR_SIZE, tpmppi->buf);
     vmstate_register_ram(&tpmppi->ram, DEVICE(obj));
-
-    memory_region_add_subregion(m, addr, &tpmppi->ram);
 }
diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c
index 91e3792248..7cd7415f30 100644
--- a/hw/tpm/tpm_tis_isa.c
+++ b/hw/tpm/tpm_tis_isa.c
@@ -134,8 +134,9 @@ static void tpm_tis_isa_realizefn(DeviceState *dev, Error **errp)
                                 TPM_TIS_ADDR_BASE, &s->mmio);
 
     if (s->ppi_enabled) {
-        tpm_ppi_init(&s->ppi, isa_address_space(ISA_DEVICE(dev)),
-                     TPM_PPI_ADDR_BASE, OBJECT(dev));
+        tpm_ppi_init_memory(&s->ppi, OBJECT(dev));
+        memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
+                                    TPM_PPI_ADDR_BASE, &s->ppi.ram);
     }
 }
 
-- 
2.39.2 (Apple Git-143)



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

* [PATCH v2 04/11] tpm_crb: use a single read-as-mem/write-as-mmio mapping
  2023-07-14  7:09 [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device Joelle van Dyne
                   ` (2 preceding siblings ...)
  2023-07-14  7:09 ` [PATCH v2 03/11] tpm_ppi: refactor memory space initialization Joelle van Dyne
@ 2023-07-14  7:09 ` Joelle van Dyne
  2023-07-14 12:03   ` Stefan Berger
  2023-07-14  7:09 ` [PATCH v2 05/11] tpm_crb: use the ISA bus Joelle van Dyne
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14  7:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Joelle van Dyne, Stefan Berger

On Apple Silicon, when Windows performs a LDP on the CRB MMIO space,
the exception is not decoded by hardware and we cannot trap the MMIO
read. This led to the idea from @agraf to use the same mapping type as
ROM devices: namely that reads should be seen as memory type and
writes should trap as MMIO.

Once that was done, the second memory mapping of the command buffer
region was redundent and was removed.

A note about the removal of the read trap for `CRB_LOC_STATE`:
The only usage was to return the most up-to-date value for
`tpmEstablished`. However, `tpmEstablished` is only cleared when a
TPM2_HashStart operation is called which only exists for locality 4.
We do not handle locality 4. Indeed, the comment for the write handler
of `CRB_LOC_CTRL` makes the same argument for why it is not calling
the backend to reset the `tpmEstablished` bit (to 1).
As this bit is unused, we do not need to worry about updating it for
reads.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 hw/tpm/tpm_crb.h        |   2 -
 hw/tpm/tpm_crb.c        |   3 -
 hw/tpm/tpm_crb_common.c | 126 +++++++++++++++++++++-------------------
 3 files changed, 65 insertions(+), 66 deletions(-)

diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
index da3a0cf256..7cdd37335f 100644
--- a/hw/tpm/tpm_crb.h
+++ b/hw/tpm/tpm_crb.h
@@ -26,9 +26,7 @@
 typedef struct TPMCRBState {
     TPMBackend *tpmbe;
     TPMBackendCmd cmd;
-    uint32_t regs[TPM_CRB_R_MAX];
     MemoryRegion mmio;
-    MemoryRegion cmdmem;
 
     size_t be_buffer_size;
 
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 598c3e0161..07c6868d8d 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -68,7 +68,6 @@ static const VMStateDescription vmstate_tpm_crb_none = {
     .name = "tpm-crb",
     .pre_save = tpm_crb_none_pre_save,
     .fields = (VMStateField[]) {
-        VMSTATE_UINT32_ARRAY(state.regs, CRBState, TPM_CRB_R_MAX),
         VMSTATE_END_OF_LIST(),
     }
 };
@@ -103,8 +102,6 @@ static void tpm_crb_none_realize(DeviceState *dev, Error **errp)
 
     memory_region_add_subregion(get_system_memory(),
         TPM_CRB_ADDR_BASE, &s->state.mmio);
-    memory_region_add_subregion(get_system_memory(),
-        TPM_CRB_ADDR_BASE + sizeof(s->state.regs), &s->state.cmdmem);
 
     if (s->state.ppi_enabled) {
         memory_region_add_subregion(get_system_memory(),
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index e56e910670..4ecf064c98 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -33,31 +33,12 @@
 #include "qom/object.h"
 #include "tpm_crb.h"
 
-static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
-                                  unsigned size)
+static uint8_t tpm_crb_get_active_locty(TPMCRBState *s, uint32_t *regs)
 {
-    TPMCRBState *s = opaque;
-    void *regs = (void *)&s->regs + (addr & ~3);
-    unsigned offset = addr & 3;
-    uint32_t val = *(uint32_t *)regs >> (8 * offset);
-
-    switch (addr) {
-    case A_CRB_LOC_STATE:
-        val |= !tpm_backend_get_tpm_established_flag(s->tpmbe);
-        break;
-    }
-
-    trace_tpm_crb_mmio_read(addr, size, val);
-
-    return val;
-}
-
-static uint8_t tpm_crb_get_active_locty(TPMCRBState *s)
-{
-    if (!ARRAY_FIELD_EX32(s->regs, CRB_LOC_STATE, locAssigned)) {
+    if (!ARRAY_FIELD_EX32(regs, CRB_LOC_STATE, locAssigned)) {
         return TPM_CRB_NO_LOCALITY;
     }
-    return ARRAY_FIELD_EX32(s->regs, CRB_LOC_STATE, activeLocality);
+    return ARRAY_FIELD_EX32(regs, CRB_LOC_STATE, activeLocality);
 }
 
 static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
@@ -65,35 +46,47 @@ static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
 {
     TPMCRBState *s = opaque;
     uint8_t locty =  addr >> 12;
+    uint32_t *regs;
+    void *mem;
 
     trace_tpm_crb_mmio_write(addr, size, val);
+    regs = memory_region_get_ram_ptr(&s->mmio);
+    mem = &regs[R_CRB_DATA_BUFFER];
+    assert(regs);
+
+    if (addr >= A_CRB_DATA_BUFFER) {
+        assert(addr + size <= TPM_CRB_ADDR_SIZE);
+        assert(size <= sizeof(val));
+        memcpy(mem + addr - A_CRB_DATA_BUFFER, &val, size);
+        memory_region_set_dirty(&s->mmio, addr, size);
+        return;
+    }
 
     switch (addr) {
     case A_CRB_CTRL_REQ:
         switch (val) {
         case CRB_CTRL_REQ_CMD_READY:
-            ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
+            ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
                              tpmIdle, 0);
             break;
         case CRB_CTRL_REQ_GO_IDLE:
-            ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
+            ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
                              tpmIdle, 1);
             break;
         }
         break;
     case A_CRB_CTRL_CANCEL:
         if (val == CRB_CANCEL_INVOKE &&
-            s->regs[R_CRB_CTRL_START] & CRB_START_INVOKE) {
+            regs[R_CRB_CTRL_START] & CRB_START_INVOKE) {
             tpm_backend_cancel_cmd(s->tpmbe);
         }
         break;
     case A_CRB_CTRL_START:
         if (val == CRB_START_INVOKE &&
-            !(s->regs[R_CRB_CTRL_START] & CRB_START_INVOKE) &&
-            tpm_crb_get_active_locty(s) == locty) {
-            void *mem = memory_region_get_ram_ptr(&s->cmdmem);
+            !(regs[R_CRB_CTRL_START] & CRB_START_INVOKE) &&
+            tpm_crb_get_active_locty(s, regs) == locty) {
 
-            s->regs[R_CRB_CTRL_START] |= CRB_START_INVOKE;
+            regs[R_CRB_CTRL_START] |= CRB_START_INVOKE;
             s->cmd = (TPMBackendCmd) {
                 .in = mem,
                 .in_len = MIN(tpm_cmd_get_size(mem), s->be_buffer_size),
@@ -110,26 +103,27 @@ static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
             /* not loc 3 or 4 */
             break;
         case CRB_LOC_CTRL_RELINQUISH:
-            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STATE,
+            ARRAY_FIELD_DP32(regs, CRB_LOC_STATE,
                              locAssigned, 0);
-            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STS,
+            ARRAY_FIELD_DP32(regs, CRB_LOC_STS,
                              Granted, 0);
             break;
         case CRB_LOC_CTRL_REQUEST_ACCESS:
-            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STS,
+            ARRAY_FIELD_DP32(regs, CRB_LOC_STS,
                              Granted, 1);
-            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STS,
+            ARRAY_FIELD_DP32(regs, CRB_LOC_STS,
                              beenSeized, 0);
-            ARRAY_FIELD_DP32(s->regs, CRB_LOC_STATE,
+            ARRAY_FIELD_DP32(regs, CRB_LOC_STATE,
                              locAssigned, 1);
             break;
         }
         break;
     }
+
+    memory_region_set_dirty(&s->mmio, 0, A_CRB_DATA_BUFFER);
 }
 
 const MemoryRegionOps tpm_crb_memory_ops = {
-    .read = tpm_crb_mmio_read,
     .write = tpm_crb_mmio_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
     .valid = {
@@ -140,12 +134,16 @@ const MemoryRegionOps tpm_crb_memory_ops = {
 
 void tpm_crb_request_completed(TPMCRBState *s, int ret)
 {
-    s->regs[R_CRB_CTRL_START] &= ~CRB_START_INVOKE;
+    uint32_t *regs = memory_region_get_ram_ptr(&s->mmio);
+
+    assert(regs);
+    regs[R_CRB_CTRL_START] &= ~CRB_START_INVOKE;
     if (ret != 0) {
-        ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
+        ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
                          tpmSts, 1); /* fatal error */
     }
-    memory_region_set_dirty(&s->cmdmem, 0, CRB_CTRL_CMD_SIZE);
+
+    memory_region_set_dirty(&s->mmio, 0, TPM_CRB_ADDR_SIZE);
 }
 
 enum TPMVersion tpm_crb_get_version(TPMCRBState *s)
@@ -162,45 +160,50 @@ int tpm_crb_pre_save(TPMCRBState *s)
 
 void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr)
 {
+    uint32_t *regs = memory_region_get_ram_ptr(&s->mmio);
+
+    assert(regs);
     if (s->ppi_enabled) {
         tpm_ppi_reset(&s->ppi);
     }
     tpm_backend_reset(s->tpmbe);
 
-    memset(s->regs, 0, sizeof(s->regs));
+    memset(regs, 0, TPM_CRB_ADDR_SIZE);
 
-    ARRAY_FIELD_DP32(s->regs, CRB_LOC_STATE,
+    ARRAY_FIELD_DP32(regs, CRB_LOC_STATE,
                      tpmRegValidSts, 1);
-    ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
+    ARRAY_FIELD_DP32(regs, CRB_LOC_STATE,
+                     tpmEstablished, 1);
+    ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
                      tpmIdle, 1);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+    ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
                      InterfaceType, CRB_INTF_TYPE_CRB_ACTIVE);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+    ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
                      InterfaceVersion, CRB_INTF_VERSION_CRB);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+    ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
                      CapLocality, CRB_INTF_CAP_LOCALITY_0_ONLY);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+    ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
                      CapCRBIdleBypass, CRB_INTF_CAP_IDLE_FAST);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+    ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
                      CapDataXferSizeSupport, CRB_INTF_CAP_XFER_SIZE_64);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+    ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
                      CapFIFO, CRB_INTF_CAP_FIFO_NOT_SUPPORTED);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+    ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
                      CapCRB, CRB_INTF_CAP_CRB_SUPPORTED);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+    ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
                      InterfaceSelector, CRB_INTF_IF_SELECTOR_CRB);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID,
+    ARRAY_FIELD_DP32(regs, CRB_INTF_ID,
                      RID, 0b0000);
-    ARRAY_FIELD_DP32(s->regs, CRB_INTF_ID2,
+    ARRAY_FIELD_DP32(regs, CRB_INTF_ID2,
                      VID, PCI_VENDOR_ID_IBM);
 
     baseaddr += A_CRB_DATA_BUFFER;
-    s->regs[R_CRB_CTRL_CMD_SIZE] = CRB_CTRL_CMD_SIZE;
-    s->regs[R_CRB_CTRL_CMD_LADDR] = (uint32_t)baseaddr;
-    s->regs[R_CRB_CTRL_CMD_HADDR] = (uint32_t)(baseaddr >> 32);
-    s->regs[R_CRB_CTRL_RSP_SIZE] = CRB_CTRL_CMD_SIZE;
-    s->regs[R_CRB_CTRL_RSP_LADDR] = (uint32_t)baseaddr;
-    s->regs[R_CRB_CTRL_RSP_HADDR] = (uint32_t)(baseaddr >> 32);
+    regs[R_CRB_CTRL_CMD_SIZE] = CRB_CTRL_CMD_SIZE;
+    regs[R_CRB_CTRL_CMD_LADDR] = (uint32_t)baseaddr;
+    regs[R_CRB_CTRL_CMD_HADDR] = (uint32_t)(baseaddr >> 32);
+    regs[R_CRB_CTRL_RSP_SIZE] = CRB_CTRL_CMD_SIZE;
+    regs[R_CRB_CTRL_RSP_LADDR] = (uint32_t)baseaddr;
+    regs[R_CRB_CTRL_RSP_HADDR] = (uint32_t)(baseaddr >> 32);
 
     s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
                             CRB_CTRL_CMD_SIZE);
@@ -208,14 +211,15 @@ void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr)
     if (tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size) < 0) {
         exit(1);
     }
+
+    memory_region_rom_device_set_romd(&s->mmio, true);
+    memory_region_set_dirty(&s->mmio, 0, TPM_CRB_ADDR_SIZE);
 }
 
 void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp)
 {
-    memory_region_init_io(&s->mmio, obj, &tpm_crb_memory_ops, s,
-        "tpm-crb-mmio", sizeof(s->regs));
-    memory_region_init_ram(&s->cmdmem, obj,
-        "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+    memory_region_init_rom_device(&s->mmio, obj, &tpm_crb_memory_ops, s,
+        "tpm-crb-mem", TPM_CRB_ADDR_SIZE, errp);
     if (s->ppi_enabled) {
         tpm_ppi_init_memory(&s->ppi, obj);
     }
-- 
2.39.2 (Apple Git-143)



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

* [PATCH v2 05/11] tpm_crb: use the ISA bus
  2023-07-14  7:09 [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device Joelle van Dyne
                   ` (3 preceding siblings ...)
  2023-07-14  7:09 ` [PATCH v2 04/11] tpm_crb: use a single read-as-mem/write-as-mmio mapping Joelle van Dyne
@ 2023-07-14  7:09 ` Joelle van Dyne
  2023-07-17 13:46   ` Igor Mammedov
  2023-07-14  7:09 ` [PATCH v2 06/11] tpm_crb: move ACPI table building to device interface Joelle van Dyne
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14  7:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Joelle van Dyne, Stefan Berger, Paolo Bonzini

Since this device is gated to only build for targets with the PC
configuration, we should use the ISA bus like with TPM TIS.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 hw/tpm/tpm_crb.c | 52 ++++++++++++++++++++++++------------------------
 hw/tpm/Kconfig   |  2 +-
 2 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 07c6868d8d..6144081d30 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -22,6 +22,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci_ids.h"
 #include "hw/acpi/tpm.h"
+#include "hw/isa/isa.h"
 #include "migration/vmstate.h"
 #include "sysemu/tpm_backend.h"
 #include "sysemu/tpm_util.h"
@@ -34,7 +35,7 @@
 #include "tpm_crb.h"
 
 struct CRBState {
-    DeviceState parent_obj;
+    ISADevice parent_obj;
 
     TPMCRBState state;
 };
@@ -43,49 +44,49 @@ typedef struct CRBState CRBState;
 DECLARE_INSTANCE_CHECKER(CRBState, CRB,
                          TYPE_TPM_CRB)
 
-static void tpm_crb_none_request_completed(TPMIf *ti, int ret)
+static void tpm_crb_isa_request_completed(TPMIf *ti, int ret)
 {
     CRBState *s = CRB(ti);
 
     tpm_crb_request_completed(&s->state, ret);
 }
 
-static enum TPMVersion tpm_crb_none_get_version(TPMIf *ti)
+static enum TPMVersion tpm_crb_isa_get_version(TPMIf *ti)
 {
     CRBState *s = CRB(ti);
 
     return tpm_crb_get_version(&s->state);
 }
 
-static int tpm_crb_none_pre_save(void *opaque)
+static int tpm_crb_isa_pre_save(void *opaque)
 {
     CRBState *s = opaque;
 
     return tpm_crb_pre_save(&s->state);
 }
 
-static const VMStateDescription vmstate_tpm_crb_none = {
+static const VMStateDescription vmstate_tpm_crb_isa = {
     .name = "tpm-crb",
-    .pre_save = tpm_crb_none_pre_save,
+    .pre_save = tpm_crb_isa_pre_save,
     .fields = (VMStateField[]) {
         VMSTATE_END_OF_LIST(),
     }
 };
 
-static Property tpm_crb_none_properties[] = {
+static Property tpm_crb_isa_properties[] = {
     DEFINE_PROP_TPMBE("tpmdev", CRBState, state.tpmbe),
     DEFINE_PROP_BOOL("ppi", CRBState, state.ppi_enabled, true),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-static void tpm_crb_none_reset(void *dev)
+static void tpm_crb_isa_reset(void *dev)
 {
     CRBState *s = CRB(dev);
 
     return tpm_crb_reset(&s->state, TPM_CRB_ADDR_BASE);
 }
 
-static void tpm_crb_none_realize(DeviceState *dev, Error **errp)
+static void tpm_crb_isa_realize(DeviceState *dev, Error **errp)
 {
     CRBState *s = CRB(dev);
 
@@ -100,52 +101,51 @@ static void tpm_crb_none_realize(DeviceState *dev, Error **errp)
 
     tpm_crb_init_memory(OBJECT(s), &s->state, errp);
 
-    memory_region_add_subregion(get_system_memory(),
+    memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
         TPM_CRB_ADDR_BASE, &s->state.mmio);
 
     if (s->state.ppi_enabled) {
-        memory_region_add_subregion(get_system_memory(),
+        memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
             TPM_PPI_ADDR_BASE, &s->state.ppi.ram);
     }
 
     if (xen_enabled()) {
-        tpm_crb_none_reset(dev);
+        tpm_crb_isa_reset(dev);
     } else {
-        qemu_register_reset(tpm_crb_none_reset, dev);
+        qemu_register_reset(tpm_crb_isa_reset, dev);
     }
 }
 
-static void tpm_crb_none_class_init(ObjectClass *klass, void *data)
+static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     TPMIfClass *tc = TPM_IF_CLASS(klass);
 
-    dc->realize = tpm_crb_none_realize;
-    device_class_set_props(dc, tpm_crb_none_properties);
-    dc->vmsd  = &vmstate_tpm_crb_none;
+    dc->realize = tpm_crb_isa_realize;
+    device_class_set_props(dc, tpm_crb_isa_properties);
+    dc->vmsd  = &vmstate_tpm_crb_isa;
     dc->user_creatable = true;
     tc->model = TPM_MODEL_TPM_CRB;
-    tc->get_version = tpm_crb_none_get_version;
-    tc->request_completed = tpm_crb_none_request_completed;
+    tc->get_version = tpm_crb_isa_get_version;
+    tc->request_completed = tpm_crb_isa_request_completed;
 
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
-static const TypeInfo tpm_crb_none_info = {
+static const TypeInfo tpm_crb_isa_info = {
     .name = TYPE_TPM_CRB,
-    /* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */
-    .parent = TYPE_DEVICE,
+    .parent = TYPE_ISA_DEVICE,
     .instance_size = sizeof(CRBState),
-    .class_init  = tpm_crb_none_class_init,
+    .class_init  = tpm_crb_isa_class_init,
     .interfaces = (InterfaceInfo[]) {
         { TYPE_TPM_IF },
         { }
     }
 };
 
-static void tpm_crb_none_register(void)
+static void tpm_crb_isa_register(void)
 {
-    type_register_static(&tpm_crb_none_info);
+    type_register_static(&tpm_crb_isa_info);
 }
 
-type_init(tpm_crb_none_register)
+type_init(tpm_crb_isa_register)
diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
index a46663288c..1fd73fe617 100644
--- a/hw/tpm/Kconfig
+++ b/hw/tpm/Kconfig
@@ -22,7 +22,7 @@ config TPM_TIS
 
 config TPM_CRB
     bool
-    depends on TPM && PC
+    depends on TPM && ISA_BUS
     select TPM_BACKEND
 
 config TPM_SPAPR
-- 
2.39.2 (Apple Git-143)



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

* [PATCH v2 06/11] tpm_crb: move ACPI table building to device interface
  2023-07-14  7:09 [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device Joelle van Dyne
                   ` (4 preceding siblings ...)
  2023-07-14  7:09 ` [PATCH v2 05/11] tpm_crb: use the ISA bus Joelle van Dyne
@ 2023-07-14  7:09 ` Joelle van Dyne
  2023-07-14 17:21   ` Stefan Berger
  2023-07-14  7:09 ` [PATCH v2 07/11] hw/arm/virt: add plug handler for TPM on SysBus Joelle van Dyne
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14  7:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Joelle van Dyne, Michael S. Tsirkin, Igor Mammedov, Ani Sinha,
	Paolo Bonzini, Richard Henderson, Eduardo Habkost,
	Marcel Apfelbaum, Stefan Berger

This logic is similar to TPM TIS ISA device. Since TPM CRB can only
support TPM 2.0 backends, we check for this in realize.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 hw/i386/acpi-build.c | 23 -----------------------
 hw/tpm/tpm_crb.c     | 29 +++++++++++++++++++++++++++++
 2 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9c74fa17ad..b767df39df 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1441,9 +1441,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
     uint32_t nr_mem = machine->ram_slots;
     int root_bus_limit = 0xFF;
     PCIBus *bus = NULL;
-#ifdef CONFIG_TPM
-    TPMIf *tpm = tpm_find();
-#endif
     bool cxl_present = false;
     int i;
     VMBusBridge *vmbus_bridge = vmbus_bridge_find();
@@ -1793,26 +1790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
         }
     }
 
-#ifdef CONFIG_TPM
-    if (TPM_IS_CRB(tpm)) {
-        dev = aml_device("TPM");
-        aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-        aml_append(dev, aml_name_decl("_STR",
-                                      aml_string("TPM 2.0 Device")));
-        crs = aml_resource_template();
-        aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
-                                           TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
-        aml_append(dev, aml_name_decl("_CRS", crs));
-
-        aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
-        aml_append(dev, aml_name_decl("_UID", aml_int(1)));
-
-        tpm_build_ppi_acpi(tpm, dev);
-
-        aml_append(sb_scope, dev);
-    }
-#endif
-
     if (pcms->sgx_epc.size != 0) {
         uint64_t epc_base = pcms->sgx_epc.base;
         uint64_t epc_size = pcms->sgx_epc.size;
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 6144081d30..594696ffb8 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -19,6 +19,8 @@
 #include "qemu/module.h"
 #include "qapi/error.h"
 #include "exec/address-spaces.h"
+#include "hw/acpi/acpi_aml_interface.h"
+#include "hw/acpi/tpm.h"
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci_ids.h"
 #include "hw/acpi/tpm.h"
@@ -99,6 +101,11 @@ static void tpm_crb_isa_realize(DeviceState *dev, Error **errp)
         return;
     }
 
+    if (tpm_crb_isa_get_version(TPM_IF(s)) != TPM_VERSION_2_0) {
+        error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
+        return;
+    }
+
     tpm_crb_init_memory(OBJECT(s), &s->state, errp);
 
     memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
@@ -116,10 +123,30 @@ static void tpm_crb_isa_realize(DeviceState *dev, Error **errp)
     }
 }
 
+static void build_tpm_crb_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
+{
+    Aml *dev, *crs;
+    CRBState *s = CRB(adev);
+    TPMIf *ti = TPM_IF(s);
+
+    dev = aml_device("TPM");
+    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
+    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
+    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
+    aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
+    crs = aml_resource_template();
+    aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE, TPM_CRB_ADDR_SIZE,
+                                      AML_READ_WRITE));
+    aml_append(dev, aml_name_decl("_CRS", crs));
+    tpm_build_ppi_acpi(ti, dev);
+    aml_append(scope, dev);
+}
+
 static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     TPMIfClass *tc = TPM_IF_CLASS(klass);
+    AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
 
     dc->realize = tpm_crb_isa_realize;
     device_class_set_props(dc, tpm_crb_isa_properties);
@@ -128,6 +155,7 @@ static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
     tc->model = TPM_MODEL_TPM_CRB;
     tc->get_version = tpm_crb_isa_get_version;
     tc->request_completed = tpm_crb_isa_request_completed;
+    adevc->build_dev_aml = build_tpm_crb_isa_aml;
 
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
@@ -139,6 +167,7 @@ static const TypeInfo tpm_crb_isa_info = {
     .class_init  = tpm_crb_isa_class_init,
     .interfaces = (InterfaceInfo[]) {
         { TYPE_TPM_IF },
+        { TYPE_ACPI_DEV_AML_IF },
         { }
     }
 };
-- 
2.39.2 (Apple Git-143)



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

* [PATCH v2 07/11] hw/arm/virt: add plug handler for TPM on SysBus
  2023-07-14  7:09 [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device Joelle van Dyne
                   ` (5 preceding siblings ...)
  2023-07-14  7:09 ` [PATCH v2 06/11] tpm_crb: move ACPI table building to device interface Joelle van Dyne
@ 2023-07-14  7:09 ` Joelle van Dyne
  2023-07-14 12:11   ` Stefan Berger
  2023-07-17 14:00   ` Igor Mammedov
  2023-07-14  7:09 ` [PATCH v2 08/11] hw/loongarch/virt: " Joelle van Dyne
                   ` (3 subsequent siblings)
  10 siblings, 2 replies; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14  7:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Joelle van Dyne, Peter Maydell, open list:Virt

TPM needs to know its own base address in order to generate its DSDT
device entry.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 hw/arm/virt.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 7d9dbc2663..432148ef47 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2732,6 +2732,37 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev,
                          dev, &error_abort);
 }
 
+#ifdef CONFIG_TPM
+static void virt_tpm_plug(VirtMachineState *vms, TPMIf *tpmif)
+{
+    PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
+    hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
+    SysBusDevice *sbdev = SYS_BUS_DEVICE(tpmif);
+    MemoryRegion *sbdev_mr;
+    hwaddr tpm_base;
+    uint64_t tpm_size;
+
+    if (!sbdev || !object_dynamic_cast(OBJECT(sbdev), TYPE_SYS_BUS_DEVICE)) {
+        return;
+    }
+
+    tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+    assert(tpm_base != -1);
+
+    tpm_base += pbus_base;
+
+    sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
+    tpm_size = memory_region_size(sbdev_mr);
+
+    if (object_property_find(OBJECT(sbdev), "baseaddr")) {
+        object_property_set_uint(OBJECT(sbdev), "baseaddr", tpm_base, NULL);
+    }
+    if (object_property_find(OBJECT(sbdev), "size")) {
+        object_property_set_uint(OBJECT(sbdev), "size", tpm_size, NULL);
+    }
+}
+#endif
+
 static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
                                             DeviceState *dev, Error **errp)
 {
@@ -2803,6 +2834,12 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
         vms->virtio_iommu_bdf = pci_get_bdf(pdev);
         create_virtio_iommu_dt_bindings(vms);
     }
+
+#ifdef CONFIG_TPM
+    if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
+        virt_tpm_plug(vms, TPM_IF(dev));
+    }
+#endif
 }
 
 static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,
-- 
2.39.2 (Apple Git-143)



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

* [PATCH v2 08/11] hw/loongarch/virt: add plug handler for TPM on SysBus
  2023-07-14  7:09 [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device Joelle van Dyne
                   ` (6 preceding siblings ...)
  2023-07-14  7:09 ` [PATCH v2 07/11] hw/arm/virt: add plug handler for TPM on SysBus Joelle van Dyne
@ 2023-07-14  7:09 ` Joelle van Dyne
  2023-07-20 17:57   ` Stefan Berger
  2023-07-14  7:09 ` [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device Joelle van Dyne
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14  7:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Joelle van Dyne, Xiaojuan Yang, Song Gao

TPM needs to know its own base address in order to generate its DSDT
device entry.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 hw/loongarch/virt.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index e19b042ce8..9c536c52bc 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -1040,6 +1040,37 @@ static void virt_mem_plug(HotplugHandler *hotplug_dev,
                          dev, &error_abort);
 }
 
+#ifdef CONFIG_TPM
+static void virt_tpm_plug(LoongArchMachineState *lams, TPMIf *tpmif)
+{
+    PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(lams->platform_bus_dev);
+    hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
+    SysBusDevice *sbdev = SYS_BUS_DEVICE(tpmif);
+    MemoryRegion *sbdev_mr;
+    hwaddr tpm_base;
+    uint64_t tpm_size;
+
+    if (!sbdev || !object_dynamic_cast(OBJECT(sbdev), TYPE_SYS_BUS_DEVICE)) {
+        return;
+    }
+
+    tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+    assert(tpm_base != -1);
+
+    tpm_base += pbus_base;
+
+    sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
+    tpm_size = memory_region_size(sbdev_mr);
+
+    if (object_property_find(OBJECT(sbdev), "baseaddr")) {
+        object_property_set_uint(OBJECT(sbdev), "baseaddr", tpm_base, NULL);
+    }
+    if (object_property_find(OBJECT(sbdev), "size")) {
+        object_property_set_uint(OBJECT(sbdev), "size", tpm_size, NULL);
+    }
+}
+#endif
+
 static void loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev,
                                         DeviceState *dev, Error **errp)
 {
@@ -1054,6 +1085,12 @@ static void loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev,
     } else if (memhp_type_supported(dev)) {
         virt_mem_plug(hotplug_dev, dev, errp);
     }
+
+#ifdef CONFIG_TPM
+    if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
+        virt_tpm_plug(lams, TPM_IF(dev));
+    }
+#endif
 }
 
 static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
-- 
2.39.2 (Apple Git-143)



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

* [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device
  2023-07-14  7:09 [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device Joelle van Dyne
                   ` (7 preceding siblings ...)
  2023-07-14  7:09 ` [PATCH v2 08/11] hw/loongarch/virt: " Joelle van Dyne
@ 2023-07-14  7:09 ` Joelle van Dyne
  2023-07-14 16:19   ` Stefan Berger
  2023-07-14  7:09 ` [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device Joelle van Dyne
  2023-07-14  7:09 ` [PATCH v2 11/11] tpm_crb: support restoring older vmstate Joelle van Dyne
  10 siblings, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14  7:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Joelle van Dyne, Shannon Zhao, Michael S. Tsirkin, Igor Mammedov,
	Ani Sinha, Peter Maydell, Xiaojuan Yang, Song Gao, Stefan Berger,
	open list:ARM ACPI Subsystem

This reduces redundent code in different machine types with ACPI table
generation. Additionally, this will allow us to support multiple TPM
interfaces. Finally, this matches up with the TPM TIS ISA
implementation.

Ideally, we would be able to call `qbus_build_aml` and avoid any TPM
specific code in the ACPI table generation. However, currently we
still have to call `build_tpm2` anyways and it does not look like
most other ACPI devices support the `ACPI_DEV_AML_IF` interface.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 hw/arm/virt-acpi-build.c  | 38 ++------------------------------------
 hw/loongarch/acpi-build.c | 38 ++------------------------------------
 hw/tpm/tpm_tis_sysbus.c   | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 39 insertions(+), 72 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 6b674231c2..49b2f19440 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -35,6 +35,7 @@
 #include "target/arm/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi_aml_interface.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/acpi/aml-build.h"
@@ -208,41 +209,6 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
     aml_append(scope, dev);
 }
 
-#ifdef CONFIG_TPM
-static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
-{
-    PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
-    hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
-    SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
-    MemoryRegion *sbdev_mr;
-    hwaddr tpm_base;
-
-    if (!sbdev) {
-        return;
-    }
-
-    tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
-    assert(tpm_base != -1);
-
-    tpm_base += pbus_base;
-
-    sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
-
-    Aml *dev = aml_device("TPM0");
-    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
-    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
-
-    Aml *crs = aml_resource_template();
-    aml_append(crs,
-               aml_memory32_fixed(tpm_base,
-                                  (uint32_t)memory_region_size(sbdev_mr),
-                                  AML_READ_WRITE));
-    aml_append(dev, aml_name_decl("_CRS", crs));
-    aml_append(scope, dev);
-}
-#endif
-
 #define ID_MAPPING_ENTRY_SIZE 20
 #define SMMU_V3_ENTRY_SIZE 68
 #define ROOT_COMPLEX_ENTRY_SIZE 36
@@ -891,7 +857,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 
     acpi_dsdt_add_power_button(scope);
 #ifdef CONFIG_TPM
-    acpi_dsdt_add_tpm(scope, vms);
+    call_dev_aml_func(DEVICE(tpm_find()), scope);
 #endif
 
     aml_append(dsdt, scope);
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index 0b62c3a2f7..4291e670c8 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -14,6 +14,7 @@
 #include "target/loongarch/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi_aml_interface.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "migration/vmstate.h"
@@ -328,41 +329,6 @@ static void build_flash_aml(Aml *scope, LoongArchMachineState *lams)
     aml_append(scope, dev);
 }
 
-#ifdef CONFIG_TPM
-static void acpi_dsdt_add_tpm(Aml *scope, LoongArchMachineState *vms)
-{
-    PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
-    hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
-    SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
-    MemoryRegion *sbdev_mr;
-    hwaddr tpm_base;
-
-    if (!sbdev) {
-        return;
-    }
-
-    tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
-    assert(tpm_base != -1);
-
-    tpm_base += pbus_base;
-
-    sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
-
-    Aml *dev = aml_device("TPM0");
-    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
-    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
-
-    Aml *crs = aml_resource_template();
-    aml_append(crs,
-               aml_memory32_fixed(tpm_base,
-                                  (uint32_t)memory_region_size(sbdev_mr),
-                                  AML_READ_WRITE));
-    aml_append(dev, aml_name_decl("_CRS", crs));
-    aml_append(scope, dev);
-}
-#endif
-
 /* build DSDT */
 static void
 build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
@@ -379,7 +345,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
     build_la_ged_aml(dsdt, machine);
     build_flash_aml(dsdt, lams);
 #ifdef CONFIG_TPM
-    acpi_dsdt_add_tpm(dsdt, lams);
+    call_dev_aml_func(DEVICE(tpm_find()), dsdt);
 #endif
     /* System State Package */
     scope = aml_scope("\\");
diff --git a/hw/tpm/tpm_tis_sysbus.c b/hw/tpm/tpm_tis_sysbus.c
index 45e63efd63..b3ea2305b5 100644
--- a/hw/tpm/tpm_tis_sysbus.c
+++ b/hw/tpm/tpm_tis_sysbus.c
@@ -30,6 +30,7 @@
 #include "hw/sysbus.h"
 #include "tpm_tis.h"
 #include "qom/object.h"
+#include "hw/acpi/acpi_aml_interface.h"
 
 struct TPMStateSysBus {
     /*< private >*/
@@ -37,6 +38,8 @@ struct TPMStateSysBus {
 
     /*< public >*/
     TPMState state; /* not a QOM object */
+    uint64_t baseaddr;
+    uint64_t size;
 };
 
 OBJECT_DECLARE_SIMPLE_TYPE(TPMStateSysBus, TPM_TIS_SYSBUS)
@@ -94,6 +97,8 @@ static Property tpm_tis_sysbus_properties[] = {
     DEFINE_PROP_UINT32("irq", TPMStateSysBus, state.irq_num, TPM_TIS_IRQ),
     DEFINE_PROP_TPMBE("tpmdev", TPMStateSysBus, state.be_driver),
     DEFINE_PROP_BOOL("ppi", TPMStateSysBus, state.ppi_enabled, false),
+    DEFINE_PROP_UINT64("baseaddr", TPMStateSysBus, baseaddr, TPM_TIS_ADDR_BASE),
+    DEFINE_PROP_UINT64("size", TPMStateSysBus, size, TPM_TIS_ADDR_SIZE),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -126,10 +131,38 @@ static void tpm_tis_sysbus_realizefn(DeviceState *dev, Error **errp)
     }
 }
 
+static void build_tpm_tis_sysbus_aml(AcpiDevAmlIf *adev, Aml *scope)
+{
+    Aml *dev, *crs;
+    TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(adev);
+    TPMIf *ti = TPM_IF(sbdev);
+
+    dev = aml_device("TPM");
+    if (tpm_tis_sysbus_get_tpm_version(ti) == TPM_VERSION_2_0) {
+        aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
+        aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
+    } else {
+        aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
+    }
+    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
+    aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
+    crs = aml_resource_template();
+    aml_append(crs, aml_memory32_fixed(sbdev->baseaddr, sbdev->size,
+                                      AML_READ_WRITE));
+    /*
+     * FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs,
+     * fix default TPM_TIS_IRQ value there to use some unused IRQ
+     */
+    /* aml_append(crs, aml_irq_no_flags(sbdev->state.irq_num)); */
+    aml_append(dev, aml_name_decl("_CRS", crs));
+    aml_append(scope, dev);
+}
+
 static void tpm_tis_sysbus_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     TPMIfClass *tc = TPM_IF_CLASS(klass);
+    AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
 
     device_class_set_props(dc, tpm_tis_sysbus_properties);
     dc->vmsd  = &vmstate_tpm_tis_sysbus;
@@ -140,6 +173,7 @@ static void tpm_tis_sysbus_class_init(ObjectClass *klass, void *data)
     tc->request_completed = tpm_tis_sysbus_request_completed;
     tc->get_version = tpm_tis_sysbus_get_tpm_version;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    adevc->build_dev_aml = build_tpm_tis_sysbus_aml;
 }
 
 static const TypeInfo tpm_tis_sysbus_info = {
@@ -150,6 +184,7 @@ static const TypeInfo tpm_tis_sysbus_info = {
     .class_init  = tpm_tis_sysbus_class_init,
     .interfaces = (InterfaceInfo[]) {
         { TYPE_TPM_IF },
+        { TYPE_ACPI_DEV_AML_IF },
         { }
     }
 };
-- 
2.39.2 (Apple Git-143)



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

* [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device
  2023-07-14  7:09 [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device Joelle van Dyne
                   ` (8 preceding siblings ...)
  2023-07-14  7:09 ` [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device Joelle van Dyne
@ 2023-07-14  7:09 ` Joelle van Dyne
  2023-07-14 14:27   ` Stefan Berger
  2023-07-17 14:23   ` Igor Mammedov
  2023-07-14  7:09 ` [PATCH v2 11/11] tpm_crb: support restoring older vmstate Joelle van Dyne
  10 siblings, 2 replies; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14  7:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Joelle van Dyne, Stefan Berger, Michael S. Tsirkin,
	Igor Mammedov, Ani Sinha, Paolo Bonzini, Peter Maydell,
	Xiaojuan Yang, Song Gao, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei,
	open list:ARM TCG CPUs, open list:RISC-V TCG CPUs

This SysBus variant of the CRB interface supports dynamically locating
the MMIO interface so that Virt machines can use it. This interface
is currently the only one supported by QEMU that works on Windows 11
ARM64. We largely follow the TPM TIS SysBus device as a template.

To try out this device with Windows 11 before OVMF is updated, you
will need to modify `sysbud-fdt.c` and change the added line from:

```c
    TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
```

to

```c
    TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
```

This change was not included because it can confuse Linux (although
from testing, it seems like Linux is able to properly ignore the
device from the TPM TIS driver and recognize it from the ACPI device
in the TPM CRB driver). A proper fix would require OVMF to recognize
the ACPI device and not depend on the FDT node for recognizing TPM.

The command line to try out this device with SWTPM is:

```
$ qemu-system-aarch64 \
    -chardev socket,id=chrtpm0,path=tpm.sock \
    -tpmdev emulator,id=tpm0,chardev=chrtpm0 \
    -device tpm-crb-device,tpmdev=tpm0
```

along with SWTPM:

```
$ swtpm \
    --ctrl type=unixio,path=tpm.sock,terminate \
    --tpmstate backend-uri=file://tpm.data \
    --tpm2
```

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 docs/specs/tpm.rst          |   1 +
 include/hw/acpi/aml-build.h |   1 +
 include/sysemu/tpm.h        |   3 +
 hw/acpi/aml-build.c         |   7 +-
 hw/arm/virt.c               |   1 +
 hw/core/sysbus-fdt.c        |   1 +
 hw/loongarch/virt.c         |   1 +
 hw/riscv/virt.c             |   1 +
 hw/tpm/tpm_crb_sysbus.c     | 170 ++++++++++++++++++++++++++++++++++++
 hw/arm/Kconfig              |   1 +
 hw/riscv/Kconfig            |   1 +
 hw/tpm/Kconfig              |   5 ++
 hw/tpm/meson.build          |   2 +
 13 files changed, 194 insertions(+), 1 deletion(-)
 create mode 100644 hw/tpm/tpm_crb_sysbus.c

diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index 2bc29c9804..95aeb49220 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -46,6 +46,7 @@ operating system.
 QEMU files related to TPM CRB interface:
  - ``hw/tpm/tpm_crb.c``
  - ``hw/tpm/tpm_crb_common.c``
+ - ``hw/tpm/tpm_crb_sysbus.c``
 
 SPAPR interface
 ---------------
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index d1fb08514b..9660e16148 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -3,6 +3,7 @@
 
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/bios-linker-loader.h"
+#include "exec/hwaddr.h"
 
 #define ACPI_BUILD_APPNAME6 "BOCHS "
 #define ACPI_BUILD_APPNAME8 "BXPC    "
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 66e3b45f30..f79c8f3575 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -47,6 +47,7 @@ struct TPMIfClass {
 #define TYPE_TPM_TIS_ISA            "tpm-tis"
 #define TYPE_TPM_TIS_SYSBUS         "tpm-tis-device"
 #define TYPE_TPM_CRB                "tpm-crb"
+#define TYPE_TPM_CRB_SYSBUS         "tpm-crb-device"
 #define TYPE_TPM_SPAPR              "tpm-spapr"
 #define TYPE_TPM_TIS_I2C            "tpm-tis-i2c"
 
@@ -56,6 +57,8 @@ struct TPMIfClass {
     object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
 #define TPM_IS_CRB(chr)                             \
     object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
+#define TPM_IS_CRB_SYSBUS(chr)                      \
+    object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
 #define TPM_IS_SPAPR(chr)                           \
     object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
 #define TPM_IS_TIS_I2C(chr)                      \
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index ea331a20d1..f809137fc9 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -31,6 +31,7 @@
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/cutils.h"
+#include "qom/object.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -2218,7 +2219,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
 {
     uint8_t start_method_params[12] = {};
     unsigned log_addr_offset;
-    uint64_t control_area_start_address;
+    uint64_t baseaddr, control_area_start_address;
     TPMIf *tpmif = tpm_find();
     uint32_t start_method;
     AcpiTable table = { .sig = "TPM2", .rev = 4,
@@ -2236,6 +2237,10 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
     } else if (TPM_IS_CRB(tpmif)) {
         control_area_start_address = TPM_CRB_ADDR_CTRL;
         start_method = TPM2_START_METHOD_CRB;
+    } else if (TPM_IS_CRB_SYSBUS(tpmif)) {
+        baseaddr = object_property_get_uint(OBJECT(tpmif), "baseaddr", NULL);
+        control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
+        start_method = TPM2_START_METHOD_CRB;
     } else {
         g_assert_not_reached();
     }
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 432148ef47..88e8b16103 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2977,6 +2977,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
 #ifdef CONFIG_TPM
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
+    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
 #endif
     mc->block_default_type = IF_VIRTIO;
     mc->no_cdrom = 1;
diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
index eebcd28f9a..9c783f88eb 100644
--- a/hw/core/sysbus-fdt.c
+++ b/hw/core/sysbus-fdt.c
@@ -493,6 +493,7 @@ static const BindingEntry bindings[] = {
 #endif
 #ifdef CONFIG_TPM
     TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node),
+    TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
 #endif
     TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
     TYPE_BINDING("", NULL), /* last element */
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 9c536c52bc..eb59fb04ee 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -1194,6 +1194,7 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
 #ifdef CONFIG_TPM
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
+    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
 #endif
 }
 
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index d90286dc46..5d639a870a 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1681,6 +1681,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
 #ifdef CONFIG_TPM
     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
+    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
 #endif
 
     if (tcg_enabled()) {
diff --git a/hw/tpm/tpm_crb_sysbus.c b/hw/tpm/tpm_crb_sysbus.c
new file mode 100644
index 0000000000..66be57a532
--- /dev/null
+++ b/hw/tpm/tpm_crb_sysbus.c
@@ -0,0 +1,170 @@
+/*
+ * tpm_crb_sysbus.c - QEMU's TPM CRB interface emulator
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * Authors:
+ *   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.
+ *
+ * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
+ * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
+ * Family “2.0” Level 00 Revision 01.03 v22
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/acpi_aml_interface.h"
+#include "hw/acpi/tpm.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "tpm_prop.h"
+#include "hw/pci/pci_ids.h"
+#include "hw/sysbus.h"
+#include "qapi/visitor.h"
+#include "qom/object.h"
+#include "sysemu/tpm_util.h"
+#include "trace.h"
+#include "tpm_crb.h"
+
+struct TPMCRBStateSysBus {
+    /*< private >*/
+    SysBusDevice parent_obj;
+
+    /*< public >*/
+    TPMCRBState state;
+    uint64_t baseaddr;
+    uint64_t size;
+};
+
+OBJECT_DECLARE_SIMPLE_TYPE(TPMCRBStateSysBus, TPM_CRB_SYSBUS)
+
+static void tpm_crb_sysbus_request_completed(TPMIf *ti, int ret)
+{
+    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
+
+    return tpm_crb_request_completed(&s->state, ret);
+}
+
+static enum TPMVersion tpm_crb_sysbus_get_tpm_version(TPMIf *ti)
+{
+    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
+
+    return tpm_crb_get_version(&s->state);
+}
+
+static int tpm_crb_sysbus_pre_save(void *opaque)
+{
+    TPMCRBStateSysBus *s = opaque;
+
+    return tpm_crb_pre_save(&s->state);
+}
+
+static const VMStateDescription vmstate_tpm_crb_sysbus = {
+    .name = "tpm-crb-sysbus",
+    .pre_save = tpm_crb_sysbus_pre_save,
+    .fields = (VMStateField[]) {
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
+static Property tpm_crb_sysbus_properties[] = {
+    DEFINE_PROP_TPMBE("tpmdev", TPMCRBStateSysBus, state.tpmbe),
+    DEFINE_PROP_UINT64("baseaddr", TPMCRBStateSysBus,
+                       baseaddr, TPM_CRB_ADDR_BASE),
+    DEFINE_PROP_UINT64("size", TPMCRBStateSysBus, size, TPM_CRB_ADDR_SIZE),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void tpm_crb_sysbus_initfn(Object *obj)
+{
+    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(obj);
+
+    tpm_crb_init_memory(obj, &s->state, NULL);
+
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->state.mmio);
+}
+
+static void tpm_crb_sysbus_reset(DeviceState *dev)
+{
+    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
+
+    return tpm_crb_reset(&s->state, s->baseaddr);
+}
+
+static void tpm_crb_sysbus_realizefn(DeviceState *dev, Error **errp)
+{
+    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
+
+    if (!tpm_find()) {
+        error_setg(errp, "at most one TPM device is permitted");
+        return;
+    }
+
+    if (!s->state.tpmbe) {
+        error_setg(errp, "'tpmdev' property is required");
+        return;
+    }
+
+    if (tpm_crb_sysbus_get_tpm_version(TPM_IF(s)) != TPM_VERSION_2_0) {
+        error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
+        return;
+    }
+}
+
+static void build_tpm_crb_sysbus_aml(AcpiDevAmlIf *adev, Aml *scope)
+{
+    Aml *dev, *crs;
+    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(adev);
+    TPMIf *ti = TPM_IF(s);
+
+    dev = aml_device("TPM");
+    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
+    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
+    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
+    aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
+    crs = aml_resource_template();
+    aml_append(crs, aml_memory32_fixed(s->baseaddr, s->size,
+                                      AML_READ_WRITE));
+    aml_append(dev, aml_name_decl("_CRS", crs));
+    aml_append(scope, dev);
+}
+
+static void tpm_crb_sysbus_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    TPMIfClass *tc = TPM_IF_CLASS(klass);
+    AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
+
+    device_class_set_props(dc, tpm_crb_sysbus_properties);
+    dc->vmsd  = &vmstate_tpm_crb_sysbus;
+    tc->model = TPM_MODEL_TPM_CRB;
+    dc->realize = tpm_crb_sysbus_realizefn;
+    dc->user_creatable = true;
+    dc->reset = tpm_crb_sysbus_reset;
+    tc->request_completed = tpm_crb_sysbus_request_completed;
+    tc->get_version = tpm_crb_sysbus_get_tpm_version;
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    adevc->build_dev_aml = build_tpm_crb_sysbus_aml;
+}
+
+static const TypeInfo tpm_crb_sysbus_info = {
+    .name = TYPE_TPM_CRB_SYSBUS,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(TPMCRBStateSysBus),
+    .instance_init = tpm_crb_sysbus_initfn,
+    .class_init  = tpm_crb_sysbus_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_TPM_IF },
+        { TYPE_ACPI_DEV_AML_IF },
+        { }
+    }
+};
+
+static void tpm_crb_sysbus_register(void)
+{
+    type_register_static(&tpm_crb_sysbus_info);
+}
+
+type_init(tpm_crb_sysbus_register)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 7e68348440..efe1beaa7b 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -5,6 +5,7 @@ config ARM_VIRT
     imply VFIO_AMD_XGBE
     imply VFIO_PLATFORM
     imply VFIO_XGMAC
+    imply TPM_CRB_SYSBUS
     imply TPM_TIS_SYSBUS
     imply TPM_TIS_I2C
     imply NVDIMM
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index b6a5eb4452..d824cb58f9 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -29,6 +29,7 @@ config RISCV_VIRT
     imply PCI_DEVICES
     imply VIRTIO_VGA
     imply TEST_DEVICES
+    imply TPM_CRB_SYSBUS
     imply TPM_TIS_SYSBUS
     select RISCV_NUMA
     select GOLDFISH_RTC
diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
index 1fd73fe617..3f294a20ba 100644
--- a/hw/tpm/Kconfig
+++ b/hw/tpm/Kconfig
@@ -25,6 +25,11 @@ config TPM_CRB
     depends on TPM && ISA_BUS
     select TPM_BACKEND
 
+config TPM_CRB_SYSBUS
+    bool
+    depends on TPM
+    select TPM_BACKEND
+
 config TPM_SPAPR
     bool
     default y
diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build
index cb8204d5bc..d96de92c16 100644
--- a/hw/tpm/meson.build
+++ b/hw/tpm/meson.build
@@ -4,6 +4,8 @@ system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: files('tpm_tis_sysbus.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS_I2C', if_true: files('tpm_tis_i2c.c'))
 system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
 system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb_common.c'))
+system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_sysbus.c'))
+system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_common.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_ppi.c'))
 system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_ppi.c'))
 
-- 
2.39.2 (Apple Git-143)



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

* [PATCH v2 11/11] tpm_crb: support restoring older vmstate
  2023-07-14  7:09 [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device Joelle van Dyne
                   ` (9 preceding siblings ...)
  2023-07-14  7:09 ` [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device Joelle van Dyne
@ 2023-07-14  7:09 ` Joelle van Dyne
  2023-07-14 14:05   ` Stefan Berger
  10 siblings, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14  7:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Joelle van Dyne, Stefan Berger

When we moved to a single mapping and modified TPM CRB's VMState, it
broke restoring of VMs that were saved on an older version. This
change allows those VMs to gracefully migrate to the new memory
mapping.

Signed-off-by: Joelle van Dyne <j@getutm.app>
---
 hw/tpm/tpm_crb.h        |  1 +
 hw/tpm/tpm_crb.c        | 14 ++++++++++++++
 hw/tpm/tpm_crb_common.c |  7 +++++++
 3 files changed, 22 insertions(+)

diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
index 7cdd37335f..7d8f643e98 100644
--- a/hw/tpm/tpm_crb.h
+++ b/hw/tpm/tpm_crb.h
@@ -70,5 +70,6 @@ enum TPMVersion tpm_crb_get_version(TPMCRBState *s);
 int tpm_crb_pre_save(TPMCRBState *s);
 void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr);
 void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp);
+void tpm_crb_restore_regs(TPMCRBState *s, uint32_t *saved_regs);
 
 #endif /* TPM_TPM_CRB_H */
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 594696ffb8..be29ca8c28 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -40,6 +40,7 @@ struct CRBState {
     ISADevice parent_obj;
 
     TPMCRBState state;
+    uint32_t legacy_regs[TPM_CRB_R_MAX];
 };
 typedef struct CRBState CRBState;
 
@@ -67,10 +68,23 @@ static int tpm_crb_isa_pre_save(void *opaque)
     return tpm_crb_pre_save(&s->state);
 }
 
+static int tpm_crb_isa_post_load(void *opaque, int version_id)
+{
+    CRBState *s = opaque;
+
+    if (version_id == 0) {
+        tpm_crb_restore_regs(&s->state, s->legacy_regs);
+    }
+    return 0;
+}
+
 static const VMStateDescription vmstate_tpm_crb_isa = {
     .name = "tpm-crb",
+    .version_id = 1,
     .pre_save = tpm_crb_isa_pre_save,
+    .post_load = tpm_crb_isa_post_load,
     .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(legacy_regs, CRBState, TPM_CRB_R_MAX),
         VMSTATE_END_OF_LIST(),
     }
 };
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 4ecf064c98..5714ac7fc4 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -224,3 +224,10 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp)
         tpm_ppi_init_memory(&s->ppi, obj);
     }
 }
+
+void tpm_crb_restore_regs(TPMCRBState *s, uint32_t *saved_regs)
+{
+    uint32_t *regs = memory_region_get_ram_ptr(&s->mmio);
+
+    memcpy(regs, saved_regs, TPM_CRB_R_MAX);
+}
-- 
2.39.2 (Apple Git-143)



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

* Re: [PATCH v2 04/11] tpm_crb: use a single read-as-mem/write-as-mmio mapping
  2023-07-14  7:09 ` [PATCH v2 04/11] tpm_crb: use a single read-as-mem/write-as-mmio mapping Joelle van Dyne
@ 2023-07-14 12:03   ` Stefan Berger
  0 siblings, 0 replies; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 12:03 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel; +Cc: Stefan Berger



On 7/14/23 03:09, Joelle van Dyne wrote:
> On Apple Silicon, when Windows performs a LDP on the CRB MMIO space,
> the exception is not decoded by hardware and we cannot trap the MMIO
> read. This led to the idea from @agraf to use the same mapping type as
> ROM devices: namely that reads should be seen as memory type and
> writes should trap as MMIO.
> 
> Once that was done, the second memory mapping of the command buffer
> region was redundent and was removed.
> 
> A note about the removal of the read trap for `CRB_LOC_STATE`:
> The only usage was to return the most up-to-date value for
> `tpmEstablished`. However, `tpmEstablished` is only cleared when a
> TPM2_HashStart operation is called which only exists for locality 4.
> We do not handle locality 4. Indeed, the comment for the write handler
> of `CRB_LOC_CTRL` makes the same argument for why it is not calling
> the backend to reset the `tpmEstablished` bit (to 1).
> As this bit is unused, we do not need to worry about updating it for
> reads.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>   hw/tpm/tpm_crb.h        |   2 -
>   hw/tpm/tpm_crb.c        |   3 -
>   hw/tpm/tpm_crb_common.c | 126 +++++++++++++++++++++-------------------
>   3 files changed, 65 insertions(+), 66 deletions(-)
> 
> diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
> index da3a0cf256..7cdd37335f 100644
> --- a/hw/tpm/tpm_crb.h
> +++ b/hw/tpm/tpm_crb.h
> @@ -26,9 +26,7 @@
>   typedef struct TPMCRBState {
>       TPMBackend *tpmbe;
>       TPMBackendCmd cmd;
> -    uint32_t regs[TPM_CRB_R_MAX];
>       MemoryRegion mmio;
> -    MemoryRegion cmdmem;
> 
>       size_t be_buffer_size;
> 
> diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
> index 598c3e0161..07c6868d8d 100644
> --- a/hw/tpm/tpm_crb.c
> +++ b/hw/tpm/tpm_crb.c
> @@ -68,7 +68,6 @@ static const VMStateDescription vmstate_tpm_crb_none = {
>       .name = "tpm-crb",
>       .pre_save = tpm_crb_none_pre_save,
>       .fields = (VMStateField[]) {
> -        VMSTATE_UINT32_ARRAY(state.regs, CRBState, TPM_CRB_R_MAX),

The same comment as stated on v1 still applies, this part has to stay since VM state contains it:

2023-07-14T12:01:38.005199Z qemu-system-x86_64: Unknown ramblock "tpm-crb-cmd", cannot accept migration
2023-07-14T12:01:38.005318Z qemu-system-x86_64: error while loading state for instance 0x0 of device 'ram'
2023-07-14T12:01:38.005350Z qemu-system-x86_64: load of migration failed: Invalid argument

    Stefan


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

* Re: [PATCH v2 07/11] hw/arm/virt: add plug handler for TPM on SysBus
  2023-07-14  7:09 ` [PATCH v2 07/11] hw/arm/virt: add plug handler for TPM on SysBus Joelle van Dyne
@ 2023-07-14 12:11   ` Stefan Berger
  2023-07-14 17:09     ` Joelle van Dyne
  2023-07-17 14:00   ` Igor Mammedov
  1 sibling, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 12:11 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel; +Cc: Peter Maydell, open list:Virt



On 7/14/23 03:09, Joelle van Dyne wrote:
> TPM needs to know its own base address in order to generate its DSDT
> device entry.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>   hw/arm/virt.c | 37 +++++++++++++++++++++++++++++++++++++
>   1 file changed, 37 insertions(+)
> 
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 7d9dbc2663..432148ef47 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -2732,6 +2732,37 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev,
>                            dev, &error_abort);
>   }
> 
> +#ifdef CONFIG_TPM
> +static void virt_tpm_plug(VirtMachineState *vms, TPMIf *tpmif)
> +{
> +    PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> +    hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;

+static void virt_tpm_plug(LoongArchMachineState *lams, TPMIf *tpmif)
+{
+    PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(lams->platform_bus_dev);
+    hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;

These seem to be the differences between the loongarch and the arm virt implementations.
Why not have a function with this signature that both archs can call?

static void virt_tpm_plug(PlatformBusDevice *pbus, hwaddr pbus_base, TPMIf *tpmif)

Regards,
    Stefan


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

* Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate
  2023-07-14  7:09 ` [PATCH v2 11/11] tpm_crb: support restoring older vmstate Joelle van Dyne
@ 2023-07-14 14:05   ` Stefan Berger
  2023-07-14 14:51     ` Stefan Berger
  0 siblings, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 14:05 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel; +Cc: Stefan Berger



On 7/14/23 03:09, Joelle van Dyne wrote:
> When we moved to a single mapping and modified TPM CRB's VMState, it
> broke restoring of VMs that were saved on an older version. This
> change allows those VMs to gracefully migrate to the new memory
> mapping.

Thanks. This has to be in 4/11 though.



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

* Re: [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device
  2023-07-14  7:09 ` [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device Joelle van Dyne
@ 2023-07-14 14:27   ` Stefan Berger
  2023-07-14 17:20     ` Joelle van Dyne
  2023-07-17 14:23   ` Igor Mammedov
  1 sibling, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 14:27 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel
  Cc: Stefan Berger, Michael S. Tsirkin, Igor Mammedov, Ani Sinha,
	Paolo Bonzini, Peter Maydell, Xiaojuan Yang, Song Gao,
	Palmer Dabbelt, Alistair Francis, Bin Meng, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, open list:ARM TCG CPUs,
	open list:RISC-V TCG CPUs



On 7/14/23 03:09, Joelle van Dyne wrote:
> This SysBus variant of the CRB interface supports dynamically locating
> the MMIO interface so that Virt machines can use it. This interface
> is currently the only one supported by QEMU that works on Windows 11
> ARM64. We largely follow the TPM TIS SysBus device as a template.
> 
> To try out this device with Windows 11 before OVMF is updated, you
> will need to modify `sysbud-fdt.c` and change the added line from:
> 
> ```c
>      TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
> ```
> 
> to
> 
> ```c
>      TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
> ```
> 
> This change was not included because it can confuse Linux (although
> from testing, it seems like Linux is able to properly ignore the
> device from the TPM TIS driver and recognize it from the ACPI device
> in the TPM CRB driver). A proper fix would require OVMF to recognize
> the ACPI device and not depend on the FDT node for recognizing TPM.
> 
> The command line to try out this device with SWTPM is:
> 
> ```
> $ qemu-system-aarch64 \
>      -chardev socket,id=chrtpm0,path=tpm.sock \
>      -tpmdev emulator,id=tpm0,chardev=chrtpm0 \
>      -device tpm-crb-device,tpmdev=tpm0
> ```
> 
> along with SWTPM:
> 
> ```
> $ swtpm \
>      --ctrl type=unixio,path=tpm.sock,terminate \
>      --tpmstate backend-uri=file://tpm.data \
>      --tpm2
> ```
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>   docs/specs/tpm.rst          |   1 +
>   include/hw/acpi/aml-build.h |   1 +
>   include/sysemu/tpm.h        |   3 +
>   hw/acpi/aml-build.c         |   7 +-
>   hw/arm/virt.c               |   1 +
>   hw/core/sysbus-fdt.c        |   1 +
>   hw/loongarch/virt.c         |   1 +
>   hw/riscv/virt.c             |   1 +
>   hw/tpm/tpm_crb_sysbus.c     | 170 ++++++++++++++++++++++++++++++++++++
>   hw/arm/Kconfig              |   1 +
>   hw/riscv/Kconfig            |   1 +
>   hw/tpm/Kconfig              |   5 ++
>   hw/tpm/meson.build          |   2 +
>   13 files changed, 194 insertions(+), 1 deletion(-)
>   create mode 100644 hw/tpm/tpm_crb_sysbus.c
> 
> diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
> index 2bc29c9804..95aeb49220 100644
> --- a/docs/specs/tpm.rst
> +++ b/docs/specs/tpm.rst
> @@ -46,6 +46,7 @@ operating system.
>   QEMU files related to TPM CRB interface:
>    - ``hw/tpm/tpm_crb.c``
>    - ``hw/tpm/tpm_crb_common.c``
> + - ``hw/tpm/tpm_crb_sysbus.c``
> 

If you added the command line to use for Windows guests to this document
I think this would be helpful. And also mention that this must be used for Windows
since the other ones don't work.


>   SPAPR interface
>   ---------------
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index d1fb08514b..9660e16148 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -3,6 +3,7 @@
> 
>   #include "hw/acpi/acpi-defs.h"
>   #include "hw/acpi/bios-linker-loader.h"
> +#include "exec/hwaddr.h"
> 
>   #define ACPI_BUILD_APPNAME6 "BOCHS "
>   #define ACPI_BUILD_APPNAME8 "BXPC    "
> diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
> index 66e3b45f30..f79c8f3575 100644
> --- a/include/sysemu/tpm.h
> +++ b/include/sysemu/tpm.h
> @@ -47,6 +47,7 @@ struct TPMIfClass {
>   #define TYPE_TPM_TIS_ISA            "tpm-tis"
>   #define TYPE_TPM_TIS_SYSBUS         "tpm-tis-device"
>   #define TYPE_TPM_CRB                "tpm-crb"
> +#define TYPE_TPM_CRB_SYSBUS         "tpm-crb-device"
>   #define TYPE_TPM_SPAPR              "tpm-spapr"
>   #define TYPE_TPM_TIS_I2C            "tpm-tis-i2c"
> 
> @@ -56,6 +57,8 @@ struct TPMIfClass {
>       object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
>   #define TPM_IS_CRB(chr)                             \
>       object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
> +#define TPM_IS_CRB_SYSBUS(chr)                      \
> +    object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
>   #define TPM_IS_SPAPR(chr)                           \
>       object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
>   #define TPM_IS_TIS_I2C(chr)                      \
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index ea331a20d1..f809137fc9 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -31,6 +31,7 @@
>   #include "hw/pci/pci_bus.h"
>   #include "hw/pci/pci_bridge.h"
>   #include "qemu/cutils.h"
> +#include "qom/object.h"
> 
>   static GArray *build_alloc_array(void)
>   {
> @@ -2218,7 +2219,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
>   {
>       uint8_t start_method_params[12] = {};
>       unsigned log_addr_offset;
> -    uint64_t control_area_start_address;
> +    uint64_t baseaddr, control_area_start_address;
>       TPMIf *tpmif = tpm_find();
>       uint32_t start_method;
>       AcpiTable table = { .sig = "TPM2", .rev = 4,
> @@ -2236,6 +2237,10 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
>       } else if (TPM_IS_CRB(tpmif)) {
>           control_area_start_address = TPM_CRB_ADDR_CTRL;
>           start_method = TPM2_START_METHOD_CRB;
> +    } else if (TPM_IS_CRB_SYSBUS(tpmif)) {
> +        baseaddr = object_property_get_uint(OBJECT(tpmif), "baseaddr", NULL);
> +        control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
> +        start_method = TPM2_START_METHOD_CRB;
>       } else {
>           g_assert_not_reached();
>       }
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 432148ef47..88e8b16103 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -2977,6 +2977,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
>       machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
>   #ifdef CONFIG_TPM
>       machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
>   #endif
>       mc->block_default_type = IF_VIRTIO;
>       mc->no_cdrom = 1;
> diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
> index eebcd28f9a..9c783f88eb 100644
> --- a/hw/core/sysbus-fdt.c
> +++ b/hw/core/sysbus-fdt.c
> @@ -493,6 +493,7 @@ static const BindingEntry bindings[] = {
>   #endif
>   #ifdef CONFIG_TPM
>       TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node),
> +    TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
>   #endif
>       TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
>       TYPE_BINDING("", NULL), /* last element */
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 9c536c52bc..eb59fb04ee 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -1194,6 +1194,7 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
>       machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>   #ifdef CONFIG_TPM
>       machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
>   #endif
>   }
> 
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index d90286dc46..5d639a870a 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -1681,6 +1681,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
>       machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>   #ifdef CONFIG_TPM
>       machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
>   #endif
> 
>       if (tcg_enabled()) {
> diff --git a/hw/tpm/tpm_crb_sysbus.c b/hw/tpm/tpm_crb_sysbus.c
> new file mode 100644
> index 0000000000..66be57a532
> --- /dev/null
> +++ b/hw/tpm/tpm_crb_sysbus.c
> @@ -0,0 +1,170 @@
> +/*
> + * tpm_crb_sysbus.c - QEMU's TPM CRB interface emulator
> + *
> + * Copyright (c) 2018 Red Hat, Inc.
> + *
> + * Authors:
> + *   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.
> + *
> + * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
> + * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
> + * Family “2.0” Level 00 Revision 01.03 v22
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/acpi/acpi_aml_interface.h"
> +#include "hw/acpi/tpm.h"
> +#include "hw/qdev-properties.h"
> +#include "migration/vmstate.h"
> +#include "tpm_prop.h"
> +#include "hw/pci/pci_ids.h"
> +#include "hw/sysbus.h"
> +#include "qapi/visitor.h"
> +#include "qom/object.h"
> +#include "sysemu/tpm_util.h"
> +#include "trace.h"
> +#include "tpm_crb.h"
> +
> +struct TPMCRBStateSysBus {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +
> +    /*< public >*/
> +    TPMCRBState state;
> +    uint64_t baseaddr;
> +    uint64_t size;
> +};
> +
> +OBJECT_DECLARE_SIMPLE_TYPE(TPMCRBStateSysBus, TPM_CRB_SYSBUS)
> +
> +static void tpm_crb_sysbus_request_completed(TPMIf *ti, int ret)
> +{
> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
> +
> +    return tpm_crb_request_completed(&s->state, ret);
> +}
> +
> +static enum TPMVersion tpm_crb_sysbus_get_tpm_version(TPMIf *ti)
> +{
> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
> +
> +    return tpm_crb_get_version(&s->state);
> +}
> +
> +static int tpm_crb_sysbus_pre_save(void *opaque)
> +{
> +    TPMCRBStateSysBus *s = opaque;
> +
> +    return tpm_crb_pre_save(&s->state);
> +}
> +
> +static const VMStateDescription vmstate_tpm_crb_sysbus = {
> +    .name = "tpm-crb-sysbus",
> +    .pre_save = tpm_crb_sysbus_pre_save,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_END_OF_LIST(),
> +    }
> +};
> +
> +static Property tpm_crb_sysbus_properties[] = {
> +    DEFINE_PROP_TPMBE("tpmdev", TPMCRBStateSysBus, state.tpmbe),
> +    DEFINE_PROP_UINT64("baseaddr", TPMCRBStateSysBus,
> +                       baseaddr, TPM_CRB_ADDR_BASE),
> +    DEFINE_PROP_UINT64("size", TPMCRBStateSysBus, size, TPM_CRB_ADDR_SIZE),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void tpm_crb_sysbus_initfn(Object *obj)
> +{
> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(obj);
> +
> +    tpm_crb_init_memory(obj, &s->state, NULL);
> +
> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->state.mmio);
> +}
> +
> +static void tpm_crb_sysbus_reset(DeviceState *dev)
> +{
> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
> +
> +    return tpm_crb_reset(&s->state, s->baseaddr);
> +}
> +
> +static void tpm_crb_sysbus_realizefn(DeviceState *dev, Error **errp)
> +{
> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
> +
> +    if (!tpm_find()) {
> +        error_setg(errp, "at most one TPM device is permitted");
> +        return;
> +    }
> +
> +    if (!s->state.tpmbe) {
> +        error_setg(errp, "'tpmdev' property is required");
> +        return;
> +    }
> +
> +    if (tpm_crb_sysbus_get_tpm_version(TPM_IF(s)) != TPM_VERSION_2_0) {
> +        error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
> +        return;
> +    }
> +}
> +
> +static void build_tpm_crb_sysbus_aml(AcpiDevAmlIf *adev, Aml *scope)
> +{
> +    Aml *dev, *crs;
> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(adev);
> +    TPMIf *ti = TPM_IF(s);

../hw/tpm/tpm_crb_sysbus.c: In function 'build_tpm_crb_sysbus_aml':
../hw/tpm/tpm_crb_sysbus.c:120:12: error: unused variable 'ti' [-Werror=unused-variable]
   120 |     TPMIf *ti = TPM_IF(s);
       |            ^~


Rest LGTM.

> +
> +    dev = aml_device("TPM");
> +    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> +    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
> +    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> +    aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
> +    crs = aml_resource_template();
> +    aml_append(crs, aml_memory32_fixed(s->baseaddr, s->size,
> +                                      AML_READ_WRITE));
> +    aml_append(dev, aml_name_decl("_CRS", crs));
> +    aml_append(scope, dev);
> +}
> +
> +static void tpm_crb_sysbus_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    TPMIfClass *tc = TPM_IF_CLASS(klass);
> +    AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
> +
> +    device_class_set_props(dc, tpm_crb_sysbus_properties);
> +    dc->vmsd  = &vmstate_tpm_crb_sysbus;
> +    tc->model = TPM_MODEL_TPM_CRB;
> +    dc->realize = tpm_crb_sysbus_realizefn;
> +    dc->user_creatable = true;
> +    dc->reset = tpm_crb_sysbus_reset;
> +    tc->request_completed = tpm_crb_sysbus_request_completed;
> +    tc->get_version = tpm_crb_sysbus_get_tpm_version;
> +    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> +    adevc->build_dev_aml = build_tpm_crb_sysbus_aml;
> +}
> +
> +static const TypeInfo tpm_crb_sysbus_info = {
> +    .name = TYPE_TPM_CRB_SYSBUS,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(TPMCRBStateSysBus),
> +    .instance_init = tpm_crb_sysbus_initfn,
> +    .class_init  = tpm_crb_sysbus_class_init,
> +    .interfaces = (InterfaceInfo[]) {
> +        { TYPE_TPM_IF },
> +        { TYPE_ACPI_DEV_AML_IF },
> +        { }
> +    }
> +};
> +
> +static void tpm_crb_sysbus_register(void)
> +{
> +    type_register_static(&tpm_crb_sysbus_info);
> +}
> +
> +type_init(tpm_crb_sysbus_register)
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index 7e68348440..efe1beaa7b 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -5,6 +5,7 @@ config ARM_VIRT
>       imply VFIO_AMD_XGBE
>       imply VFIO_PLATFORM
>       imply VFIO_XGMAC
> +    imply TPM_CRB_SYSBUS
>       imply TPM_TIS_SYSBUS
>       imply TPM_TIS_I2C
>       imply NVDIMM
> diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
> index b6a5eb4452..d824cb58f9 100644
> --- a/hw/riscv/Kconfig
> +++ b/hw/riscv/Kconfig
> @@ -29,6 +29,7 @@ config RISCV_VIRT
>       imply PCI_DEVICES
>       imply VIRTIO_VGA
>       imply TEST_DEVICES
> +    imply TPM_CRB_SYSBUS
>       imply TPM_TIS_SYSBUS
>       select RISCV_NUMA
>       select GOLDFISH_RTC
> diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
> index 1fd73fe617..3f294a20ba 100644
> --- a/hw/tpm/Kconfig
> +++ b/hw/tpm/Kconfig
> @@ -25,6 +25,11 @@ config TPM_CRB
>       depends on TPM && ISA_BUS
>       select TPM_BACKEND
> 
> +config TPM_CRB_SYSBUS
> +    bool
> +    depends on TPM
> +    select TPM_BACKEND
> +
>   config TPM_SPAPR
>       bool
>       default y
> diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build
> index cb8204d5bc..d96de92c16 100644
> --- a/hw/tpm/meson.build
> +++ b/hw/tpm/meson.build
> @@ -4,6 +4,8 @@ system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: files('tpm_tis_sysbus.c'))
>   system_ss.add(when: 'CONFIG_TPM_TIS_I2C', if_true: files('tpm_tis_i2c.c'))
>   system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
>   system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb_common.c'))
> +system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_sysbus.c'))
> +system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_common.c'))
>   system_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_ppi.c'))
>   system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_ppi.c'))
> 


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

* Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate
  2023-07-14 14:05   ` Stefan Berger
@ 2023-07-14 14:51     ` Stefan Berger
  2023-07-14 17:04       ` Joelle van Dyne
  0 siblings, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 14:51 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel; +Cc: Stefan Berger



On 7/14/23 10:05, Stefan Berger wrote:
> 
> 
> On 7/14/23 03:09, Joelle van Dyne wrote:
>> When we moved to a single mapping and modified TPM CRB's VMState, it
>> broke restoring of VMs that were saved on an older version. This
>> change allows those VMs to gracefully migrate to the new memory
>> mapping.
> 
> Thanks. This has to be in 4/11 though.
> 

After applying the whole series and trying to resume state taken with current git
master I cannot restore it but it leads to this error here. I would just leave it
completely untouched in 4/11.

2023-07-14T14:46:34.547550Z qemu-system-x86_64: Unknown ramblock "tpm-crb-cmd", cannot accept migration
2023-07-14T14:46:34.547799Z qemu-system-x86_64: error while loading state for instance 0x0 of device 'ram'
2023-07-14T14:46:34.547835Z qemu-system-x86_64: load of migration failed: Invalid argument

    Stefan


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

* Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device
  2023-07-14  7:09 ` [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device Joelle van Dyne
@ 2023-07-14 16:19   ` Stefan Berger
  2023-07-14 17:29     ` Joelle van Dyne
  0 siblings, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 16:19 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel
  Cc: Shannon Zhao, Michael S. Tsirkin, Igor Mammedov, Ani Sinha,
	Peter Maydell, Xiaojuan Yang, Song Gao, Stefan Berger,
	open list:ARM ACPI Subsystem



On 7/14/23 03:09, Joelle van Dyne wrote:
> This reduces redundent code in different machine types with ACPI table
> generation. Additionally, this will allow us to support multiple TPM
> interfaces. Finally, this matches up with the TPM TIS ISA

I don't know whether we would want multiple devices. tpm_find() usage is certainly not prepared for multiple devices.

> implementation.
> 
> Ideally, we would be able to call `qbus_build_aml` and avoid any TPM
> specific code in the ACPI table generation. However, currently we
> still have to call `build_tpm2` anyways and it does not look like
> most other ACPI devices support the `ACPI_DEV_AML_IF` interface.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>   hw/arm/virt-acpi-build.c  | 38 ++------------------------------------
>   hw/loongarch/acpi-build.c | 38 ++------------------------------------
>   hw/tpm/tpm_tis_sysbus.c   | 35 +++++++++++++++++++++++++++++++++++
>   3 files changed, 39 insertions(+), 72 deletions(-)
> 
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 6b674231c2..49b2f19440 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -35,6 +35,7 @@
>   #include "target/arm/cpu.h"
>   #include "hw/acpi/acpi-defs.h"
>   #include "hw/acpi/acpi.h"
> +#include "hw/acpi/acpi_aml_interface.h"
>   #include "hw/nvram/fw_cfg.h"
>   #include "hw/acpi/bios-linker-loader.h"
>   #include "hw/acpi/aml-build.h"
> @@ -208,41 +209,6 @@ static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
>       aml_append(scope, dev);
>   }
> 
> -#ifdef CONFIG_TPM
> -static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
> -{
> -    PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> -    hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
> -    SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
> -    MemoryRegion *sbdev_mr;
> -    hwaddr tpm_base;
> -
> -    if (!sbdev) {
> -        return;
> -    }
> -
> -    tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
> -    assert(tpm_base != -1);
> -
> -    tpm_base += pbus_base;
> -
> -    sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
> -
> -    Aml *dev = aml_device("TPM0");
> -    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> -    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
> -    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
> -
> -    Aml *crs = aml_resource_template();
> -    aml_append(crs,
> -               aml_memory32_fixed(tpm_base,
> -                                  (uint32_t)memory_region_size(sbdev_mr),
> -                                  AML_READ_WRITE));
> -    aml_append(dev, aml_name_decl("_CRS", crs));
> -    aml_append(scope, dev);
> -}
> -#endif
> -
>   #define ID_MAPPING_ENTRY_SIZE 20
>   #define SMMU_V3_ENTRY_SIZE 68
>   #define ROOT_COMPLEX_ENTRY_SIZE 36
> @@ -891,7 +857,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> 
>       acpi_dsdt_add_power_button(scope);
>   #ifdef CONFIG_TPM
> -    acpi_dsdt_add_tpm(scope, vms);
> +    call_dev_aml_func(DEVICE(tpm_find()), scope);
>   #endif
> 
>       aml_append(dsdt, scope);
> diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
> index 0b62c3a2f7..4291e670c8 100644
> --- a/hw/loongarch/acpi-build.c
> +++ b/hw/loongarch/acpi-build.c
> @@ -14,6 +14,7 @@
>   #include "target/loongarch/cpu.h"
>   #include "hw/acpi/acpi-defs.h"
>   #include "hw/acpi/acpi.h"
> +#include "hw/acpi/acpi_aml_interface.h"
>   #include "hw/nvram/fw_cfg.h"
>   #include "hw/acpi/bios-linker-loader.h"
>   #include "migration/vmstate.h"
> @@ -328,41 +329,6 @@ static void build_flash_aml(Aml *scope, LoongArchMachineState *lams)
>       aml_append(scope, dev);
>   }
> 
> -#ifdef CONFIG_TPM
> -static void acpi_dsdt_add_tpm(Aml *scope, LoongArchMachineState *vms)
> -{
> -    PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> -    hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
> -    SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
> -    MemoryRegion *sbdev_mr;
> -    hwaddr tpm_base;
> -
> -    if (!sbdev) {
> -        return;
> -    }
> -
> -    tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
> -    assert(tpm_base != -1);
> -
> -    tpm_base += pbus_base;
> -
> -    sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
> -
> -    Aml *dev = aml_device("TPM0");
> -    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> -    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
> -    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
> -
> -    Aml *crs = aml_resource_template();
> -    aml_append(crs,
> -               aml_memory32_fixed(tpm_base,
> -                                  (uint32_t)memory_region_size(sbdev_mr),
> -                                  AML_READ_WRITE));
> -    aml_append(dev, aml_name_decl("_CRS", crs));
> -    aml_append(scope, dev);
> -}
> -#endif
> -

Good for the consolidation.

>   /* build DSDT */
>   static void
>   build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
> @@ -379,7 +345,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
>       build_la_ged_aml(dsdt, machine);
>       build_flash_aml(dsdt, lams);
>   #ifdef CONFIG_TPM
> -    acpi_dsdt_add_tpm(dsdt, lams);
> +    call_dev_aml_func(DEVICE(tpm_find()), dsdt);
>   #endif
>       /* System State Package */
>       scope = aml_scope("\\");
> diff --git a/hw/tpm/tpm_tis_sysbus.c b/hw/tpm/tpm_tis_sysbus.c
> index 45e63efd63..b3ea2305b5 100644
> --- a/hw/tpm/tpm_tis_sysbus.c
> +++ b/hw/tpm/tpm_tis_sysbus.c
> @@ -30,6 +30,7 @@
>   #include "hw/sysbus.h"
>   #include "tpm_tis.h"
>   #include "qom/object.h"
> +#include "hw/acpi/acpi_aml_interface.h"
> 
>   struct TPMStateSysBus {
>       /*< private >*/
> @@ -37,6 +38,8 @@ struct TPMStateSysBus {
> 
>       /*< public >*/
>       TPMState state; /* not a QOM object */
> +    uint64_t baseaddr;
> +    uint64_t size;

Does moving the TIS to a different address help on aarch64?

Can the size really be an option? I don't see it useful and if one gave the wrong size it may break things.

>   };
> 
>   OBJECT_DECLARE_SIMPLE_TYPE(TPMStateSysBus, TPM_TIS_SYSBUS)
> @@ -94,6 +97,8 @@ static Property tpm_tis_sysbus_properties[] = {
>       DEFINE_PROP_UINT32("irq", TPMStateSysBus, state.irq_num, TPM_TIS_IRQ),
>       DEFINE_PROP_TPMBE("tpmdev", TPMStateSysBus, state.be_driver),
>       DEFINE_PROP_BOOL("ppi", TPMStateSysBus, state.ppi_enabled, false),
> +    DEFINE_PROP_UINT64("baseaddr", TPMStateSysBus, baseaddr, TPM_TIS_ADDR_BASE),
> +    DEFINE_PROP_UINT64("size", TPMStateSysBus, size, TPM_TIS_ADDR_SIZE),


>       DEFINE_PROP_END_OF_LIST(),
>   };
> 
> @@ -126,10 +131,38 @@ static void tpm_tis_sysbus_realizefn(DeviceState *dev, Error **errp)
>       }
>   }
> 
> +static void build_tpm_tis_sysbus_aml(AcpiDevAmlIf *adev, Aml *scope)
> +{
> +    Aml *dev, *crs;
> +    TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(adev);
> +    TPMIf *ti = TPM_IF(sbdev);
> +
> +    dev = aml_device("TPM");
> +    if (tpm_tis_sysbus_get_tpm_version(ti) == TPM_VERSION_2_0) {
> +        aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> +        aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
> +    } else {
> +        aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
> +    }
> +    aml_append(dev, aml_name_decl("_UID", aml_int(0)));
> +    aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
> +    crs = aml_resource_template();
> +    aml_append(crs, aml_memory32_fixed(sbdev->baseaddr, sbdev->size,
> +                                      AML_READ_WRITE));
> +    /*
> +     * FIXME: TPM_TIS_IRQ=5 conflicts with PNP0C0F irqs,
> +     * fix default TPM_TIS_IRQ value there to use some unused IRQ
> +     */
> +    /* aml_append(crs, aml_irq_no_flags(sbdev->state.irq_num)); */
> +    aml_append(dev, aml_name_decl("_CRS", crs));
> +    aml_append(scope, dev);
> +}
> +
>   static void tpm_tis_sysbus_class_init(ObjectClass *klass, void *data)
>   {
>       DeviceClass *dc = DEVICE_CLASS(klass);
>       TPMIfClass *tc = TPM_IF_CLASS(klass);
> +    AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
> 
>       device_class_set_props(dc, tpm_tis_sysbus_properties);
>       dc->vmsd  = &vmstate_tpm_tis_sysbus;
> @@ -140,6 +173,7 @@ static void tpm_tis_sysbus_class_init(ObjectClass *klass, void *data)
>       tc->request_completed = tpm_tis_sysbus_request_completed;
>       tc->get_version = tpm_tis_sysbus_get_tpm_version;
>       set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> +    adevc->build_dev_aml = build_tpm_tis_sysbus_aml;
>   }
> 
>   static const TypeInfo tpm_tis_sysbus_info = {
> @@ -150,6 +184,7 @@ static const TypeInfo tpm_tis_sysbus_info = {
>       .class_init  = tpm_tis_sysbus_class_init,
>       .interfaces = (InterfaceInfo[]) {
>           { TYPE_TPM_IF },
> +        { TYPE_ACPI_DEV_AML_IF },
>           { }
>       }
>   };


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

* Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate
  2023-07-14 14:51     ` Stefan Berger
@ 2023-07-14 17:04       ` Joelle van Dyne
  2023-07-14 18:22         ` Stefan Berger
  0 siblings, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14 17:04 UTC (permalink / raw)
  To: Stefan Berger; +Cc: Joelle van Dyne, qemu-devel, Stefan Berger

On Fri, Jul 14, 2023 at 7:51 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>
>
>
> On 7/14/23 10:05, Stefan Berger wrote:
> >
> >
> > On 7/14/23 03:09, Joelle van Dyne wrote:
> >> When we moved to a single mapping and modified TPM CRB's VMState, it
> >> broke restoring of VMs that were saved on an older version. This
> >> change allows those VMs to gracefully migrate to the new memory
> >> mapping.
> >
> > Thanks. This has to be in 4/11 though.
> >
>
> After applying the whole series and trying to resume state taken with current git
> master I cannot restore it but it leads to this error here. I would just leave it
> completely untouched in 4/11.
>
> 2023-07-14T14:46:34.547550Z qemu-system-x86_64: Unknown ramblock "tpm-crb-cmd", cannot accept migration
> 2023-07-14T14:46:34.547799Z qemu-system-x86_64: error while loading state for instance 0x0 of device 'ram'
> 2023-07-14T14:46:34.547835Z qemu-system-x86_64: load of migration failed: Invalid argument
>
>     Stefan

To be clear, you are asking to back out of 4/11? That patch changes
how the registers are mapped so it's impossible to support the old
style register mapping. This patch attempts to fix that with a
migration path but I realized that I missed the "tpm-crb-cmd"
ramblock. It can be added to v3 for this patch. Similar to the logic
to have `legacy_regs` we will add a `legacy_cmdmem` memory region that
is not registered with the system bus but only exists to migrate the
data. Would that work? Also open to better ideas on migrating legacy
saved state.

If we back out of 4/11 (the split mapping), then the proposed way for
working on Apple Silicon would not be available and we would have to
go down the path of emulating AArch64 instruction in HVF backend (or
decide not to support Apple Silicon).


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

* Re: [PATCH v2 07/11] hw/arm/virt: add plug handler for TPM on SysBus
  2023-07-14 12:11   ` Stefan Berger
@ 2023-07-14 17:09     ` Joelle van Dyne
  0 siblings, 0 replies; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14 17:09 UTC (permalink / raw)
  To: Stefan Berger; +Cc: Joelle van Dyne, qemu-devel, Peter Maydell, open list:Virt

On Fri, Jul 14, 2023 at 5:11 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>
>
>
> On 7/14/23 03:09, Joelle van Dyne wrote:
> > TPM needs to know its own base address in order to generate its DSDT
> > device entry.
> >
> > Signed-off-by: Joelle van Dyne <j@getutm.app>
> > ---
> >   hw/arm/virt.c | 37 +++++++++++++++++++++++++++++++++++++
> >   1 file changed, 37 insertions(+)
> >
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index 7d9dbc2663..432148ef47 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -2732,6 +2732,37 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev,
> >                            dev, &error_abort);
> >   }
> >
> > +#ifdef CONFIG_TPM
> > +static void virt_tpm_plug(VirtMachineState *vms, TPMIf *tpmif)
> > +{
> > +    PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> > +    hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
>
> +static void virt_tpm_plug(LoongArchMachineState *lams, TPMIf *tpmif)
> +{
> +    PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(lams->platform_bus_dev);
> +    hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
>
> These seem to be the differences between the loongarch and the arm virt implementations.
> Why not have a function with this signature that both archs can call?
>
> static void virt_tpm_plug(PlatformBusDevice *pbus, hwaddr pbus_base, TPMIf *tpmif)
>
> Regards,
>     Stefan

That was the first intended solution, but the code that this is
replacing was copy-pasted and as I don't know anything about this arch
or know how to test it, this caused the least amount of changes to
that target architecture (no additional includes, changes to the build
scripts, etc). I don't think there is currently a common "virt" module
that all the "virt" targets use so we would have to create that. It
seemed out of scope for this TPM patchset and could be something for a
different patch set. tl;dr: the code it replaces was copy-pasted so
it's not strictly making things worse.


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

* Re: [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device
  2023-07-14 14:27   ` Stefan Berger
@ 2023-07-14 17:20     ` Joelle van Dyne
  2023-07-14 17:52       ` Stefan Berger
  0 siblings, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14 17:20 UTC (permalink / raw)
  To: Stefan Berger
  Cc: Joelle van Dyne, qemu-devel, Stefan Berger, Michael S. Tsirkin,
	Igor Mammedov, Ani Sinha, Paolo Bonzini, Peter Maydell,
	Xiaojuan Yang, Song Gao, Palmer Dabbelt, Alistair Francis,
	Bin Meng, Weiwei Li, Daniel Henrique Barboza, Liu Zhiwei,
	open list:ARM TCG CPUs, open list:RISC-V TCG CPUs

On Fri, Jul 14, 2023 at 7:27 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>
>
>
> On 7/14/23 03:09, Joelle van Dyne wrote:
> > This SysBus variant of the CRB interface supports dynamically locating
> > the MMIO interface so that Virt machines can use it. This interface
> > is currently the only one supported by QEMU that works on Windows 11
> > ARM64. We largely follow the TPM TIS SysBus device as a template.
> >
> > To try out this device with Windows 11 before OVMF is updated, you
> > will need to modify `sysbud-fdt.c` and change the added line from:
> >
> > ```c
> >      TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
> > ```
> >
> > to
> >
> > ```c
> >      TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
> > ```
> >
> > This change was not included because it can confuse Linux (although
> > from testing, it seems like Linux is able to properly ignore the
> > device from the TPM TIS driver and recognize it from the ACPI device
> > in the TPM CRB driver). A proper fix would require OVMF to recognize
> > the ACPI device and not depend on the FDT node for recognizing TPM.
> >
> > The command line to try out this device with SWTPM is:
> >
> > ```
> > $ qemu-system-aarch64 \
> >      -chardev socket,id=chrtpm0,path=tpm.sock \
> >      -tpmdev emulator,id=tpm0,chardev=chrtpm0 \
> >      -device tpm-crb-device,tpmdev=tpm0
> > ```
> >
> > along with SWTPM:
> >
> > ```
> > $ swtpm \
> >      --ctrl type=unixio,path=tpm.sock,terminate \
> >      --tpmstate backend-uri=file://tpm.data \
> >      --tpm2
> > ```
> >
> > Signed-off-by: Joelle van Dyne <j@getutm.app>
> > ---
> >   docs/specs/tpm.rst          |   1 +
> >   include/hw/acpi/aml-build.h |   1 +
> >   include/sysemu/tpm.h        |   3 +
> >   hw/acpi/aml-build.c         |   7 +-
> >   hw/arm/virt.c               |   1 +
> >   hw/core/sysbus-fdt.c        |   1 +
> >   hw/loongarch/virt.c         |   1 +
> >   hw/riscv/virt.c             |   1 +
> >   hw/tpm/tpm_crb_sysbus.c     | 170 ++++++++++++++++++++++++++++++++++++
> >   hw/arm/Kconfig              |   1 +
> >   hw/riscv/Kconfig            |   1 +
> >   hw/tpm/Kconfig              |   5 ++
> >   hw/tpm/meson.build          |   2 +
> >   13 files changed, 194 insertions(+), 1 deletion(-)
> >   create mode 100644 hw/tpm/tpm_crb_sysbus.c
> >
> > diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
> > index 2bc29c9804..95aeb49220 100644
> > --- a/docs/specs/tpm.rst
> > +++ b/docs/specs/tpm.rst
> > @@ -46,6 +46,7 @@ operating system.
> >   QEMU files related to TPM CRB interface:
> >    - ``hw/tpm/tpm_crb.c``
> >    - ``hw/tpm/tpm_crb_common.c``
> > + - ``hw/tpm/tpm_crb_sysbus.c``
> >
>
> If you added the command line to use for Windows guests to this document
> I think this would be helpful. And also mention that this must be used for Windows
> since the other ones don't work.
>
>
> >   SPAPR interface
> >   ---------------
> > diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> > index d1fb08514b..9660e16148 100644
> > --- a/include/hw/acpi/aml-build.h
> > +++ b/include/hw/acpi/aml-build.h
> > @@ -3,6 +3,7 @@
> >
> >   #include "hw/acpi/acpi-defs.h"
> >   #include "hw/acpi/bios-linker-loader.h"
> > +#include "exec/hwaddr.h"
> >
> >   #define ACPI_BUILD_APPNAME6 "BOCHS "
> >   #define ACPI_BUILD_APPNAME8 "BXPC    "
> > diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
> > index 66e3b45f30..f79c8f3575 100644
> > --- a/include/sysemu/tpm.h
> > +++ b/include/sysemu/tpm.h
> > @@ -47,6 +47,7 @@ struct TPMIfClass {
> >   #define TYPE_TPM_TIS_ISA            "tpm-tis"
> >   #define TYPE_TPM_TIS_SYSBUS         "tpm-tis-device"
> >   #define TYPE_TPM_CRB                "tpm-crb"
> > +#define TYPE_TPM_CRB_SYSBUS         "tpm-crb-device"
> >   #define TYPE_TPM_SPAPR              "tpm-spapr"
> >   #define TYPE_TPM_TIS_I2C            "tpm-tis-i2c"
> >
> > @@ -56,6 +57,8 @@ struct TPMIfClass {
> >       object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
> >   #define TPM_IS_CRB(chr)                             \
> >       object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
> > +#define TPM_IS_CRB_SYSBUS(chr)                      \
> > +    object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
> >   #define TPM_IS_SPAPR(chr)                           \
> >       object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
> >   #define TPM_IS_TIS_I2C(chr)                      \
> > diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> > index ea331a20d1..f809137fc9 100644
> > --- a/hw/acpi/aml-build.c
> > +++ b/hw/acpi/aml-build.c
> > @@ -31,6 +31,7 @@
> >   #include "hw/pci/pci_bus.h"
> >   #include "hw/pci/pci_bridge.h"
> >   #include "qemu/cutils.h"
> > +#include "qom/object.h"
> >
> >   static GArray *build_alloc_array(void)
> >   {
> > @@ -2218,7 +2219,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
> >   {
> >       uint8_t start_method_params[12] = {};
> >       unsigned log_addr_offset;
> > -    uint64_t control_area_start_address;
> > +    uint64_t baseaddr, control_area_start_address;
> >       TPMIf *tpmif = tpm_find();
> >       uint32_t start_method;
> >       AcpiTable table = { .sig = "TPM2", .rev = 4,
> > @@ -2236,6 +2237,10 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
> >       } else if (TPM_IS_CRB(tpmif)) {
> >           control_area_start_address = TPM_CRB_ADDR_CTRL;
> >           start_method = TPM2_START_METHOD_CRB;
> > +    } else if (TPM_IS_CRB_SYSBUS(tpmif)) {
> > +        baseaddr = object_property_get_uint(OBJECT(tpmif), "baseaddr", NULL);
> > +        control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
> > +        start_method = TPM2_START_METHOD_CRB;
> >       } else {
> >           g_assert_not_reached();
> >       }
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index 432148ef47..88e8b16103 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -2977,6 +2977,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
> >       machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
> >   #ifdef CONFIG_TPM
> >       machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> > +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
> >   #endif
> >       mc->block_default_type = IF_VIRTIO;
> >       mc->no_cdrom = 1;
> > diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
> > index eebcd28f9a..9c783f88eb 100644
> > --- a/hw/core/sysbus-fdt.c
> > +++ b/hw/core/sysbus-fdt.c
> > @@ -493,6 +493,7 @@ static const BindingEntry bindings[] = {
> >   #endif
> >   #ifdef CONFIG_TPM
> >       TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node),
> > +    TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
> >   #endif
> >       TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
> >       TYPE_BINDING("", NULL), /* last element */
> > diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> > index 9c536c52bc..eb59fb04ee 100644
> > --- a/hw/loongarch/virt.c
> > +++ b/hw/loongarch/virt.c
> > @@ -1194,6 +1194,7 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
> >       machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> >   #ifdef CONFIG_TPM
> >       machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> > +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
> >   #endif
> >   }
> >
> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > index d90286dc46..5d639a870a 100644
> > --- a/hw/riscv/virt.c
> > +++ b/hw/riscv/virt.c
> > @@ -1681,6 +1681,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
> >       machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> >   #ifdef CONFIG_TPM
> >       machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> > +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
> >   #endif
> >
> >       if (tcg_enabled()) {
> > diff --git a/hw/tpm/tpm_crb_sysbus.c b/hw/tpm/tpm_crb_sysbus.c
> > new file mode 100644
> > index 0000000000..66be57a532
> > --- /dev/null
> > +++ b/hw/tpm/tpm_crb_sysbus.c
> > @@ -0,0 +1,170 @@
> > +/*
> > + * tpm_crb_sysbus.c - QEMU's TPM CRB interface emulator
> > + *
> > + * Copyright (c) 2018 Red Hat, Inc.
> > + *
> > + * Authors:
> > + *   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.
> > + *
> > + * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
> > + * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
> > + * Family “2.0” Level 00 Revision 01.03 v22
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "hw/acpi/acpi_aml_interface.h"
> > +#include "hw/acpi/tpm.h"
> > +#include "hw/qdev-properties.h"
> > +#include "migration/vmstate.h"
> > +#include "tpm_prop.h"
> > +#include "hw/pci/pci_ids.h"
> > +#include "hw/sysbus.h"
> > +#include "qapi/visitor.h"
> > +#include "qom/object.h"
> > +#include "sysemu/tpm_util.h"
> > +#include "trace.h"
> > +#include "tpm_crb.h"
> > +
> > +struct TPMCRBStateSysBus {
> > +    /*< private >*/
> > +    SysBusDevice parent_obj;
> > +
> > +    /*< public >*/
> > +    TPMCRBState state;
> > +    uint64_t baseaddr;
> > +    uint64_t size;
> > +};
> > +
> > +OBJECT_DECLARE_SIMPLE_TYPE(TPMCRBStateSysBus, TPM_CRB_SYSBUS)
> > +
> > +static void tpm_crb_sysbus_request_completed(TPMIf *ti, int ret)
> > +{
> > +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
> > +
> > +    return tpm_crb_request_completed(&s->state, ret);
> > +}
> > +
> > +static enum TPMVersion tpm_crb_sysbus_get_tpm_version(TPMIf *ti)
> > +{
> > +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
> > +
> > +    return tpm_crb_get_version(&s->state);
> > +}
> > +
> > +static int tpm_crb_sysbus_pre_save(void *opaque)
> > +{
> > +    TPMCRBStateSysBus *s = opaque;
> > +
> > +    return tpm_crb_pre_save(&s->state);
> > +}
> > +
> > +static const VMStateDescription vmstate_tpm_crb_sysbus = {
> > +    .name = "tpm-crb-sysbus",
> > +    .pre_save = tpm_crb_sysbus_pre_save,
> > +    .fields = (VMStateField[]) {
> > +        VMSTATE_END_OF_LIST(),
> > +    }
> > +};
> > +
> > +static Property tpm_crb_sysbus_properties[] = {
> > +    DEFINE_PROP_TPMBE("tpmdev", TPMCRBStateSysBus, state.tpmbe),
> > +    DEFINE_PROP_UINT64("baseaddr", TPMCRBStateSysBus,
> > +                       baseaddr, TPM_CRB_ADDR_BASE),
> > +    DEFINE_PROP_UINT64("size", TPMCRBStateSysBus, size, TPM_CRB_ADDR_SIZE),
> > +    DEFINE_PROP_END_OF_LIST(),
> > +};
> > +
> > +static void tpm_crb_sysbus_initfn(Object *obj)
> > +{
> > +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(obj);
> > +
> > +    tpm_crb_init_memory(obj, &s->state, NULL);
> > +
> > +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->state.mmio);
> > +}
> > +
> > +static void tpm_crb_sysbus_reset(DeviceState *dev)
> > +{
> > +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
> > +
> > +    return tpm_crb_reset(&s->state, s->baseaddr);
> > +}
> > +
> > +static void tpm_crb_sysbus_realizefn(DeviceState *dev, Error **errp)
> > +{
> > +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
> > +
> > +    if (!tpm_find()) {
> > +        error_setg(errp, "at most one TPM device is permitted");
> > +        return;
> > +    }
> > +
> > +    if (!s->state.tpmbe) {
> > +        error_setg(errp, "'tpmdev' property is required");
> > +        return;
> > +    }
> > +
> > +    if (tpm_crb_sysbus_get_tpm_version(TPM_IF(s)) != TPM_VERSION_2_0) {
> > +        error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
> > +        return;
> > +    }
> > +}
> > +
> > +static void build_tpm_crb_sysbus_aml(AcpiDevAmlIf *adev, Aml *scope)
> > +{
> > +    Aml *dev, *crs;
> > +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(adev);
> > +    TPMIf *ti = TPM_IF(s);
>
> ../hw/tpm/tpm_crb_sysbus.c: In function 'build_tpm_crb_sysbus_aml':
> ../hw/tpm/tpm_crb_sysbus.c:120:12: error: unused variable 'ti' [-Werror=unused-variable]
>    120 |     TPMIf *ti = TPM_IF(s);
>        |            ^~
>
>
> Rest LGTM.
>
> > +
> > +    dev = aml_device("TPM");
> > +    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> > +    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
> > +    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> > +    aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
> > +    crs = aml_resource_template();
> > +    aml_append(crs, aml_memory32_fixed(s->baseaddr, s->size,
> > +                                      AML_READ_WRITE));
> > +    aml_append(dev, aml_name_decl("_CRS", crs));
> > +    aml_append(scope, dev);
> > +}
> > +
> > +static void tpm_crb_sysbus_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +    TPMIfClass *tc = TPM_IF_CLASS(klass);
> > +    AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
> > +
> > +    device_class_set_props(dc, tpm_crb_sysbus_properties);
> > +    dc->vmsd  = &vmstate_tpm_crb_sysbus;
> > +    tc->model = TPM_MODEL_TPM_CRB;
> > +    dc->realize = tpm_crb_sysbus_realizefn;
> > +    dc->user_creatable = true;
> > +    dc->reset = tpm_crb_sysbus_reset;
> > +    tc->request_completed = tpm_crb_sysbus_request_completed;
> > +    tc->get_version = tpm_crb_sysbus_get_tpm_version;
> > +    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> > +    adevc->build_dev_aml = build_tpm_crb_sysbus_aml;
> > +}
> > +
> > +static const TypeInfo tpm_crb_sysbus_info = {
> > +    .name = TYPE_TPM_CRB_SYSBUS,
> > +    .parent = TYPE_SYS_BUS_DEVICE,
> > +    .instance_size = sizeof(TPMCRBStateSysBus),
> > +    .instance_init = tpm_crb_sysbus_initfn,
> > +    .class_init  = tpm_crb_sysbus_class_init,
> > +    .interfaces = (InterfaceInfo[]) {
> > +        { TYPE_TPM_IF },
> > +        { TYPE_ACPI_DEV_AML_IF },
> > +        { }
> > +    }
> > +};
> > +
> > +static void tpm_crb_sysbus_register(void)
> > +{
> > +    type_register_static(&tpm_crb_sysbus_info);
> > +}
> > +
> > +type_init(tpm_crb_sysbus_register)
> > diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> > index 7e68348440..efe1beaa7b 100644
> > --- a/hw/arm/Kconfig
> > +++ b/hw/arm/Kconfig
> > @@ -5,6 +5,7 @@ config ARM_VIRT
> >       imply VFIO_AMD_XGBE
> >       imply VFIO_PLATFORM
> >       imply VFIO_XGMAC
> > +    imply TPM_CRB_SYSBUS
> >       imply TPM_TIS_SYSBUS
> >       imply TPM_TIS_I2C
> >       imply NVDIMM
> > diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
> > index b6a5eb4452..d824cb58f9 100644
> > --- a/hw/riscv/Kconfig
> > +++ b/hw/riscv/Kconfig
> > @@ -29,6 +29,7 @@ config RISCV_VIRT
> >       imply PCI_DEVICES
> >       imply VIRTIO_VGA
> >       imply TEST_DEVICES
> > +    imply TPM_CRB_SYSBUS
> >       imply TPM_TIS_SYSBUS
> >       select RISCV_NUMA
> >       select GOLDFISH_RTC
> > diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
> > index 1fd73fe617..3f294a20ba 100644
> > --- a/hw/tpm/Kconfig
> > +++ b/hw/tpm/Kconfig
> > @@ -25,6 +25,11 @@ config TPM_CRB
> >       depends on TPM && ISA_BUS
> >       select TPM_BACKEND
> >
> > +config TPM_CRB_SYSBUS
> > +    bool
> > +    depends on TPM
> > +    select TPM_BACKEND
> > +
> >   config TPM_SPAPR
> >       bool
> >       default y
> > diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build
> > index cb8204d5bc..d96de92c16 100644
> > --- a/hw/tpm/meson.build
> > +++ b/hw/tpm/meson.build
> > @@ -4,6 +4,8 @@ system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: files('tpm_tis_sysbus.c'))
> >   system_ss.add(when: 'CONFIG_TPM_TIS_I2C', if_true: files('tpm_tis_i2c.c'))
> >   system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
> >   system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb_common.c'))
> > +system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_sysbus.c'))
> > +system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_common.c'))
> >   system_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_ppi.c'))
> >   system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_ppi.c'))
> >

New commit description looks good?

"This SysBus variant of the CRB interface supports dynamically
locating the MMIO interface so that Virt machines can use it. This
interface is currently the only one supported by QEMU that works on
Windows 11 ARM64 as 'tpm-tis-device' does not work with current
Windows drivers. We largely follow that device as a template."

Also, I'm not sure what else you need for the Windows command. Do you
mean the command to initiate a Windows install? Because I feel like
there would be a lot of text there that would be off-topic from the
commit. Additionally, do we also need to include steps on creating the
QCOW boot device, setting up the UEFI secure boot, and so on? Because
there's quite a few steps involved to get a working Windows boot and
I'm sure it's documented in length in various blog posts.


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

* Re: [PATCH v2 06/11] tpm_crb: move ACPI table building to device interface
  2023-07-14  7:09 ` [PATCH v2 06/11] tpm_crb: move ACPI table building to device interface Joelle van Dyne
@ 2023-07-14 17:21   ` Stefan Berger
  2023-07-17 13:42     ` Igor Mammedov
  0 siblings, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 17:21 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel
  Cc: Michael S. Tsirkin, Igor Mammedov, Ani Sinha, Paolo Bonzini,
	Richard Henderson, Eduardo Habkost, Marcel Apfelbaum,
	Stefan Berger



On 7/14/23 03:09, Joelle van Dyne wrote:
> This logic is similar to TPM TIS ISA device. Since TPM CRB can only
> support TPM 2.0 backends, we check for this in realize.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>

This patch changes the order of in which the ACPI table elements are created but doesn't matter and also doesn't seem to upset ACPI test cases from what I saw:

Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>

> ---
>   hw/i386/acpi-build.c | 23 -----------------------
>   hw/tpm/tpm_crb.c     | 29 +++++++++++++++++++++++++++++
>   2 files changed, 29 insertions(+), 23 deletions(-)
> 
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 9c74fa17ad..b767df39df 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -1441,9 +1441,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>       uint32_t nr_mem = machine->ram_slots;
>       int root_bus_limit = 0xFF;
>       PCIBus *bus = NULL;
> -#ifdef CONFIG_TPM
> -    TPMIf *tpm = tpm_find();
> -#endif
>       bool cxl_present = false;
>       int i;
>       VMBusBridge *vmbus_bridge = vmbus_bridge_find();
> @@ -1793,26 +1790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>           }
>       }
> 
> -#ifdef CONFIG_TPM
> -    if (TPM_IS_CRB(tpm)) {
> -        dev = aml_device("TPM");
> -        aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> -        aml_append(dev, aml_name_decl("_STR",
> -                                      aml_string("TPM 2.0 Device")));
> -        crs = aml_resource_template();
> -        aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
> -                                           TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
> -        aml_append(dev, aml_name_decl("_CRS", crs));
> -
> -        aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
> -        aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> -
> -        tpm_build_ppi_acpi(tpm, dev);
> -
> -        aml_append(sb_scope, dev);
> -    }
> -#endif
> -
>       if (pcms->sgx_epc.size != 0) {
>           uint64_t epc_base = pcms->sgx_epc.base;
>           uint64_t epc_size = pcms->sgx_epc.size;
> diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
> index 6144081d30..594696ffb8 100644
> --- a/hw/tpm/tpm_crb.c
> +++ b/hw/tpm/tpm_crb.c
> @@ -19,6 +19,8 @@
>   #include "qemu/module.h"
>   #include "qapi/error.h"
>   #include "exec/address-spaces.h"
> +#include "hw/acpi/acpi_aml_interface.h"
> +#include "hw/acpi/tpm.h"
>   #include "hw/qdev-properties.h"
>   #include "hw/pci/pci_ids.h"
>   #include "hw/acpi/tpm.h"
> @@ -99,6 +101,11 @@ static void tpm_crb_isa_realize(DeviceState *dev, Error **errp)
>           return;
>       }
> 
> +    if (tpm_crb_isa_get_version(TPM_IF(s)) != TPM_VERSION_2_0) {
> +        error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
> +        return;
> +    }
> +
>       tpm_crb_init_memory(OBJECT(s), &s->state, errp);
> 
>       memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
> @@ -116,10 +123,30 @@ static void tpm_crb_isa_realize(DeviceState *dev, Error **errp)
>       }
>   }
> 
> +static void build_tpm_crb_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
> +{
> +    Aml *dev, *crs;
> +    CRBState *s = CRB(adev);
> +    TPMIf *ti = TPM_IF(s);
> +
> +    dev = aml_device("TPM");
> +    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> +    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
> +    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> +    aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
> +    crs = aml_resource_template();
> +    aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE, TPM_CRB_ADDR_SIZE,
> +                                      AML_READ_WRITE));
> +    aml_append(dev, aml_name_decl("_CRS", crs));
> +    tpm_build_ppi_acpi(ti, dev);
> +    aml_append(scope, dev);
> +}
> +
>   static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
>   {
>       DeviceClass *dc = DEVICE_CLASS(klass);
>       TPMIfClass *tc = TPM_IF_CLASS(klass);
> +    AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
> 
>       dc->realize = tpm_crb_isa_realize;
>       device_class_set_props(dc, tpm_crb_isa_properties);
> @@ -128,6 +155,7 @@ static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
>       tc->model = TPM_MODEL_TPM_CRB;
>       tc->get_version = tpm_crb_isa_get_version;
>       tc->request_completed = tpm_crb_isa_request_completed;
> +    adevc->build_dev_aml = build_tpm_crb_isa_aml;
> 
>       set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>   }
> @@ -139,6 +167,7 @@ static const TypeInfo tpm_crb_isa_info = {
>       .class_init  = tpm_crb_isa_class_init,
>       .interfaces = (InterfaceInfo[]) {
>           { TYPE_TPM_IF },
> +        { TYPE_ACPI_DEV_AML_IF },
>           { }
>       }
>   };


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

* Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device
  2023-07-14 16:19   ` Stefan Berger
@ 2023-07-14 17:29     ` Joelle van Dyne
  2023-07-14 17:37       ` Stefan Berger
  2023-07-17 14:06       ` Igor Mammedov
  0 siblings, 2 replies; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14 17:29 UTC (permalink / raw)
  To: Stefan Berger
  Cc: Joelle van Dyne, qemu-devel, Shannon Zhao, Michael S. Tsirkin,
	Igor Mammedov, Ani Sinha, Peter Maydell, Xiaojuan Yang, Song Gao,
	Stefan Berger, open list:ARM ACPI Subsystem

On Fri, Jul 14, 2023 at 9:19 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>
>
>
>
> I don't know whether we would want multiple devices. tpm_find() usage is certainly not prepared for multiple devices.
Sorry, "multiple TPM interfaces" here does not mean "at the same
time". Will clarify the description.

>
>
> Good for the consolidation.
>
>
> Does moving the TIS to a different address help on aarch64?
That was the first thing we tried and no it doesn't help.
>
> Can the size really be an option? I don't see it useful and if one gave the wrong size it may break things.
It was added for consistency (otherwise we have to determine the size
by looking at the interface everywhere). Also, it is possible for the
size to be larger than the constant. For example, Apple Silicon uses
16KiB page sizes and we may decide to force the device to be 16KiB
aligned (not sure if this is needed yet while we still track down why
the dual mapping was not working). In that case, we would need to
inform the OS of the true region size to prevent any overlap issues.
Both baseaddr and size should be provided only by the plug handler in
the virt machine, otherwise things may break even if we get rid of
size and have just an incorrect baseaddr.

>
>
>


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

* Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device
  2023-07-14 17:29     ` Joelle van Dyne
@ 2023-07-14 17:37       ` Stefan Berger
  2023-07-14 17:39         ` Joelle van Dyne
  2023-07-17 14:06       ` Igor Mammedov
  1 sibling, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 17:37 UTC (permalink / raw)
  To: Joelle van Dyne
  Cc: qemu-devel, Shannon Zhao, Michael S. Tsirkin, Igor Mammedov,
	Ani Sinha, Peter Maydell, Xiaojuan Yang, Song Gao, Stefan Berger,
	open list:ARM ACPI Subsystem



On 7/14/23 13:29, Joelle van Dyne wrote:
> On Fri, Jul 14, 2023 at 9:19 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>
>>
>>
>>
>> I don't know whether we would want multiple devices. tpm_find() usage is certainly not prepared for multiple devices.
> Sorry, "multiple TPM interfaces" here does not mean "at the same
> time". Will clarify the description.
> 
>>
>>
>> Good for the consolidation.
>>
>>
>> Does moving the TIS to a different address help on aarch64?
> That was the first thing we tried and no it doesn't help.

I would remove it if we don't have a known alternative address that makes it work. If we do, I think we should document it in tpm.rst.


>>
>> Can the size really be an option? I don't see it useful and if one gave the wrong size it may break things.
> It was added for consistency (otherwise we have to determine the size
> by looking at the interface everywhere). Also, it is possible for the
> size to be larger than the constant. For example, Apple Silicon uses
> 16KiB page sizes and we may decide to force the device to be 16KiB
> aligned (not sure if this is needed yet while we still track down why
> the dual mapping was not working). In that case, we would need to
> inform the OS of the true region size to prevent any overlap issues.
> Both baseaddr and size should be provided only by the plug handler in
> the virt machine, otherwise things may break even if we get rid of
> size and have just an incorrect baseaddr.
> 
>>
>>
>>


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

* Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device
  2023-07-14 17:37       ` Stefan Berger
@ 2023-07-14 17:39         ` Joelle van Dyne
  2023-07-14 17:43           ` Stefan Berger
  0 siblings, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14 17:39 UTC (permalink / raw)
  To: Stefan Berger
  Cc: Joelle van Dyne, qemu-devel, Shannon Zhao, Michael S. Tsirkin,
	Igor Mammedov, Ani Sinha, Peter Maydell, Xiaojuan Yang, Song Gao,
	Stefan Berger, open list:ARM ACPI Subsystem

On Fri, Jul 14, 2023 at 10:37 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>
>
>
> On 7/14/23 13:29, Joelle van Dyne wrote:
> > On Fri, Jul 14, 2023 at 9:19 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
> >>
> >>
> >>
> >>
> >> I don't know whether we would want multiple devices. tpm_find() usage is certainly not prepared for multiple devices.
> > Sorry, "multiple TPM interfaces" here does not mean "at the same
> > time". Will clarify the description.
> >
> >>
> >>
> >> Good for the consolidation.
> >>
> >>
> >> Does moving the TIS to a different address help on aarch64?
> > That was the first thing we tried and no it doesn't help.
>
> I would remove it if we don't have a known alternative address that makes it work. If we do, I think we should document it in tpm.rst.
"It" is referring to tpm-tis-device? Note that it does work fine with Linux VMs.

>
>
> >>
> >> Can the size really be an option? I don't see it useful and if one gave the wrong size it may break things.
> > It was added for consistency (otherwise we have to determine the size
> > by looking at the interface everywhere). Also, it is possible for the
> > size to be larger than the constant. For example, Apple Silicon uses
> > 16KiB page sizes and we may decide to force the device to be 16KiB
> > aligned (not sure if this is needed yet while we still track down why
> > the dual mapping was not working). In that case, we would need to
> > inform the OS of the true region size to prevent any overlap issues.
> > Both baseaddr and size should be provided only by the plug handler in
> > the virt machine, otherwise things may break even if we get rid of
> > size and have just an incorrect baseaddr.
> >
> >>
> >>
> >>


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

* Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device
  2023-07-14 17:39         ` Joelle van Dyne
@ 2023-07-14 17:43           ` Stefan Berger
  2023-07-14 17:46             ` Joelle van Dyne
  0 siblings, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 17:43 UTC (permalink / raw)
  To: Joelle van Dyne
  Cc: qemu-devel, Shannon Zhao, Michael S. Tsirkin, Igor Mammedov,
	Ani Sinha, Peter Maydell, Xiaojuan Yang, Song Gao, Stefan Berger,
	open list:ARM ACPI Subsystem



On 7/14/23 13:39, Joelle van Dyne wrote:
> On Fri, Jul 14, 2023 at 10:37 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>
>>
>>
>> On 7/14/23 13:29, Joelle van Dyne wrote:
>>> On Fri, Jul 14, 2023 at 9:19 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>>>
>>>>
>>>>
>>>>
>>>> I don't know whether we would want multiple devices. tpm_find() usage is certainly not prepared for multiple devices.
>>> Sorry, "multiple TPM interfaces" here does not mean "at the same
>>> time". Will clarify the description.
>>>
>>>>
>>>>
>>>> Good for the consolidation.
>>>>
>>>>
>>>> Does moving the TIS to a different address help on aarch64?
>>> That was the first thing we tried and no it doesn't help.
>>
>> I would remove it if we don't have a known alternative address that makes it work. If we do, I think we should document it in tpm.rst.
> "It" is referring to tpm-tis-device? Note that it does work fine with Linux VMs.

yes, tpm_tis_sysbus and I know it works with Liunux but I see this discussion here around Win 11 on aarch64. Why do we need to user another address than the standard address if for Win 11 on aarch64 it doesn't get it to work.

> 
>>
>>
>>>>
>>>> Can the size really be an option? I don't see it useful and if one gave the wrong size it may break things.
>>> It was added for consistency (otherwise we have to determine the size
>>> by looking at the interface everywhere). Also, it is possible for the
>>> size to be larger than the constant. For example, Apple Silicon uses
>>> 16KiB page sizes and we may decide to force the device to be 16KiB
>>> aligned (not sure if this is needed yet while we still track down why
>>> the dual mapping was not working). In that case, we would need to
>>> inform the OS of the true region size to prevent any overlap issues.
>>> Both baseaddr and size should be provided only by the plug handler in
>>> the virt machine, otherwise things may break even if we get rid of
>>> size and have just an incorrect baseaddr.
>>>
>>>>
>>>>
>>>>


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

* Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device
  2023-07-14 17:43           ` Stefan Berger
@ 2023-07-14 17:46             ` Joelle van Dyne
  2023-07-14 18:01               ` Stefan Berger
  0 siblings, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14 17:46 UTC (permalink / raw)
  To: Stefan Berger
  Cc: Joelle van Dyne, qemu-devel, Shannon Zhao, Michael S. Tsirkin,
	Igor Mammedov, Ani Sinha, Peter Maydell, Xiaojuan Yang, Song Gao,
	Stefan Berger, open list:ARM ACPI Subsystem

On Fri, Jul 14, 2023 at 10:43 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>
>
>
> On 7/14/23 13:39, Joelle van Dyne wrote:
> > On Fri, Jul 14, 2023 at 10:37 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
> >>
> >>
> >>
> >> On 7/14/23 13:29, Joelle van Dyne wrote:
> >>> On Fri, Jul 14, 2023 at 9:19 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> I don't know whether we would want multiple devices. tpm_find() usage is certainly not prepared for multiple devices.
> >>> Sorry, "multiple TPM interfaces" here does not mean "at the same
> >>> time". Will clarify the description.
> >>>
> >>>>
> >>>>
> >>>> Good for the consolidation.
> >>>>
> >>>>
> >>>> Does moving the TIS to a different address help on aarch64?
> >>> That was the first thing we tried and no it doesn't help.
> >>
> >> I would remove it if we don't have a known alternative address that makes it work. If we do, I think we should document it in tpm.rst.
> > "It" is referring to tpm-tis-device? Note that it does work fine with Linux VMs.
>
> yes, tpm_tis_sysbus and I know it works with Liunux but I see this discussion here around Win 11 on aarch64. Why do we need to user another address than the standard address if for Win 11 on aarch64 it doesn't get it to work.
The standard address won't work for Linux either.

TPM TIS on standard address on ARM64 Virt machines = collision with
DRAM, will not instantiate
TPM TIS on SysBus with dynamically allocated address = works on Linux,
cannot start on Windows

>
> >
> >>
> >>
> >>>>
> >>>> Can the size really be an option? I don't see it useful and if one gave the wrong size it may break things.
> >>> It was added for consistency (otherwise we have to determine the size
> >>> by looking at the interface everywhere). Also, it is possible for the
> >>> size to be larger than the constant. For example, Apple Silicon uses
> >>> 16KiB page sizes and we may decide to force the device to be 16KiB
> >>> aligned (not sure if this is needed yet while we still track down why
> >>> the dual mapping was not working). In that case, we would need to
> >>> inform the OS of the true region size to prevent any overlap issues.
> >>> Both baseaddr and size should be provided only by the plug handler in
> >>> the virt machine, otherwise things may break even if we get rid of
> >>> size and have just an incorrect baseaddr.
> >>>
> >>>>
> >>>>
> >>>>


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

* Re: [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device
  2023-07-14 17:20     ` Joelle van Dyne
@ 2023-07-14 17:52       ` Stefan Berger
  0 siblings, 0 replies; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 17:52 UTC (permalink / raw)
  To: Joelle van Dyne
  Cc: qemu-devel, Stefan Berger, Michael S. Tsirkin, Igor Mammedov,
	Ani Sinha, Paolo Bonzini, Peter Maydell, Xiaojuan Yang, Song Gao,
	Palmer Dabbelt, Alistair Francis, Bin Meng, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, open list:ARM TCG CPUs,
	open list:RISC-V TCG CPUs



On 7/14/23 13:20, Joelle van Dyne wrote:
> On Fri, Jul 14, 2023 at 7:27 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>
>>
>>
>> On 7/14/23 03:09, Joelle van Dyne wrote:
>>> This SysBus variant of the CRB interface supports dynamically locating
>>> the MMIO interface so that Virt machines can use it. This interface
>>> is currently the only one supported by QEMU that works on Windows 11
>>> ARM64. We largely follow the TPM TIS SysBus device as a template.
>>>
>>> To try out this device with Windows 11 before OVMF is updated, you
>>> will need to modify `sysbud-fdt.c` and change the added line from:
>>>
>>> ```c
>>>       TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
>>> ```
>>>
>>> to
>>>
>>> ```c
>>>       TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
>>> ```
>>>
>>> This change was not included because it can confuse Linux (although
>>> from testing, it seems like Linux is able to properly ignore the
>>> device from the TPM TIS driver and recognize it from the ACPI device
>>> in the TPM CRB driver). A proper fix would require OVMF to recognize
>>> the ACPI device and not depend on the FDT node for recognizing TPM.
>>>
>>> The command line to try out this device with SWTPM is:
>>>
>>> ```
>>> $ qemu-system-aarch64 \
>>>       -chardev socket,id=chrtpm0,path=tpm.sock \
>>>       -tpmdev emulator,id=tpm0,chardev=chrtpm0 \
>>>       -device tpm-crb-device,tpmdev=tpm0
>>> ```
>>>
>>> along with SWTPM:
>>>
>>> ```
>>> $ swtpm \
>>>       --ctrl type=unixio,path=tpm.sock,terminate \
>>>       --tpmstate backend-uri=file://tpm.data \
>>>       --tpm2
>>> ```
>>>
>>> Signed-off-by: Joelle van Dyne <j@getutm.app>
>>> ---
>>>    docs/specs/tpm.rst          |   1 +
>>>    include/hw/acpi/aml-build.h |   1 +
>>>    include/sysemu/tpm.h        |   3 +
>>>    hw/acpi/aml-build.c         |   7 +-
>>>    hw/arm/virt.c               |   1 +
>>>    hw/core/sysbus-fdt.c        |   1 +
>>>    hw/loongarch/virt.c         |   1 +
>>>    hw/riscv/virt.c             |   1 +
>>>    hw/tpm/tpm_crb_sysbus.c     | 170 ++++++++++++++++++++++++++++++++++++
>>>    hw/arm/Kconfig              |   1 +
>>>    hw/riscv/Kconfig            |   1 +
>>>    hw/tpm/Kconfig              |   5 ++
>>>    hw/tpm/meson.build          |   2 +
>>>    13 files changed, 194 insertions(+), 1 deletion(-)
>>>    create mode 100644 hw/tpm/tpm_crb_sysbus.c
>>>
>>> diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
>>> index 2bc29c9804..95aeb49220 100644
>>> --- a/docs/specs/tpm.rst
>>> +++ b/docs/specs/tpm.rst
>>> @@ -46,6 +46,7 @@ operating system.
>>>    QEMU files related to TPM CRB interface:
>>>     - ``hw/tpm/tpm_crb.c``
>>>     - ``hw/tpm/tpm_crb_common.c``
>>> + - ``hw/tpm/tpm_crb_sysbus.c``
>>>
>>
>> If you added the command line to use for Windows guests to this document
>> I think this would be helpful. And also mention that this must be used for Windows
>> since the other ones don't work.
>>
>>
>>>    SPAPR interface
>>>    ---------------
>>> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
>>> index d1fb08514b..9660e16148 100644
>>> --- a/include/hw/acpi/aml-build.h
>>> +++ b/include/hw/acpi/aml-build.h
>>> @@ -3,6 +3,7 @@
>>>
>>>    #include "hw/acpi/acpi-defs.h"
>>>    #include "hw/acpi/bios-linker-loader.h"
>>> +#include "exec/hwaddr.h"
>>>
>>>    #define ACPI_BUILD_APPNAME6 "BOCHS "
>>>    #define ACPI_BUILD_APPNAME8 "BXPC    "
>>> diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
>>> index 66e3b45f30..f79c8f3575 100644
>>> --- a/include/sysemu/tpm.h
>>> +++ b/include/sysemu/tpm.h
>>> @@ -47,6 +47,7 @@ struct TPMIfClass {
>>>    #define TYPE_TPM_TIS_ISA            "tpm-tis"
>>>    #define TYPE_TPM_TIS_SYSBUS         "tpm-tis-device"
>>>    #define TYPE_TPM_CRB                "tpm-crb"
>>> +#define TYPE_TPM_CRB_SYSBUS         "tpm-crb-device"
>>>    #define TYPE_TPM_SPAPR              "tpm-spapr"
>>>    #define TYPE_TPM_TIS_I2C            "tpm-tis-i2c"
>>>
>>> @@ -56,6 +57,8 @@ struct TPMIfClass {
>>>        object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
>>>    #define TPM_IS_CRB(chr)                             \
>>>        object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
>>> +#define TPM_IS_CRB_SYSBUS(chr)                      \
>>> +    object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
>>>    #define TPM_IS_SPAPR(chr)                           \
>>>        object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
>>>    #define TPM_IS_TIS_I2C(chr)                      \
>>> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
>>> index ea331a20d1..f809137fc9 100644
>>> --- a/hw/acpi/aml-build.c
>>> +++ b/hw/acpi/aml-build.c
>>> @@ -31,6 +31,7 @@
>>>    #include "hw/pci/pci_bus.h"
>>>    #include "hw/pci/pci_bridge.h"
>>>    #include "qemu/cutils.h"
>>> +#include "qom/object.h"
>>>
>>>    static GArray *build_alloc_array(void)
>>>    {
>>> @@ -2218,7 +2219,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
>>>    {
>>>        uint8_t start_method_params[12] = {};
>>>        unsigned log_addr_offset;
>>> -    uint64_t control_area_start_address;
>>> +    uint64_t baseaddr, control_area_start_address;
>>>        TPMIf *tpmif = tpm_find();
>>>        uint32_t start_method;
>>>        AcpiTable table = { .sig = "TPM2", .rev = 4,
>>> @@ -2236,6 +2237,10 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
>>>        } else if (TPM_IS_CRB(tpmif)) {
>>>            control_area_start_address = TPM_CRB_ADDR_CTRL;
>>>            start_method = TPM2_START_METHOD_CRB;
>>> +    } else if (TPM_IS_CRB_SYSBUS(tpmif)) {
>>> +        baseaddr = object_property_get_uint(OBJECT(tpmif), "baseaddr", NULL);
>>> +        control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
>>> +        start_method = TPM2_START_METHOD_CRB;
>>>        } else {
>>>            g_assert_not_reached();
>>>        }
>>> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
>>> index 432148ef47..88e8b16103 100644
>>> --- a/hw/arm/virt.c
>>> +++ b/hw/arm/virt.c
>>> @@ -2977,6 +2977,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
>>>        machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
>>>    #ifdef CONFIG_TPM
>>>        machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
>>> +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
>>>    #endif
>>>        mc->block_default_type = IF_VIRTIO;
>>>        mc->no_cdrom = 1;
>>> diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
>>> index eebcd28f9a..9c783f88eb 100644
>>> --- a/hw/core/sysbus-fdt.c
>>> +++ b/hw/core/sysbus-fdt.c
>>> @@ -493,6 +493,7 @@ static const BindingEntry bindings[] = {
>>>    #endif
>>>    #ifdef CONFIG_TPM
>>>        TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node),
>>> +    TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
>>>    #endif
>>>        TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
>>>        TYPE_BINDING("", NULL), /* last element */
>>> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
>>> index 9c536c52bc..eb59fb04ee 100644
>>> --- a/hw/loongarch/virt.c
>>> +++ b/hw/loongarch/virt.c
>>> @@ -1194,6 +1194,7 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
>>>        machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>>>    #ifdef CONFIG_TPM
>>>        machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
>>> +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
>>>    #endif
>>>    }
>>>
>>> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
>>> index d90286dc46..5d639a870a 100644
>>> --- a/hw/riscv/virt.c
>>> +++ b/hw/riscv/virt.c
>>> @@ -1681,6 +1681,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
>>>        machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>>>    #ifdef CONFIG_TPM
>>>        machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
>>> +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
>>>    #endif
>>>
>>>        if (tcg_enabled()) {
>>> diff --git a/hw/tpm/tpm_crb_sysbus.c b/hw/tpm/tpm_crb_sysbus.c
>>> new file mode 100644
>>> index 0000000000..66be57a532
>>> --- /dev/null
>>> +++ b/hw/tpm/tpm_crb_sysbus.c
>>> @@ -0,0 +1,170 @@
>>> +/*
>>> + * tpm_crb_sysbus.c - QEMU's TPM CRB interface emulator
>>> + *
>>> + * Copyright (c) 2018 Red Hat, Inc.
>>> + *
>>> + * Authors:
>>> + *   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.
>>> + *
>>> + * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
>>> + * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
>>> + * Family “2.0” Level 00 Revision 01.03 v22
>>> + */
>>> +
>>> +#include "qemu/osdep.h"
>>> +#include "hw/acpi/acpi_aml_interface.h"
>>> +#include "hw/acpi/tpm.h"
>>> +#include "hw/qdev-properties.h"
>>> +#include "migration/vmstate.h"
>>> +#include "tpm_prop.h"
>>> +#include "hw/pci/pci_ids.h"
>>> +#include "hw/sysbus.h"
>>> +#include "qapi/visitor.h"
>>> +#include "qom/object.h"
>>> +#include "sysemu/tpm_util.h"
>>> +#include "trace.h"
>>> +#include "tpm_crb.h"
>>> +
>>> +struct TPMCRBStateSysBus {
>>> +    /*< private >*/
>>> +    SysBusDevice parent_obj;
>>> +
>>> +    /*< public >*/
>>> +    TPMCRBState state;
>>> +    uint64_t baseaddr;
>>> +    uint64_t size;
>>> +};
>>> +
>>> +OBJECT_DECLARE_SIMPLE_TYPE(TPMCRBStateSysBus, TPM_CRB_SYSBUS)
>>> +
>>> +static void tpm_crb_sysbus_request_completed(TPMIf *ti, int ret)
>>> +{
>>> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
>>> +
>>> +    return tpm_crb_request_completed(&s->state, ret);
>>> +}
>>> +
>>> +static enum TPMVersion tpm_crb_sysbus_get_tpm_version(TPMIf *ti)
>>> +{
>>> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
>>> +
>>> +    return tpm_crb_get_version(&s->state);
>>> +}
>>> +
>>> +static int tpm_crb_sysbus_pre_save(void *opaque)
>>> +{
>>> +    TPMCRBStateSysBus *s = opaque;
>>> +
>>> +    return tpm_crb_pre_save(&s->state);
>>> +}
>>> +
>>> +static const VMStateDescription vmstate_tpm_crb_sysbus = {
>>> +    .name = "tpm-crb-sysbus",
>>> +    .pre_save = tpm_crb_sysbus_pre_save,
>>> +    .fields = (VMStateField[]) {
>>> +        VMSTATE_END_OF_LIST(),
>>> +    }
>>> +};
>>> +
>>> +static Property tpm_crb_sysbus_properties[] = {
>>> +    DEFINE_PROP_TPMBE("tpmdev", TPMCRBStateSysBus, state.tpmbe),
>>> +    DEFINE_PROP_UINT64("baseaddr", TPMCRBStateSysBus,
>>> +                       baseaddr, TPM_CRB_ADDR_BASE),
>>> +    DEFINE_PROP_UINT64("size", TPMCRBStateSysBus, size, TPM_CRB_ADDR_SIZE),
>>> +    DEFINE_PROP_END_OF_LIST(),
>>> +};
>>> +
>>> +static void tpm_crb_sysbus_initfn(Object *obj)
>>> +{
>>> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(obj);
>>> +
>>> +    tpm_crb_init_memory(obj, &s->state, NULL);
>>> +
>>> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->state.mmio);
>>> +}
>>> +
>>> +static void tpm_crb_sysbus_reset(DeviceState *dev)
>>> +{
>>> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
>>> +
>>> +    return tpm_crb_reset(&s->state, s->baseaddr);
>>> +}
>>> +
>>> +static void tpm_crb_sysbus_realizefn(DeviceState *dev, Error **errp)
>>> +{
>>> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
>>> +
>>> +    if (!tpm_find()) {
>>> +        error_setg(errp, "at most one TPM device is permitted");
>>> +        return;
>>> +    }
>>> +
>>> +    if (!s->state.tpmbe) {
>>> +        error_setg(errp, "'tpmdev' property is required");
>>> +        return;
>>> +    }
>>> +
>>> +    if (tpm_crb_sysbus_get_tpm_version(TPM_IF(s)) != TPM_VERSION_2_0) {
>>> +        error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
>>> +        return;
>>> +    }
>>> +}
>>> +
>>> +static void build_tpm_crb_sysbus_aml(AcpiDevAmlIf *adev, Aml *scope)
>>> +{
>>> +    Aml *dev, *crs;
>>> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(adev);
>>> +    TPMIf *ti = TPM_IF(s);
>>
>> ../hw/tpm/tpm_crb_sysbus.c: In function 'build_tpm_crb_sysbus_aml':
>> ../hw/tpm/tpm_crb_sysbus.c:120:12: error: unused variable 'ti' [-Werror=unused-variable]
>>     120 |     TPMIf *ti = TPM_IF(s);
>>         |            ^~
>>
>>
>> Rest LGTM.
>>
>>> +
>>> +    dev = aml_device("TPM");
>>> +    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
>>> +    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
>>> +    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
>>> +    aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
>>> +    crs = aml_resource_template();
>>> +    aml_append(crs, aml_memory32_fixed(s->baseaddr, s->size,
>>> +                                      AML_READ_WRITE));
>>> +    aml_append(dev, aml_name_decl("_CRS", crs));
>>> +    aml_append(scope, dev);
>>> +}
>>> +
>>> +static void tpm_crb_sysbus_class_init(ObjectClass *klass, void *data)
>>> +{
>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>> +    TPMIfClass *tc = TPM_IF_CLASS(klass);
>>> +    AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
>>> +
>>> +    device_class_set_props(dc, tpm_crb_sysbus_properties);
>>> +    dc->vmsd  = &vmstate_tpm_crb_sysbus;
>>> +    tc->model = TPM_MODEL_TPM_CRB;
>>> +    dc->realize = tpm_crb_sysbus_realizefn;
>>> +    dc->user_creatable = true;
>>> +    dc->reset = tpm_crb_sysbus_reset;
>>> +    tc->request_completed = tpm_crb_sysbus_request_completed;
>>> +    tc->get_version = tpm_crb_sysbus_get_tpm_version;
>>> +    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>>> +    adevc->build_dev_aml = build_tpm_crb_sysbus_aml;
>>> +}
>>> +
>>> +static const TypeInfo tpm_crb_sysbus_info = {
>>> +    .name = TYPE_TPM_CRB_SYSBUS,
>>> +    .parent = TYPE_SYS_BUS_DEVICE,
>>> +    .instance_size = sizeof(TPMCRBStateSysBus),
>>> +    .instance_init = tpm_crb_sysbus_initfn,
>>> +    .class_init  = tpm_crb_sysbus_class_init,
>>> +    .interfaces = (InterfaceInfo[]) {
>>> +        { TYPE_TPM_IF },
>>> +        { TYPE_ACPI_DEV_AML_IF },
>>> +        { }
>>> +    }
>>> +};
>>> +
>>> +static void tpm_crb_sysbus_register(void)
>>> +{
>>> +    type_register_static(&tpm_crb_sysbus_info);
>>> +}
>>> +
>>> +type_init(tpm_crb_sysbus_register)
>>> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
>>> index 7e68348440..efe1beaa7b 100644
>>> --- a/hw/arm/Kconfig
>>> +++ b/hw/arm/Kconfig
>>> @@ -5,6 +5,7 @@ config ARM_VIRT
>>>        imply VFIO_AMD_XGBE
>>>        imply VFIO_PLATFORM
>>>        imply VFIO_XGMAC
>>> +    imply TPM_CRB_SYSBUS
>>>        imply TPM_TIS_SYSBUS
>>>        imply TPM_TIS_I2C
>>>        imply NVDIMM
>>> diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
>>> index b6a5eb4452..d824cb58f9 100644
>>> --- a/hw/riscv/Kconfig
>>> +++ b/hw/riscv/Kconfig
>>> @@ -29,6 +29,7 @@ config RISCV_VIRT
>>>        imply PCI_DEVICES
>>>        imply VIRTIO_VGA
>>>        imply TEST_DEVICES
>>> +    imply TPM_CRB_SYSBUS
>>>        imply TPM_TIS_SYSBUS
>>>        select RISCV_NUMA
>>>        select GOLDFISH_RTC
>>> diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
>>> index 1fd73fe617..3f294a20ba 100644
>>> --- a/hw/tpm/Kconfig
>>> +++ b/hw/tpm/Kconfig
>>> @@ -25,6 +25,11 @@ config TPM_CRB
>>>        depends on TPM && ISA_BUS
>>>        select TPM_BACKEND
>>>
>>> +config TPM_CRB_SYSBUS
>>> +    bool
>>> +    depends on TPM
>>> +    select TPM_BACKEND
>>> +
>>>    config TPM_SPAPR
>>>        bool
>>>        default y
>>> diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build
>>> index cb8204d5bc..d96de92c16 100644
>>> --- a/hw/tpm/meson.build
>>> +++ b/hw/tpm/meson.build
>>> @@ -4,6 +4,8 @@ system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: files('tpm_tis_sysbus.c'))
>>>    system_ss.add(when: 'CONFIG_TPM_TIS_I2C', if_true: files('tpm_tis_i2c.c'))
>>>    system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
>>>    system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb_common.c'))
>>> +system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_sysbus.c'))
>>> +system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_common.c'))
>>>    system_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_ppi.c'))
>>>    system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_ppi.c'))
>>>
> 
> New commit description looks good?
> 
> "This SysBus variant of the CRB interface supports dynamically
> locating the MMIO interface so that Virt machines can use it. This
> interface is currently the only one supported by QEMU that works on
> Windows 11 ARM64 as 'tpm-tis-device' does not work with current
> Windows drivers. We largely follow that device as a template."

Sounds good.
> 
> Also, I'm not sure what else you need for the Windows command. Do you
> mean the command to initiate a Windows install? Because I feel like

No. docs/spec/tpm.rst has this here at the moment for aarch64:

In case an Arm virt machine is emulated, use the following command line:

.. code-block:: console

   qemu-system-aarch64 -machine virt,gic-version=3,accel=kvm \
     -cpu host -m 4G \
     -nographic -no-acpi \
     -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
     -tpmdev emulator,id=tpm0,chardev=chrtpm \
     -device tpm-tis-device,tpmdev=tpm0 \
     -device virtio-blk-pci,drive=drv0 \
     -drive format=qcow2,file=hda.qcow2,if=none,id=drv0 \
     -drive if=pflash,format=raw,file=flash0.img,readonly=on \
     -drive if=pflash,format=raw,file=flash1.img


Above his I would put:

In case an Arm virt machine is emulated to run Windows or Linux, use the following command line:

.. code-block:: console

   qemu-system-aarch64 -machine virt,gic-version=3,accel=kvm \
     -cpu host -m 4G \
     -nographic -no-acpi \
     -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
     -tpmdev emulator,id=tpm0,chardev=chrtpm \
     -device tpm-crb-device,tpmdev=tpm0 \
     ...

and adjust the text below to:

In case an Arm virt machine is emulated to run Linux, you may also use the following command line:

.. code-block:: console

   qemu-system-aarch64 -machine virt,gic-version=3,accel=kvm \
     -cpu host -m 4G \
     -nographic -no-acpi \
     -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
     -tpmdev emulator,id=tpm0,chardev=chrtpm \
     -device tpm-tis-device,tpmdev=tpm0 \
     -device virtio-blk-pci,drive=drv0 \
     -drive format=qcow2,file=hda.qcow2,if=none,id=drv0 \
     -drive if=pflash,format=raw,file=flash0.img,readonly=on \
     -drive if=pflash,format=raw,file=flash1.img

> there would be a lot of text there that would be off-topic from the
> commit. Additionally, do we also need to include steps on creating the
> QCOW boot device, setting up the UEFI secure boot, and so on? Because
> there's quite a few steps involved to get a working Windows boot and
> I'm sure it's documented in length in various blog posts.


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

* Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device
  2023-07-14 17:46             ` Joelle van Dyne
@ 2023-07-14 18:01               ` Stefan Berger
  2023-07-14 18:15                 ` Joelle van Dyne
  0 siblings, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 18:01 UTC (permalink / raw)
  To: Joelle van Dyne, Eric Auger
  Cc: qemu-devel, Shannon Zhao, Michael S. Tsirkin, Igor Mammedov,
	Ani Sinha, Peter Maydell, Xiaojuan Yang, Song Gao, Stefan Berger,
	open list:ARM ACPI Subsystem



On 7/14/23 13:46, Joelle van Dyne wrote:
> On Fri, Jul 14, 2023 at 10:43 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>
>>
>>
>> On 7/14/23 13:39, Joelle van Dyne wrote:
>>> On Fri, Jul 14, 2023 at 10:37 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>>>
>>>>
>>>>
>>>> On 7/14/23 13:29, Joelle van Dyne wrote:
>>>>> On Fri, Jul 14, 2023 at 9:19 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> I don't know whether we would want multiple devices. tpm_find() usage is certainly not prepared for multiple devices.
>>>>> Sorry, "multiple TPM interfaces" here does not mean "at the same
>>>>> time". Will clarify the description.
>>>>>
>>>>>>
>>>>>>
>>>>>> Good for the consolidation.
>>>>>>
>>>>>>
>>>>>> Does moving the TIS to a different address help on aarch64?
>>>>> That was the first thing we tried and no it doesn't help.
>>>>
>>>> I would remove it if we don't have a known alternative address that makes it work. If we do, I think we should document it in tpm.rst.
>>> "It" is referring to tpm-tis-device? Note that it does work fine with Linux VMs.
>>
>> yes, tpm_tis_sysbus and I know it works with Liunux but I see this discussion here around Win 11 on aarch64. Why do we need to user another address than the standard address if for Win 11 on aarch64 it doesn't get it to work.
> The standard address won't work for Linux either.
> 
> TPM TIS on standard address on ARM64 Virt machines = collision with
> DRAM, will not instantiate

I thought that this was working with Linux on the aarch64 virt board as contributed by Eric Auger.

https://github.com/qemu/qemu/commit/fcaa204194e15ba24cd53087dd616aabbc29e64f

Also I had tested it to some extent: https://github.com/stefanberger/swtpm/issues/493#issuecomment-885221109



> TPM TIS on SysBus with dynamically allocated address = works on Linux,
> cannot start on Windows
> 
>>
>>>
>>>>
>>>>
>>>>>>
>>>>>> Can the size really be an option? I don't see it useful and if one gave the wrong size it may break things.
>>>>> It was added for consistency (otherwise we have to determine the size
>>>>> by looking at the interface everywhere). Also, it is possible for the
>>>>> size to be larger than the constant. For example, Apple Silicon uses
>>>>> 16KiB page sizes and we may decide to force the device to be 16KiB
>>>>> aligned (not sure if this is needed yet while we still track down why
>>>>> the dual mapping was not working). In that case, we would need to
>>>>> inform the OS of the true region size to prevent any overlap issues.
>>>>> Both baseaddr and size should be provided only by the plug handler in
>>>>> the virt machine, otherwise things may break even if we get rid of
>>>>> size and have just an incorrect baseaddr.
>>>>>
>>>>>>
>>>>>>
>>>>>>


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

* Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device
  2023-07-14 18:01               ` Stefan Berger
@ 2023-07-14 18:15                 ` Joelle van Dyne
  0 siblings, 0 replies; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14 18:15 UTC (permalink / raw)
  To: Stefan Berger
  Cc: Joelle van Dyne, Eric Auger, qemu-devel, Shannon Zhao,
	Michael S. Tsirkin, Igor Mammedov, Ani Sinha, Peter Maydell,
	Xiaojuan Yang, Song Gao, Stefan Berger,
	open list:ARM ACPI Subsystem

On Fri, Jul 14, 2023 at 11:01 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>
>
>
> On 7/14/23 13:46, Joelle van Dyne wrote:
> > On Fri, Jul 14, 2023 at 10:43 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
> >>
> >>
> >>
> >> On 7/14/23 13:39, Joelle van Dyne wrote:
> >>> On Fri, Jul 14, 2023 at 10:37 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 7/14/23 13:29, Joelle van Dyne wrote:
> >>>>> On Fri, Jul 14, 2023 at 9:19 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>> I don't know whether we would want multiple devices. tpm_find() usage is certainly not prepared for multiple devices.
> >>>>> Sorry, "multiple TPM interfaces" here does not mean "at the same
> >>>>> time". Will clarify the description.
> >>>>>
> >>>>>>
> >>>>>>
> >>>>>> Good for the consolidation.
> >>>>>>
> >>>>>>
> >>>>>> Does moving the TIS to a different address help on aarch64?
> >>>>> That was the first thing we tried and no it doesn't help.
> >>>>
> >>>> I would remove it if we don't have a known alternative address that makes it work. If we do, I think we should document it in tpm.rst.
> >>> "It" is referring to tpm-tis-device? Note that it does work fine with Linux VMs.
> >>
> >> yes, tpm_tis_sysbus and I know it works with Liunux but I see this discussion here around Win 11 on aarch64. Why do we need to user another address than the standard address if for Win 11 on aarch64 it doesn't get it to work.
> > The standard address won't work for Linux either.
> >
> > TPM TIS on standard address on ARM64 Virt machines = collision with
> > DRAM, will not instantiate
>
> I thought that this was working with Linux on the aarch64 virt board as contributed by Eric Auger.
>
> https://github.com/qemu/qemu/commit/fcaa204194e15ba24cd53087dd616aabbc29e64f
>
> Also I had tested it to some extent: https://github.com/stefanberger/swtpm/issues/493#issuecomment-885221109
I think I know where the confusion is. Both your examples use
"tpm-tis-device" which indeed uses the SysBus and gets a dynamic
address. In this patch, the removed code that generates the AML gets
this address by poking into the SysBus device, getting its base, then
adding the offset from the TIS device to it. In the change, we move
that code to get the address to earlier in the Virt init sequence
(before the machine is realized) in order to tell the TIS device what
its own base address is. Then, during the AML generation phase, we can
just tell the TIS device to "generate your own AML" which is now
possible because it knows its own base address. This is also how the
TIS ISA bus device does it but that is simpler because it can just use
the default address.

Separately, there is a `build_tpm2` table function which also needs
the device base address but only for CRB devices (TIS has the field
set to 0) so it's irrelevant here.

>
>
>
> > TPM TIS on SysBus with dynamically allocated address = works on Linux,
> > cannot start on Windows
> >
> >>
> >>>
> >>>>
> >>>>
> >>>>>>
> >>>>>> Can the size really be an option? I don't see it useful and if one gave the wrong size it may break things.
> >>>>> It was added for consistency (otherwise we have to determine the size
> >>>>> by looking at the interface everywhere). Also, it is possible for the
> >>>>> size to be larger than the constant. For example, Apple Silicon uses
> >>>>> 16KiB page sizes and we may decide to force the device to be 16KiB
> >>>>> aligned (not sure if this is needed yet while we still track down why
> >>>>> the dual mapping was not working). In that case, we would need to
> >>>>> inform the OS of the true region size to prevent any overlap issues.
> >>>>> Both baseaddr and size should be provided only by the plug handler in
> >>>>> the virt machine, otherwise things may break even if we get rid of
> >>>>> size and have just an incorrect baseaddr.
> >>>>>
> >>>>>>
> >>>>>>
> >>>>>>


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

* Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate
  2023-07-14 17:04       ` Joelle van Dyne
@ 2023-07-14 18:22         ` Stefan Berger
  2023-07-14 18:41           ` Stefan Berger
  0 siblings, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 18:22 UTC (permalink / raw)
  To: Joelle van Dyne; +Cc: qemu-devel, Stefan Berger

On 7/14/23 13:04, Joelle van Dyne wrote:
> On Fri, Jul 14, 2023 at 7:51 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>
>>
>>
>> On 7/14/23 10:05, Stefan Berger wrote:
>>>
>>>
>>> On 7/14/23 03:09, Joelle van Dyne wrote:
>>>> When we moved to a single mapping and modified TPM CRB's VMState, it
>>>> broke restoring of VMs that were saved on an older version. This
>>>> change allows those VMs to gracefully migrate to the new memory
>>>> mapping.
>>>
>>> Thanks. This has to be in 4/11 though.
>>>
>>
>> After applying the whole series and trying to resume state taken with current git
>> master I cannot restore it but it leads to this error here. I would just leave it
>> completely untouched in 4/11.
>>
>> 2023-07-14T14:46:34.547550Z qemu-system-x86_64: Unknown ramblock "tpm-crb-cmd", cannot accept migration
>> 2023-07-14T14:46:34.547799Z qemu-system-x86_64: error while loading state for instance 0x0 of device 'ram'
>> 2023-07-14T14:46:34.547835Z qemu-system-x86_64: load of migration failed: Invalid argument
>>
>>      Stefan
> 
> To be clear, you are asking to back out of 4/11? That patch changes
> how the registers are mapped so it's impossible to support the old
> style register mapping. This patch attempts to fix that with a

Why can we not keep the old style register mapping as 'secondary mapping'?

The expectation is that old VM state / CRB state can be used by the new QEMU and
also new QEMU CRB state should be readable by old QEMU. So in a way the old 'secondary'
mmaping has to hold the true value of the registers so that the latter works.


> migration path but I realized that I missed the "tpm-crb-cmd"
> ramblock. It can be added to v3 for this patch. Similar to the logic
> to have `legacy_regs` we will add a `legacy_cmdmem` memory region that
> is not registered with the system bus but only exists to migrate the
> data. Would that work? Also open to better ideas on migrating legacy
> saved state.
> 
> If we back out of 4/11 (the split mapping), then the proposed way for
> working on Apple Silicon would not be available and we would have to
> go down the path of emulating AArch64 instruction in HVF backend (or
> decide not to support Apple Silicon).


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

* Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate
  2023-07-14 18:22         ` Stefan Berger
@ 2023-07-14 18:41           ` Stefan Berger
  2023-07-14 18:49             ` Joelle van Dyne
  0 siblings, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 18:41 UTC (permalink / raw)
  To: Joelle van Dyne; +Cc: qemu-devel, Stefan Berger



On 7/14/23 14:22, Stefan Berger wrote:
> On 7/14/23 13:04, Joelle van Dyne wrote:
>> On Fri, Jul 14, 2023 at 7:51 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>>
>>>
>>>
>>> On 7/14/23 10:05, Stefan Berger wrote:
>>>>
>>>>
>>>> On 7/14/23 03:09, Joelle van Dyne wrote:
>>>>> When we moved to a single mapping and modified TPM CRB's VMState, it
>>>>> broke restoring of VMs that were saved on an older version. This
>>>>> change allows those VMs to gracefully migrate to the new memory
>>>>> mapping.
>>>>
>>>> Thanks. This has to be in 4/11 though.
>>>>
>>>
>>> After applying the whole series and trying to resume state taken with current git
>>> master I cannot restore it but it leads to this error here. I would just leave it
>>> completely untouched in 4/11.
>>>
>>> 2023-07-14T14:46:34.547550Z qemu-system-x86_64: Unknown ramblock "tpm-crb-cmd", cannot accept migration
>>> 2023-07-14T14:46:34.547799Z qemu-system-x86_64: error while loading state for instance 0x0 of device 'ram'
>>> 2023-07-14T14:46:34.547835Z qemu-system-x86_64: load of migration failed: Invalid argument
>>>
>>>      Stefan
>>
>> To be clear, you are asking to back out of 4/11? That patch changes
>> how the registers are mapped so it's impossible to support the old
>> style register mapping. This patch attempts to fix that with a
> 
> Why can we not keep the old style register mapping as 'secondary mapping'?

I think the first goal should be for existing TPM CRB device not to change anything, they
keep their .read and .write behaivor as it.

If you need different .read behavior for the sysbus device due to AARCH64 then it may want to use its own MemoryRegionOps.

I am fairly sure that you could refactor the core of the existing tpm_crb_mmio_write() and have it work on s->regs and mmio regs.
The former would be used by existing code, the latter for CRB sysbus calling into this new function from a wrapper.

    Stefan


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

* Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate
  2023-07-14 18:41           ` Stefan Berger
@ 2023-07-14 18:49             ` Joelle van Dyne
  2023-07-14 19:12               ` Stefan Berger
  2023-07-17 14:33               ` Igor Mammedov
  0 siblings, 2 replies; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14 18:49 UTC (permalink / raw)
  To: Stefan Berger; +Cc: Joelle van Dyne, qemu-devel, Stefan Berger

On Fri, Jul 14, 2023 at 11:41 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>
>
>
> On 7/14/23 14:22, Stefan Berger wrote:
> > On 7/14/23 13:04, Joelle van Dyne wrote:
> >> On Fri, Jul 14, 2023 at 7:51 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
> >>>
> >>>
> >>>
> >>> On 7/14/23 10:05, Stefan Berger wrote:
> >>>>
> >>>>
> >>>> On 7/14/23 03:09, Joelle van Dyne wrote:
> >>>>> When we moved to a single mapping and modified TPM CRB's VMState, it
> >>>>> broke restoring of VMs that were saved on an older version. This
> >>>>> change allows those VMs to gracefully migrate to the new memory
> >>>>> mapping.
> >>>>
> >>>> Thanks. This has to be in 4/11 though.
> >>>>
> >>>
> >>> After applying the whole series and trying to resume state taken with current git
> >>> master I cannot restore it but it leads to this error here. I would just leave it
> >>> completely untouched in 4/11.
> >>>
> >>> 2023-07-14T14:46:34.547550Z qemu-system-x86_64: Unknown ramblock "tpm-crb-cmd", cannot accept migration
> >>> 2023-07-14T14:46:34.547799Z qemu-system-x86_64: error while loading state for instance 0x0 of device 'ram'
> >>> 2023-07-14T14:46:34.547835Z qemu-system-x86_64: load of migration failed: Invalid argument
> >>>
> >>>      Stefan
> >>
> >> To be clear, you are asking to back out of 4/11? That patch changes
> >> how the registers are mapped so it's impossible to support the old
> >> style register mapping. This patch attempts to fix that with a
> >
> > Why can we not keep the old style register mapping as 'secondary mapping'?
>
> I think the first goal should be for existing TPM CRB device not to change anything, they
> keep their .read and .write behaivor as it.
>
> If you need different .read behavior for the sysbus device due to AARCH64 then it may want to use its own MemoryRegionOps.
>
> I am fairly sure that you could refactor the core of the existing tpm_crb_mmio_write() and have it work on s->regs and mmio regs.
> The former would be used by existing code, the latter for CRB sysbus calling into this new function from a wrapper.
>
>     Stefan

I agree that new QEMU should be able to read old QEMU state but vice
versa is not always true. There's been many changes in the past that
incremented the vmstate's version_id to indicate that the state format
has changed. Also, we are not changing the .read behavior because in
the old code, the only field that gets a dynamic update is
tpmEstablished which we found is never changed. So effectively, .read
is just doing a memcpy of the `regs` state. This makes it possible to
map the page as memory while retaining the same behavior as before.
(We are changing the code but not the behavior).

The issue with Windows's buggy tpm.sys driver is that fundamentally it
cannot work with MemoryRegionOps. The way MMIO is implemented is that
a hole is left in the guest memory space so when the device registers
are accessed, the hypervisor traps it and sends it over to QEMU to
handle. QEMU looks up the address, sees its a valid MMIO mapping, and
calls into the MemoryRegionOps implementation. When tpm.sys does a LDP
instruction access to the hole, the information for QEMU to determine
if it's a valid access is not provided. Other hypervisors like Apple's
VZ.framework and VMware will read the guest PC, manually decode the
AArch64 instruction, determine the type of access, read the guest Rn
registers, does a TLB lookup to determine the physical address, then
emulate the MMIO. None of this capability currently exists in QEMU's
ARM64 backend. That's why we decided the easier path is to tell QEMU
that this mapping is RAM for read purposes and MMIO only for write
purposes (thankfully Windows does not do a STP or we'd be hosed).


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

* Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate
  2023-07-14 18:49             ` Joelle van Dyne
@ 2023-07-14 19:12               ` Stefan Berger
  2023-07-14 19:44                 ` Joelle van Dyne
  2023-07-17 14:40                 ` Peter Maydell
  2023-07-17 14:33               ` Igor Mammedov
  1 sibling, 2 replies; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 19:12 UTC (permalink / raw)
  To: Joelle van Dyne; +Cc: qemu-devel, Stefan Berger



On 7/14/23 14:49, Joelle van Dyne wrote:
> On Fri, Jul 14, 2023 at 11:41 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>
>>
>>
>> On 7/14/23 14:22, Stefan Berger wrote:
>>> On 7/14/23 13:04, Joelle van Dyne wrote:
>>>> On Fri, Jul 14, 2023 at 7:51 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>>>>
>>>>>
>>>>>
>>>>> On 7/14/23 10:05, Stefan Berger wrote:
>>>>>>
>>>>>>
>>>>>> On 7/14/23 03:09, Joelle van Dyne wrote:
>>>>>>> When we moved to a single mapping and modified TPM CRB's VMState, it
>>>>>>> broke restoring of VMs that were saved on an older version. This
>>>>>>> change allows those VMs to gracefully migrate to the new memory
>>>>>>> mapping.
>>>>>>
>>>>>> Thanks. This has to be in 4/11 though.
>>>>>>
>>>>>
>>>>> After applying the whole series and trying to resume state taken with current git
>>>>> master I cannot restore it but it leads to this error here. I would just leave it
>>>>> completely untouched in 4/11.
>>>>>
>>>>> 2023-07-14T14:46:34.547550Z qemu-system-x86_64: Unknown ramblock "tpm-crb-cmd", cannot accept migration
>>>>> 2023-07-14T14:46:34.547799Z qemu-system-x86_64: error while loading state for instance 0x0 of device 'ram'
>>>>> 2023-07-14T14:46:34.547835Z qemu-system-x86_64: load of migration failed: Invalid argument
>>>>>
>>>>>       Stefan
>>>>
>>>> To be clear, you are asking to back out of 4/11? That patch changes
>>>> how the registers are mapped so it's impossible to support the old
>>>> style register mapping. This patch attempts to fix that with a
>>>
>>> Why can we not keep the old style register mapping as 'secondary mapping'?
>>
>> I think the first goal should be for existing TPM CRB device not to change anything, they
>> keep their .read and .write behaivor as it.
>>
>> If you need different .read behavior for the sysbus device due to AARCH64 then it may want to use its own MemoryRegionOps.
>>
>> I am fairly sure that you could refactor the core of the existing tpm_crb_mmio_write() and have it work on s->regs and mmio regs.
>> The former would be used by existing code, the latter for CRB sysbus calling into this new function from a wrapper.
>>
>>      Stefan
> 
> I agree that new QEMU should be able to read old QEMU state but vice
> versa is not always true. There's been many changes in the past that
> incremented the vmstate's version_id to indicate that the state format
> has changed. Also, we are not changing the .read behavior because in

Unfortunately the CRB device is being used by x86 on some distros
and the expectation is that this existing device can also downgrade
to a previous version of QEMU I would say. I have read people migrating
from RHEL 9.x even to RHEL 8.x and the expectation is that this works.

Now you are introducing a new device and I think you can leave
the existing device with its s->regs alone and have the new device
with its mmio regs work a little different just to preserve the QEMU
downgrade for x86.

> the old code, the only field that gets a dynamic update is
> tpmEstablished which we found is never changed. So effectively, .read

Correct and that's why you don't need a .read in the new device.

> is just doing a memcpy of the `regs` state. This makes it possible to
> map the page as memory while retaining the same behavior as before.
> (We are changing the code but not the behavior).
> 
> The issue with Windows's buggy tpm.sys driver is that fundamentally it
> cannot work with MemoryRegionOps. The way MMIO is implemented is that

At least not with the .read part as it seems and you have to have the
.write part to be able to react to cmd transfers etc.

> a hole is left in the guest memory space so when the device registers
> are accessed, the hypervisor traps it and sends it over to QEMU to
> handle. QEMU looks up the address, sees its a valid MMIO mapping, and
> calls into the MemoryRegionOps implementation. When tpm.sys does a LDP
> instruction access to the hole, the information for QEMU to determine
> if it's a valid access is not provided. Other hypervisors like Apple's
> VZ.framework and VMware will read the guest PC, manually decode the
> AArch64 instruction, determine the type of access, read the guest Rn
> registers, does a TLB lookup to determine the physical address, then
> emulate the MMIO. None of this capability currently exists in QEMU's
> ARM64 backend. That's why we decided the easier path is to tell QEMU
> that this mapping is RAM for read purposes and MMIO only for write
> purposes (thankfully Windows does not do a STP or we'd be hosed).

Thanks, this confirms what I thought.

    Stefan


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

* Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate
  2023-07-14 19:12               ` Stefan Berger
@ 2023-07-14 19:44                 ` Joelle van Dyne
  2023-07-14 19:56                   ` Stefan Berger
  2023-07-17 14:40                 ` Peter Maydell
  1 sibling, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-07-14 19:44 UTC (permalink / raw)
  To: Stefan Berger; +Cc: Joelle van Dyne, qemu-devel, Stefan Berger

On Fri, Jul 14, 2023 at 12:12 PM Stefan Berger <stefanb@linux.ibm.com> wrote:
>
>
>
> On 7/14/23 14:49, Joelle van Dyne wrote:
> > On Fri, Jul 14, 2023 at 11:41 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
> >>
> >>
> >>
> >> On 7/14/23 14:22, Stefan Berger wrote:
> >>> On 7/14/23 13:04, Joelle van Dyne wrote:
> >>>> On Fri, Jul 14, 2023 at 7:51 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
> >>>>>
> >>>>>
> >>>>>
> >>>>> On 7/14/23 10:05, Stefan Berger wrote:
> >>>>>>
> >>>>>>
> >>>>>> On 7/14/23 03:09, Joelle van Dyne wrote:
> >>>>>>> When we moved to a single mapping and modified TPM CRB's VMState, it
> >>>>>>> broke restoring of VMs that were saved on an older version. This
> >>>>>>> change allows those VMs to gracefully migrate to the new memory
> >>>>>>> mapping.
> >>>>>>
> >>>>>> Thanks. This has to be in 4/11 though.
> >>>>>>
> >>>>>
> >>>>> After applying the whole series and trying to resume state taken with current git
> >>>>> master I cannot restore it but it leads to this error here. I would just leave it
> >>>>> completely untouched in 4/11.
> >>>>>
> >>>>> 2023-07-14T14:46:34.547550Z qemu-system-x86_64: Unknown ramblock "tpm-crb-cmd", cannot accept migration
> >>>>> 2023-07-14T14:46:34.547799Z qemu-system-x86_64: error while loading state for instance 0x0 of device 'ram'
> >>>>> 2023-07-14T14:46:34.547835Z qemu-system-x86_64: load of migration failed: Invalid argument
> >>>>>
> >>>>>       Stefan
> >>>>
> >>>> To be clear, you are asking to back out of 4/11? That patch changes
> >>>> how the registers are mapped so it's impossible to support the old
> >>>> style register mapping. This patch attempts to fix that with a
> >>>
> >>> Why can we not keep the old style register mapping as 'secondary mapping'?
> >>
> >> I think the first goal should be for existing TPM CRB device not to change anything, they
> >> keep their .read and .write behaivor as it.
> >>
> >> If you need different .read behavior for the sysbus device due to AARCH64 then it may want to use its own MemoryRegionOps.
> >>
> >> I am fairly sure that you could refactor the core of the existing tpm_crb_mmio_write() and have it work on s->regs and mmio regs.
> >> The former would be used by existing code, the latter for CRB sysbus calling into this new function from a wrapper.
> >>
> >>      Stefan
> >
> > I agree that new QEMU should be able to read old QEMU state but vice
> > versa is not always true. There's been many changes in the past that
> > incremented the vmstate's version_id to indicate that the state format
> > has changed. Also, we are not changing the .read behavior because in
>
> Unfortunately the CRB device is being used by x86 on some distros
> and the expectation is that this existing device can also downgrade
> to a previous version of QEMU I would say. I have read people migrating
> from RHEL 9.x even to RHEL 8.x and the expectation is that this works.
But would the migration even work due to other parts of QEMU? The only
way you can, say, migrate from QEMU 8.1.0 to 8.0.0 is if every single
VMstate has its version_id unchanged. Does QEMU provide that
guarantee? I'm fine with changing it but just want to make sure
expectations are set correctly. Have you tested a downgrade and found
that no other device impeded the process?

>
> Now you are introducing a new device and I think you can leave
> the existing device with its s->regs alone and have the new device
> with its mmio regs work a little different just to preserve the QEMU
> downgrade for x86.
>
> > the old code, the only field that gets a dynamic update is
> > tpmEstablished which we found is never changed. So effectively, .read
>
> Correct and that's why you don't need a .read in the new device.
>
> > is just doing a memcpy of the `regs` state. This makes it possible to
> > map the page as memory while retaining the same behavior as before.
> > (We are changing the code but not the behavior).
> >
> > The issue with Windows's buggy tpm.sys driver is that fundamentally it
> > cannot work with MemoryRegionOps. The way MMIO is implemented is that
>
> At least not with the .read part as it seems and you have to have the
> .write part to be able to react to cmd transfers etc.
>
> > a hole is left in the guest memory space so when the device registers
> > are accessed, the hypervisor traps it and sends it over to QEMU to
> > handle. QEMU looks up the address, sees its a valid MMIO mapping, and
> > calls into the MemoryRegionOps implementation. When tpm.sys does a LDP
> > instruction access to the hole, the information for QEMU to determine
> > if it's a valid access is not provided. Other hypervisors like Apple's
> > VZ.framework and VMware will read the guest PC, manually decode the
> > AArch64 instruction, determine the type of access, read the guest Rn
> > registers, does a TLB lookup to determine the physical address, then
> > emulate the MMIO. None of this capability currently exists in QEMU's
> > ARM64 backend. That's why we decided the easier path is to tell QEMU
> > that this mapping is RAM for read purposes and MMIO only for write
> > purposes (thankfully Windows does not do a STP or we'd be hosed).
>
> Thanks, this confirms what I thought.
>
>     Stefan


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

* Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate
  2023-07-14 19:44                 ` Joelle van Dyne
@ 2023-07-14 19:56                   ` Stefan Berger
  0 siblings, 0 replies; 52+ messages in thread
From: Stefan Berger @ 2023-07-14 19:56 UTC (permalink / raw)
  To: Joelle van Dyne; +Cc: qemu-devel, Stefan Berger



On 7/14/23 15:44, Joelle van Dyne wrote:
> On Fri, Jul 14, 2023 at 12:12 PM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>
>>
>>
>> On 7/14/23 14:49, Joelle van Dyne wrote:
>>> On Fri, Jul 14, 2023 at 11:41 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>>>
>>>>
>>>>
>>>> On 7/14/23 14:22, Stefan Berger wrote:
>>>>> On 7/14/23 13:04, Joelle van Dyne wrote:
>>>>>> On Fri, Jul 14, 2023 at 7:51 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On 7/14/23 10:05, Stefan Berger wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> On 7/14/23 03:09, Joelle van Dyne wrote:
>>>>>>>>> When we moved to a single mapping and modified TPM CRB's VMState, it
>>>>>>>>> broke restoring of VMs that were saved on an older version. This
>>>>>>>>> change allows those VMs to gracefully migrate to the new memory
>>>>>>>>> mapping.
>>>>>>>>
>>>>>>>> Thanks. This has to be in 4/11 though.
>>>>>>>>
>>>>>>>
>>>>>>> After applying the whole series and trying to resume state taken with current git
>>>>>>> master I cannot restore it but it leads to this error here. I would just leave it
>>>>>>> completely untouched in 4/11.
>>>>>>>
>>>>>>> 2023-07-14T14:46:34.547550Z qemu-system-x86_64: Unknown ramblock "tpm-crb-cmd", cannot accept migration
>>>>>>> 2023-07-14T14:46:34.547799Z qemu-system-x86_64: error while loading state for instance 0x0 of device 'ram'
>>>>>>> 2023-07-14T14:46:34.547835Z qemu-system-x86_64: load of migration failed: Invalid argument
>>>>>>>
>>>>>>>        Stefan
>>>>>>
>>>>>> To be clear, you are asking to back out of 4/11? That patch changes
>>>>>> how the registers are mapped so it's impossible to support the old
>>>>>> style register mapping. This patch attempts to fix that with a
>>>>>
>>>>> Why can we not keep the old style register mapping as 'secondary mapping'?
>>>>
>>>> I think the first goal should be for existing TPM CRB device not to change anything, they
>>>> keep their .read and .write behaivor as it.
>>>>
>>>> If you need different .read behavior for the sysbus device due to AARCH64 then it may want to use its own MemoryRegionOps.
>>>>
>>>> I am fairly sure that you could refactor the core of the existing tpm_crb_mmio_write() and have it work on s->regs and mmio regs.
>>>> The former would be used by existing code, the latter for CRB sysbus calling into this new function from a wrapper.
>>>>
>>>>       Stefan
>>>
>>> I agree that new QEMU should be able to read old QEMU state but vice
>>> versa is not always true. There's been many changes in the past that
>>> incremented the vmstate's version_id to indicate that the state format
>>> has changed. Also, we are not changing the .read behavior because in
>>
>> Unfortunately the CRB device is being used by x86 on some distros
>> and the expectation is that this existing device can also downgrade
>> to a previous version of QEMU I would say. I have read people migrating
>> from RHEL 9.x even to RHEL 8.x and the expectation is that this works.
> But would the migration even work due to other parts of QEMU? The only
> way you can, say, migrate from QEMU 8.1.0 to 8.0.0 is if every single
> VMstate has its version_id unchanged. Does QEMU provide that
> guarantee? I'm fine with changing it but just want to make sure
> expectations are set correctly. Have you tested a downgrade and found
> that no other device impeded the process?

No I have not done this. The best we can do is that CRB at least is not the
reason that is causing such a failure and since we are introducing a new
device it need not be the reason, either.

   Stefan


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

* Re: [PATCH v2 06/11] tpm_crb: move ACPI table building to device interface
  2023-07-14 17:21   ` Stefan Berger
@ 2023-07-17 13:42     ` Igor Mammedov
  2023-08-01  3:02       ` Joelle van Dyne
  0 siblings, 1 reply; 52+ messages in thread
From: Igor Mammedov @ 2023-07-17 13:42 UTC (permalink / raw)
  To: Stefan Berger
  Cc: Joelle van Dyne, qemu-devel, Michael S. Tsirkin, Ani Sinha,
	Paolo Bonzini, Richard Henderson, Eduardo Habkost,
	Marcel Apfelbaum, Stefan Berger

On Fri, 14 Jul 2023 13:21:33 -0400
Stefan Berger <stefanb@linux.ibm.com> wrote:

> On 7/14/23 03:09, Joelle van Dyne wrote:
> > This logic is similar to TPM TIS ISA device. Since TPM CRB can only
> > support TPM 2.0 backends, we check for this in realize.
> > 
> > Signed-off-by: Joelle van Dyne <j@getutm.app>  
> 
> This patch changes the order of in which the ACPI table elements are created but doesn't matter and also doesn't seem to upset ACPI test cases from what I saw:

it seems we do have tests for TIS only (which I added when I was refactoring it to TYPE_ACPI_DEV_AML_IF)
perhaps add a test for CRB before this patch a follow process described in bios-tables-test.c
for updating expected blob

>
> Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
> 
> > ---
> >   hw/i386/acpi-build.c | 23 -----------------------
> >   hw/tpm/tpm_crb.c     | 29 +++++++++++++++++++++++++++++
> >   2 files changed, 29 insertions(+), 23 deletions(-)
> > 
> > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > index 9c74fa17ad..b767df39df 100644
> > --- a/hw/i386/acpi-build.c
> > +++ b/hw/i386/acpi-build.c
> > @@ -1441,9 +1441,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> >       uint32_t nr_mem = machine->ram_slots;
> >       int root_bus_limit = 0xFF;
> >       PCIBus *bus = NULL;
> > -#ifdef CONFIG_TPM
> > -    TPMIf *tpm = tpm_find();
> > -#endif
> >       bool cxl_present = false;
> >       int i;
> >       VMBusBridge *vmbus_bridge = vmbus_bridge_find();
> > @@ -1793,26 +1790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> >           }
> >       }
> > 
> > -#ifdef CONFIG_TPM
> > -    if (TPM_IS_CRB(tpm)) {
> > -        dev = aml_device("TPM");
> > -        aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> > -        aml_append(dev, aml_name_decl("_STR",
> > -                                      aml_string("TPM 2.0 Device")));
> > -        crs = aml_resource_template();
> > -        aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
> > -                                           TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
> > -        aml_append(dev, aml_name_decl("_CRS", crs));
> > -
> > -        aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
> > -        aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> > -
> > -        tpm_build_ppi_acpi(tpm, dev);
> > -
> > -        aml_append(sb_scope, dev);
> > -    }
> > -#endif
> > -
> >       if (pcms->sgx_epc.size != 0) {
> >           uint64_t epc_base = pcms->sgx_epc.base;
> >           uint64_t epc_size = pcms->sgx_epc.size;
> > diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
> > index 6144081d30..594696ffb8 100644
> > --- a/hw/tpm/tpm_crb.c
> > +++ b/hw/tpm/tpm_crb.c
> > @@ -19,6 +19,8 @@
> >   #include "qemu/module.h"
> >   #include "qapi/error.h"
> >   #include "exec/address-spaces.h"
> > +#include "hw/acpi/acpi_aml_interface.h"
> > +#include "hw/acpi/tpm.h"
> >   #include "hw/qdev-properties.h"
> >   #include "hw/pci/pci_ids.h"
> >   #include "hw/acpi/tpm.h"
> > @@ -99,6 +101,11 @@ static void tpm_crb_isa_realize(DeviceState *dev, Error **errp)
> >           return;
> >       }
> > 
> > +    if (tpm_crb_isa_get_version(TPM_IF(s)) != TPM_VERSION_2_0) {
> > +        error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
> > +        return;
> > +    }
> > +
> >       tpm_crb_init_memory(OBJECT(s), &s->state, errp);
> > 
> >       memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
> > @@ -116,10 +123,30 @@ static void tpm_crb_isa_realize(DeviceState *dev, Error **errp)
> >       }
> >   }
> > 
> > +static void build_tpm_crb_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
> > +{
> > +    Aml *dev, *crs;
> > +    CRBState *s = CRB(adev);
> > +    TPMIf *ti = TPM_IF(s);
> > +
> > +    dev = aml_device("TPM");
> > +    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> > +    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
> > +    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> > +    aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
> > +    crs = aml_resource_template();
> > +    aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE, TPM_CRB_ADDR_SIZE,
> > +                                      AML_READ_WRITE));
> > +    aml_append(dev, aml_name_decl("_CRS", crs));
> > +    tpm_build_ppi_acpi(ti, dev);
> > +    aml_append(scope, dev);
> > +}
> > +
> >   static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
> >   {
> >       DeviceClass *dc = DEVICE_CLASS(klass);
> >       TPMIfClass *tc = TPM_IF_CLASS(klass);
> > +    AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
> > 
> >       dc->realize = tpm_crb_isa_realize;
> >       device_class_set_props(dc, tpm_crb_isa_properties);
> > @@ -128,6 +155,7 @@ static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
> >       tc->model = TPM_MODEL_TPM_CRB;
> >       tc->get_version = tpm_crb_isa_get_version;
> >       tc->request_completed = tpm_crb_isa_request_completed;
> > +    adevc->build_dev_aml = build_tpm_crb_isa_aml;
> > 
> >       set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> >   }
> > @@ -139,6 +167,7 @@ static const TypeInfo tpm_crb_isa_info = {
> >       .class_init  = tpm_crb_isa_class_init,
> >       .interfaces = (InterfaceInfo[]) {
> >           { TYPE_TPM_IF },
> > +        { TYPE_ACPI_DEV_AML_IF },
> >           { }
> >       }
> >   };  
> 



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

* Re: [PATCH v2 05/11] tpm_crb: use the ISA bus
  2023-07-14  7:09 ` [PATCH v2 05/11] tpm_crb: use the ISA bus Joelle van Dyne
@ 2023-07-17 13:46   ` Igor Mammedov
  2023-07-18 14:16     ` Stefan Berger
  0 siblings, 1 reply; 52+ messages in thread
From: Igor Mammedov @ 2023-07-17 13:46 UTC (permalink / raw)
  To: Joelle van Dyne; +Cc: qemu-devel, Stefan Berger, Paolo Bonzini

On Fri, 14 Jul 2023 00:09:21 -0700
Joelle van Dyne <j@getutm.app> wrote:

> Since this device is gated to only build for targets with the PC
> configuration, we should use the ISA bus like with TPM TIS.

does it affect migration in any way?
From guest pov it looks like there a new ISA device will appear
and then if you do ping pong migration between old - new QEMU will really it work?

If it will, then commit message here shall describe why it safe and why it works


> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>  hw/tpm/tpm_crb.c | 52 ++++++++++++++++++++++++------------------------
>  hw/tpm/Kconfig   |  2 +-
>  2 files changed, 27 insertions(+), 27 deletions(-)
> 
> diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
> index 07c6868d8d..6144081d30 100644
> --- a/hw/tpm/tpm_crb.c
> +++ b/hw/tpm/tpm_crb.c
> @@ -22,6 +22,7 @@
>  #include "hw/qdev-properties.h"
>  #include "hw/pci/pci_ids.h"
>  #include "hw/acpi/tpm.h"
> +#include "hw/isa/isa.h"
>  #include "migration/vmstate.h"
>  #include "sysemu/tpm_backend.h"
>  #include "sysemu/tpm_util.h"
> @@ -34,7 +35,7 @@
>  #include "tpm_crb.h"
>  
>  struct CRBState {
> -    DeviceState parent_obj;
> +    ISADevice parent_obj;
>  
>      TPMCRBState state;
>  };
> @@ -43,49 +44,49 @@ typedef struct CRBState CRBState;
>  DECLARE_INSTANCE_CHECKER(CRBState, CRB,
>                           TYPE_TPM_CRB)
>  
> -static void tpm_crb_none_request_completed(TPMIf *ti, int ret)
> +static void tpm_crb_isa_request_completed(TPMIf *ti, int ret)
>  {
>      CRBState *s = CRB(ti);
>  
>      tpm_crb_request_completed(&s->state, ret);
>  }
>  
> -static enum TPMVersion tpm_crb_none_get_version(TPMIf *ti)
> +static enum TPMVersion tpm_crb_isa_get_version(TPMIf *ti)
>  {
>      CRBState *s = CRB(ti);
>  
>      return tpm_crb_get_version(&s->state);
>  }
>  
> -static int tpm_crb_none_pre_save(void *opaque)
> +static int tpm_crb_isa_pre_save(void *opaque)
>  {
>      CRBState *s = opaque;
>  
>      return tpm_crb_pre_save(&s->state);
>  }
>  
> -static const VMStateDescription vmstate_tpm_crb_none = {
> +static const VMStateDescription vmstate_tpm_crb_isa = {
>      .name = "tpm-crb",
> -    .pre_save = tpm_crb_none_pre_save,
> +    .pre_save = tpm_crb_isa_pre_save,
>      .fields = (VMStateField[]) {
>          VMSTATE_END_OF_LIST(),
>      }
>  };
>  
> -static Property tpm_crb_none_properties[] = {
> +static Property tpm_crb_isa_properties[] = {
>      DEFINE_PROP_TPMBE("tpmdev", CRBState, state.tpmbe),
>      DEFINE_PROP_BOOL("ppi", CRBState, state.ppi_enabled, true),
>      DEFINE_PROP_END_OF_LIST(),
>  };
>  
> -static void tpm_crb_none_reset(void *dev)
> +static void tpm_crb_isa_reset(void *dev)
>  {
>      CRBState *s = CRB(dev);
>  
>      return tpm_crb_reset(&s->state, TPM_CRB_ADDR_BASE);
>  }
>  
> -static void tpm_crb_none_realize(DeviceState *dev, Error **errp)
> +static void tpm_crb_isa_realize(DeviceState *dev, Error **errp)
>  {
>      CRBState *s = CRB(dev);
>  
> @@ -100,52 +101,51 @@ static void tpm_crb_none_realize(DeviceState *dev, Error **errp)
>  
>      tpm_crb_init_memory(OBJECT(s), &s->state, errp);
>  
> -    memory_region_add_subregion(get_system_memory(),
> +    memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
>          TPM_CRB_ADDR_BASE, &s->state.mmio);
>  
>      if (s->state.ppi_enabled) {
> -        memory_region_add_subregion(get_system_memory(),
> +        memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
>              TPM_PPI_ADDR_BASE, &s->state.ppi.ram);
>      }
>  
>      if (xen_enabled()) {
> -        tpm_crb_none_reset(dev);
> +        tpm_crb_isa_reset(dev);
>      } else {
> -        qemu_register_reset(tpm_crb_none_reset, dev);
> +        qemu_register_reset(tpm_crb_isa_reset, dev);
>      }
>  }
>  
> -static void tpm_crb_none_class_init(ObjectClass *klass, void *data)
> +static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      TPMIfClass *tc = TPM_IF_CLASS(klass);
>  
> -    dc->realize = tpm_crb_none_realize;
> -    device_class_set_props(dc, tpm_crb_none_properties);
> -    dc->vmsd  = &vmstate_tpm_crb_none;
> +    dc->realize = tpm_crb_isa_realize;
> +    device_class_set_props(dc, tpm_crb_isa_properties);
> +    dc->vmsd  = &vmstate_tpm_crb_isa;
>      dc->user_creatable = true;
>      tc->model = TPM_MODEL_TPM_CRB;
> -    tc->get_version = tpm_crb_none_get_version;
> -    tc->request_completed = tpm_crb_none_request_completed;
> +    tc->get_version = tpm_crb_isa_get_version;
> +    tc->request_completed = tpm_crb_isa_request_completed;
>  
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>  }
>  
> -static const TypeInfo tpm_crb_none_info = {
> +static const TypeInfo tpm_crb_isa_info = {
>      .name = TYPE_TPM_CRB,
> -    /* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */
> -    .parent = TYPE_DEVICE,
> +    .parent = TYPE_ISA_DEVICE,
>      .instance_size = sizeof(CRBState),
> -    .class_init  = tpm_crb_none_class_init,
> +    .class_init  = tpm_crb_isa_class_init,
>      .interfaces = (InterfaceInfo[]) {
>          { TYPE_TPM_IF },
>          { }
>      }
>  };
>  
> -static void tpm_crb_none_register(void)
> +static void tpm_crb_isa_register(void)
>  {
> -    type_register_static(&tpm_crb_none_info);
> +    type_register_static(&tpm_crb_isa_info);
>  }
>  
> -type_init(tpm_crb_none_register)
> +type_init(tpm_crb_isa_register)
> diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
> index a46663288c..1fd73fe617 100644
> --- a/hw/tpm/Kconfig
> +++ b/hw/tpm/Kconfig
> @@ -22,7 +22,7 @@ config TPM_TIS
>  
>  config TPM_CRB
>      bool
> -    depends on TPM && PC
> +    depends on TPM && ISA_BUS
>      select TPM_BACKEND
>  
>  config TPM_SPAPR



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

* Re: [PATCH v2 07/11] hw/arm/virt: add plug handler for TPM on SysBus
  2023-07-14  7:09 ` [PATCH v2 07/11] hw/arm/virt: add plug handler for TPM on SysBus Joelle van Dyne
  2023-07-14 12:11   ` Stefan Berger
@ 2023-07-17 14:00   ` Igor Mammedov
  1 sibling, 0 replies; 52+ messages in thread
From: Igor Mammedov @ 2023-07-17 14:00 UTC (permalink / raw)
  To: Joelle van Dyne; +Cc: qemu-devel, Peter Maydell, open list:Virt

On Fri, 14 Jul 2023 00:09:23 -0700
Joelle van Dyne <j@getutm.app> wrote:

> TPM needs to know its own base address in order to generate its DSDT
> device entry.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>  hw/arm/virt.c | 37 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 37 insertions(+)
> 
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 7d9dbc2663..432148ef47 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -2732,6 +2732,37 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev,
>                           dev, &error_abort);
>  }
>  
> +#ifdef CONFIG_TPM

ifdefs are not really welcome, usually we use stubs instead
see stubs/virtio-md-pci.c or hw/display/acpi-vga-stub.c as an example.

> +static void virt_tpm_plug(VirtMachineState *vms, TPMIf *tpmif)
> +{
> +    PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> +    hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
> +    SysBusDevice *sbdev = SYS_BUS_DEVICE(tpmif);
> +    MemoryRegion *sbdev_mr;
> +    hwaddr tpm_base;
> +    uint64_t tpm_size;
> +
> +    if (!sbdev || !object_dynamic_cast(OBJECT(sbdev), TYPE_SYS_BUS_DEVICE)) {
it seems object_dynamic_cast() can deal with NULL object,  perhaps drop !sbdev part

> +        return;
> +    }
> +
> +    tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
> +    assert(tpm_base != -1);
> +
> +    tpm_base += pbus_base;
> +
> +    sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
> +    tpm_size = memory_region_size(sbdev_mr);
> +

> +    if (object_property_find(OBJECT(sbdev), "baseaddr")) {
> +        object_property_set_uint(OBJECT(sbdev), "baseaddr", tpm_base, NULL);
> +    }
> +    if (object_property_find(OBJECT(sbdev), "size")) {
> +        object_property_set_uint(OBJECT(sbdev), "size", tpm_size, NULL);
> +    }
why both properties wrapped into conditions?
Also can addr/size be wrong and cause property setter fail?
(if yes then you'd need to s/, NULL, &error_abort/)


> +}
> +#endif
> +
>  static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
>                                              DeviceState *dev, Error **errp)
>  {
> @@ -2803,6 +2834,12 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
>          vms->virtio_iommu_bdf = pci_get_bdf(pdev);
>          create_virtio_iommu_dt_bindings(vms);
>      }
> +
> +#ifdef CONFIG_TPM
> +    if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
> +        virt_tpm_plug(vms, TPM_IF(dev));
> +    }
> +#endif
>  }
>  
>  static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,



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

* Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device
  2023-07-14 17:29     ` Joelle van Dyne
  2023-07-14 17:37       ` Stefan Berger
@ 2023-07-17 14:06       ` Igor Mammedov
  1 sibling, 0 replies; 52+ messages in thread
From: Igor Mammedov @ 2023-07-17 14:06 UTC (permalink / raw)
  To: Joelle van Dyne
  Cc: Stefan Berger, qemu-devel, Shannon Zhao, Michael S. Tsirkin,
	Ani Sinha, Peter Maydell, Xiaojuan Yang, Song Gao, Stefan Berger,
	open list:ARM ACPI Subsystem

On Fri, 14 Jul 2023 10:29:31 -0700
Joelle van Dyne <j@getutm.app> wrote:

> On Fri, Jul 14, 2023 at 9:19 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
> >
> >
> >
> >
> > I don't know whether we would want multiple devices. tpm_find() usage is certainly not prepared for multiple devices.  
> Sorry, "multiple TPM interfaces" here does not mean "at the same
> time". Will clarify the description.
> 
> >
> >
> > Good for the consolidation.
> >
> >
> > Does moving the TIS to a different address help on aarch64?  
> That was the first thing we tried and no it doesn't help.
> >
> > Can the size really be an option? I don't see it useful and if one gave the wrong size it may break things.  
> It was added for consistency (otherwise we have to determine the size
> by looking at the interface everywhere). Also, it is possible for the
> size to be larger than the constant. For example, Apple Silicon uses
> 16KiB page sizes and we may decide to force the device to be 16KiB
> aligned (not sure if this is needed yet while we still track down why
> the dual mapping was not working). In that case, we would need to
> inform the OS of the true region size to prevent any overlap issues.
> Both baseaddr and size should be provided only by the plug handler in
> the virt machine, otherwise things may break even if we get rid of
> size and have just an incorrect baseaddr.
> 
if properties  (address/size) are for internal use, it would be better to use
x- prefix as not give user false promise that user can expect them working if
they provided them.

> >
> >  
> 



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

* Re: [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device
  2023-07-14  7:09 ` [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device Joelle van Dyne
  2023-07-14 14:27   ` Stefan Berger
@ 2023-07-17 14:23   ` Igor Mammedov
  2023-10-29  2:21     ` Joelle van Dyne
  1 sibling, 1 reply; 52+ messages in thread
From: Igor Mammedov @ 2023-07-17 14:23 UTC (permalink / raw)
  To: Joelle van Dyne
  Cc: qemu-devel, Stefan Berger, Michael S. Tsirkin, Ani Sinha,
	Paolo Bonzini, Peter Maydell, Xiaojuan Yang, Song Gao,
	Palmer Dabbelt, Alistair Francis, Bin Meng, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, open list:ARM TCG CPUs,
	open list:RISC-V TCG CPUs

On Fri, 14 Jul 2023 00:09:26 -0700
Joelle van Dyne <j@getutm.app> wrote:

> This SysBus variant of the CRB interface supports dynamically locating
> the MMIO interface so that Virt machines can use it. This interface
> is currently the only one supported by QEMU that works on Windows 11
> ARM64. We largely follow the TPM TIS SysBus device as a template.
> 
> To try out this device with Windows 11 before OVMF is updated, you
> will need to modify `sysbud-fdt.c` and change the added line from:
> 
> ```c
>     TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
> ```
> 
> to
> 
> ```c
>     TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
> ```
> 
> This change was not included because it can confuse Linux (although
> from testing, it seems like Linux is able to properly ignore the
> device from the TPM TIS driver and recognize it from the ACPI device
> in the TPM CRB driver). A proper fix would require OVMF to recognize
> the ACPI device and not depend on the FDT node for recognizing TPM.
> 
> The command line to try out this device with SWTPM is:
> 
> ```
> $ qemu-system-aarch64 \
>     -chardev socket,id=chrtpm0,path=tpm.sock \
>     -tpmdev emulator,id=tpm0,chardev=chrtpm0 \
>     -device tpm-crb-device,tpmdev=tpm0
> ```
> 
> along with SWTPM:
> 
> ```
> $ swtpm \
>     --ctrl type=unixio,path=tpm.sock,terminate \
>     --tpmstate backend-uri=file://tpm.data \
>     --tpm2
> ```
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>
> ---
>  docs/specs/tpm.rst          |   1 +
>  include/hw/acpi/aml-build.h |   1 +
>  include/sysemu/tpm.h        |   3 +
>  hw/acpi/aml-build.c         |   7 +-
>  hw/arm/virt.c               |   1 +
>  hw/core/sysbus-fdt.c        |   1 +
>  hw/loongarch/virt.c         |   1 +
>  hw/riscv/virt.c             |   1 +
>  hw/tpm/tpm_crb_sysbus.c     | 170 ++++++++++++++++++++++++++++++++++++
>  hw/arm/Kconfig              |   1 +
>  hw/riscv/Kconfig            |   1 +
>  hw/tpm/Kconfig              |   5 ++
>  hw/tpm/meson.build          |   2 +
>  13 files changed, 194 insertions(+), 1 deletion(-)
>  create mode 100644 hw/tpm/tpm_crb_sysbus.c
> 
> diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
> index 2bc29c9804..95aeb49220 100644
> --- a/docs/specs/tpm.rst
> +++ b/docs/specs/tpm.rst
> @@ -46,6 +46,7 @@ operating system.
>  QEMU files related to TPM CRB interface:
>   - ``hw/tpm/tpm_crb.c``
>   - ``hw/tpm/tpm_crb_common.c``
> + - ``hw/tpm/tpm_crb_sysbus.c``
>  
>  SPAPR interface
>  ---------------
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index d1fb08514b..9660e16148 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -3,6 +3,7 @@
>  
>  #include "hw/acpi/acpi-defs.h"
>  #include "hw/acpi/bios-linker-loader.h"
> +#include "exec/hwaddr.h"
>  
>  #define ACPI_BUILD_APPNAME6 "BOCHS "
>  #define ACPI_BUILD_APPNAME8 "BXPC    "
> diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
> index 66e3b45f30..f79c8f3575 100644
> --- a/include/sysemu/tpm.h
> +++ b/include/sysemu/tpm.h
> @@ -47,6 +47,7 @@ struct TPMIfClass {
>  #define TYPE_TPM_TIS_ISA            "tpm-tis"
>  #define TYPE_TPM_TIS_SYSBUS         "tpm-tis-device"
>  #define TYPE_TPM_CRB                "tpm-crb"
> +#define TYPE_TPM_CRB_SYSBUS         "tpm-crb-device"
>  #define TYPE_TPM_SPAPR              "tpm-spapr"
>  #define TYPE_TPM_TIS_I2C            "tpm-tis-i2c"
>  
> @@ -56,6 +57,8 @@ struct TPMIfClass {
>      object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
>  #define TPM_IS_CRB(chr)                             \
>      object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
> +#define TPM_IS_CRB_SYSBUS(chr)                      \
> +    object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
>  #define TPM_IS_SPAPR(chr)                           \
>      object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
>  #define TPM_IS_TIS_I2C(chr)                      \
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index ea331a20d1..f809137fc9 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -31,6 +31,7 @@
>  #include "hw/pci/pci_bus.h"
>  #include "hw/pci/pci_bridge.h"
>  #include "qemu/cutils.h"
> +#include "qom/object.h"
>  
>  static GArray *build_alloc_array(void)
>  {
> @@ -2218,7 +2219,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
>  {
>      uint8_t start_method_params[12] = {};
>      unsigned log_addr_offset;
> -    uint64_t control_area_start_address;
> +    uint64_t baseaddr, control_area_start_address;
>      TPMIf *tpmif = tpm_find();
>      uint32_t start_method;
>      AcpiTable table = { .sig = "TPM2", .rev = 4,
> @@ -2236,6 +2237,10 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
>      } else if (TPM_IS_CRB(tpmif)) {
>          control_area_start_address = TPM_CRB_ADDR_CTRL;
>          start_method = TPM2_START_METHOD_CRB;
> +    } else if (TPM_IS_CRB_SYSBUS(tpmif)) {
> +        baseaddr = object_property_get_uint(OBJECT(tpmif), "baseaddr", NULL);
> +        control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
> +        start_method = TPM2_START_METHOD_CRB;
>      } else {
>          g_assert_not_reached();
>      }
> diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> index 432148ef47..88e8b16103 100644
> --- a/hw/arm/virt.c
> +++ b/hw/arm/virt.c
> @@ -2977,6 +2977,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
>      machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
>  #ifdef CONFIG_TPM
>      machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
>  #endif
>      mc->block_default_type = IF_VIRTIO;
>      mc->no_cdrom = 1;
> diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
> index eebcd28f9a..9c783f88eb 100644
> --- a/hw/core/sysbus-fdt.c
> +++ b/hw/core/sysbus-fdt.c
> @@ -493,6 +493,7 @@ static const BindingEntry bindings[] = {
>  #endif
>  #ifdef CONFIG_TPM
>      TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node),
> +    TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
>  #endif
>      TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
>      TYPE_BINDING("", NULL), /* last element */
> diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> index 9c536c52bc..eb59fb04ee 100644
> --- a/hw/loongarch/virt.c
> +++ b/hw/loongarch/virt.c
> @@ -1194,6 +1194,7 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
>      machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>  #ifdef CONFIG_TPM
>      machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
>  #endif
>  }
>  
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index d90286dc46..5d639a870a 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -1681,6 +1681,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
>      machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
>  #ifdef CONFIG_TPM
>      machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
>  #endif
>  
>      if (tcg_enabled()) {
> diff --git a/hw/tpm/tpm_crb_sysbus.c b/hw/tpm/tpm_crb_sysbus.c
> new file mode 100644
> index 0000000000..66be57a532
> --- /dev/null
> +++ b/hw/tpm/tpm_crb_sysbus.c
> @@ -0,0 +1,170 @@
> +/*
> + * tpm_crb_sysbus.c - QEMU's TPM CRB interface emulator
> + *
> + * Copyright (c) 2018 Red Hat, Inc.
> + *
> + * Authors:
> + *   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.
> + *
> + * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
> + * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
> + * Family “2.0” Level 00 Revision 01.03 v22
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/acpi/acpi_aml_interface.h"
> +#include "hw/acpi/tpm.h"
> +#include "hw/qdev-properties.h"
> +#include "migration/vmstate.h"
> +#include "tpm_prop.h"
> +#include "hw/pci/pci_ids.h"
> +#include "hw/sysbus.h"
> +#include "qapi/visitor.h"
> +#include "qom/object.h"
> +#include "sysemu/tpm_util.h"
> +#include "trace.h"
> +#include "tpm_crb.h"

is it possible to weed off some unnecessary includes?

> +
> +struct TPMCRBStateSysBus {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +
> +    /*< public >*/
> +    TPMCRBState state;
> +    uint64_t baseaddr;
> +    uint64_t size;
> +};
> +
> +OBJECT_DECLARE_SIMPLE_TYPE(TPMCRBStateSysBus, TPM_CRB_SYSBUS)
> +
> +static void tpm_crb_sysbus_request_completed(TPMIf *ti, int ret)
> +{
> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
> +
> +    return tpm_crb_request_completed(&s->state, ret);
> +}
> +
> +static enum TPMVersion tpm_crb_sysbus_get_tpm_version(TPMIf *ti)
> +{
> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
> +
> +    return tpm_crb_get_version(&s->state);
> +}
> +
> +static int tpm_crb_sysbus_pre_save(void *opaque)
> +{
> +    TPMCRBStateSysBus *s = opaque;
> +
> +    return tpm_crb_pre_save(&s->state);
> +}
> +
> +static const VMStateDescription vmstate_tpm_crb_sysbus = {
> +    .name = "tpm-crb-sysbus",
> +    .pre_save = tpm_crb_sysbus_pre_save,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_END_OF_LIST(),
> +    }
> +};
> +
> +static Property tpm_crb_sysbus_properties[] = {
> +    DEFINE_PROP_TPMBE("tpmdev", TPMCRBStateSysBus, state.tpmbe),
> +    DEFINE_PROP_UINT64("baseaddr", TPMCRBStateSysBus,
> +                       baseaddr, TPM_CRB_ADDR_BASE),
> +    DEFINE_PROP_UINT64("size", TPMCRBStateSysBus, size, TPM_CRB_ADDR_SIZE),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void tpm_crb_sysbus_initfn(Object *obj)
> +{
> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(obj);
> +
> +    tpm_crb_init_memory(obj, &s->state, NULL);
> +
> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->state.mmio);
> +}
> +
> +static void tpm_crb_sysbus_reset(DeviceState *dev)
> +{
> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
> +
> +    return tpm_crb_reset(&s->state, s->baseaddr);
> +}
> +
> +static void tpm_crb_sysbus_realizefn(DeviceState *dev, Error **errp)
> +{
> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
> +
> +    if (!tpm_find()) {
> +        error_setg(errp, "at most one TPM device is permitted");
> +        return;
> +    }
> +
> +    if (!s->state.tpmbe) {
> +        error_setg(errp, "'tpmdev' property is required");
> +        return;
> +    }

above parts can be common with ISA vesion

> +    if (tpm_crb_sysbus_get_tpm_version(TPM_IF(s)) != TPM_VERSION_2_0) {
> +        error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
> +        return;
why ISA version doesn't require this?

> +    }
> +}
> +
> +static void build_tpm_crb_sysbus_aml(AcpiDevAmlIf *adev, Aml *scope)
> +{
> +    Aml *dev, *crs;
> +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(adev);
> +    TPMIf *ti = TPM_IF(s);
> +
> +    dev = aml_device("TPM");
> +    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> +    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
> +    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> +    aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
> +    crs = aml_resource_template();
> +    aml_append(crs, aml_memory32_fixed(s->baseaddr, s->size,
> +                                      AML_READ_WRITE));
> +    aml_append(dev, aml_name_decl("_CRS", crs));
> +    aml_append(scope, dev);
> +}

this almost matches isa version, modulo hard-codded address/size
(suggest to generalize and reuse it in both places)
and ppi, why sysbus variant doesn't implement PPI parts?

> +
> +static void tpm_crb_sysbus_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    TPMIfClass *tc = TPM_IF_CLASS(klass);
> +    AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
> +
> +    device_class_set_props(dc, tpm_crb_sysbus_properties);
> +    dc->vmsd  = &vmstate_tpm_crb_sysbus;
> +    tc->model = TPM_MODEL_TPM_CRB;
> +    dc->realize = tpm_crb_sysbus_realizefn;
> +    dc->user_creatable = true;
> +    dc->reset = tpm_crb_sysbus_reset;
> +    tc->request_completed = tpm_crb_sysbus_request_completed;
> +    tc->get_version = tpm_crb_sysbus_get_tpm_version;
> +    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> +    adevc->build_dev_aml = build_tpm_crb_sysbus_aml;
> +}
> +
> +static const TypeInfo tpm_crb_sysbus_info = {
> +    .name = TYPE_TPM_CRB_SYSBUS,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(TPMCRBStateSysBus),
> +    .instance_init = tpm_crb_sysbus_initfn,
> +    .class_init  = tpm_crb_sysbus_class_init,
> +    .interfaces = (InterfaceInfo[]) {
> +        { TYPE_TPM_IF },
> +        { TYPE_ACPI_DEV_AML_IF },
> +        { }
> +    }
> +};
> +
> +static void tpm_crb_sysbus_register(void)
> +{
> +    type_register_static(&tpm_crb_sysbus_info);
> +}
> +
> +type_init(tpm_crb_sysbus_register)
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index 7e68348440..efe1beaa7b 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -5,6 +5,7 @@ config ARM_VIRT
>      imply VFIO_AMD_XGBE
>      imply VFIO_PLATFORM
>      imply VFIO_XGMAC
> +    imply TPM_CRB_SYSBUS
>      imply TPM_TIS_SYSBUS
>      imply TPM_TIS_I2C
>      imply NVDIMM
> diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
> index b6a5eb4452..d824cb58f9 100644
> --- a/hw/riscv/Kconfig
> +++ b/hw/riscv/Kconfig
> @@ -29,6 +29,7 @@ config RISCV_VIRT
>      imply PCI_DEVICES
>      imply VIRTIO_VGA
>      imply TEST_DEVICES
> +    imply TPM_CRB_SYSBUS
>      imply TPM_TIS_SYSBUS
>      select RISCV_NUMA
>      select GOLDFISH_RTC
> diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
> index 1fd73fe617..3f294a20ba 100644
> --- a/hw/tpm/Kconfig
> +++ b/hw/tpm/Kconfig
> @@ -25,6 +25,11 @@ config TPM_CRB
>      depends on TPM && ISA_BUS
>      select TPM_BACKEND
>  
> +config TPM_CRB_SYSBUS
> +    bool
> +    depends on TPM
> +    select TPM_BACKEND
> +
>  config TPM_SPAPR
>      bool
>      default y
> diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build
> index cb8204d5bc..d96de92c16 100644
> --- a/hw/tpm/meson.build
> +++ b/hw/tpm/meson.build
> @@ -4,6 +4,8 @@ system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: files('tpm_tis_sysbus.c'))
>  system_ss.add(when: 'CONFIG_TPM_TIS_I2C', if_true: files('tpm_tis_i2c.c'))
>  system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
>  system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb_common.c'))
> +system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_sysbus.c'))
> +system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_common.c'))
>  system_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_ppi.c'))
>  system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_ppi.c'))
>  



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

* Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate
  2023-07-14 18:49             ` Joelle van Dyne
  2023-07-14 19:12               ` Stefan Berger
@ 2023-07-17 14:33               ` Igor Mammedov
  1 sibling, 0 replies; 52+ messages in thread
From: Igor Mammedov @ 2023-07-17 14:33 UTC (permalink / raw)
  To: Joelle van Dyne
  Cc: Stefan Berger, qemu-devel, Stefan Berger, Juan Quintela, qemu-arm

On Fri, 14 Jul 2023 11:49:03 -0700
Joelle van Dyne <j@getutm.app> wrote:

> On Fri, Jul 14, 2023 at 11:41 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
> >
> >
> >
> > On 7/14/23 14:22, Stefan Berger wrote:  
> > > On 7/14/23 13:04, Joelle van Dyne wrote:  
> > >> On Fri, Jul 14, 2023 at 7:51 AM Stefan Berger <stefanb@linux.ibm.com> wrote:  
> > >>>
> > >>>
> > >>>
> > >>> On 7/14/23 10:05, Stefan Berger wrote:  
> > >>>>
> > >>>>
> > >>>> On 7/14/23 03:09, Joelle van Dyne wrote:  
> > >>>>> When we moved to a single mapping and modified TPM CRB's VMState, it
> > >>>>> broke restoring of VMs that were saved on an older version. This
> > >>>>> change allows those VMs to gracefully migrate to the new memory
> > >>>>> mapping.  
> > >>>>
> > >>>> Thanks. This has to be in 4/11 though.
> > >>>>  
> > >>>
> > >>> After applying the whole series and trying to resume state taken with current git
> > >>> master I cannot restore it but it leads to this error here. I would just leave it
> > >>> completely untouched in 4/11.
> > >>>
> > >>> 2023-07-14T14:46:34.547550Z qemu-system-x86_64: Unknown ramblock "tpm-crb-cmd", cannot accept migration
> > >>> 2023-07-14T14:46:34.547799Z qemu-system-x86_64: error while loading state for instance 0x0 of device 'ram'
> > >>> 2023-07-14T14:46:34.547835Z qemu-system-x86_64: load of migration failed: Invalid argument
> > >>>
> > >>>      Stefan  
> > >>
> > >> To be clear, you are asking to back out of 4/11? That patch changes
> > >> how the registers are mapped so it's impossible to support the old
> > >> style register mapping. This patch attempts to fix that with a  
> > >
> > > Why can we not keep the old style register mapping as 'secondary mapping'?  
> >
> > I think the first goal should be for existing TPM CRB device not to change anything, they
> > keep their .read and .write behaivor as it.
> >
> > If you need different .read behavior for the sysbus device due to AARCH64 then it may want to use its own MemoryRegionOps.
> >
> > I am fairly sure that you could refactor the core of the existing tpm_crb_mmio_write() and have it work on s->regs and mmio regs.
> > The former would be used by existing code, the latter for CRB sysbus calling into this new function from a wrapper.
> >
> >     Stefan  
> 
> I agree that new QEMU should be able to read old QEMU state but vice
> versa is not always true. There's been many changes in the past that
> incremented the vmstate's version_id to indicate that the state format
> has changed. Also, we are not changing the .read behavior because in
> the old code, the only field that gets a dynamic update is
> tpmEstablished which we found is never changed. So effectively, .read
> is just doing a memcpy of the `regs` state. This makes it possible to
> map the page as memory while retaining the same behavior as before.
> (We are changing the code but not the behavior).
> 
> The issue with Windows's buggy tpm.sys driver is that fundamentally it
> cannot work with MemoryRegionOps. The way MMIO is implemented is that
> a hole is left in the guest memory space so when the device registers
> are accessed, the hypervisor traps it and sends it over to QEMU to
> handle. QEMU looks up the address, sees its a valid MMIO mapping, and
> calls into the MemoryRegionOps implementation. When tpm.sys does a LDP
> instruction access to the hole, the information for QEMU to determine
> if it's a valid access is not provided. Other hypervisors like Apple's
> VZ.framework and VMware will read the guest PC, manually decode the
> AArch64 instruction, determine the type of access, read the guest Rn
> registers, does a TLB lookup to determine the physical address, then
> emulate the MMIO. None of this capability currently exists in QEMU's
> ARM64 backend. That's why we decided the easier path is to tell QEMU
> that this mapping is RAM for read purposes and MMIO only for write
> purposes (thankfully Windows does not do a STP or we'd be hosed).

CCing migration and ARM folks for more exposure



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

* Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate
  2023-07-14 19:12               ` Stefan Berger
  2023-07-14 19:44                 ` Joelle van Dyne
@ 2023-07-17 14:40                 ` Peter Maydell
  1 sibling, 0 replies; 52+ messages in thread
From: Peter Maydell @ 2023-07-17 14:40 UTC (permalink / raw)
  To: Stefan Berger; +Cc: Joelle van Dyne, qemu-devel, Stefan Berger

On Fri, 14 Jul 2023 at 20:13, Stefan Berger <stefanb@linux.ibm.com> wrote:
> Unfortunately the CRB device is being used by x86 on some distros
> and the expectation is that this existing device can also downgrade
> to a previous version of QEMU I would say. I have read people migrating
> from RHEL 9.x even to RHEL 8.x and the expectation is that this works.

If you want both-ways migration compatibility for the
change of implementation to use a RAM-backed MR rather
than an MMIO MR:

 * make sure the new RAM-backed memory region is created
   using a memory_region_init_*_nomigrate() function so that
   we don't try to migrate the RAM as RAM
 * keep the regs array in the device struct, and add a comment
   that it's only used during migration
 * keep the vmstate entry for the regs array as it is
 * in the device's vmstate pre_save hook, copy from the
   backing RAM into the regs array (watch out for
   endianness issues :-))
 * in the vmstate post_load hook, copy from the regs
   array into the backing RAM

-- PMM


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

* Re: [PATCH v2 05/11] tpm_crb: use the ISA bus
  2023-07-17 13:46   ` Igor Mammedov
@ 2023-07-18 14:16     ` Stefan Berger
  2023-08-01  1:46       ` Joelle van Dyne
  0 siblings, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-18 14:16 UTC (permalink / raw)
  To: Igor Mammedov, Joelle van Dyne; +Cc: qemu-devel, Stefan Berger, Paolo Bonzini



On 7/17/23 09:46, Igor Mammedov wrote:
> On Fri, 14 Jul 2023 00:09:21 -0700
> Joelle van Dyne <j@getutm.app> wrote:
> 
>> Since this device is gated to only build for targets with the PC
>> configuration, we should use the ISA bus like with TPM TIS.
> 
> does it affect migration in any way?
>  From guest pov it looks like there a new ISA device will appear
> and then if you do ping pong migration between old - new QEMU will really it work?


> 
> If it will, then commit message here shall describe why it safe and why it works
> 
I would just leave the existing device as-is. This seems safest and we know thta it works.
    Stefan


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

* Re: [PATCH v2 08/11] hw/loongarch/virt: add plug handler for TPM on SysBus
  2023-07-14  7:09 ` [PATCH v2 08/11] hw/loongarch/virt: " Joelle van Dyne
@ 2023-07-20 17:57   ` Stefan Berger
  2023-08-03 11:35     ` Stefan Berger
  0 siblings, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-07-20 17:57 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel; +Cc: Xiaojuan Yang, Song Gao



On 7/14/23 03:09, Joelle van Dyne wrote:
> TPM needs to know its own base address in order to generate its DSDT
> device entry.
> 
> Signed-off-by: Joelle van Dyne <j@getutm.app>


It would be great to also cover the crb-device  with tests:

from tests/qtest/meson.build:

   (config_all.has_key('CONFIG_TCG') and config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ?            \
     ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) +                                         \

It should be easy to make a copy of these two tis-device tests and rename them to crb-device tests, adapt them, and run them at least on aarch64.

Regards,
    Stefan


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

* Re: [PATCH v2 05/11] tpm_crb: use the ISA bus
  2023-07-18 14:16     ` Stefan Berger
@ 2023-08-01  1:46       ` Joelle van Dyne
  2023-10-17 14:24         ` Alexander Graf
  0 siblings, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-08-01  1:46 UTC (permalink / raw)
  To: Stefan Berger, Alexander Graf
  Cc: Igor Mammedov, Joelle van Dyne, qemu-devel, Stefan Berger, Paolo Bonzini

On Tue, Jul 18, 2023 at 7:16 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>
>
>
> On 7/17/23 09:46, Igor Mammedov wrote:
> > On Fri, 14 Jul 2023 00:09:21 -0700
> > Joelle van Dyne <j@getutm.app> wrote:
> >
> >> Since this device is gated to only build for targets with the PC
> >> configuration, we should use the ISA bus like with TPM TIS.
> >
> > does it affect migration in any way?
> >  From guest pov it looks like there a new ISA device will appear
> > and then if you do ping pong migration between old - new QEMU will really it work?
>
>
> >
> > If it will, then commit message here shall describe why it safe and why it works
> >
> I would just leave the existing device as-is. This seems safest and we know thta it works.
>     Stefan

Alexander, do you have any comments here? I know you wanted to move
away from the default bus. The concern is that switching from the
default bus to the ISA bus may cause issues in migration. The current
course of action is to drop this patch.


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

* Re: [PATCH v2 06/11] tpm_crb: move ACPI table building to device interface
  2023-07-17 13:42     ` Igor Mammedov
@ 2023-08-01  3:02       ` Joelle van Dyne
  2023-08-01 19:38         ` Stefan Berger
  0 siblings, 1 reply; 52+ messages in thread
From: Joelle van Dyne @ 2023-08-01  3:02 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: Stefan Berger, Joelle van Dyne, qemu-devel, Michael S. Tsirkin,
	Ani Sinha, Paolo Bonzini, Richard Henderson, Eduardo Habkost,
	Marcel Apfelbaum, Stefan Berger

On Mon, Jul 17, 2023 at 6:42 AM Igor Mammedov <imammedo@redhat.com> wrote:
>
> On Fri, 14 Jul 2023 13:21:33 -0400
> Stefan Berger <stefanb@linux.ibm.com> wrote:
>
> > On 7/14/23 03:09, Joelle van Dyne wrote:
> > > This logic is similar to TPM TIS ISA device. Since TPM CRB can only
> > > support TPM 2.0 backends, we check for this in realize.
> > >
> > > Signed-off-by: Joelle van Dyne <j@getutm.app>
> >
> > This patch changes the order of in which the ACPI table elements are created but doesn't matter and also doesn't seem to upset ACPI test cases from what I saw:
>
> it seems we do have tests for TIS only (which I added when I was refactoring it to TYPE_ACPI_DEV_AML_IF)
> perhaps add a test for CRB before this patch a follow process described in bios-tables-test.c
> for updating expected blob
I read the file and looked at the commits for TIS tests but I'm not
sure I understand how it works. At what point do I specify that the
CRB device should be created for the test?

>
> >
> > Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
> >
> > > ---
> > >   hw/i386/acpi-build.c | 23 -----------------------
> > >   hw/tpm/tpm_crb.c     | 29 +++++++++++++++++++++++++++++
> > >   2 files changed, 29 insertions(+), 23 deletions(-)
> > >
> > > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > > index 9c74fa17ad..b767df39df 100644
> > > --- a/hw/i386/acpi-build.c
> > > +++ b/hw/i386/acpi-build.c
> > > @@ -1441,9 +1441,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> > >       uint32_t nr_mem = machine->ram_slots;
> > >       int root_bus_limit = 0xFF;
> > >       PCIBus *bus = NULL;
> > > -#ifdef CONFIG_TPM
> > > -    TPMIf *tpm = tpm_find();
> > > -#endif
> > >       bool cxl_present = false;
> > >       int i;
> > >       VMBusBridge *vmbus_bridge = vmbus_bridge_find();
> > > @@ -1793,26 +1790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> > >           }
> > >       }
> > >
> > > -#ifdef CONFIG_TPM
> > > -    if (TPM_IS_CRB(tpm)) {
> > > -        dev = aml_device("TPM");
> > > -        aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> > > -        aml_append(dev, aml_name_decl("_STR",
> > > -                                      aml_string("TPM 2.0 Device")));
> > > -        crs = aml_resource_template();
> > > -        aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
> > > -                                           TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
> > > -        aml_append(dev, aml_name_decl("_CRS", crs));
> > > -
> > > -        aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
> > > -        aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> > > -
> > > -        tpm_build_ppi_acpi(tpm, dev);
> > > -
> > > -        aml_append(sb_scope, dev);
> > > -    }
> > > -#endif
> > > -
> > >       if (pcms->sgx_epc.size != 0) {
> > >           uint64_t epc_base = pcms->sgx_epc.base;
> > >           uint64_t epc_size = pcms->sgx_epc.size;
> > > diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
> > > index 6144081d30..594696ffb8 100644
> > > --- a/hw/tpm/tpm_crb.c
> > > +++ b/hw/tpm/tpm_crb.c
> > > @@ -19,6 +19,8 @@
> > >   #include "qemu/module.h"
> > >   #include "qapi/error.h"
> > >   #include "exec/address-spaces.h"
> > > +#include "hw/acpi/acpi_aml_interface.h"
> > > +#include "hw/acpi/tpm.h"
> > >   #include "hw/qdev-properties.h"
> > >   #include "hw/pci/pci_ids.h"
> > >   #include "hw/acpi/tpm.h"
> > > @@ -99,6 +101,11 @@ static void tpm_crb_isa_realize(DeviceState *dev, Error **errp)
> > >           return;
> > >       }
> > >
> > > +    if (tpm_crb_isa_get_version(TPM_IF(s)) != TPM_VERSION_2_0) {
> > > +        error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
> > > +        return;
> > > +    }
> > > +
> > >       tpm_crb_init_memory(OBJECT(s), &s->state, errp);
> > >
> > >       memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
> > > @@ -116,10 +123,30 @@ static void tpm_crb_isa_realize(DeviceState *dev, Error **errp)
> > >       }
> > >   }
> > >
> > > +static void build_tpm_crb_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
> > > +{
> > > +    Aml *dev, *crs;
> > > +    CRBState *s = CRB(adev);
> > > +    TPMIf *ti = TPM_IF(s);
> > > +
> > > +    dev = aml_device("TPM");
> > > +    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> > > +    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
> > > +    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> > > +    aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
> > > +    crs = aml_resource_template();
> > > +    aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE, TPM_CRB_ADDR_SIZE,
> > > +                                      AML_READ_WRITE));
> > > +    aml_append(dev, aml_name_decl("_CRS", crs));
> > > +    tpm_build_ppi_acpi(ti, dev);
> > > +    aml_append(scope, dev);
> > > +}
> > > +
> > >   static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
> > >   {
> > >       DeviceClass *dc = DEVICE_CLASS(klass);
> > >       TPMIfClass *tc = TPM_IF_CLASS(klass);
> > > +    AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
> > >
> > >       dc->realize = tpm_crb_isa_realize;
> > >       device_class_set_props(dc, tpm_crb_isa_properties);
> > > @@ -128,6 +155,7 @@ static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
> > >       tc->model = TPM_MODEL_TPM_CRB;
> > >       tc->get_version = tpm_crb_isa_get_version;
> > >       tc->request_completed = tpm_crb_isa_request_completed;
> > > +    adevc->build_dev_aml = build_tpm_crb_isa_aml;
> > >
> > >       set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> > >   }
> > > @@ -139,6 +167,7 @@ static const TypeInfo tpm_crb_isa_info = {
> > >       .class_init  = tpm_crb_isa_class_init,
> > >       .interfaces = (InterfaceInfo[]) {
> > >           { TYPE_TPM_IF },
> > > +        { TYPE_ACPI_DEV_AML_IF },
> > >           { }
> > >       }
> > >   };
> >
>


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

* Re: [PATCH v2 06/11] tpm_crb: move ACPI table building to device interface
  2023-08-01  3:02       ` Joelle van Dyne
@ 2023-08-01 19:38         ` Stefan Berger
  2023-08-07 10:20           ` Igor Mammedov
  0 siblings, 1 reply; 52+ messages in thread
From: Stefan Berger @ 2023-08-01 19:38 UTC (permalink / raw)
  To: Joelle van Dyne, Igor Mammedov
  Cc: qemu-devel, Michael S. Tsirkin, Ani Sinha, Paolo Bonzini,
	Richard Henderson, Eduardo Habkost, Marcel Apfelbaum,
	Stefan Berger



On 7/31/23 23:02, Joelle van Dyne wrote:
> On Mon, Jul 17, 2023 at 6:42 AM Igor Mammedov <imammedo@redhat.com> wrote:
>>
>> On Fri, 14 Jul 2023 13:21:33 -0400
>> Stefan Berger <stefanb@linux.ibm.com> wrote:
>>
>>> On 7/14/23 03:09, Joelle van Dyne wrote:
>>>> This logic is similar to TPM TIS ISA device. Since TPM CRB can only
>>>> support TPM 2.0 backends, we check for this in realize.
>>>>
>>>> Signed-off-by: Joelle van Dyne <j@getutm.app>
>>>
>>> This patch changes the order of in which the ACPI table elements are created but doesn't matter and also doesn't seem to upset ACPI test cases from what I saw:
>>
>> it seems we do have tests for TIS only (which I added when I was refactoring it to TYPE_ACPI_DEV_AML_IF)
>> perhaps add a test for CRB before this patch a follow process described in bios-tables-test.c
>> for updating expected blob
> I read the file and looked at the commits for TIS tests but I'm not
> sure I understand how it works. At what point do I specify that the
> CRB device should be created for the test?

For me it would be a bit of trial an error as well. So here's my best guess:

Did you look at b193e5f9cccb322b0febd5a2aba486? You basically have to find out which files
are going to change due to extending the tests, so doing something like in that patch comes
after you found out which files are changing and iirc the tests are going to complain about
those files. So I would try to first add CRB tests similar to the following to tests/qtest/bios-tables-test.c.
in one patch, then run the test cases and they will tell you which files changed, and then
add a patch similar to b193e5f9cccb322b0febd5a2aba486 before the test-enabling patch.

             if (tpm_model_is_available("-machine q35", "tpm-tis")) {
                 qtest_add_func("acpi/q35/tpm2-tis", test_acpi_q35_tcg_tpm2_tis);
                 qtest_add_func("acpi/q35/tpm12-tis",
                                test_acpi_q35_tcg_tpm12_tis);
             }

I would try to something like the above to aarch64 here:

     } else if (strcmp(arch, "aarch64") == 0) {
         if (has_tcg && qtest_has_device("virtio-blk-pci")) {
             qtest_add_func("acpi/virt", test_acpi_virt_tcg);
             qtest_add_func("acpi/virt/acpihmatvirt",
                             test_acpi_virt_tcg_acpi_hmat);


Then you run the tests again then it should create those files with the ACPI data and you copy them
to their destination (like in ca745d2277496464b54fd832c15c45d0227325bb) and remove the changes from
tests/qtest/bios-tables-test-allowed-diff.h and that becomes your 3rd patch. Once you run the tests
again with the 3rd patch there should be no more complaints about ACPI related changes.

Since CRB ACPI tests are not enabled right now you can add these patches somewhere in the middle of
the series or also at the end.


I hope this helps.

    Stefan


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

* Re: [PATCH v2 08/11] hw/loongarch/virt: add plug handler for TPM on SysBus
  2023-07-20 17:57   ` Stefan Berger
@ 2023-08-03 11:35     ` Stefan Berger
  0 siblings, 0 replies; 52+ messages in thread
From: Stefan Berger @ 2023-08-03 11:35 UTC (permalink / raw)
  To: Joelle van Dyne, qemu-devel; +Cc: Xiaojuan Yang, Song Gao



On 7/20/23 13:57, Stefan Berger wrote:
> 
> 
> On 7/14/23 03:09, Joelle van Dyne wrote:
>> TPM needs to know its own base address in order to generate its DSDT
>> device entry.
>>
>> Signed-off-by: Joelle van Dyne <j@getutm.app>
> 
> 
> It would be great to also cover the crb-device  with tests:
> 
> from tests/qtest/meson.build:
> 
>    (config_all.has_key('CONFIG_TCG') and config_all_devices.has_key('CONFIG_TPM_TIS_SYSBUS') ?            \
>      ['tpm-tis-device-test', 'tpm-tis-device-swtpm-test'] : []) +                                         \
> 
> It should be easy to make a copy of these two tis-device tests and rename them to crb-device tests, adapt them, and run them at least on aarch64.

... actually make a copy of the files tests/qtest/tpm-crb-swtpm-test.c & tests/qtest/tpm-crb-test.c.

> 
> Regards,
>     Stefan


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

* Re: [PATCH v2 06/11] tpm_crb: move ACPI table building to device interface
  2023-08-01 19:38         ` Stefan Berger
@ 2023-08-07 10:20           ` Igor Mammedov
  0 siblings, 0 replies; 52+ messages in thread
From: Igor Mammedov @ 2023-08-07 10:20 UTC (permalink / raw)
  To: Stefan Berger
  Cc: Joelle van Dyne, qemu-devel, Michael S. Tsirkin, Ani Sinha,
	Paolo Bonzini, Richard Henderson, Eduardo Habkost,
	Marcel Apfelbaum, Stefan Berger

On Tue, 1 Aug 2023 15:38:32 -0400
Stefan Berger <stefanb@linux.ibm.com> wrote:

> On 7/31/23 23:02, Joelle van Dyne wrote:
> > On Mon, Jul 17, 2023 at 6:42 AM Igor Mammedov <imammedo@redhat.com> wrote:  
> >>
> >> On Fri, 14 Jul 2023 13:21:33 -0400
> >> Stefan Berger <stefanb@linux.ibm.com> wrote:
> >>  
> >>> On 7/14/23 03:09, Joelle van Dyne wrote:  
> >>>> This logic is similar to TPM TIS ISA device. Since TPM CRB can only
> >>>> support TPM 2.0 backends, we check for this in realize.
> >>>>
> >>>> Signed-off-by: Joelle van Dyne <j@getutm.app>  
> >>>
> >>> This patch changes the order of in which the ACPI table elements are created but doesn't matter and also doesn't seem to upset ACPI test cases from what I saw:  
> >>
> >> it seems we do have tests for TIS only (which I added when I was refactoring it to TYPE_ACPI_DEV_AML_IF)
> >> perhaps add a test for CRB before this patch a follow process described in bios-tables-test.c
> >> for updating expected blob  
> > I read the file and looked at the commits for TIS tests but I'm not
> > sure I understand how it works. At what point do I specify that the
> > CRB device should be created for the test?  
> 
> For me it would be a bit of trial an error as well. So here's my best guess:
[...]
> Then you run the tests again then it should create those files with the ACPI data and you copy them
> to their destination (like in ca745d2277496464b54fd832c15c45d0227325bb) and remove the changes from
> tests/qtest/bios-tables-test-allowed-diff.h and that becomes your 3rd patch. Once you run the tests
> again with the 3rd patch there should be no more complaints about ACPI related changes.

ACPI tables update procedure as described bios-tables-test.c looks more or less
reasonable to me (heavily biased view) for someone else to follow. It shouldn't
be 'trial an error'. If something is unclear in the process, lets improve
description (while your mind is still not poisoned by knowledge how it works). 

Here is latest patches that one can use as a model for changing ACPI tables.
45d9d318c8 tests: acpi: x86: whitelist expected blobs
44d975ef34 x86: acpi: workaround Windows not handling name references in Package properly
6e510855a9 tests: acpi: x86: update expected blobs

> Since CRB ACPI tests are not enabled right now you can add these patches somewhere in the middle of
> the series or also at the end.
> 
> 
> I hope this helps.
> 
>     Stefan
> 



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

* Re: [PATCH v2 05/11] tpm_crb: use the ISA bus
  2023-08-01  1:46       ` Joelle van Dyne
@ 2023-10-17 14:24         ` Alexander Graf
  0 siblings, 0 replies; 52+ messages in thread
From: Alexander Graf @ 2023-10-17 14:24 UTC (permalink / raw)
  To: Joelle van Dyne, Stefan Berger
  Cc: Igor Mammedov, qemu-devel, Stefan Berger, Paolo Bonzini

Hi Joelle,

On 01.08.23 03:46, Joelle van Dyne wrote:
> On Tue, Jul 18, 2023 at 7:16 AM Stefan Berger <stefanb@linux.ibm.com> wrote:
>>
>>
>> On 7/17/23 09:46, Igor Mammedov wrote:
>>> On Fri, 14 Jul 2023 00:09:21 -0700
>>> Joelle van Dyne <j@getutm.app> wrote:
>>>
>>>> Since this device is gated to only build for targets with the PC
>>>> configuration, we should use the ISA bus like with TPM TIS.
>>> does it affect migration in any way?
>>>   From guest pov it looks like there a new ISA device will appear
>>> and then if you do ping pong migration between old - new QEMU will really it work?
>>
>>> If it will, then commit message here shall describe why it safe and why it works
>>>
>> I would just leave the existing device as-is. This seems safest and we know thta it works.
>>      Stefan
> Alexander, do you have any comments here? I know you wanted to move
> away from the default bus. The concern is that switching from the
> default bus to the ISA bus may cause issues in migration. The current
> course of action is to drop this patch.


The big problem I have with the CRB device is this code:

https://gitlab.com/qemu-project/qemu/-/blob/master/hw/tpm/tpm_crb.c?ref_type=heads#L297-305

It's a device that maps itself autonomously into system memory. The way 
mapping is supposed to work is that the parent of the device maps it 
into a bus region. If the parent is a machine, it is free to also map it 
into system memory. But a device should not even know what system memory 
is :).

That said, I'm happy if we just introduce a new "sane" sysdev TPM CRB 
device that we use for non-PCs and leave the current layering violating 
one as is.


Alex



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

* Re: [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device
  2023-07-17 14:23   ` Igor Mammedov
@ 2023-10-29  2:21     ` Joelle van Dyne
  0 siblings, 0 replies; 52+ messages in thread
From: Joelle van Dyne @ 2023-10-29  2:21 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: Joelle van Dyne, qemu-devel, Stefan Berger, Michael S. Tsirkin,
	Ani Sinha, Paolo Bonzini, Peter Maydell, Xiaojuan Yang, Song Gao,
	Palmer Dabbelt, Alistair Francis, Bin Meng, Weiwei Li,
	Daniel Henrique Barboza, Liu Zhiwei, open list:ARM TCG CPUs,
	open list:RISC-V TCG CPUs

On Mon, Jul 17, 2023 at 7:23 AM Igor Mammedov <imammedo@redhat.com> wrote:
>
> On Fri, 14 Jul 2023 00:09:26 -0700
> Joelle van Dyne <j@getutm.app> wrote:
>
> > This SysBus variant of the CRB interface supports dynamically locating
> > the MMIO interface so that Virt machines can use it. This interface
> > is currently the only one supported by QEMU that works on Windows 11
> > ARM64. We largely follow the TPM TIS SysBus device as a template.
> >
> > To try out this device with Windows 11 before OVMF is updated, you
> > will need to modify `sysbud-fdt.c` and change the added line from:
> >
> > ```c
> >     TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
> > ```
> >
> > to
> >
> > ```c
> >     TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
> > ```
> >
> > This change was not included because it can confuse Linux (although
> > from testing, it seems like Linux is able to properly ignore the
> > device from the TPM TIS driver and recognize it from the ACPI device
> > in the TPM CRB driver). A proper fix would require OVMF to recognize
> > the ACPI device and not depend on the FDT node for recognizing TPM.
> >
> > The command line to try out this device with SWTPM is:
> >
> > ```
> > $ qemu-system-aarch64 \
> >     -chardev socket,id=chrtpm0,path=tpm.sock \
> >     -tpmdev emulator,id=tpm0,chardev=chrtpm0 \
> >     -device tpm-crb-device,tpmdev=tpm0
> > ```
> >
> > along with SWTPM:
> >
> > ```
> > $ swtpm \
> >     --ctrl type=unixio,path=tpm.sock,terminate \
> >     --tpmstate backend-uri=file://tpm.data \
> >     --tpm2
> > ```
> >
> > Signed-off-by: Joelle van Dyne <j@getutm.app>
> > ---
> >  docs/specs/tpm.rst          |   1 +
> >  include/hw/acpi/aml-build.h |   1 +
> >  include/sysemu/tpm.h        |   3 +
> >  hw/acpi/aml-build.c         |   7 +-
> >  hw/arm/virt.c               |   1 +
> >  hw/core/sysbus-fdt.c        |   1 +
> >  hw/loongarch/virt.c         |   1 +
> >  hw/riscv/virt.c             |   1 +
> >  hw/tpm/tpm_crb_sysbus.c     | 170 ++++++++++++++++++++++++++++++++++++
> >  hw/arm/Kconfig              |   1 +
> >  hw/riscv/Kconfig            |   1 +
> >  hw/tpm/Kconfig              |   5 ++
> >  hw/tpm/meson.build          |   2 +
> >  13 files changed, 194 insertions(+), 1 deletion(-)
> >  create mode 100644 hw/tpm/tpm_crb_sysbus.c
> >
> > diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
> > index 2bc29c9804..95aeb49220 100644
> > --- a/docs/specs/tpm.rst
> > +++ b/docs/specs/tpm.rst
> > @@ -46,6 +46,7 @@ operating system.
> >  QEMU files related to TPM CRB interface:
> >   - ``hw/tpm/tpm_crb.c``
> >   - ``hw/tpm/tpm_crb_common.c``
> > + - ``hw/tpm/tpm_crb_sysbus.c``
> >
> >  SPAPR interface
> >  ---------------
> > diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> > index d1fb08514b..9660e16148 100644
> > --- a/include/hw/acpi/aml-build.h
> > +++ b/include/hw/acpi/aml-build.h
> > @@ -3,6 +3,7 @@
> >
> >  #include "hw/acpi/acpi-defs.h"
> >  #include "hw/acpi/bios-linker-loader.h"
> > +#include "exec/hwaddr.h"
> >
> >  #define ACPI_BUILD_APPNAME6 "BOCHS "
> >  #define ACPI_BUILD_APPNAME8 "BXPC    "
> > diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
> > index 66e3b45f30..f79c8f3575 100644
> > --- a/include/sysemu/tpm.h
> > +++ b/include/sysemu/tpm.h
> > @@ -47,6 +47,7 @@ struct TPMIfClass {
> >  #define TYPE_TPM_TIS_ISA            "tpm-tis"
> >  #define TYPE_TPM_TIS_SYSBUS         "tpm-tis-device"
> >  #define TYPE_TPM_CRB                "tpm-crb"
> > +#define TYPE_TPM_CRB_SYSBUS         "tpm-crb-device"
> >  #define TYPE_TPM_SPAPR              "tpm-spapr"
> >  #define TYPE_TPM_TIS_I2C            "tpm-tis-i2c"
> >
> > @@ -56,6 +57,8 @@ struct TPMIfClass {
> >      object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
> >  #define TPM_IS_CRB(chr)                             \
> >      object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
> > +#define TPM_IS_CRB_SYSBUS(chr)                      \
> > +    object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
> >  #define TPM_IS_SPAPR(chr)                           \
> >      object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
> >  #define TPM_IS_TIS_I2C(chr)                      \
> > diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> > index ea331a20d1..f809137fc9 100644
> > --- a/hw/acpi/aml-build.c
> > +++ b/hw/acpi/aml-build.c
> > @@ -31,6 +31,7 @@
> >  #include "hw/pci/pci_bus.h"
> >  #include "hw/pci/pci_bridge.h"
> >  #include "qemu/cutils.h"
> > +#include "qom/object.h"
> >
> >  static GArray *build_alloc_array(void)
> >  {
> > @@ -2218,7 +2219,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
> >  {
> >      uint8_t start_method_params[12] = {};
> >      unsigned log_addr_offset;
> > -    uint64_t control_area_start_address;
> > +    uint64_t baseaddr, control_area_start_address;
> >      TPMIf *tpmif = tpm_find();
> >      uint32_t start_method;
> >      AcpiTable table = { .sig = "TPM2", .rev = 4,
> > @@ -2236,6 +2237,10 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
> >      } else if (TPM_IS_CRB(tpmif)) {
> >          control_area_start_address = TPM_CRB_ADDR_CTRL;
> >          start_method = TPM2_START_METHOD_CRB;
> > +    } else if (TPM_IS_CRB_SYSBUS(tpmif)) {
> > +        baseaddr = object_property_get_uint(OBJECT(tpmif), "baseaddr", NULL);
> > +        control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
> > +        start_method = TPM2_START_METHOD_CRB;
> >      } else {
> >          g_assert_not_reached();
> >      }
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index 432148ef47..88e8b16103 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -2977,6 +2977,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
> >      machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
> >  #ifdef CONFIG_TPM
> >      machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> > +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
> >  #endif
> >      mc->block_default_type = IF_VIRTIO;
> >      mc->no_cdrom = 1;
> > diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
> > index eebcd28f9a..9c783f88eb 100644
> > --- a/hw/core/sysbus-fdt.c
> > +++ b/hw/core/sysbus-fdt.c
> > @@ -493,6 +493,7 @@ static const BindingEntry bindings[] = {
> >  #endif
> >  #ifdef CONFIG_TPM
> >      TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node),
> > +    TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
> >  #endif
> >      TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
> >      TYPE_BINDING("", NULL), /* last element */
> > diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
> > index 9c536c52bc..eb59fb04ee 100644
> > --- a/hw/loongarch/virt.c
> > +++ b/hw/loongarch/virt.c
> > @@ -1194,6 +1194,7 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
> >      machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> >  #ifdef CONFIG_TPM
> >      machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> > +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
> >  #endif
> >  }
> >
> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > index d90286dc46..5d639a870a 100644
> > --- a/hw/riscv/virt.c
> > +++ b/hw/riscv/virt.c
> > @@ -1681,6 +1681,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
> >      machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
> >  #ifdef CONFIG_TPM
> >      machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
> > +    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
> >  #endif
> >
> >      if (tcg_enabled()) {
> > diff --git a/hw/tpm/tpm_crb_sysbus.c b/hw/tpm/tpm_crb_sysbus.c
> > new file mode 100644
> > index 0000000000..66be57a532
> > --- /dev/null
> > +++ b/hw/tpm/tpm_crb_sysbus.c
> > @@ -0,0 +1,170 @@
> > +/*
> > + * tpm_crb_sysbus.c - QEMU's TPM CRB interface emulator
> > + *
> > + * Copyright (c) 2018 Red Hat, Inc.
> > + *
> > + * Authors:
> > + *   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.
> > + *
> > + * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
> > + * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
> > + * Family “2.0” Level 00 Revision 01.03 v22
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "hw/acpi/acpi_aml_interface.h"
> > +#include "hw/acpi/tpm.h"
> > +#include "hw/qdev-properties.h"
> > +#include "migration/vmstate.h"
> > +#include "tpm_prop.h"
> > +#include "hw/pci/pci_ids.h"
> > +#include "hw/sysbus.h"
> > +#include "qapi/visitor.h"
> > +#include "qom/object.h"
> > +#include "sysemu/tpm_util.h"
> > +#include "trace.h"
> > +#include "tpm_crb.h"
>
> is it possible to weed off some unnecessary includes?
Done.

>
> > +
> > +struct TPMCRBStateSysBus {
> > +    /*< private >*/
> > +    SysBusDevice parent_obj;
> > +
> > +    /*< public >*/
> > +    TPMCRBState state;
> > +    uint64_t baseaddr;
> > +    uint64_t size;
> > +};
> > +
> > +OBJECT_DECLARE_SIMPLE_TYPE(TPMCRBStateSysBus, TPM_CRB_SYSBUS)
> > +
> > +static void tpm_crb_sysbus_request_completed(TPMIf *ti, int ret)
> > +{
> > +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
> > +
> > +    return tpm_crb_request_completed(&s->state, ret);
> > +}
> > +
> > +static enum TPMVersion tpm_crb_sysbus_get_tpm_version(TPMIf *ti)
> > +{
> > +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(ti);
> > +
> > +    return tpm_crb_get_version(&s->state);
> > +}
> > +
> > +static int tpm_crb_sysbus_pre_save(void *opaque)
> > +{
> > +    TPMCRBStateSysBus *s = opaque;
> > +
> > +    return tpm_crb_pre_save(&s->state);
> > +}
> > +
> > +static const VMStateDescription vmstate_tpm_crb_sysbus = {
> > +    .name = "tpm-crb-sysbus",
> > +    .pre_save = tpm_crb_sysbus_pre_save,
> > +    .fields = (VMStateField[]) {
> > +        VMSTATE_END_OF_LIST(),
> > +    }
> > +};
> > +
> > +static Property tpm_crb_sysbus_properties[] = {
> > +    DEFINE_PROP_TPMBE("tpmdev", TPMCRBStateSysBus, state.tpmbe),
> > +    DEFINE_PROP_UINT64("baseaddr", TPMCRBStateSysBus,
> > +                       baseaddr, TPM_CRB_ADDR_BASE),
> > +    DEFINE_PROP_UINT64("size", TPMCRBStateSysBus, size, TPM_CRB_ADDR_SIZE),
> > +    DEFINE_PROP_END_OF_LIST(),
> > +};
> > +
> > +static void tpm_crb_sysbus_initfn(Object *obj)
> > +{
> > +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(obj);
> > +
> > +    tpm_crb_init_memory(obj, &s->state, NULL);
> > +
> > +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->state.mmio);
> > +}
> > +
> > +static void tpm_crb_sysbus_reset(DeviceState *dev)
> > +{
> > +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
> > +
> > +    return tpm_crb_reset(&s->state, s->baseaddr);
> > +}
> > +
> > +static void tpm_crb_sysbus_realizefn(DeviceState *dev, Error **errp)
> > +{
> > +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(dev);
> > +
> > +    if (!tpm_find()) {
> > +        error_setg(errp, "at most one TPM device is permitted");
> > +        return;
> > +    }
> > +
> > +    if (!s->state.tpmbe) {
> > +        error_setg(errp, "'tpmdev' property is required");
> > +        return;
> > +    }
>
> above parts can be common with ISA vesion
This was done in order to abstract away the callback interface. All
the common code uses `TPMCRBState` instead of `TPMIf` as the argument
and it is cleaner this way IMO.

>
> > +    if (tpm_crb_sysbus_get_tpm_version(TPM_IF(s)) != TPM_VERSION_2_0) {
> > +        error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
> > +        return;
> why ISA version doesn't require this?
TPM CRB is only defined for 2.0. We can add this in the ISA version
but it would break any existing VM which depended on this erroneous
behaviour. Better to keep this check only on the new device.

>
> > +    }
> > +}
> > +
> > +static void build_tpm_crb_sysbus_aml(AcpiDevAmlIf *adev, Aml *scope)
> > +{
> > +    Aml *dev, *crs;
> > +    TPMCRBStateSysBus *s = TPM_CRB_SYSBUS(adev);
> > +    TPMIf *ti = TPM_IF(s);
> > +
> > +    dev = aml_device("TPM");
> > +    aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> > +    aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
> > +    aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> > +    aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
> > +    crs = aml_resource_template();
> > +    aml_append(crs, aml_memory32_fixed(s->baseaddr, s->size,
> > +                                      AML_READ_WRITE));
> > +    aml_append(dev, aml_name_decl("_CRS", crs));
> > +    aml_append(scope, dev);
> > +}
>
> this almost matches isa version, modulo hard-codded address/size
> (suggest to generalize and reuse it in both places)
Done.

> and ppi, why sysbus variant doesn't implement PPI parts?
The support has not been implemented. See
4c46fe2ed492f35f411632c8b5a8442f322bc3f0 for disabling this option on
TIS sysbus devices.

>
> > +
> > +static void tpm_crb_sysbus_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +    TPMIfClass *tc = TPM_IF_CLASS(klass);
> > +    AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
> > +
> > +    device_class_set_props(dc, tpm_crb_sysbus_properties);
> > +    dc->vmsd  = &vmstate_tpm_crb_sysbus;
> > +    tc->model = TPM_MODEL_TPM_CRB;
> > +    dc->realize = tpm_crb_sysbus_realizefn;
> > +    dc->user_creatable = true;
> > +    dc->reset = tpm_crb_sysbus_reset;
> > +    tc->request_completed = tpm_crb_sysbus_request_completed;
> > +    tc->get_version = tpm_crb_sysbus_get_tpm_version;
> > +    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> > +    adevc->build_dev_aml = build_tpm_crb_sysbus_aml;
> > +}
> > +
> > +static const TypeInfo tpm_crb_sysbus_info = {
> > +    .name = TYPE_TPM_CRB_SYSBUS,
> > +    .parent = TYPE_SYS_BUS_DEVICE,
> > +    .instance_size = sizeof(TPMCRBStateSysBus),
> > +    .instance_init = tpm_crb_sysbus_initfn,
> > +    .class_init  = tpm_crb_sysbus_class_init,
> > +    .interfaces = (InterfaceInfo[]) {
> > +        { TYPE_TPM_IF },
> > +        { TYPE_ACPI_DEV_AML_IF },
> > +        { }
> > +    }
> > +};
> > +
> > +static void tpm_crb_sysbus_register(void)
> > +{
> > +    type_register_static(&tpm_crb_sysbus_info);
> > +}
> > +
> > +type_init(tpm_crb_sysbus_register)
> > diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> > index 7e68348440..efe1beaa7b 100644
> > --- a/hw/arm/Kconfig
> > +++ b/hw/arm/Kconfig
> > @@ -5,6 +5,7 @@ config ARM_VIRT
> >      imply VFIO_AMD_XGBE
> >      imply VFIO_PLATFORM
> >      imply VFIO_XGMAC
> > +    imply TPM_CRB_SYSBUS
> >      imply TPM_TIS_SYSBUS
> >      imply TPM_TIS_I2C
> >      imply NVDIMM
> > diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
> > index b6a5eb4452..d824cb58f9 100644
> > --- a/hw/riscv/Kconfig
> > +++ b/hw/riscv/Kconfig
> > @@ -29,6 +29,7 @@ config RISCV_VIRT
> >      imply PCI_DEVICES
> >      imply VIRTIO_VGA
> >      imply TEST_DEVICES
> > +    imply TPM_CRB_SYSBUS
> >      imply TPM_TIS_SYSBUS
> >      select RISCV_NUMA
> >      select GOLDFISH_RTC
> > diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
> > index 1fd73fe617..3f294a20ba 100644
> > --- a/hw/tpm/Kconfig
> > +++ b/hw/tpm/Kconfig
> > @@ -25,6 +25,11 @@ config TPM_CRB
> >      depends on TPM && ISA_BUS
> >      select TPM_BACKEND
> >
> > +config TPM_CRB_SYSBUS
> > +    bool
> > +    depends on TPM
> > +    select TPM_BACKEND
> > +
> >  config TPM_SPAPR
> >      bool
> >      default y
> > diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build
> > index cb8204d5bc..d96de92c16 100644
> > --- a/hw/tpm/meson.build
> > +++ b/hw/tpm/meson.build
> > @@ -4,6 +4,8 @@ system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: files('tpm_tis_sysbus.c'))
> >  system_ss.add(when: 'CONFIG_TPM_TIS_I2C', if_true: files('tpm_tis_i2c.c'))
> >  system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
> >  system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb_common.c'))
> > +system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_sysbus.c'))
> > +system_ss.add(when: 'CONFIG_TPM_CRB_SYSBUS', if_true: files('tpm_crb_common.c'))
> >  system_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_ppi.c'))
> >  system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_ppi.c'))
> >
>


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

end of thread, other threads:[~2023-10-29  2:23 UTC | newest]

Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-14  7:09 [PATCH v2 00/11] tpm: introduce TPM CRB SysBus device Joelle van Dyne
2023-07-14  7:09 ` [PATCH v2 01/11] tpm_crb: refactor common code Joelle van Dyne
2023-07-14  7:09 ` [PATCH v2 02/11] tpm_crb: CTRL_RSP_ADDR is 64-bits wide Joelle van Dyne
2023-07-14  7:09 ` [PATCH v2 03/11] tpm_ppi: refactor memory space initialization Joelle van Dyne
2023-07-14  7:09 ` [PATCH v2 04/11] tpm_crb: use a single read-as-mem/write-as-mmio mapping Joelle van Dyne
2023-07-14 12:03   ` Stefan Berger
2023-07-14  7:09 ` [PATCH v2 05/11] tpm_crb: use the ISA bus Joelle van Dyne
2023-07-17 13:46   ` Igor Mammedov
2023-07-18 14:16     ` Stefan Berger
2023-08-01  1:46       ` Joelle van Dyne
2023-10-17 14:24         ` Alexander Graf
2023-07-14  7:09 ` [PATCH v2 06/11] tpm_crb: move ACPI table building to device interface Joelle van Dyne
2023-07-14 17:21   ` Stefan Berger
2023-07-17 13:42     ` Igor Mammedov
2023-08-01  3:02       ` Joelle van Dyne
2023-08-01 19:38         ` Stefan Berger
2023-08-07 10:20           ` Igor Mammedov
2023-07-14  7:09 ` [PATCH v2 07/11] hw/arm/virt: add plug handler for TPM on SysBus Joelle van Dyne
2023-07-14 12:11   ` Stefan Berger
2023-07-14 17:09     ` Joelle van Dyne
2023-07-17 14:00   ` Igor Mammedov
2023-07-14  7:09 ` [PATCH v2 08/11] hw/loongarch/virt: " Joelle van Dyne
2023-07-20 17:57   ` Stefan Berger
2023-08-03 11:35     ` Stefan Berger
2023-07-14  7:09 ` [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device Joelle van Dyne
2023-07-14 16:19   ` Stefan Berger
2023-07-14 17:29     ` Joelle van Dyne
2023-07-14 17:37       ` Stefan Berger
2023-07-14 17:39         ` Joelle van Dyne
2023-07-14 17:43           ` Stefan Berger
2023-07-14 17:46             ` Joelle van Dyne
2023-07-14 18:01               ` Stefan Berger
2023-07-14 18:15                 ` Joelle van Dyne
2023-07-17 14:06       ` Igor Mammedov
2023-07-14  7:09 ` [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device Joelle van Dyne
2023-07-14 14:27   ` Stefan Berger
2023-07-14 17:20     ` Joelle van Dyne
2023-07-14 17:52       ` Stefan Berger
2023-07-17 14:23   ` Igor Mammedov
2023-10-29  2:21     ` Joelle van Dyne
2023-07-14  7:09 ` [PATCH v2 11/11] tpm_crb: support restoring older vmstate Joelle van Dyne
2023-07-14 14:05   ` Stefan Berger
2023-07-14 14:51     ` Stefan Berger
2023-07-14 17:04       ` Joelle van Dyne
2023-07-14 18:22         ` Stefan Berger
2023-07-14 18:41           ` Stefan Berger
2023-07-14 18:49             ` Joelle van Dyne
2023-07-14 19:12               ` Stefan Berger
2023-07-14 19:44                 ` Joelle van Dyne
2023-07-14 19:56                   ` Stefan Berger
2023-07-17 14:40                 ` Peter Maydell
2023-07-17 14:33               ` Igor Mammedov

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.