From nobody Fri Jun 16 06:23:05 2023 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4Qj8Gx3Nf2z4fJc4; Fri, 16 Jun 2023 06:23:05 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4Qj8Gx2pzJz3w3P; Fri, 16 Jun 2023 06:23:05 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1686896585; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Mijnsl1vNQEV+ILTNzPYJEbKSBTh6cao4+QCjkG0NMU=; b=nG5JipzPw0Gtulq+wd66LOmFGli5elhOzPeygCkM39QRD96Ag648ID6PYHSu1+3MEH4Zva rXiEtTEfO3c/RV43QpIPjnMllzqN+JCzdKtYJMzy17DSbkwSAdIDFyejK4RKVsbArTFE0J jKaxW3WFidUvM2efi6fAtPuVjtiWK5AS5Q5BC6ow8E0A7M9BArMIGnpwF94Tjw+mR/rW4G Dc+120gJh098iYIqhhMD14S/pTM6qpXCVSiERFT6s50oq+h8kz1Mbtvrf9Ydvicoy/Zx/j k0sPrZQ9kWuZ8Z/KcWVygbbH3+zSrcqvYLV6WFCimQK+xDwxgZIfWlYh2RlNag== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1686896585; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Mijnsl1vNQEV+ILTNzPYJEbKSBTh6cao4+QCjkG0NMU=; b=KXQrD2Xr0KTXvFF5TpBm15koFmGb5VieHdkn1U6qz6CfoHr5sLRit2H7dYbtPG4DPC416B O0Ily4pyOYZ3SUVU9GfpxmZ6CL2ljz2CISJtc9m5BtLT5XC+lk5lGvjEPRC3BjTF2zVYoP /udVolitkJdklA6EGAmp4G69KcB0wvCWA/MjjYRjgvg1nYaMvinSYiJzP92n/C5HhhKwS5 deQnNLV176UvxtNB7MiOmuLzCJAtgXKk6PLl+Hg/Mf0y6lgMbo2JNvtE1vC20htTg+gSWc U2Re1T7wBtVZMEZh0W40OZuys7b3S45QbXolIR6EPptDDr7NyQHRGmhROhYXaQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1686896585; a=rsa-sha256; cv=none; b=PfrzKZ9GrcIOGPP5MgM4aZSaRpX0Vy2UDoYylDeYkmHCSlOCBN2fTeoIKk4Ire+m2jn9jj aBiybwS9IF5f10CxxiZn45Jvs7QxY3Hy1OoyEFrOm3NKWiAYYz/86xNxRD8x5ejMGcmnjI manDz3mv76AvebQPbYEq9c7xAIg5gI3lYiJ7yJfkJj3zN0vhgr5HHScgbN/VartgLWHfxW 7QMr20V14PT1nf4dKrDaUVAj+0L3GsIu+KmTMNTTsdR7YfGdF/rmuliVE3vvErGG0D4YfH OX2FoTY4N6NoJVfWJM6i//6x3sQGUbFaG/mwIfccD3FC50clsDBftnxHanyfRA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4Qj8Gx1sn8zHH8; Fri, 16 Jun 2023 06:23:05 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 35G6N55r051651; Fri, 16 Jun 2023 06:23:05 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 35G6N5E7051650; Fri, 16 Jun 2023 06:23:05 GMT (envelope-from git) Date: Fri, 16 Jun 2023 06:23:05 GMT Message-Id: <202306160623.35G6N5E7051650@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: =?utf-8?Q?Corvin=20K=C3=B6hne?= Subject: git: 0917f925b46e - main - bhyve: add basic CRB interface for TPM devices List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: corvink X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 0917f925b46e3142c4373d1591bf22014d0f338e Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by corvink: URL: https://cgit.FreeBSD.org/src/commit/?id=0917f925b46e3142c4373d1591bf22014d0f338e commit 0917f925b46e3142c4373d1591bf22014d0f338e Author: Corvin Köhne AuthorDate: 2022-08-29 10:10:43 +0000 Commit: Corvin Köhne CommitDate: 2023-06-16 06:22:53 +0000 bhyve: add basic CRB interface for TPM devices Add a basic emulation for the command and response buffer interface of TPM devices. This commit only implements some CRB register and resets them. Reviewed by: markj MFC after: 1 week Sponsored by: Beckhoff Automation GmbH & Co. KG Differential Revision: https://reviews.freebsd.org/D40456 --- usr.sbin/bhyve/Makefile | 1 + usr.sbin/bhyve/tpm_device.c | 29 ++++++ usr.sbin/bhyve/tpm_intf.h | 35 +++++++ usr.sbin/bhyve/tpm_intf_crb.c | 232 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 297 insertions(+) diff --git a/usr.sbin/bhyve/Makefile b/usr.sbin/bhyve/Makefile index fc880566228b..9b8a7274d793 100644 --- a/usr.sbin/bhyve/Makefile +++ b/usr.sbin/bhyve/Makefile @@ -77,6 +77,7 @@ SRCS= \ task_switch.c \ tpm_device.c \ tpm_emul_passthru.c \ + tpm_intf_crb.c \ uart_emul.c \ usb_emul.c \ usb_mouse.c \ diff --git a/usr.sbin/bhyve/tpm_device.c b/usr.sbin/bhyve/tpm_device.c index 3a847cc53a9b..e1db0bab1ee9 100644 --- a/usr.sbin/bhyve/tpm_device.c +++ b/usr.sbin/bhyve/tpm_device.c @@ -18,17 +18,21 @@ #include "config.h" #include "tpm_device.h" #include "tpm_emul.h" +#include "tpm_intf.h" #define TPM_ACPI_DEVICE_NAME "TPM" #define TPM_ACPI_HARDWARE_ID "MSFT0101" SET_DECLARE(tpm_emul_set, struct tpm_emul); +SET_DECLARE(tpm_intf_set, struct tpm_intf); struct tpm_device { struct vmctx *vm_ctx; struct acpi_device *acpi_dev; struct tpm_emul *emul; void *emul_sc; + struct tpm_intf *intf; + void *intf_sc; }; static const struct acpi_device_emul tpm_acpi_device_emul = { @@ -42,6 +46,8 @@ tpm_device_destroy(struct tpm_device *const dev) if (dev == NULL) return; + if (dev->intf != NULL && dev->intf->deinit != NULL) + dev->intf->deinit(dev->intf_sc); if (dev->emul != NULL && dev->emul->deinit != NULL) dev->emul->deinit(dev->emul_sc); @@ -55,6 +61,7 @@ tpm_device_create(struct tpm_device **const new_dev, struct vmctx *const vm_ctx, { struct tpm_device *dev = NULL; struct tpm_emul **ppemul; + struct tpm_intf **ppintf; const char *value; int error; @@ -63,6 +70,8 @@ tpm_device_create(struct tpm_device **const new_dev, struct vmctx *const vm_ctx, goto err_out; } + set_config_value_node_if_unset(nvl, "intf", "crb"); + value = get_config_value_node(nvl, "version"); assert(value != NULL); if (strcmp(value, "2.0")) { @@ -104,6 +113,26 @@ tpm_device_create(struct tpm_device **const new_dev, struct vmctx *const vm_ctx, goto err_out; } + value = get_config_value_node(nvl, "intf"); + SET_FOREACH(ppintf, tpm_intf_set) { + if (strcmp(value, (*ppintf)->name)) { + continue; + } + dev->intf = *ppintf; + break; + } + if (dev->intf == NULL) { + warnx("TPM interface \"%s\" not found", value); + error = EINVAL; + goto err_out; + } + + if (dev->intf->init) { + error = dev->intf->init(&dev->intf_sc); + if (error) + goto err_out; + } + *new_dev = dev; return (0); diff --git a/usr.sbin/bhyve/tpm_intf.h b/usr.sbin/bhyve/tpm_intf.h new file mode 100644 index 000000000000..7de7bc6d4435 --- /dev/null +++ b/usr.sbin/bhyve/tpm_intf.h @@ -0,0 +1,35 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG + * Author: Corvin Köhne + */ + +#pragma once + +#include "config.h" +#include "tpm_device.h" + +#define TPM_INTF_TYPE_FIFO_PTP 0x0 +#define TPM_INTF_TYPE_CRB 0x1 +#define TPM_INTF_TYPE_FIFO_TIS 0xF + +#define TPM_INTF_VERSION_FIFO 0 +#define TPM_INTF_VERSION_CRB 1 + +#define TPM_INTF_CAP_CRB_DATA_XFER_SIZE_4 0 +#define TPM_INTF_CAP_CRB_DATA_XFER_SIZE_8 1 +#define TPM_INTF_CAP_CRB_DATA_XFER_SIZE_32 2 +#define TPM_INTF_CAP_CRB_DATA_XFER_SIZE_64 3 + +#define TPM_INTF_SELECTOR_FIFO 0 +#define TPM_INTF_SELECTOR_CRB 1 + +struct tpm_intf { + const char *name; + + int (*init)(void **sc); + void (*deinit)(void *sc); + int (*build_acpi_table)(void *sc); +}; +#define TPM_INTF_SET(x) DATA_SET(tpm_intf_set, x) diff --git a/usr.sbin/bhyve/tpm_intf_crb.c b/usr.sbin/bhyve/tpm_intf_crb.c new file mode 100644 index 000000000000..5fd640b2d5c9 --- /dev/null +++ b/usr.sbin/bhyve/tpm_intf_crb.c @@ -0,0 +1,232 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2022 Beckhoff Automation GmbH & Co. KG + * Author: Corvin Köhne + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "basl.h" +#include "config.h" +#include "mem.h" +#include "qemu_fwcfg.h" +#include "tpm_intf.h" + +#define TPM_CRB_ADDRESS 0xFED40000 +#define TPM_CRB_REGS_SIZE 0x1000 + +#define TPM_CRB_DATA_BUFFER_ADDRESS \ + (TPM_CRB_ADDRESS + offsetof(struct tpm_crb_regs, data_buffer)) +#define TPM_CRB_DATA_BUFFER_SIZE 0xF80 + +#define TPM_CRB_LOCALITIES_MAX 5 + +struct tpm_crb_regs { + union tpm_crb_reg_loc_state { + struct { + uint32_t tpm_established : 1; + uint32_t loc_assigned : 1; + uint32_t active_locality : 3; + uint32_t _reserved : 2; + uint32_t tpm_req_valid_sts : 1; + }; + uint32_t val; + } loc_state; /* 0h */ + uint8_t _reserved1[4]; /* 4h */ + union tpm_crb_reg_loc_ctrl { + struct { + uint32_t request_access : 1; + uint32_t relinquish : 1; + uint32_t seize : 1; + uint32_t reset_establishment_bit : 1; + }; + uint32_t val; + } loc_ctrl; /* 8h */ + union tpm_crb_reg_loc_sts { + struct { + uint32_t granted : 1; + uint32_t been_seized : 1; + }; + uint32_t val; + } loc_sts; /* Ch */ + uint8_t _reserved2[0x20]; /* 10h */ + union tpm_crb_reg_intf_id { + struct { + uint64_t interface_type : 4; + uint64_t interface_version : 4; + uint64_t cap_locality : 1; + uint64_t cap_crb_idle_bypass : 1; + uint64_t _reserved1 : 1; + uint64_t cap_data_xfer_size_support : 2; + uint64_t cap_fifo : 1; + uint64_t cap_crb : 1; + uint64_t _reserved2 : 2; + uint64_t interface_selector : 2; + uint64_t intf_sel_lock : 1; + uint64_t _reserved3 : 4; + uint64_t rid : 8; + uint64_t vid : 16; + uint64_t did : 16; + }; + uint64_t val; + } intf_id; /* 30h */ + union tpm_crb_reg_ctrl_ext { + struct { + uint32_t clear; + uint32_t remaining_bytes; + }; + uint64_t val; + } ctrl_ext; /* 38 */ + union tpm_crb_reg_ctrl_req { + struct { + uint32_t cmd_ready : 1; + uint32_t go_idle : 1; + }; + uint32_t val; + } ctrl_req; /* 40h */ + union tpm_crb_reg_ctrl_sts { + struct { + uint32_t tpm_sts : 1; + uint32_t tpm_idle : 1; + }; + uint32_t val; + } ctrl_sts; /* 44h */ + union tpm_crb_reg_ctrl_cancel { + struct { + uint32_t cancel : 1; + }; + uint32_t val; + } ctrl_cancel; /* 48h */ + union tpm_crb_reg_ctrl_start { + struct { + uint32_t start : 1; + }; + uint32_t val; + } ctrl_start; /* 4Ch*/ + uint32_t int_enable; /* 50h */ + uint32_t int_sts; /* 54h */ + uint32_t cmd_size; /* 58h */ + uint32_t cmd_addr_lo; /* 5Ch */ + uint32_t cmd_addr_hi; /* 60h */ + uint32_t rsp_size; /* 64h */ + uint64_t rsp_addr; /* 68h */ + uint8_t _reserved3[0x10]; /* 70h */ + uint8_t data_buffer[TPM_CRB_DATA_BUFFER_SIZE]; /* 80h */ +} __packed; +static_assert(sizeof(struct tpm_crb_regs) == TPM_CRB_REGS_SIZE, + "Invalid size of tpm_crb"); + +#define CRB_CMD_SIZE_READ(regs) (regs.cmd_size) +#define CRB_CMD_SIZE_WRITE(regs, val) \ + do { \ + regs.cmd_size = val; \ + } while (0) +#define CRB_CMD_ADDR_READ(regs) \ + (((uint64_t)regs.cmd_addr_hi << 32) | regs.cmd_addr_lo) +#define CRB_CMD_ADDR_WRITE(regs, val) \ + do { \ + regs.cmd_addr_lo = val & 0xFFFFFFFF; \ + regs.cmd_addr_hi = val >> 32; \ + } while (0) +#define CRB_RSP_SIZE_READ(regs) (regs.rsp_size) +#define CRB_RSP_SIZE_WRITE(regs, val) \ + do { \ + regs.rsp_size = val; \ + } while (0) +#define CRB_RSP_ADDR_READ(regs) (regs.rsp_addr) +#define CRB_RSP_ADDR_WRITE(regs, val) \ + do { \ + regs.rsp_addr = val; \ + } while (0) + +struct tpm_crb { + struct tpm_crb_regs regs; +}; + +static int +tpm_crb_init(void **sc) +{ + struct tpm_crb *crb = NULL; + int error; + + assert(sc != NULL); + + crb = calloc(1, sizeof(struct tpm_crb)); + if (crb == NULL) { + warnx("%s: failed to allocate tpm crb", __func__); + error = ENOMEM; + goto err_out; + } + + memset(crb, 0, sizeof(*crb)); + + crb->regs.loc_state.tpm_req_valid_sts = true; + crb->regs.loc_state.tpm_established = true; + + crb->regs.intf_id.interface_type = TPM_INTF_TYPE_CRB; + crb->regs.intf_id.interface_version = TPM_INTF_VERSION_CRB; + crb->regs.intf_id.cap_locality = false; + crb->regs.intf_id.cap_crb_idle_bypass = false; + crb->regs.intf_id.cap_data_xfer_size_support = + TPM_INTF_CAP_CRB_DATA_XFER_SIZE_64; + crb->regs.intf_id.cap_fifo = false; + crb->regs.intf_id.cap_crb = true; + crb->regs.intf_id.interface_selector = TPM_INTF_SELECTOR_CRB; + crb->regs.intf_id.intf_sel_lock = false; + crb->regs.intf_id.rid = 0; + crb->regs.intf_id.vid = 0x1014; /* IBM */ + crb->regs.intf_id.did = 0x1014; /* IBM */ + + crb->regs.ctrl_sts.tpm_idle = true; + + CRB_CMD_SIZE_WRITE(crb->regs, TPM_CRB_DATA_BUFFER_SIZE); + CRB_CMD_ADDR_WRITE(crb->regs, TPM_CRB_DATA_BUFFER_ADDRESS); + CRB_RSP_SIZE_WRITE(crb->regs, TPM_CRB_DATA_BUFFER_SIZE); + CRB_RSP_ADDR_WRITE(crb->regs, TPM_CRB_DATA_BUFFER_ADDRESS); + + *sc = crb; + + return (0); + +err_out: + free(crb); + + return (error); +} + +static void +tpm_crb_deinit(void *sc) +{ + struct tpm_crb *crb; + + if (sc == NULL) { + return; + } + + crb = sc; + + free(crb); +} + +static struct tpm_intf tpm_intf_crb = { + .name = "crb", + .init = tpm_crb_init, + .deinit = tpm_crb_deinit, +}; +TPM_INTF_SET(tpm_intf_crb);