From nobody Mon Apr 29 02:31:25 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1516371270781625.3162768291364; Fri, 19 Jan 2018 06:14:30 -0800 (PST) Received: from localhost ([::1]:51498 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ecXR8-00027B-0a for importer@patchew.org; Fri, 19 Jan 2018 09:14:30 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56534) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ecXO6-00085T-Ph for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:32 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ecXO0-0004bx-Sx for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:22 -0500 Received: from mx1.redhat.com ([209.132.183.28]:34474) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ecXO0-0004bM-Ke for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:16 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E349247F6; Fri, 19 Jan 2018 14:11:15 +0000 (UTC) Received: from localhost (ovpn-112-58.ams2.redhat.com [10.36.112.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id B198660C8A; Fri, 19 Jan 2018 14:11:12 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Fri, 19 Jan 2018 15:11:00 +0100 Message-Id: <20180119141105.29095-2-marcandre.lureau@redhat.com> In-Reply-To: <20180119141105.29095-1-marcandre.lureau@redhat.com> References: <20180119141105.29095-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Fri, 19 Jan 2018 14:11:15 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v2 1/5] tpm: lookup cancel path under tpm device class X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , stefanb@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Since Linux commit 313d21eeab9282e, tpm devices have their own device class "tpm" and the cancel path must be looked up under /sys/class/tpm/ instead of /sys/class/misc/. Signed-off-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Stefan Berger --- hw/tpm/tpm_passthrough.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c index 29142f38bb..f2563ac668 100644 --- a/hw/tpm/tpm_passthrough.c +++ b/hw/tpm/tpm_passthrough.c @@ -216,7 +216,8 @@ static size_t tpm_passthrough_get_buffer_size(TPMBacken= d *tb) * Unless path or file descriptor set has been provided by user, * determine the sysfs cancel file following kernel documentation * in Documentation/ABI/stable/sysfs-class-tpm. - * From /dev/tpm0 create /sys/class/misc/tpm0/device/cancel + * From /dev/tpm0 create /sys/class/tpm/tpm0/device/cancel + * before 4.0: /sys/class/misc/tpm0/device/cancel */ static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt) { @@ -227,26 +228,35 @@ static int tpm_passthrough_open_sysfs_cancel(TPMPasst= hruState *tpm_pt) if (tpm_pt->options->cancel_path) { fd =3D qemu_open(tpm_pt->options->cancel_path, O_WRONLY); if (fd < 0) { - error_report("Could not open TPM cancel path : %s", + error_report("tpm_passthrough: Could not open TPM cancel path:= %s", strerror(errno)); } return fd; } =20 dev =3D strrchr(tpm_pt->tpm_dev, '/'); - if (dev) { - dev++; - if (snprintf(path, sizeof(path), "/sys/class/misc/%s/device/cancel= ", - dev) < sizeof(path)) { - fd =3D qemu_open(path, O_WRONLY); - if (fd < 0) { - error_report("tpm_passthrough: Could not open TPM cancel " - "path %s : %s", path, strerror(errno)); + if (!dev) { + error_report("tpm_passthrough: Bad TPM device path %s", + tpm_pt->tpm_dev); + return -1; + } + + dev++; + if (snprintf(path, sizeof(path), "/sys/class/tpm/%s/device/cancel", + dev) < sizeof(path)) { + fd =3D qemu_open(path, O_WRONLY); + if (fd < 0) { + if (snprintf(path, sizeof(path), "/sys/class/misc/%s/device/ca= ncel", + dev) < sizeof(path)) { + fd =3D qemu_open(path, O_WRONLY); } } + } + + if (fd < 0) { + error_report("tpm_passthrough: Could not guess TPM cancel path"); } else { - error_report("tpm_passthrough: Bad TPM device path %s", - tpm_pt->tpm_dev); + tpm_pt->options->cancel_path =3D g_strdup(path); } =20 return fd; --=20 2.16.0.rc1.1.gef27df75a1 From nobody Mon Apr 29 02:31:25 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (208.118.235.17 [208.118.235.17]) by mx.zohomail.com with SMTPS id 1516371468949194.7543908693542; Fri, 19 Jan 2018 06:17:48 -0800 (PST) Received: from localhost ([::1]:51602 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ecXUF-0004xS-3b for importer@patchew.org; Fri, 19 Jan 2018 09:17:43 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56536) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ecXO6-00085X-RH for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:29 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ecXO2-0004fU-Lm for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:22 -0500 Received: from mx1.redhat.com ([209.132.183.28]:40492) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ecXO2-0004dY-D3 for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:18 -0500 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AAA651A4085; Fri, 19 Jan 2018 14:11:17 +0000 (UTC) Received: from localhost (ovpn-112-58.ams2.redhat.com [10.36.112.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3422A60C8A; Fri, 19 Jan 2018 14:11:17 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Fri, 19 Jan 2018 15:11:01 +0100 Message-Id: <20180119141105.29095-3-marcandre.lureau@redhat.com> In-Reply-To: <20180119141105.29095-1-marcandre.lureau@redhat.com> References: <20180119141105.29095-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 19 Jan 2018 14:11:17 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v2 2/5] tpm: replace GThreadPool with AIO threadpool X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , stefanb@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" The TPM backend uses a GThreadPool to handle IO in a seperate thread. However, GThreadPool isn't integrated with Qemu main loops, making it unnecessarily complicated to deal with. Qemu has a AIO threadpool, that is better integrated with loops and various IO functions, provides completion BH by default etc. Remove the only user of GThreadPool from qemu, use AIO threadpool. Note that the backend: - no longer accepts queing multiple requests (unneeded so far) - increase ref to itself when handling a command, for extra safety - tpm_backend_thread_end() is renamed tpm_backend_finish_sync() and will wait for completion of BH (request_completed), which will help migration handling. Signed-off-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Stefan Berger Tested-by: Stefan Berger --- include/sysemu/tpm_backend.h | 12 ++++++++-- backends/tpm.c | 52 +++++++++++++++++++++++-----------------= ---- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index 0d6c994a62..a69593e0cd 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -45,9 +45,8 @@ struct TPMBackend { /*< protected >*/ TPMIf *tpmif; bool opened; - GThreadPool *thread_pool; bool had_startup_error; - QEMUBH *bh; + TPMBackendCmd *cmd; =20 /* */ char *id; @@ -196,6 +195,15 @@ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s); */ size_t tpm_backend_get_buffer_size(TPMBackend *s); =20 +/** + * tpm_backend_finish_sync: + * @s: the backend to call into + * + * Finish the pending command synchronously (this will call aio_poll() + * on qemu main AIOContext until it ends) + */ +void tpm_backend_finish_sync(TPMBackend *s); + /** * tpm_backend_query_tpm: * @s: the backend diff --git a/backends/tpm.c b/backends/tpm.c index 91222c5164..143807aa37 100644 --- a/backends/tpm.c +++ b/backends/tpm.c @@ -19,30 +19,35 @@ #include "sysemu/tpm.h" #include "qemu/thread.h" #include "qemu/main-loop.h" +#include "block/thread-pool.h" +#include "qemu/error-report.h" =20 -static void tpm_backend_request_completed_bh(void *opaque) +static void tpm_backend_request_completed(void *opaque, int ret) { TPMBackend *s =3D TPM_BACKEND(opaque); TPMIfClass *tic =3D TPM_IF_GET_CLASS(s->tpmif); =20 tic->request_completed(s->tpmif); + + /* no need for atomic, as long the BQL is taken */ + s->cmd =3D NULL; + object_unref(OBJECT(s)); } =20 -static void tpm_backend_worker_thread(gpointer data, gpointer user_data) +static int tpm_backend_worker_thread(gpointer data) { - TPMBackend *s =3D TPM_BACKEND(user_data); + TPMBackend *s =3D TPM_BACKEND(data); TPMBackendClass *k =3D TPM_BACKEND_GET_CLASS(s); =20 - k->handle_request(s, (TPMBackendCmd *)data); + k->handle_request(s, s->cmd); =20 - qemu_bh_schedule(s->bh); + return 0; } =20 -static void tpm_backend_thread_end(TPMBackend *s) +void tpm_backend_finish_sync(TPMBackend *s) { - if (s->thread_pool) { - g_thread_pool_free(s->thread_pool, FALSE, TRUE); - s->thread_pool =3D NULL; + while (s->cmd) { + aio_poll(qemu_get_aio_context(), true); } } =20 @@ -74,10 +79,7 @@ int tpm_backend_startup_tpm(TPMBackend *s, size_t buffer= size) TPMBackendClass *k =3D TPM_BACKEND_GET_CLASS(s); =20 /* terminate a running TPM */ - tpm_backend_thread_end(s); - - s->thread_pool =3D g_thread_pool_new(tpm_backend_worker_thread, s, 1, = TRUE, - NULL); + tpm_backend_finish_sync(s); =20 res =3D k->startup_tpm ? k->startup_tpm(s, buffersize) : 0; =20 @@ -93,7 +95,17 @@ bool tpm_backend_had_startup_error(TPMBackend *s) =20 void tpm_backend_deliver_request(TPMBackend *s, TPMBackendCmd *cmd) { - g_thread_pool_push(s->thread_pool, cmd, NULL); + ThreadPool *pool =3D aio_get_thread_pool(qemu_get_aio_context()); + + if (s->cmd !=3D NULL) { + error_report("There is a TPM request pending"); + return; + } + + s->cmd =3D cmd; + object_ref(OBJECT(s)); + thread_pool_submit_aio(pool, tpm_backend_worker_thread, s, + tpm_backend_request_completed, s); } =20 void tpm_backend_reset(TPMBackend *s) @@ -104,7 +116,7 @@ void tpm_backend_reset(TPMBackend *s) k->reset(s); } =20 - tpm_backend_thread_end(s); + tpm_backend_finish_sync(s); =20 s->had_startup_error =3D false; } @@ -159,28 +171,18 @@ TPMInfo *tpm_backend_query_tpm(TPMBackend *s) return info; } =20 -static void tpm_backend_instance_init(Object *obj) -{ - TPMBackend *s =3D TPM_BACKEND(obj); - - s->bh =3D qemu_bh_new(tpm_backend_request_completed_bh, s); -} - static void tpm_backend_instance_finalize(Object *obj) { TPMBackend *s =3D TPM_BACKEND(obj); =20 object_unref(OBJECT(s->tpmif)); g_free(s->id); - tpm_backend_thread_end(s); - qemu_bh_delete(s->bh); } =20 static const TypeInfo tpm_backend_info =3D { .name =3D TYPE_TPM_BACKEND, .parent =3D TYPE_OBJECT, .instance_size =3D sizeof(TPMBackend), - .instance_init =3D tpm_backend_instance_init, .instance_finalize =3D tpm_backend_instance_finalize, .class_size =3D sizeof(TPMBackendClass), .abstract =3D true, --=20 2.16.0.rc1.1.gef27df75a1 From nobody Mon Apr 29 02:31:25 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1516371303630602.0728818688965; Fri, 19 Jan 2018 06:15:03 -0800 (PST) Received: from localhost ([::1]:51500 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ecXRe-0002cR-P4 for importer@patchew.org; Fri, 19 Jan 2018 09:15:02 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56588) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ecXOA-00088l-Ss for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:28 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ecXO7-0004mC-JR for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:26 -0500 Received: from mx1.redhat.com ([209.132.183.28]:60512) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ecXO7-0004lU-AX for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:23 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 95B7EC0567A2; Fri, 19 Jan 2018 14:11:22 +0000 (UTC) Received: from localhost (ovpn-112-58.ams2.redhat.com [10.36.112.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id 0565260852; Fri, 19 Jan 2018 14:11:18 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Fri, 19 Jan 2018 15:11:02 +0100 Message-Id: <20180119141105.29095-4-marcandre.lureau@redhat.com> In-Reply-To: <20180119141105.29095-1-marcandre.lureau@redhat.com> References: <20180119141105.29095-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Fri, 19 Jan 2018 14:11:22 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v2 3/5] tpm: report backend request error X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , stefanb@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Use an Error** for request to let the caller handle error reporting. This will also allow to inform the frontend of a backend error. Signed-off-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Stefan Berger --- include/sysemu/tpm.h | 2 +- include/sysemu/tpm_backend.h | 3 ++- backends/tpm.c | 9 +++++++-- hw/tpm/tpm_emulator.c | 21 ++++++--------------- hw/tpm/tpm_passthrough.c | 31 +++++++++++++++---------------- hw/tpm/tpm_tis.c | 3 ++- 6 files changed, 33 insertions(+), 36 deletions(-) diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h index 852e02687c..ac04a9d4a2 100644 --- a/include/sysemu/tpm.h +++ b/include/sysemu/tpm.h @@ -41,7 +41,7 @@ typedef struct TPMIfClass { InterfaceClass parent_class; =20 enum TpmModel model; - void (*request_completed)(TPMIf *obj); + void (*request_completed)(TPMIf *obj, int ret); enum TPMVersion (*get_version)(TPMIf *obj); } TPMIfClass; =20 diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index a69593e0cd..7e166ef954 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -18,6 +18,7 @@ #include "qapi-types.h" #include "qemu/option.h" #include "sysemu/tpm.h" +#include "qapi/error.h" =20 #define TYPE_TPM_BACKEND "tpm-backend" #define TPM_BACKEND(obj) \ @@ -84,7 +85,7 @@ struct TPMBackendClass { =20 TpmTypeOptions *(*get_tpm_options)(TPMBackend *t); =20 - void (*handle_request)(TPMBackend *s, TPMBackendCmd *cmd); + void (*handle_request)(TPMBackend *s, TPMBackendCmd *cmd, Error **errp= ); }; =20 /** diff --git a/backends/tpm.c b/backends/tpm.c index 143807aa37..d617ba7c52 100644 --- a/backends/tpm.c +++ b/backends/tpm.c @@ -27,7 +27,7 @@ static void tpm_backend_request_completed(void *opaque, i= nt ret) TPMBackend *s =3D TPM_BACKEND(opaque); TPMIfClass *tic =3D TPM_IF_GET_CLASS(s->tpmif); =20 - tic->request_completed(s->tpmif); + tic->request_completed(s->tpmif, ret); =20 /* no need for atomic, as long the BQL is taken */ s->cmd =3D NULL; @@ -38,8 +38,13 @@ static int tpm_backend_worker_thread(gpointer data) { TPMBackend *s =3D TPM_BACKEND(data); TPMBackendClass *k =3D TPM_BACKEND_GET_CLASS(s); + Error *err =3D NULL; =20 - k->handle_request(s, s->cmd); + k->handle_request(s, s->cmd, &err); + if (err) { + error_report_err(err); + return -1; + } =20 return 0; } diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index 35c78de5a9..52552af9f9 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -185,28 +185,19 @@ static int tpm_emulator_set_locality(TPMEmulator *tpm= _emu, uint8_t locty_number, return 0; } =20 -static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd) +static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd, + Error **errp) { TPMEmulator *tpm_emu =3D TPM_EMULATOR(tb); - Error *err =3D NULL; =20 DPRINTF("processing TPM command"); =20 - if (tpm_emulator_set_locality(tpm_emu, cmd->locty, &err) < 0) { - goto error; - } - - if (tpm_emulator_unix_tx_bufs(tpm_emu, cmd->in, cmd->in_len, + if (tpm_emulator_set_locality(tpm_emu, cmd->locty, errp) < 0 || + tpm_emulator_unix_tx_bufs(tpm_emu, cmd->in, cmd->in_len, cmd->out, cmd->out_len, - &cmd->selftest_done, &err) < 0) { - goto error; + &cmd->selftest_done, errp) < 0) { + tpm_util_write_fatal_error_response(cmd->out, cmd->out_len); } - - return; - -error: - tpm_util_write_fatal_error_response(cmd->out, cmd->out_len); - error_report_err(err); } =20 static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu) diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c index f2563ac668..37dce15801 100644 --- a/hw/tpm/tpm_passthrough.c +++ b/hw/tpm/tpm_passthrough.c @@ -80,10 +80,11 @@ static int tpm_passthrough_unix_read(int fd, uint8_t *b= uf, uint32_t len) } return ret; } -static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt, - const uint8_t *in, uint32_t in_len, - uint8_t *out, uint32_t out_len, - bool *selftest_done) + +static void tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt, + const uint8_t *in, uint32_t in_le= n, + uint8_t *out, uint32_t out_len, + bool *selftest_done, Error **errp) { ssize_t ret; bool is_selftest; @@ -99,9 +100,8 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState= *tpm_pt, ret =3D qemu_write_full(tpm_pt->tpm_fd, in, in_len); if (ret !=3D in_len) { if (!tpm_pt->tpm_op_canceled || errno !=3D ECANCELED) { - error_report("tpm_passthrough: error while transmitting data " - "to TPM: %s (%i)", - strerror(errno), errno); + error_setg_errno(errp, errno, "tpm_passthrough: error while " + "transmitting data to TPM"); } goto err_exit; } @@ -111,15 +111,14 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruSt= ate *tpm_pt, ret =3D tpm_passthrough_unix_read(tpm_pt->tpm_fd, out, out_len); if (ret < 0) { if (!tpm_pt->tpm_op_canceled || errno !=3D ECANCELED) { - error_report("tpm_passthrough: error while reading data from " - "TPM: %s (%i)", - strerror(errno), errno); + error_setg_errno(errp, errno, "tpm_passthrough: error while " + "reading data from TPM"); } } else if (ret < sizeof(struct tpm_resp_hdr) || be32_to_cpu(((struct tpm_resp_hdr *)out)->len) !=3D ret) { ret =3D -1; - error_report("tpm_passthrough: received invalid response " - "packet from TPM"); + error_setg_errno(errp, errno, "tpm_passthrough: received invalid " + "response packet from TPM"); } =20 if (is_selftest && (ret >=3D sizeof(struct tpm_resp_hdr))) { @@ -133,18 +132,18 @@ err_exit: } =20 tpm_pt->tpm_executing =3D false; - - return ret; } =20 -static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd *= cmd) +static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd *= cmd, + Error **errp) { TPMPassthruState *tpm_pt =3D TPM_PASSTHROUGH(tb); =20 DPRINTF("tpm_passthrough: processing command %p\n", cmd); =20 tpm_passthrough_unix_tx_bufs(tpm_pt, cmd->in, cmd->in_len, - cmd->out, cmd->out_len, &cmd->selftest_do= ne); + cmd->out, cmd->out_len, &cmd->selftest_do= ne, + errp); } =20 static void tpm_passthrough_reset(TPMBackend *tb) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 8b5eb01a2c..08f41d2707 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -393,7 +393,7 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t loc= ty, uint8_t newlocty) /* * Callback from the TPM to indicate that the response was received. */ -static void tpm_tis_request_completed(TPMIf *ti) +static void tpm_tis_request_completed(TPMIf *ti, int ret) { TPMState *s =3D TPM(ti); uint8_t locty =3D s->cmd.locty; @@ -405,6 +405,7 @@ static void tpm_tis_request_completed(TPMIf *ti) } } =20 + /* FIXME: report error if ret !=3D 0 */ tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); s->loc[locty].state =3D TPM_TIS_STATE_COMPLETION; --=20 2.16.0.rc1.1.gef27df75a1 From nobody Mon Apr 29 02:31:25 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1516371661104352.87057789412745; Fri, 19 Jan 2018 06:21:01 -0800 (PST) Received: from localhost ([::1]:51672 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ecXXQ-0007kv-3j for importer@patchew.org; Fri, 19 Jan 2018 09:21:00 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56643) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ecXOG-0008De-7x for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ecXOD-0004rZ-Od for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:32 -0500 Received: from mx1.redhat.com ([209.132.183.28]:34164) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ecXOD-0004r1-GE for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:29 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9984D7E42A; Fri, 19 Jan 2018 14:11:28 +0000 (UTC) Received: from localhost (ovpn-112-58.ams2.redhat.com [10.36.112.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id E7CC260852; Fri, 19 Jan 2018 14:11:23 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Fri, 19 Jan 2018 15:11:03 +0100 Message-Id: <20180119141105.29095-5-marcandre.lureau@redhat.com> In-Reply-To: <20180119141105.29095-1-marcandre.lureau@redhat.com> References: <20180119141105.29095-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Fri, 19 Jan 2018 14:11:28 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Eduardo Habkost , "Michael S. Tsirkin" , stefanb@linux.vnet.ibm.com, Markus Armbruster , Paolo Bonzini , Igor Mammedov , Marcel Apfelbaum , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" 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 =E2=80=9C2.0=E2=80=9D Level 00 Revision 01.03 v22. The PTP allows device implementation to switch between TIS and CRB model at run time, but given that CRB is a simpler device to implement, I chose to implement it as a different device. The device doesn't implement other locality than 0 for now (my laptop TPM doesn't either, so I assume this isn't so bad) The command/reply memory region is statically allocated after the CRB registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I wonder if the BIOS could or should allocate it instead, or what size to use, again this seems to fit well expectations) The PTP doesn't specify a particular bus to put the device. So I added it on the system bus directly, so it could hopefully be used easily on a different platform than x86. Currently, it fails to init on piix, because error_on_sysbus_device() check. The check may be changed in a near future, see discussion on the qemu-devel ML. Tested with some success with Linux upstream and Windows 10, seabios & modified ovmf. The device is recognized and correctly transmit command/response with passthrough & emu. However, we are missing PPI ACPI part atm. Signed-off-by: Marc-Andr=C3=A9 Lureau Signed-off-by: Stefan Berger --- qapi/tpm.json | 5 +- include/hw/acpi/tpm.h | 72 ++++++++ include/sysemu/tpm.h | 3 + hw/i386/acpi-build.c | 34 +++- hw/tpm/tpm_crb.c | 327 +++++++++++++++++++++++++++++++++= ++++ default-configs/i386-softmmu.mak | 1 + default-configs/x86_64-softmmu.mak | 1 + hw/tpm/Makefile.objs | 1 + 8 files changed, 434 insertions(+), 10 deletions(-) create mode 100644 hw/tpm/tpm_crb.c diff --git a/qapi/tpm.json b/qapi/tpm.json index 7093f268fb..d50deef5e9 100644 --- a/qapi/tpm.json +++ b/qapi/tpm.json @@ -11,10 +11,11 @@ # An enumeration of TPM models # # @tpm-tis: TPM TIS model +# @tpm-crb: TPM CRB model (since 2.12) # # Since: 1.5 ## -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] } +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] } =20 ## # @query-tpm-models: @@ -28,7 +29,7 @@ # Example: # # -> { "execute": "query-tpm-models" } -# <- { "return": [ "tpm-tis" ] } +# <- { "return": [ "tpm-tis", "tpm-crb" ] } # ## { 'command': 'query-tpm-models', 'returns': ['TpmModel'] } diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h index 6d516c6a7f..b0048515fa 100644 --- a/include/hw/acpi/tpm.h +++ b/include/hw/acpi/tpm.h @@ -16,11 +16,82 @@ #ifndef HW_ACPI_TPM_H #define HW_ACPI_TPM_H =20 +#include "qemu/osdep.h" + #define TPM_TIS_ADDR_BASE 0xFED40000 #define TPM_TIS_ADDR_SIZE 0x5000 =20 #define TPM_TIS_IRQ 5 =20 +struct crb_regs { + union { + uint32_t reg; + struct { + unsigned tpm_established:1; + unsigned loc_assigned:1; + unsigned active_locality:3; + unsigned reserved:2; + unsigned tpm_reg_valid_sts:1; + } bits; + } loc_state; + uint32_t reserved1; + uint32_t loc_ctrl; + union { + uint32_t reg; + struct { + unsigned granted:1; + unsigned been_seized:1; + } bits; + } loc_sts; + uint8_t reserved2[32]; + union { + uint64_t reg; + struct { + unsigned type:4; + unsigned version:4; + unsigned cap_locality:1; + unsigned cap_crb_idle_bypass:1; + unsigned reserved1:1; + unsigned cap_data_xfer_size_support:2; + unsigned cap_fifo:1; + unsigned cap_crb:1; + unsigned cap_if_res:2; + unsigned if_selector:2; + unsigned if_selector_lock:1; + unsigned reserved2:4; + unsigned rid:8; + unsigned vid:16; + unsigned did:16; + } bits; + } intf_id; + uint64_t ctrl_ext; + + uint32_t ctrl_req; + union { + uint32_t reg; + struct { + unsigned tpm_sts:1; + unsigned tpm_idle:1; + unsigned reserved:30; + } bits; + } ctrl_sts; + uint32_t ctrl_cancel; + uint32_t ctrl_start; + uint32_t ctrl_int_enable; + uint32_t ctrl_int_sts; + uint32_t ctrl_cmd_size; + uint32_t ctrl_cmd_pa_low; + uint32_t ctrl_cmd_pa_high; + uint32_t ctrl_rsp_size; + uint64_t ctrl_rsp_pa; + uint8_t reserved3[0x10]; +} QEMU_PACKED; + +#define TPM_CRB_ADDR_BASE 0xFED40000 +#define TPM_CRB_ADDR_SIZE 0x1000 +#define TPM_CRB_ADDR_CTRL \ + (TPM_CRB_ADDR_BASE + offsetof(struct crb_regs, ctrl_req)) + #define TPM_LOG_AREA_MINIMUM_SIZE (64 * 1024) =20 #define TPM_TCPA_ACPI_CLASS_CLIENT 0 @@ -30,5 +101,6 @@ #define TPM2_ACPI_CLASS_SERVER 1 =20 #define TPM2_START_METHOD_MMIO 6 +#define TPM2_START_METHOD_CRB 7 =20 #endif /* HW_ACPI_TPM_H */ diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h index ac04a9d4a2..233b1a3fc3 100644 --- a/include/sysemu/tpm.h +++ b/include/sysemu/tpm.h @@ -46,9 +46,12 @@ typedef struct TPMIfClass { } TPMIfClass; =20 #define TYPE_TPM_TIS "tpm-tis" +#define TYPE_TPM_CRB "tpm-crb" =20 #define TPM_IS_TIS(chr) \ object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS) +#define TPM_IS_CRB(chr) \ + object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB) =20 /* returns NULL unless there is exactly one TPM device */ static inline TPMIf *tpm_find(void) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index dc4b2b9ffe..ed78c4ed9f 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2224,6 +2224,22 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(sb_scope, scope); } } + + if (TPM_IS_CRB(tpm_find())) { + dev =3D aml_device("TPM"); + aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101"))); + crs =3D aml_resource_template(); + aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE, + TPM_CRB_ADDR_SIZE, AML_READ_WRI= TE)); + aml_append(dev, aml_name_decl("_CRS", crs)); + + method =3D aml_method("_STA", 0, AML_NOTSERIALIZED); + aml_append(method, aml_return(aml_int(0x0f))); + aml_append(dev, method); + + aml_append(sb_scope, dev); + } + aml_append(dsdt, sb_scope); =20 /* copy AML table into ACPI tables blob and patch header there */ @@ -2285,18 +2301,20 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, = GArray *tcpalog) if (TPM_IS_TIS(tpm_find())) { tpm2_ptr->control_area_address =3D cpu_to_le64(0); tpm2_ptr->start_method =3D cpu_to_le32(TPM2_START_METHOD_MMIO); - - tpm2_ptr->log_area_minimum_length =3D - cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE); - - /* log area start address to be filled by Guest linker */ - bios_linker_loader_add_pointer(linker, - ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size, - ACPI_BUILD_TPMLOG_FILE, 0); + } else if (TPM_IS_CRB(tpm_find())) { + tpm2_ptr->control_area_address =3D cpu_to_le64(TPM_CRB_ADDR_CTRL); + tpm2_ptr->start_method =3D cpu_to_le32(TPM2_START_METHOD_CRB); } else { g_warn_if_reached(); } =20 + tpm2_ptr->log_area_minimum_length =3D + cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE); + + /* log area start address to be filled by Guest linker */ + bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE, + log_addr_offset, log_addr_size, + ACPI_BUILD_TPMLOG_FILE, 0); build_header(linker, table_data, (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL, NUL= L); } diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c new file mode 100644 index 0000000000..908ca18d92 --- /dev/null +++ b/hw/tpm/tpm_crb.c @@ -0,0 +1,327 @@ +/* + * tpm_crb.c - QEMU's TPM CRB interface emulator + * + * Copyright (c) 2017 Red Hat, Inc. + * + * Authors: + * Marc-Andr=C3=A9 Lureau + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * 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 =E2=80=9C2.0=E2=80=9D Level 00 Revision 01.03 v22 + */ + +#include "qemu/osdep.h" + +#include "qemu-common.h" +#include "qapi/error.h" +#include "hw/sysbus.h" +#include "exec/address-spaces.h" + +#include "hw/pci/pci_ids.h" +#include "hw/acpi/tpm.h" +#include "sysemu/tpm_backend.h" +#include "tpm_int.h" +#include "tpm_util.h" + +typedef struct CRBState { + SysBusDevice parent_obj; + + TPMBackend *tpmbe; + TPMBackendCmd cmd; + struct crb_regs regs; + MemoryRegion mmio; + MemoryRegion cmdmem; + + size_t be_buffer_size; +} CRBState; + +#define CRB(obj) OBJECT_CHECK(CRBState, (obj), TYPE_TPM_CRB) + +#define DEBUG_CRB 0 + +#define DPRINTF(fmt, ...) do { \ + if (DEBUG_CRB) { \ + printf(fmt, ## __VA_ARGS__); \ + } \ + } while (0) + +#define CRB_ADDR_LOC_STATE offsetof(struct crb_regs, loc_state) +#define CRB_ADDR_LOC_CTRL offsetof(struct crb_regs, loc_ctrl) +#define CRB_ADDR_CTRL_REQ offsetof(struct crb_regs, ctrl_req) +#define CRB_ADDR_CTRL_CANCEL offsetof(struct crb_regs, ctrl_cancel) +#define CRB_ADDR_CTRL_START offsetof(struct crb_regs, ctrl_start) + +#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_INTF_IF_SELECTOR_UNLOCKED 0b0 + +#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - sizeof(struct crb_regs)) + +enum crb_loc_ctrl { + CRB_LOC_CTRL_REQUEST_ACCESS =3D BIT(0), + CRB_LOC_CTRL_RELINQUISH =3D BIT(1), + CRB_LOC_CTRL_SEIZE =3D BIT(2), + CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT =3D BIT(3), +}; + +enum crb_ctrl_req { + CRB_CTRL_REQ_CMD_READY =3D BIT(0), + CRB_CTRL_REQ_GO_IDLE =3D BIT(1), +}; + +enum crb_start { + CRB_START_INVOKE =3D BIT(0), +}; + +enum crb_cancel { + CRB_CANCEL_INVOKE =3D BIT(0), +}; + +static const char *addr_desc(unsigned off) +{ + struct crb_regs crb; + + switch (off) { +#define CASE(field) \ + case offsetof(struct crb_regs, field) ... \ + offsetof(struct crb_regs, field) + sizeof(crb.field) - 1: \ + return G_STRINGIFY(field); + CASE(loc_state); + CASE(reserved1); + CASE(loc_ctrl); + CASE(loc_sts); + CASE(reserved2); + CASE(intf_id); + CASE(ctrl_ext); + CASE(ctrl_req); + CASE(ctrl_sts); + CASE(ctrl_cancel); + CASE(ctrl_start); + CASE(ctrl_int_enable); + CASE(ctrl_int_sts); + CASE(ctrl_cmd_size); + CASE(ctrl_cmd_pa_low); + CASE(ctrl_cmd_pa_high); + CASE(ctrl_rsp_size); + CASE(ctrl_rsp_pa); +#undef CASE + } + return NULL; +} + +static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr, + unsigned size) +{ + CRBState *s =3D CRB(opaque); + DPRINTF("CRB read 0x%lx:%s len:%u\n", + addr, addr_desc(addr), size); + void *regs =3D (void *)&s->regs + addr; + + switch (size) { + case 1: + return *(uint8_t *)regs; + case 2: + return *(uint16_t *)regs; + case 4: + return *(uint32_t *)regs; + default: + g_return_val_if_reached(-1); + } +} + +static void tpm_crb_mmio_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + CRBState *s =3D CRB(opaque); + DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n", + addr, addr_desc(addr), size, val); + + switch (addr) { + case CRB_ADDR_CTRL_REQ: + switch (val) { + case CRB_CTRL_REQ_CMD_READY: + s->regs.ctrl_sts.bits.tpm_idle =3D 0; + break; + case CRB_CTRL_REQ_GO_IDLE: + s->regs.ctrl_sts.bits.tpm_idle =3D 1; + break; + } + break; + case CRB_ADDR_CTRL_CANCEL: + if (val =3D=3D CRB_CANCEL_INVOKE && s->regs.ctrl_start & CRB_START= _INVOKE) { + tpm_backend_cancel_cmd(s->tpmbe); + } + break; + case CRB_ADDR_CTRL_START: + if (val =3D=3D CRB_START_INVOKE && + !(s->regs.ctrl_start & CRB_START_INVOKE)) { + void *mem =3D memory_region_get_ram_ptr(&s->cmdmem); + + s->regs.ctrl_start |=3D CRB_START_INVOKE; + s->cmd =3D (TPMBackendCmd) { + .in =3D mem, + .in_len =3D MIN(tpm_cmd_get_size(mem), s->be_buffer_size), + .out =3D mem, + .out_len =3D s->be_buffer_size, + }; + + tpm_backend_deliver_request(s->tpmbe, &s->cmd); + } + break; + case CRB_ADDR_LOC_CTRL: + switch (val) { + case CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT: + /* not loc 3 or 4 */ + break; + case CRB_LOC_CTRL_RELINQUISH: + break; + case CRB_LOC_CTRL_REQUEST_ACCESS: + s->regs.loc_sts.bits.granted =3D 1; + s->regs.loc_sts.bits.been_seized =3D 0; + s->regs.loc_state.bits.loc_assigned =3D 1; + s->regs.loc_state.bits.tpm_reg_valid_sts =3D 1; + break; + } + break; + } +} + +static const MemoryRegionOps tpm_crb_memory_ops =3D { + .read =3D tpm_crb_mmio_read, + .write =3D tpm_crb_mmio_write, + .endianness =3D DEVICE_LITTLE_ENDIAN, + .valid =3D { + .min_access_size =3D 1, + .max_access_size =3D 4, + }, +}; + +static void tpm_crb_reset(DeviceState *dev) +{ + CRBState *s =3D CRB(dev); + + tpm_backend_reset(s->tpmbe); + + s->be_buffer_size =3D MIN(tpm_backend_get_buffer_size(s->tpmbe), + CRB_CTRL_CMD_SIZE); + + s->regs =3D (struct crb_regs) { + .intf_id.bits =3D { + .type =3D CRB_INTF_TYPE_CRB_ACTIVE, + .version =3D CRB_INTF_VERSION_CRB, + .cap_locality =3D CRB_INTF_CAP_LOCALITY_0_ONLY, + .cap_crb_idle_bypass =3D CRB_INTF_CAP_IDLE_FAST, + .cap_data_xfer_size_support =3D CRB_INTF_CAP_XFER_SIZE_64, + .cap_fifo =3D CRB_INTF_CAP_FIFO_NOT_SUPPORTED, + .cap_crb =3D CRB_INTF_CAP_CRB_SUPPORTED, + .cap_if_res =3D 0b0, + .if_selector =3D CRB_INTF_IF_SELECTOR_CRB, + .if_selector_lock =3D CRB_INTF_IF_SELECTOR_UNLOCKED, + .rid =3D 0b0001, + .vid =3D PCI_VENDOR_ID_IBM, + .did =3D 0b0001, + }, + .ctrl_cmd_size =3D CRB_CTRL_CMD_SIZE, + .ctrl_cmd_pa_low =3D TPM_CRB_ADDR_BASE + sizeof(struct crb_regs), + .ctrl_rsp_size =3D CRB_CTRL_CMD_SIZE, + .ctrl_rsp_pa =3D TPM_CRB_ADDR_BASE + sizeof(struct crb_regs), + }; + + tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size); +} + +static void tpm_crb_request_completed(TPMIf *ti, int ret) +{ + CRBState *s =3D CRB(ti); + + s->regs.ctrl_start &=3D ~CRB_START_INVOKE; + if (ret !=3D 0) { + s->regs.ctrl_sts.bits.tpm_sts =3D 1; /* fatal error */ + } +} + +static enum TPMVersion tpm_crb_get_version(TPMIf *ti) +{ + CRBState *s =3D CRB(ti); + + return tpm_backend_get_tpm_version(s->tpmbe); +} + +static const VMStateDescription vmstate_tpm_crb =3D { + .name =3D "tpm-crb", + .unmigratable =3D 1, +}; + +static Property tpm_crb_properties[] =3D { + DEFINE_PROP_TPMBE("tpmdev", CRBState, tpmbe), + DEFINE_PROP_END_OF_LIST(), +}; + +static void tpm_crb_realizefn(DeviceState *dev, Error **errp) +{ + CRBState *s =3D CRB(dev); + SysBusDevice *sbd =3D SYS_BUS_DEVICE(dev); + + if (!tpm_find()) { + error_setg(errp, "at most one TPM device is permitted"); + return; + } + if (!s->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(struct crb_regs)); + memory_region_init_ram(&s->cmdmem, OBJECT(s), + "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp); + + sysbus_init_mmio(sbd, &s->mmio); + sysbus_mmio_map(sbd, 0, TPM_CRB_ADDR_BASE); + /* allocate ram in bios instead? */ + memory_region_add_subregion(get_system_memory(), + TPM_CRB_ADDR_BASE + sizeof(struct crb_regs), &s->cmdmem); +} + +static void tpm_crb_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + TPMIfClass *tc =3D TPM_IF_CLASS(klass); + + dc->realize =3D tpm_crb_realizefn; + dc->props =3D tpm_crb_properties; + dc->reset =3D tpm_crb_reset; + dc->vmsd =3D &vmstate_tpm_crb; + dc->user_creatable =3D true; + tc->model =3D TPM_MODEL_TPM_CRB; + tc->get_version =3D tpm_crb_get_version; + tc->request_completed =3D tpm_crb_request_completed; +} + +static const TypeInfo tpm_crb_info =3D { + .name =3D TYPE_TPM_CRB, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(CRBState), + .class_init =3D tpm_crb_class_init, + .interfaces =3D (InterfaceInfo[]) { + { TYPE_TPM_IF }, + { } + } +}; + +static void tpm_crb_register(void) +{ + type_register_static(&tpm_crb_info); +} + +type_init(tpm_crb_register) diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmm= u.mak index 95ac4b464a..ac27700e79 100644 --- a/default-configs/i386-softmmu.mak +++ b/default-configs/i386-softmmu.mak @@ -37,6 +37,7 @@ CONFIG_APPLESMC=3Dy CONFIG_I8259=3Dy CONFIG_PFLASH_CFI01=3Dy CONFIG_TPM_TIS=3D$(CONFIG_TPM) +CONFIG_TPM_CRB=3D$(CONFIG_TPM) CONFIG_MC146818RTC=3Dy CONFIG_PCI_PIIX=3Dy CONFIG_WDT_IB700=3Dy diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-so= ftmmu.mak index 0221236825..b2104ade19 100644 --- a/default-configs/x86_64-softmmu.mak +++ b/default-configs/x86_64-softmmu.mak @@ -37,6 +37,7 @@ CONFIG_APPLESMC=3Dy CONFIG_I8259=3Dy CONFIG_PFLASH_CFI01=3Dy CONFIG_TPM_TIS=3D$(CONFIG_TPM) +CONFIG_TPM_CRB=3D$(CONFIG_TPM) CONFIG_MC146818RTC=3Dy CONFIG_PCI_PIIX=3Dy CONFIG_WDT_IB700=3Dy diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs index 7a93b24636..1dc9f8bf2c 100644 --- a/hw/tpm/Makefile.objs +++ b/hw/tpm/Makefile.objs @@ -1,4 +1,5 @@ common-obj-y +=3D tpm_util.o common-obj-$(CONFIG_TPM_TIS) +=3D tpm_tis.o +common-obj-$(CONFIG_TPM_CRB) +=3D tpm_crb.o common-obj-$(CONFIG_TPM_PASSTHROUGH) +=3D tpm_passthrough.o common-obj-$(CONFIG_TPM_EMULATOR) +=3D tpm_emulator.o --=20 2.16.0.rc1.1.gef27df75a1 From nobody Mon Apr 29 02:31:25 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1516371254852359.3032024534864; Fri, 19 Jan 2018 06:14:14 -0800 (PST) Received: from localhost ([::1]:51496 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ecXQq-0001ol-IT for importer@patchew.org; Fri, 19 Jan 2018 09:14:12 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56676) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ecXOK-0008Hn-CN for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ecXOH-0004sz-Ad for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:36 -0500 Received: from mx1.redhat.com ([209.132.183.28]:40666) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1ecXOH-0004sb-5S for qemu-devel@nongnu.org; Fri, 19 Jan 2018 09:11:33 -0500 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6CF774D4A4; Fri, 19 Jan 2018 14:11:32 +0000 (UTC) Received: from localhost (ovpn-112-58.ams2.redhat.com [10.36.112.58]) by smtp.corp.redhat.com (Postfix) with ESMTP id DFC465D6B7; Fri, 19 Jan 2018 14:11:29 +0000 (UTC) From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= To: qemu-devel@nongnu.org Date: Fri, 19 Jan 2018 15:11:04 +0100 Message-Id: <20180119141105.29095-6-marcandre.lureau@redhat.com> In-Reply-To: <20180119141105.29095-1-marcandre.lureau@redhat.com> References: <20180119141105.29095-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 19 Jan 2018 14:11:32 +0000 (UTC) Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH v2 5/5] tpm: extend TPM CRB with state migration support X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , stefanb@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" From: Stefan Berger We need to synchronize with the backend thread to make sure that a command being processed by the external TPM emulator has completed and its response been received. In case the bottom half did not run, we run the function it is supposed to run. Signed-off-by: Stefan Berger [ Marc-Andr=C3=A9 - drop memory_region_get_ram_ptr(cmdmem) copy as it should be migrated already ] Signed-off-by: Marc-Andr=C3=A9 Lureau --- hw/tpm/tpm_crb.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c index 908ca18d92..63d53384c5 100644 --- a/hw/tpm/tpm_crb.c +++ b/hw/tpm/tpm_crb.c @@ -257,9 +257,39 @@ static enum TPMVersion tpm_crb_get_version(TPMIf *ti) return tpm_backend_get_tpm_version(s->tpmbe); } =20 +/* persistent state handling */ + +static int tpm_crb_pre_save(void *opaque) +{ + CRBState *s =3D opaque; + + tpm_backend_finish_sync(s->tpmbe); + + return 0; +} + static const VMStateDescription vmstate_tpm_crb =3D { .name =3D "tpm-crb", - .unmigratable =3D 1, + .pre_save =3D tpm_crb_pre_save, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32(regs.loc_state.reg, CRBState), + VMSTATE_UINT32(regs.loc_ctrl, CRBState), + VMSTATE_UINT32(regs.loc_sts.reg, CRBState), + VMSTATE_UINT64(regs.intf_id.reg, CRBState), + VMSTATE_UINT64(regs.ctrl_ext, CRBState), + VMSTATE_UINT32(regs.ctrl_req, CRBState), + VMSTATE_UINT32(regs.ctrl_sts.reg, CRBState), + VMSTATE_UINT32(regs.ctrl_cancel, CRBState), + VMSTATE_UINT32(regs.ctrl_start, CRBState), + VMSTATE_UINT32(regs.ctrl_int_enable, CRBState), + VMSTATE_UINT32(regs.ctrl_int_sts, CRBState), + VMSTATE_UINT32(regs.ctrl_cmd_size, CRBState), + VMSTATE_UINT32(regs.ctrl_cmd_pa_low, CRBState), + VMSTATE_UINT32(regs.ctrl_rsp_size, CRBState), + VMSTATE_UINT64(regs.ctrl_rsp_pa, CRBState), + + VMSTATE_END_OF_LIST(), + } }; =20 static Property tpm_crb_properties[] =3D { --=20 2.16.0.rc1.1.gef27df75a1