From nobody Tue Jun 20 09:01:01 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 4QlgbL14kZz4dsnZ; Tue, 20 Jun 2023 09:01:02 +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 4QlgbL0Yg6z42Vl; Tue, 20 Jun 2023 09:01:02 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1687251662; 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=XYT1ZpmcqH3xksWQLM0NHvEIpauSvknru2qVxujWodE=; b=Gjc3LT+xbFNEoubocQVsxYRLqgQEiJfiFT7QBnSCO6algJAaKcK4nwdlHSs53yjwLXFBeQ XU8np5GNFe2tsXBcdFp0JPwxBLIIdPIqSaGO+9QsqeS9YVRjs1YOVyFVwvVG7MGHz7ZWLc zZ1nYXfJ2yMPrWxDZ/D6ShOmBujUKN0O8xU5qrUsM1fZoz0YQAHJ3XP4qqiEbYSA6pS2v8 7pMxuwRGmNcWVr/9G+vkJPGn3HrXMxH6alTEECb4JYgysT+I3iqPiJapiHC7CseJZvRY0v w28Usgl9InJFPFfP0rbaYyyS17U5SUwHgAwc6P8mzPJoBWGojbawNcTkfILHrg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1687251662; 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=XYT1ZpmcqH3xksWQLM0NHvEIpauSvknru2qVxujWodE=; b=PuLV32JhiynHsNtHtd9xeDwpzB60rujrHnJAvnsiTls5Y8vaFK5txxrgRkOs4wk2lpK/DW AjytZQDvO+gn8GCIWIZuZqWR9Q/cpGFZ4HV0pGRMz2aU/MWnDwBxHVTrHdKSJT7yyp09ay tmFgtuv6BehBWbtIS2I8pC6Qh+LUK4rGbeLtFqzg9Gi5jBh6dcrmlOTW04Yz/BUB/uJxbb IVZW7LCxaKUZh98HvUZBgbQK9jlBq4xjes2ib6wFW1DJLHEPN4/NuBdzSUG2sy/dEgUEU0 TJ5cLRKh1SUJHTCvBcI49kEUOxlRcrEpyTYnuC/60uCW13IuYPCLJO6Byru2Vg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1687251662; a=rsa-sha256; cv=none; b=Yemu4TJNvB7M3g078u1pLfj+trgD4aHt1wsAnrPUwtLWNtkyneDcuBhD1DJnrc0juqkKMG Pnjb7zZrhyoTjd4nv9Sa527KuAZlf2fJ3IkJonAtH9jruHYivV4tL0kBBJ8jfN4JVgu3BC e2RroQNGmvljraXzORjgWQRS7MOWGDtIhrOHQgH7tlQtvcZxdFzzH42ej2Y8u+72Ov4K7k DPbhVh7CYEWHSt/hzdPHg+s8NEXLDFdlNzEh8nHg27c4pq5LuDTr4o0Npt7igAcN5pYc/u wsQVTQUaHd+abERIXtlbDJ5buk2MTonX1yZh8cuN0eM2NO2ISEIAIfuFQPUQyw== 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 4QlgbK6Tg0zst4; Tue, 20 Jun 2023 09:01:01 +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 35K911QI009682; Tue, 20 Jun 2023 09:01:01 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 35K9118Y009681; Tue, 20 Jun 2023 09:01:01 GMT (envelope-from git) Date: Tue, 20 Jun 2023 09:01:01 GMT Message-Id: <202306200901.35K9118Y009681@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: 0daf5f02cfaf - main - bhyve/tpm: create crb thread for sending tpm commands 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: 0daf5f02cfaf08a7fad75d934bbea50242c98ab3 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by corvink: URL: https://cgit.FreeBSD.org/src/commit/?id=0daf5f02cfaf08a7fad75d934bbea50242c98ab3 commit 0daf5f02cfaf08a7fad75d934bbea50242c98ab3 Author: Corvin Köhne AuthorDate: 2022-08-29 10:10:44 +0000 Commit: Corvin Köhne CommitDate: 2023-06-20 08:59:00 +0000 bhyve/tpm: create crb thread for sending tpm commands Commands send to a tpm are very slow. They can take up to several seconds for completion. For that reason, create a thread which issues the commands to the tpm device. Reviewed by: markj MFC after: 1 week Sponsored by: Beckhoff Automation GmbH & Co. KG Differential Revision: https://reviews.freebsd.org/D40458 --- usr.sbin/bhyve/tpm_device.c | 2 +- usr.sbin/bhyve/tpm_emul.h | 2 + usr.sbin/bhyve/tpm_intf.h | 3 +- usr.sbin/bhyve/tpm_intf_crb.c | 102 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 105 insertions(+), 4 deletions(-) diff --git a/usr.sbin/bhyve/tpm_device.c b/usr.sbin/bhyve/tpm_device.c index 94e9f1ffdc27..3ff480d5e6bb 100644 --- a/usr.sbin/bhyve/tpm_device.c +++ b/usr.sbin/bhyve/tpm_device.c @@ -141,7 +141,7 @@ tpm_device_create(struct tpm_device **const new_dev, struct vmctx *const vm_ctx, } if (dev->intf->init) { - error = dev->intf->init(&dev->intf_sc); + error = dev->intf->init(&dev->intf_sc, dev->emul, dev->emul_sc); if (error) goto err_out; } diff --git a/usr.sbin/bhyve/tpm_emul.h b/usr.sbin/bhyve/tpm_emul.h index f75c0318d37e..24452c92d3b8 100644 --- a/usr.sbin/bhyve/tpm_emul.h +++ b/usr.sbin/bhyve/tpm_emul.h @@ -18,5 +18,7 @@ struct tpm_emul { int (*init)(void **sc, nvlist_t *nvl); void (*deinit)(void *sc); + int (*execute_cmd)(void *sc, void *cmd, uint32_t cmd_size, void *rsp, + uint32_t rsp_size); }; #define TPM_EMUL_SET(x) DATA_SET(tpm_emul_set, x) diff --git a/usr.sbin/bhyve/tpm_intf.h b/usr.sbin/bhyve/tpm_intf.h index 3003d8fbd754..020743c0c3f1 100644 --- a/usr.sbin/bhyve/tpm_intf.h +++ b/usr.sbin/bhyve/tpm_intf.h @@ -11,6 +11,7 @@ #include "config.h" #include "tpm_device.h" +#include "tpm_emul.h" #define TPM_INTF_TYPE_FIFO_PTP 0x0 #define TPM_INTF_TYPE_CRB 0x1 @@ -30,7 +31,7 @@ struct tpm_intf { const char *name; - int (*init)(void **sc); + int (*init)(void **sc, struct tpm_emul *emul, void *emul_sc); void (*deinit)(void *sc); int (*build_acpi_table)(void *sc, struct vmctx *vm_ctx); }; diff --git a/usr.sbin/bhyve/tpm_intf_crb.c b/usr.sbin/bhyve/tpm_intf_crb.c index b8ae33c5ec0a..a920eb5a67e6 100644 --- a/usr.sbin/bhyve/tpm_intf_crb.c +++ b/usr.sbin/bhyve/tpm_intf_crb.c @@ -26,6 +26,7 @@ #include "config.h" #include "mem.h" #include "qemu_fwcfg.h" +#include "tpm_device.h" #include "tpm_intf.h" #define TPM_CRB_ADDRESS 0xFED40000 @@ -45,6 +46,8 @@ #define TPM_CRB_LOG_AREA_FWCFG_NAME "etc/tpm/log" +#define TPM_CRB_INTF_NAME "crb" + struct tpm_crb_regs { union tpm_crb_reg_loc_state { struct { @@ -164,17 +167,82 @@ static_assert(sizeof(struct tpm_crb_regs) == TPM_CRB_REGS_SIZE, } while (0) struct tpm_crb { + struct tpm_emul *emul; + void *emul_sc; uint8_t tpm_log_area[TPM_CRB_LOG_AREA_MINIMUM_SIZE]; struct tpm_crb_regs regs; + pthread_t thread; + pthread_mutex_t mutex; + pthread_cond_t cond; + bool closing; }; +static void * +tpm_crb_thread(void *const arg) +{ + struct tpm_crb *const crb = arg; + + pthread_mutex_lock(&crb->mutex); + for (;;) { + pthread_cond_wait(&crb->cond, &crb->mutex); + + if (crb->closing) + break; + + const uint64_t cmd_addr = CRB_CMD_ADDR_READ(crb->regs); + const uint64_t rsp_addr = CRB_RSP_ADDR_READ(crb->regs); + const uint32_t cmd_size = CRB_CMD_SIZE_READ(crb->regs); + const uint32_t rsp_size = CRB_RSP_SIZE_READ(crb->regs); + + const uint64_t cmd_off = cmd_addr - TPM_CRB_DATA_BUFFER_ADDRESS; + const uint64_t rsp_off = rsp_addr - TPM_CRB_DATA_BUFFER_ADDRESS; + + if (cmd_off > TPM_CRB_DATA_BUFFER_SIZE || + cmd_off + cmd_size > TPM_CRB_DATA_BUFFER_SIZE || + rsp_off > TPM_CRB_DATA_BUFFER_SIZE || + rsp_off + rsp_size > TPM_CRB_DATA_BUFFER_SIZE) { + warnx( + "%s: invalid cmd [%16lx, %16lx] --> [%16lx, %16lx]\n\r", + __func__, cmd_addr, cmd_addr + cmd_size, rsp_addr, + rsp_addr + rsp_size); + break; + } + + /* + * The command response buffer interface uses a single buffer + * for sending a command to and receiving a response from the + * tpm. To avoid reading old data from the command buffer which + * might be a security issue, we zero out the command buffer + * before writing the response into it. The rsp_size parameter + * is controlled by the guest and it's not guaranteed that the + * response has a size of rsp_size (e.g. if the tpm returned an + * error, the response would have a different size than + * expected). For that reason, use a second buffer for the + * response. + */ + uint8_t rsp[TPM_CRB_DATA_BUFFER_SIZE] = { 0 }; + crb->emul->execute_cmd(crb->emul_sc, + &crb->regs.data_buffer[cmd_off], cmd_size, &rsp[rsp_off], + rsp_size); + + memset(crb->regs.data_buffer, 0, TPM_CRB_DATA_BUFFER_SIZE); + memcpy(&crb->regs.data_buffer[rsp_off], &rsp[rsp_off], rsp_size); + + crb->regs.ctrl_start.start = false; + } + pthread_mutex_unlock(&crb->mutex); + + return (NULL); +} + static int -tpm_crb_init(void **sc) +tpm_crb_init(void **sc, struct tpm_emul *emul, void *emul_sc) { struct tpm_crb *crb = NULL; int error; assert(sc != NULL); + assert(emul != NULL); crb = calloc(1, sizeof(struct tpm_crb)); if (crb == NULL) { @@ -185,6 +253,9 @@ tpm_crb_init(void **sc) memset(crb, 0, sizeof(*crb)); + crb->emul = emul; + crb->emul_sc = emul_sc; + crb->regs.loc_state.tpm_req_valid_sts = true; crb->regs.loc_state.tpm_established = true; @@ -216,6 +287,26 @@ tpm_crb_init(void **sc) goto err_out; } + error = pthread_mutex_init(&crb->mutex, NULL); + if (error) { + warnc(error, "%s: failed to init mutex", __func__); + goto err_out; + } + + error = pthread_cond_init(&crb->cond, NULL); + if (error) { + warnc(error, "%s: failed to init cond", __func__); + goto err_out; + } + + error = pthread_create(&crb->thread, NULL, tpm_crb_thread, crb); + if (error) { + warnx("%s: failed to create thread\n", __func__); + goto err_out; + } + + pthread_set_name_np(crb->thread, "tpm_intf_crb"); + *sc = crb; return (0); @@ -237,6 +328,13 @@ tpm_crb_deinit(void *sc) crb = sc; + crb->closing = true; + pthread_cond_signal(&crb->cond); + pthread_join(crb->thread, NULL); + + pthread_cond_destroy(&crb->cond); + pthread_mutex_destroy(&crb->mutex); + free(crb); } @@ -275,7 +373,7 @@ tpm_crb_build_acpi_table(void *sc __unused, struct vmctx *vm_ctx) } static struct tpm_intf tpm_intf_crb = { - .name = "crb", + .name = TPM_CRB_INTF_NAME, .init = tpm_crb_init, .deinit = tpm_crb_deinit, .build_acpi_table = tpm_crb_build_acpi_table,