From nobody Mon Apr 29 06:19:56 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 1517265046745559.4382043376552; Mon, 29 Jan 2018 14:30:46 -0800 (PST) Received: from localhost ([::1]:44305 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egHws-000840-0d for importer@patchew.org; Mon, 29 Jan 2018 17:30:46 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34980) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egHs0-0004ZZ-22 for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:45 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1egHrw-0005tM-UB for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:44 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:45660) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1egHrw-0005sf-L0 for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:40 -0500 Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w0TMPOap000752 for ; Mon, 29 Jan 2018 17:25:39 -0500 Received: from e14.ny.us.ibm.com (e14.ny.us.ibm.com [129.33.205.204]) by mx0a-001b2d01.pphosted.com with ESMTP id 2ftbjqhw0q-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 29 Jan 2018 17:25:38 -0500 Received: from localhost by e14.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 29 Jan 2018 17:25:37 -0500 Received: from b01cxnp22035.gho.pok.ibm.com (9.57.198.25) by e14.ny.us.ibm.com (146.89.104.201) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 29 Jan 2018 17:25:35 -0500 Received: from b01ledav002.gho.pok.ibm.com (b01ledav002.gho.pok.ibm.com [9.57.199.107]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w0TMPYtV48562370; Mon, 29 Jan 2018 22:25:34 GMT Received: from b01ledav002.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 278B9124035; Mon, 29 Jan 2018 17:22:23 -0500 (EST) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b01ledav002.gho.pok.ibm.com (Postfix) with ESMTP id 1915312403F; Mon, 29 Jan 2018 17:22:23 -0500 (EST) From: Stefan Berger To: qemu-devel@nongnu.org Date: Mon, 29 Jan 2018 17:25:14 -0500 X-Mailer: git-send-email 2.5.5 In-Reply-To: <1517264719-18288-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1517264719-18288-1-git-send-email-stefanb@linux.vnet.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 18012922-0052-0000-0000-000002AB4E10 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008450; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000248; SDB=6.00982231; UDB=6.00498037; IPR=6.00761513; BA=6.00005799; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00019275; XFM=3.00000015; UTC=2018-01-29 22:25:36 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18012922-0053-0000-0000-000053676567 Message-Id: <1517264719-18288-2-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-01-29_12:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1801290286 Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by mx0a-001b2d01.pphosted.com id w0TMPOap000752 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.156.1 Subject: [Qemu-devel] [PULL v2 1/6] tpm: Set the flags of the CMD_INIT command to 0 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: peter.maydell@linaro.org, marcandre.lureau@redhat.com, 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 flags of the CMD_INIT control channel command were not initialized properly. Fix this and set to 0. Signed-off-by: Stefan Berger Reviewed-by: Marc-Andr=C3=A9 Lureau --- hw/tpm/tpm_emulator.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index 35c78de..532d3e3 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -320,7 +320,9 @@ static int tpm_emulator_set_buffer_size(TPMBackend *tb, static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize) { TPMEmulator *tpm_emu =3D TPM_EMULATOR(tb); - ptm_init init; + ptm_init init =3D { + .u.req.init_flags =3D 0, + }; ptm_res res; =20 if (buffersize !=3D 0 && --=20 2.5.5 From nobody Mon Apr 29 06:19:56 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 1517265175519844.0637312936736; Mon, 29 Jan 2018 14:32:55 -0800 (PST) Received: from localhost ([::1]:44532 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egHyw-0000zH-Kx for importer@patchew.org; Mon, 29 Jan 2018 17:32:54 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34997) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egHs0-0004Zh-RJ for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:46 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1egHrx-0005tf-KR for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:44 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:51372) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1egHrx-0005tA-B5 for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:41 -0500 Received: from pps.filterd (m0098394.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w0TMNhYi050686 for ; Mon, 29 Jan 2018 17:25:40 -0500 Received: from e13.ny.us.ibm.com (e13.ny.us.ibm.com [129.33.205.203]) by mx0a-001b2d01.pphosted.com with ESMTP id 2ft8bc2471-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 29 Jan 2018 17:25:39 -0500 Received: from localhost by e13.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 29 Jan 2018 17:25:38 -0500 Received: from b01cxnp22035.gho.pok.ibm.com (9.57.198.25) by e13.ny.us.ibm.com (146.89.104.200) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 29 Jan 2018 17:25:36 -0500 Received: from b01ledav002.gho.pok.ibm.com (b01ledav002.gho.pok.ibm.com [9.57.199.107]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w0TMPZZv48562376; Mon, 29 Jan 2018 22:25:35 GMT Received: from b01ledav002.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3F17512403F; Mon, 29 Jan 2018 17:22:24 -0500 (EST) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b01ledav002.gho.pok.ibm.com (Postfix) with ESMTP id 28208124037; Mon, 29 Jan 2018 17:22:24 -0500 (EST) From: Stefan Berger To: qemu-devel@nongnu.org Date: Mon, 29 Jan 2018 17:25:15 -0500 X-Mailer: git-send-email 2.5.5 In-Reply-To: <1517264719-18288-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1517264719-18288-1-git-send-email-stefanb@linux.vnet.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 18012922-0008-0000-0000-000002C8D883 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008450; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000248; SDB=6.00982231; UDB=6.00498038; IPR=6.00761513; BA=6.00005799; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00019275; XFM=3.00000015; UTC=2018-01-29 22:25:37 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18012922-0009-0000-0000-0000381588DC Message-Id: <1517264719-18288-3-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-01-29_12:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1801290286 Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by mx0a-001b2d01.pphosted.com id w0TMNhYi050686 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.156.1 Subject: [Qemu-devel] [PULL v2 2/6] tpm: fix alignment issues 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: peter.maydell@linaro.org, marcandre.lureau@redhat.com, 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: Marc-Andr=C3=A9 Lureau The new tpm-crb-test fails on sparc host: TEST: tests/tpm-crb-test... (pid=3D230409) /i386/tpm-crb/test: Broken pipe FAIL GTester: last random seed: R02S29cea50247fe1efa59ee885a26d51a85 (pid=3D230423) FAIL: tests/tpm-crb-test and generates a new clang sanitizer runtime warning: /home/petmay01/linaro/qemu-for-merges/hw/tpm/tpm_util.h:36:24: runtime error: load of misaligned address 0x7fdc24c00002 for type 'const uint32_t' (aka 'const unsigned int'), which requires 4 byte alignment 0x7fdc24c00002: note: pointer points here The sparc architecture does not allow misaligned loads and will segfault if you try them. For example, this function: static inline uint32_t tpm_cmd_get_size(const void *b) { return be32_to_cpu(*(const uint32_t *)(b + 2)); } Should read, return ldl_be_p(b + 2); As a general rule you can't take an arbitrary pointer into a byte buffer and try to interpret it as a structure or a pointer to a larger-than-bytesize-data simply by casting the pointer. Use this clean up as an opportunity to remove unnecessary temporary buffers and casts. Reported-by: Peter Maydell Signed-off-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- hw/tpm/tpm_emulator.c | 14 ++++----- hw/tpm/tpm_passthrough.c | 6 ++-- hw/tpm/tpm_util.c | 75 ++++++++++++++++++++++----------------------= ---- hw/tpm/tpm_util.h | 17 ++++++++++- 4 files changed, 58 insertions(+), 54 deletions(-) diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index 532d3e3..81bf7d1 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -120,7 +120,6 @@ static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_e= mu, { ssize_t ret; bool is_selftest =3D false; - const struct tpm_resp_hdr *hdr =3D NULL; =20 if (selftest_done) { *selftest_done =3D false; @@ -132,22 +131,21 @@ static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm= _emu, return -1; } =20 - ret =3D qio_channel_read_all(tpm_emu->data_ioc, (char *)out, sizeof(*h= dr), - err); + ret =3D qio_channel_read_all(tpm_emu->data_ioc, (char *)out, + sizeof(struct tpm_resp_hdr), err); if (ret !=3D 0) { return -1; } =20 - hdr =3D (struct tpm_resp_hdr *)out; - out +=3D sizeof(*hdr); - ret =3D qio_channel_read_all(tpm_emu->data_ioc, (char *)out, - be32_to_cpu(hdr->len) - sizeof(*hdr) , err); + ret =3D qio_channel_read_all(tpm_emu->data_ioc, + (char *)out + sizeof(struct tpm_resp_hdr), + tpm_cmd_get_size(out) - sizeof(struct tpm_resp_hdr), err); if (ret !=3D 0) { return -1; } =20 if (is_selftest) { - *selftest_done =3D (be32_to_cpu(hdr->errcode) =3D=3D 0); + *selftest_done =3D tpm_cmd_get_errcode(out) =3D=3D 0; } =20 return 0; diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c index 29142f3..537e11a 100644 --- a/hw/tpm/tpm_passthrough.c +++ b/hw/tpm/tpm_passthrough.c @@ -87,7 +87,6 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState = *tpm_pt, { ssize_t ret; bool is_selftest; - const struct tpm_resp_hdr *hdr; =20 /* FIXME: protect shared variables or use other sync mechanism */ tpm_pt->tpm_op_canceled =3D false; @@ -116,15 +115,14 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruSt= ate *tpm_pt, strerror(errno), errno); } } else if (ret < sizeof(struct tpm_resp_hdr) || - be32_to_cpu(((struct tpm_resp_hdr *)out)->len) !=3D ret) { + tpm_cmd_get_size(out) !=3D ret) { ret =3D -1; error_report("tpm_passthrough: received invalid response " "packet from TPM"); } =20 if (is_selftest && (ret >=3D sizeof(struct tpm_resp_hdr))) { - hdr =3D (struct tpm_resp_hdr *)out; - *selftest_done =3D (be32_to_cpu(hdr->errcode) =3D=3D 0); + *selftest_done =3D tpm_cmd_get_errcode(out) =3D=3D 0; } =20 err_exit: diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c index 747075e..8abde59 100644 --- a/hw/tpm/tpm_util.c +++ b/hw/tpm/tpm_util.c @@ -106,20 +106,16 @@ const PropertyInfo qdev_prop_tpm =3D { void tpm_util_write_fatal_error_response(uint8_t *out, uint32_t out_len) { if (out_len >=3D sizeof(struct tpm_resp_hdr)) { - struct tpm_resp_hdr *resp =3D (struct tpm_resp_hdr *)out; - - resp->tag =3D cpu_to_be16(TPM_TAG_RSP_COMMAND); - resp->len =3D cpu_to_be32(sizeof(struct tpm_resp_hdr)); - resp->errcode =3D cpu_to_be32(TPM_FAIL); + stw_be_p(out, TPM_TAG_RSP_COMMAND); + stl_be_p(out + 2, sizeof(struct tpm_resp_hdr)); + stl_be_p(out + 6, TPM_FAIL); } } =20 bool tpm_util_is_selftest(const uint8_t *in, uint32_t in_len) { - struct tpm_req_hdr *hdr =3D (struct tpm_req_hdr *)in; - - if (in_len >=3D sizeof(*hdr)) { - return (be32_to_cpu(hdr->ordinal) =3D=3D TPM_ORD_ContinueSelfTest); + if (in_len >=3D sizeof(struct tpm_req_hdr)) { + return tpm_cmd_get_ordinal(in) =3D=3D TPM_ORD_ContinueSelfTest; } =20 return false; @@ -129,12 +125,11 @@ bool tpm_util_is_selftest(const uint8_t *in, uint32_t= in_len) * Send request to a TPM device. We expect a response within one second. */ static int tpm_util_request(int fd, - unsigned char *request, + const void *request, size_t requestlen, - unsigned char *response, + void *response, size_t responselen) { - struct tpm_resp_hdr *resp; fd_set readfds; int n; struct timeval tv =3D { @@ -164,9 +159,8 @@ static int tpm_util_request(int fd, return -EFAULT; } =20 - resp =3D (struct tpm_resp_hdr *)response; /* check the header */ - if (be32_to_cpu(resp->len) !=3D n) { + if (tpm_cmd_get_size(response) !=3D n) { return -EMSGSIZE; } =20 @@ -178,12 +172,11 @@ static int tpm_util_request(int fd, * (error response is fine). */ static int tpm_util_test(int fd, - unsigned char *request, + const void *request, size_t requestlen, uint16_t *return_tag) { - struct tpm_resp_hdr *resp; - unsigned char buf[1024]; + char buf[1024]; ssize_t ret; =20 ret =3D tpm_util_request(fd, request, requestlen, @@ -192,8 +185,7 @@ static int tpm_util_test(int fd, return ret; } =20 - resp =3D (struct tpm_resp_hdr *)buf; - *return_tag =3D be16_to_cpu(resp->tag); + *return_tag =3D tpm_cmd_get_tag(buf); =20 return 0; } @@ -228,7 +220,7 @@ int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_ve= rsion) int ret; =20 /* Send TPM 2 command */ - ret =3D tpm_util_test(tpm_fd, (unsigned char *)&test_req_tpm2, + ret =3D tpm_util_test(tpm_fd, &test_req_tpm2, sizeof(test_req_tpm2), &return_tag); /* TPM 2 would respond with a tag of TPM2_ST_NO_SESSIONS */ if (!ret && return_tag =3D=3D TPM2_ST_NO_SESSIONS) { @@ -237,7 +229,7 @@ int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_ve= rsion) } =20 /* Send TPM 1.2 command */ - ret =3D tpm_util_test(tpm_fd, (unsigned char *)&test_req, + ret =3D tpm_util_test(tpm_fd, &test_req, sizeof(test_req), &return_tag); if (!ret && return_tag =3D=3D TPM_TAG_RSP_COMMAND) { *tpm_version =3D TPM_VERSION_1_2; @@ -253,7 +245,6 @@ int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_ve= rsion) int tpm_util_get_buffer_size(int tpm_fd, TPMVersion tpm_version, size_t *buffersize) { - unsigned char buf[1024]; int ret; =20 switch (tpm_version) { @@ -277,26 +268,27 @@ int tpm_util_get_buffer_size(int tpm_fd, TPMVersion t= pm_version, struct tpm_resp_hdr hdr; uint32_t len; uint32_t buffersize; - } QEMU_PACKED *tpm_resp =3D (struct tpm_resp_get_buffer_size *)buf; + } QEMU_PACKED tpm_resp; =20 - ret =3D tpm_util_request(tpm_fd, (unsigned char *)&tpm_get_buffer_= size, - sizeof(tpm_get_buffer_size), buf, sizeof(bu= f)); + ret =3D tpm_util_request(tpm_fd, &tpm_get_buffer_size, + sizeof(tpm_get_buffer_size), + &tpm_resp, sizeof(tpm_resp)); if (ret < 0) { return ret; } =20 - if (be32_to_cpu(tpm_resp->hdr.len) !=3D sizeof(*tpm_resp) || - be32_to_cpu(tpm_resp->len) !=3D sizeof(uint32_t)) { + if (be32_to_cpu(tpm_resp.hdr.len) !=3D sizeof(tpm_resp) || + be32_to_cpu(tpm_resp.len) !=3D sizeof(uint32_t)) { DPRINTF("tpm_resp->hdr.len =3D %u, expected =3D %zu\n", - be32_to_cpu(tpm_resp->hdr.len), sizeof(*tpm_resp)); + be32_to_cpu(tpm_resp.hdr.len), sizeof(tpm_resp)); DPRINTF("tpm_resp->len =3D %u, expected =3D %zu\n", - be32_to_cpu(tpm_resp->len), sizeof(uint32_t)); + be32_to_cpu(tpm_resp.len), sizeof(uint32_t)); error_report("tpm_util: Got unexpected response to " "TPM_GetCapability; errcode: 0x%x", - be32_to_cpu(tpm_resp->hdr.errcode)); + be32_to_cpu(tpm_resp.hdr.errcode)); return -EFAULT; } - *buffersize =3D be32_to_cpu(tpm_resp->buffersize); + *buffersize =3D be32_to_cpu(tpm_resp.buffersize); break; } case TPM_VERSION_2_0: { @@ -324,27 +316,28 @@ int tpm_util_get_buffer_size(int tpm_fd, TPMVersion t= pm_version, uint32_t value1; uint32_t property2; uint32_t value2; - } QEMU_PACKED *tpm2_resp =3D (struct tpm2_resp_get_buffer_size *)b= uf; + } QEMU_PACKED tpm2_resp; =20 - ret =3D tpm_util_request(tpm_fd, (unsigned char *)&tpm2_get_buffer= _size, - sizeof(tpm2_get_buffer_size), buf, sizeof(b= uf)); + ret =3D tpm_util_request(tpm_fd, &tpm2_get_buffer_size, + sizeof(tpm2_get_buffer_size), + &tpm2_resp, sizeof(tpm2_resp)); if (ret < 0) { return ret; } =20 - if (be32_to_cpu(tpm2_resp->hdr.len) !=3D sizeof(*tpm2_resp) || - be32_to_cpu(tpm2_resp->count) !=3D 2) { + if (be32_to_cpu(tpm2_resp.hdr.len) !=3D sizeof(tpm2_resp) || + be32_to_cpu(tpm2_resp.count) !=3D 2) { DPRINTF("tpm2_resp->hdr.len =3D %u, expected =3D %zu\n", - be32_to_cpu(tpm2_resp->hdr.len), sizeof(*tpm2_resp)); + be32_to_cpu(tpm2_resp.hdr.len), sizeof(tpm2_resp)); DPRINTF("tpm2_resp->len =3D %u, expected =3D %u\n", - be32_to_cpu(tpm2_resp->count), 2); + be32_to_cpu(tpm2_resp.count), 2); error_report("tpm_util: Got unexpected response to " "TPM2_GetCapability; errcode: 0x%x", - be32_to_cpu(tpm2_resp->hdr.errcode)); + be32_to_cpu(tpm2_resp.hdr.errcode)); return -EFAULT; } - *buffersize =3D MAX(be32_to_cpu(tpm2_resp->value1), - be32_to_cpu(tpm2_resp->value2)); + *buffersize =3D MAX(be32_to_cpu(tpm2_resp.value1), + be32_to_cpu(tpm2_resp.value2)); break; } case TPM_VERSION_UNSPEC: diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h index 19b2847..f003d15 100644 --- a/hw/tpm/tpm_util.h +++ b/hw/tpm/tpm_util.h @@ -31,9 +31,24 @@ bool tpm_util_is_selftest(const uint8_t *in, uint32_t in= _len); =20 int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version); =20 +static inline uint16_t tpm_cmd_get_tag(const void *b) +{ + return lduw_be_p(b); +} + static inline uint32_t tpm_cmd_get_size(const void *b) { - return be32_to_cpu(*(const uint32_t *)(b + 2)); + return ldl_be_p(b + 2); +} + +static inline uint32_t tpm_cmd_get_ordinal(const void *b) +{ + return ldl_be_p(b + 6); +} + +static inline uint32_t tpm_cmd_get_errcode(const void *b) +{ + return ldl_be_p(b + 6); } =20 int tpm_util_get_buffer_size(int tpm_fd, TPMVersion tpm_version, --=20 2.5.5 From nobody Mon Apr 29 06:19:56 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 1517264883722659.2879442298554; Mon, 29 Jan 2018 14:28:03 -0800 (PST) Received: from localhost ([::1]:44216 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egHu7-0005h3-A0 for importer@patchew.org; Mon, 29 Jan 2018 17:27:55 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34971) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egHrz-0004Xh-Dc for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:44 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1egHrw-0005sy-8s for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:43 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:35048 helo=mx0a-001b2d01.pphosted.com) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1egHrw-0005sU-3F for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:40 -0500 Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w0TMNfZg033883 for ; Mon, 29 Jan 2018 17:25:39 -0500 Received: from e18.ny.us.ibm.com (e18.ny.us.ibm.com [129.33.205.208]) by mx0a-001b2d01.pphosted.com with ESMTP id 2ft873tbvr-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 29 Jan 2018 17:25:38 -0500 Received: from localhost by e18.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 29 Jan 2018 17:25:38 -0500 Received: from b01cxnp23034.gho.pok.ibm.com (9.57.198.29) by e18.ny.us.ibm.com (146.89.104.205) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 29 Jan 2018 17:25:37 -0500 Received: from b01ledav002.gho.pok.ibm.com (b01ledav002.gho.pok.ibm.com [9.57.199.107]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w0TMPaE147775898; Mon, 29 Jan 2018 22:25:36 GMT Received: from b01ledav002.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4C47A124037; Mon, 29 Jan 2018 17:22:25 -0500 (EST) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b01ledav002.gho.pok.ibm.com (Postfix) with ESMTP id 361A9124035; Mon, 29 Jan 2018 17:22:25 -0500 (EST) From: Stefan Berger To: qemu-devel@nongnu.org Date: Mon, 29 Jan 2018 17:25:16 -0500 X-Mailer: git-send-email 2.5.5 In-Reply-To: <1517264719-18288-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1517264719-18288-1-git-send-email-stefanb@linux.vnet.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 18012922-0044-0000-0000-000003D7C9F1 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008450; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000248; SDB=6.00982230; UDB=6.00498037; IPR=6.00761513; BA=6.00005799; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00019275; XFM=3.00000015; UTC=2018-01-29 22:25:38 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18012922-0045-0000-0000-000008073316 Message-Id: <1517264719-18288-4-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-01-29_12:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1801290286 Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by mx0a-001b2d01.pphosted.com id w0TMNfZg033883 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.158.5 Subject: [Qemu-devel] [PULL v2 3/6] 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: peter.maydell@linaro.org, marcandre.lureau@redhat.com, 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: Marc-Andr=C3=A9 Lureau 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 Signed-off-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 537e11a..fc42fe0 100644 --- a/hw/tpm/tpm_passthrough.c +++ b/hw/tpm/tpm_passthrough.c @@ -214,7 +214,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) { @@ -225,26 +226,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.5.5 From nobody Mon Apr 29 06:19:56 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 1517264884167738.1523524072445; Mon, 29 Jan 2018 14:28:04 -0800 (PST) Received: from localhost ([::1]:44218 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egHuF-0005oY-9Q for importer@patchew.org; Mon, 29 Jan 2018 17:28:03 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35006) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egHs2-0004aB-4K for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:47 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1egHry-0005uJ-UM for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:46 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:43068) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1egHry-0005tu-Kh for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:42 -0500 Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w0TMPMJX025483 for ; Mon, 29 Jan 2018 17:25:41 -0500 Received: from e18.ny.us.ibm.com (e18.ny.us.ibm.com [129.33.205.208]) by mx0a-001b2d01.pphosted.com with ESMTP id 2ft8bc9y14-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 29 Jan 2018 17:25:41 -0500 Received: from localhost by e18.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 29 Jan 2018 17:25:40 -0500 Received: from b01cxnp22036.gho.pok.ibm.com (9.57.198.26) by e18.ny.us.ibm.com (146.89.104.205) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 29 Jan 2018 17:25:38 -0500 Received: from b01ledav002.gho.pok.ibm.com (b01ledav002.gho.pok.ibm.com [9.57.199.107]) by b01cxnp22036.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w0TMPbRl49217692; Mon, 29 Jan 2018 22:25:37 GMT Received: from b01ledav002.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 50A80124037; Mon, 29 Jan 2018 17:22:26 -0500 (EST) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b01ledav002.gho.pok.ibm.com (Postfix) with ESMTP id 43431124035; Mon, 29 Jan 2018 17:22:26 -0500 (EST) From: Stefan Berger To: qemu-devel@nongnu.org Date: Mon, 29 Jan 2018 17:25:17 -0500 X-Mailer: git-send-email 2.5.5 In-Reply-To: <1517264719-18288-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1517264719-18288-1-git-send-email-stefanb@linux.vnet.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 18012922-0044-0000-0000-000003D7C9F2 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008450; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000248; SDB=6.00982230; UDB=6.00498037; IPR=6.00761513; BA=6.00005799; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00019275; XFM=3.00000015; UTC=2018-01-29 22:25:39 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18012922-0045-0000-0000-000008073317 Message-Id: <1517264719-18288-5-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-01-29_12:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1801290286 Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by mx0a-001b2d01.pphosted.com id w0TMPMJX025483 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.156.1 Subject: [Qemu-devel] [PULL v2 4/6] 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: peter.maydell@linaro.org, marcandre.lureau@redhat.com, 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: Marc-Andr=C3=A9 Lureau 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 Signed-off-by: Stefan Berger --- backends/tpm.c | 52 +++++++++++++++++++++++-----------------= ---- include/sysemu/tpm_backend.h | 12 ++++++++-- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/backends/tpm.c b/backends/tpm.c index 91222c5..143807a 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, diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index 0d6c994..a69593e 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; @@ -197,6 +196,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 * --=20 2.5.5 From nobody Mon Apr 29 06:19:56 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 1517265056044537.4560925843693; Mon, 29 Jan 2018 14:30:56 -0800 (PST) Received: from localhost ([::1]:44354 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egHx1-0008BD-76 for importer@patchew.org; Mon, 29 Jan 2018 17:30:55 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:34998) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egHs0-0004Zi-Ru for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:46 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1egHrz-0005uV-8n for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:44 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:38360) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1egHry-0005u1-W1 for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:43 -0500 Received: from pps.filterd (m0098393.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w0TMNlid031796 for ; Mon, 29 Jan 2018 17:25:42 -0500 Received: from e13.ny.us.ibm.com (e13.ny.us.ibm.com [129.33.205.203]) by mx0a-001b2d01.pphosted.com with ESMTP id 2ftbbvj7p9-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 29 Jan 2018 17:25:41 -0500 Received: from localhost by e13.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 29 Jan 2018 17:25:40 -0500 Received: from b01cxnp23034.gho.pok.ibm.com (9.57.198.29) by e13.ny.us.ibm.com (146.89.104.200) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 29 Jan 2018 17:25:39 -0500 Received: from b01ledav002.gho.pok.ibm.com (b01ledav002.gho.pok.ibm.com [9.57.199.107]) by b01cxnp23034.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w0TMPcK647710274; Mon, 29 Jan 2018 22:25:38 GMT Received: from b01ledav002.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5FA1F12403F; Mon, 29 Jan 2018 17:22:27 -0500 (EST) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b01ledav002.gho.pok.ibm.com (Postfix) with ESMTP id 477F0124035; Mon, 29 Jan 2018 17:22:27 -0500 (EST) From: Stefan Berger To: qemu-devel@nongnu.org Date: Mon, 29 Jan 2018 17:25:18 -0500 X-Mailer: git-send-email 2.5.5 In-Reply-To: <1517264719-18288-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1517264719-18288-1-git-send-email-stefanb@linux.vnet.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 18012922-0008-0000-0000-000002C8D884 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008450; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000248; SDB=6.00982231; UDB=6.00498038; IPR=6.00761513; BA=6.00005799; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00019275; XFM=3.00000015; UTC=2018-01-29 22:25:40 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18012922-0009-0000-0000-0000381588E2 Message-Id: <1517264719-18288-6-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-01-29_12:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1801290286 Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by mx0a-001b2d01.pphosted.com id w0TMNlid031796 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.156.1 Subject: [Qemu-devel] [PULL v2 5/6] 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: peter.maydell@linaro.org, marcandre.lureau@redhat.com, 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: Marc-Andr=C3=A9 Lureau 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 Signed-off-by: Stefan Berger --- backends/tpm.c | 9 +++++++-- hw/tpm/tpm_emulator.c | 21 ++++++--------------- hw/tpm/tpm_passthrough.c | 31 +++++++++++++++---------------- hw/tpm/tpm_tis.c | 3 ++- include/sysemu/tpm.h | 2 +- include/sysemu/tpm_backend.h | 3 ++- 6 files changed, 33 insertions(+), 36 deletions(-) diff --git a/backends/tpm.c b/backends/tpm.c index 143807a..d617ba7 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 81bf7d1..710a9ec 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -183,28 +183,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 fc42fe0..a495fe0 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; @@ -98,9 +99,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; } @@ -110,15 +110,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) || tpm_cmd_get_size(out) !=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))) { @@ -131,18 +130,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 8b5eb01..08f41d2 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; diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h index 852e026..ac04a9d 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 a69593e..7e166ef 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 /** --=20 2.5.5 From nobody Mon Apr 29 06:19:56 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 1517264965800147.5672015988797; Mon, 29 Jan 2018 14:29:25 -0800 (PST) Received: from localhost ([::1]:44219 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egHvY-0006s7-Qs for importer@patchew.org; Mon, 29 Jan 2018 17:29:24 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35022) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1egHs4-0004bm-H5 for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:54 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1egHs1-0005wy-7O for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:48 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:35542 helo=mx0a-001b2d01.pphosted.com) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1egHs0-0005w2-E2 for qemu-devel@nongnu.org; Mon, 29 Jan 2018 17:25:44 -0500 Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w0TMNgNs034038 for ; Mon, 29 Jan 2018 17:25:44 -0500 Received: from e11.ny.us.ibm.com (e11.ny.us.ibm.com [129.33.205.201]) by mx0a-001b2d01.pphosted.com with ESMTP id 2ft873tby1-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 29 Jan 2018 17:25:43 -0500 Received: from localhost by e11.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 29 Jan 2018 17:25:43 -0500 Received: from b01cxnp22033.gho.pok.ibm.com (9.57.198.23) by e11.ny.us.ibm.com (146.89.104.198) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 29 Jan 2018 17:25:40 -0500 Received: from b01ledav002.gho.pok.ibm.com (b01ledav002.gho.pok.ibm.com [9.57.199.107]) by b01cxnp22033.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w0TMPdix38338616; Mon, 29 Jan 2018 22:25:39 GMT Received: from b01ledav002.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6AC5C124037; Mon, 29 Jan 2018 17:22:28 -0500 (EST) Received: from sbct-3.watson.ibm.com (unknown [9.47.158.153]) by b01ledav002.gho.pok.ibm.com (Postfix) with ESMTP id 56CD312403F; Mon, 29 Jan 2018 17:22:28 -0500 (EST) From: Stefan Berger To: qemu-devel@nongnu.org Date: Mon, 29 Jan 2018 17:25:19 -0500 X-Mailer: git-send-email 2.5.5 In-Reply-To: <1517264719-18288-1-git-send-email-stefanb@linux.vnet.ibm.com> References: <1517264719-18288-1-git-send-email-stefanb@linux.vnet.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 x-cbid: 18012922-2213-0000-0000-00000263DE99 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00008450; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000248; SDB=6.00982231; UDB=6.00498037; IPR=6.00761513; BA=6.00005799; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00019275; XFM=3.00000015; UTC=2018-01-29 22:25:41 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18012922-2214-0000-0000-000058EF8EA7 Message-Id: <1517264719-18288-7-git-send-email-stefanb@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-01-29_12:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=3 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1801290286 Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by mx0a-001b2d01.pphosted.com id w0TMNgNs034038 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] [fuzzy] X-Received-From: 148.163.158.5 Subject: [Qemu-devel] [PULL v2 6/6] 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: peter.maydell@linaro.org, marcandre.lureau@redhat.com, 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: Marc-Andr=C3=A9 Lureau 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) 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 Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- default-configs/i386-softmmu.mak | 1 + default-configs/x86_64-softmmu.mak | 1 + hw/i386/acpi-build.c | 34 ++++- hw/tpm/Makefile.objs | 1 + hw/tpm/tpm_crb.c | 303 +++++++++++++++++++++++++++++++++= ++++ include/hw/acpi/tpm.h | 51 +++++++ include/sysemu/tpm.h | 3 + qapi/tpm.json | 5 +- tests/Makefile.include | 2 + tests/tpm-crb-test.c | 275 +++++++++++++++++++++++++++++++++ 10 files changed, 666 insertions(+), 10 deletions(-) create mode 100644 hw/tpm/tpm_crb.c create mode 100644 tests/tpm-crb-test.c diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmm= u.mak index 95ac4b4..ac27700 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 0221236..b2104ad 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/i386/acpi-build.c b/hw/i386/acpi-build.c index dc4b2b9..ed78c4e 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/Makefile.objs b/hw/tpm/Makefile.objs index 7a93b24..1dc9f8b 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 diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c new file mode 100644 index 0000000..687d255 --- /dev/null +++ b/hw/tpm/tpm_crb.c @@ -0,0 +1,303 @@ +/* + * tpm_crb.c - QEMU's TPM CRB interface emulator + * + * Copyright (c) 2018 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 "exec/address-spaces.h" + +#include "hw/qdev-core.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 "tpm_int.h" +#include "tpm_util.h" + +typedef 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; +} 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_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 =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 uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr, + unsigned size) +{ + CRBState *s =3D CRB(opaque); + void *regs =3D (void *)&s->regs + (addr & ~3); + unsigned offset =3D addr & 3; + uint32_t val =3D *(uint32_t *)regs >> (8 * offset); + + DPRINTF("CRB read 0x" TARGET_FMT_plx " len:%u val: 0x%" PRIx32 "\n", + addr, size, val); + return val; +} + +static void tpm_crb_mmio_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + CRBState *s =3D CRB(opaque); + DPRINTF("CRB write 0x" TARGET_FMT_plx " len:%u val: 0x%" PRIx64 "\n", + 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 =3D=3D 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 =3D=3D CRB_START_INVOKE && + !(s->regs[R_CRB_CTRL_START] & CRB_START_INVOKE)) { + void *mem =3D memory_region_get_ram_ptr(&s->cmdmem); + + s->regs[R_CRB_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 A_CRB_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: + 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); + ARRAY_FIELD_DP32(s->regs, CRB_LOC_STATE, + tpmRegValidSts, 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_request_completed(TPMIf *ti, int ret) +{ + CRBState *s =3D CRB(ti); + + s->regs[R_CRB_CTRL_START] &=3D ~CRB_START_INVOKE; + if (ret !=3D 0) { + ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS, + tpmSts, 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 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", + .pre_save =3D tpm_crb_pre_save, + .fields =3D (VMStateField[]) { + VMSTATE_UINT32_ARRAY(regs, CRBState, TPM_CRB_R_MAX), + VMSTATE_END_OF_LIST(), + } +}; + +static Property tpm_crb_properties[] =3D { + DEFINE_PROP_TPMBE("tpmdev", CRBState, tpmbe), + DEFINE_PROP_END_OF_LIST(), +}; + +static void tpm_crb_realize(DeviceState *dev, Error **errp) +{ + CRBState *s =3D CRB(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(s->regs)); + memory_region_init_ram(&s->cmdmem, OBJECT(s), + "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp); + + memory_region_add_subregion(get_system_memory(), + TPM_CRB_ADDR_BASE, &s->mmio); + memory_region_add_subregion(get_system_memory(), + TPM_CRB_ADDR_BASE + sizeof(s->regs), &s->cmdmem); + + tpm_backend_reset(s->tpmbe); + + 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] =3D CRB_CTRL_CMD_SIZE; + s->regs[R_CRB_CTRL_CMD_LADDR] =3D TPM_CRB_ADDR_BASE + A_CRB_DATA_BUFFE= R; + s->regs[R_CRB_CTRL_RSP_SIZE] =3D CRB_CTRL_CMD_SIZE; + s->regs[R_CRB_CTRL_RSP_ADDR] =3D TPM_CRB_ADDR_BASE + A_CRB_DATA_BUFFER; + + s->be_buffer_size =3D MIN(tpm_backend_get_buffer_size(s->tpmbe), + CRB_CTRL_CMD_SIZE); + + tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size); +} + +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_realize; + dc->props =3D tpm_crb_properties; + 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; + + set_bit(DEVICE_CATEGORY_MISC, dc->categories); +} + +static const TypeInfo tpm_crb_info =3D { + .name =3D TYPE_TPM_CRB, + /* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */ + .parent =3D TYPE_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/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h index 6d516c6..96fd3a9 100644 --- a/include/hw/acpi/tpm.h +++ b/include/hw/acpi/tpm.h @@ -16,11 +16,61 @@ #ifndef HW_ACPI_TPM_H #define HW_ACPI_TPM_H =20 +#include "hw/registerfields.h" + #define TPM_TIS_ADDR_BASE 0xFED40000 #define TPM_TIS_ADDR_SIZE 0x5000 =20 #define TPM_TIS_IRQ 5 =20 +REG32(CRB_LOC_STATE, 0x00) + FIELD(CRB_LOC_STATE, tpmEstablished, 0, 1) + FIELD(CRB_LOC_STATE, locAssigned, 1, 1) + FIELD(CRB_LOC_STATE, activeLocality, 2, 3) + FIELD(CRB_LOC_STATE, reserved, 5, 2) + FIELD(CRB_LOC_STATE, tpmRegValidSts, 7, 1) +REG32(CRB_LOC_CTRL, 0x08) +REG32(CRB_LOC_STS, 0x0C) + FIELD(CRB_LOC_STS, Granted, 0, 1) + FIELD(CRB_LOC_STS, beenSeized, 1, 1) +REG32(CRB_INTF_ID, 0x30) + FIELD(CRB_INTF_ID, InterfaceType, 0, 4) + FIELD(CRB_INTF_ID, InterfaceVersion, 4, 4) + FIELD(CRB_INTF_ID, CapLocality, 8, 1) + FIELD(CRB_INTF_ID, CapCRBIdleBypass, 9, 1) + FIELD(CRB_INTF_ID, Reserved1, 10, 1) + FIELD(CRB_INTF_ID, CapDataXferSizeSupport, 11, 2) + FIELD(CRB_INTF_ID, CapFIFO, 13, 1) + FIELD(CRB_INTF_ID, CapCRB, 14, 1) + FIELD(CRB_INTF_ID, CapIFRes, 15, 2) + FIELD(CRB_INTF_ID, InterfaceSelector, 17, 2) + FIELD(CRB_INTF_ID, IntfSelLock, 19, 1) + FIELD(CRB_INTF_ID, Reserved2, 20, 4) + FIELD(CRB_INTF_ID, RID, 24, 8) +REG32(CRB_INTF_ID2, 0x34) + FIELD(CRB_INTF_ID2, VID, 0, 16) + FIELD(CRB_INTF_ID2, DID, 16, 16) +REG32(CRB_CTRL_EXT, 0x38) +REG32(CRB_CTRL_REQ, 0x40) +REG32(CRB_CTRL_STS, 0x44) + FIELD(CRB_CTRL_STS, tpmSts, 0, 1) + FIELD(CRB_CTRL_STS, tpmIdle, 1, 1) +REG32(CRB_CTRL_CANCEL, 0x48) +REG32(CRB_CTRL_START, 0x4C) +REG32(CRB_INT_ENABLED, 0x50) +REG32(CRB_INT_STS, 0x54) +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_DATA_BUFFER, 0x80) + +#define TPM_CRB_ADDR_BASE 0xFED40000 +#define TPM_CRB_ADDR_SIZE 0x1000 +#define TPM_CRB_ADDR_CTRL (TPM_CRB_ADDR_BASE + A_CRB_CTRL_REQ) +#define TPM_CRB_R_MAX R_CRB_DATA_BUFFER + #define TPM_LOG_AREA_MINIMUM_SIZE (64 * 1024) =20 #define TPM_TCPA_ACPI_CLASS_CLIENT 0 @@ -30,5 +80,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 ac04a9d..233b1a3 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/qapi/tpm.json b/qapi/tpm.json index 7093f26..d50deef 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/tests/Makefile.include b/tests/Makefile.include index 851aafe..ca82e0c 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -286,6 +286,7 @@ check-qtest-i386-$(CONFIG_VHOST_USER_NET_TEST_i386) += =3D tests/vhost-user-test$(EX ifeq ($(CONFIG_VHOST_USER_NET_TEST_i386),) check-qtest-x86_64-$(CONFIG_VHOST_USER_NET_TEST_x86_64) +=3D tests/vhost-u= ser-test$(EXESUF) endif +check-qtest-i386-$(CONFIG_TPM) +=3D tests/tpm-crb-test$(EXESUF) check-qtest-i386-$(CONFIG_SLIRP) +=3D tests/test-netfilter$(EXESUF) check-qtest-i386-$(CONFIG_POSIX) +=3D tests/test-filter-mirror$(EXESUF) check-qtest-i386-$(CONFIG_POSIX) +=3D tests/test-filter-redirector$(EXESUF) @@ -708,6 +709,7 @@ tests/test-crypto-tlssession$(EXESUF): tests/test-crypt= o-tlssession.o \ tests/test-io-task$(EXESUF): tests/test-io-task.o $(test-io-obj-y) tests/test-io-channel-socket$(EXESUF): tests/test-io-channel-socket.o \ tests/io-channel-helpers.o $(test-io-obj-y) +tests/tpm-crb-test$(EXESUF): tests/tpm-crb-test.o $(test-io-obj-y) tests/test-io-channel-file$(EXESUF): tests/test-io-channel-file.o \ tests/io-channel-helpers.o $(test-io-obj-y) tests/test-io-channel-tls$(EXESUF): tests/test-io-channel-tls.o \ diff --git a/tests/tpm-crb-test.c b/tests/tpm-crb-test.c new file mode 100644 index 0000000..8bf1507 --- /dev/null +++ b/tests/tpm-crb-test.c @@ -0,0 +1,275 @@ +/* + * QTest testcase for TPM CRB + * + * Copyright (c) 2018 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. + */ + +#include "qemu/osdep.h" +#include + +#include "hw/acpi/tpm.h" +#include "hw/tpm/tpm_ioctl.h" +#include "io/channel-socket.h" +#include "libqtest.h" +#include "qapi/error.h" + +#define TPM_RC_FAILURE 0x101 +#define TPM2_ST_NO_SESSIONS 0x8001 + +struct tpm_hdr { + uint16_t tag; + uint32_t len; + uint32_t code; /*ordinal/error */ + char buffer[]; +} QEMU_PACKED; + +typedef struct TestState { + CompatGMutex data_mutex; + CompatGCond data_cond; + SocketAddress *addr; + QIOChannel *tpm_ioc; + GThread *emu_tpm_thread; + struct tpm_hdr *tpm_msg; +} TestState; + +static void test_wait_cond(TestState *s) +{ + gint64 end_time =3D g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; + + g_mutex_lock(&s->data_mutex); + if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) { + g_assert_not_reached(); + } + g_mutex_unlock(&s->data_mutex); +} + +static void *emu_tpm_thread(void *data) +{ + TestState *s =3D data; + QIOChannel *ioc =3D s->tpm_ioc; + + s->tpm_msg =3D g_new(struct tpm_hdr, 1); + while (true) { + int minhlen =3D sizeof(s->tpm_msg->tag) + sizeof(s->tpm_msg->len); + + if (!qio_channel_read(ioc, (char *)s->tpm_msg, minhlen, &error_abo= rt)) { + break; + } + s->tpm_msg->tag =3D be16_to_cpu(s->tpm_msg->tag); + s->tpm_msg->len =3D be32_to_cpu(s->tpm_msg->len); + g_assert_cmpint(s->tpm_msg->len, >=3D, minhlen); + g_assert_cmpint(s->tpm_msg->tag, =3D=3D, TPM2_ST_NO_SESSIONS); + + s->tpm_msg =3D g_realloc(s->tpm_msg, s->tpm_msg->len); + qio_channel_read(ioc, (char *)&s->tpm_msg->code, + s->tpm_msg->len - minhlen, &error_abort); + s->tpm_msg->code =3D be32_to_cpu(s->tpm_msg->code); + + /* reply error */ + s->tpm_msg->tag =3D cpu_to_be16(TPM2_ST_NO_SESSIONS); + s->tpm_msg->len =3D cpu_to_be32(sizeof(struct tpm_hdr)); + s->tpm_msg->code =3D cpu_to_be32(TPM_RC_FAILURE); + qio_channel_write(ioc, (char *)s->tpm_msg, be32_to_cpu(s->tpm_msg-= >len), + &error_abort); + } + + g_free(s->tpm_msg); + s->tpm_msg =3D NULL; + object_unref(OBJECT(s->tpm_ioc)); + return NULL; +} + +static void *emu_ctrl_thread(void *data) +{ + TestState *s =3D data; + QIOChannelSocket *lioc =3D qio_channel_socket_new(); + QIOChannel *ioc; + + qio_channel_socket_listen_sync(lioc, s->addr, &error_abort); + g_cond_signal(&s->data_cond); + + qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN); + ioc =3D QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort)); + g_assert(ioc); + + { + uint32_t cmd =3D 0; + struct iovec iov =3D { .iov_base =3D &cmd, .iov_len =3D sizeof(cmd= ) }; + int *pfd =3D NULL; + size_t nfd =3D 0; + + qio_channel_readv_full(ioc, &iov, 1, &pfd, &nfd, &error_abort); + cmd =3D be32_to_cpu(cmd); + g_assert_cmpint(cmd, =3D=3D, CMD_SET_DATAFD); + g_assert_cmpint(nfd, =3D=3D, 1); + s->tpm_ioc =3D QIO_CHANNEL(qio_channel_socket_new_fd(*pfd, &error_= abort)); + g_free(pfd); + + cmd =3D 0; + qio_channel_write(ioc, (char *)&cmd, sizeof(cmd), &error_abort); + + s->emu_tpm_thread =3D g_thread_new(NULL, emu_tpm_thread, s); + } + + while (true) { + uint32_t cmd; + ssize_t ret; + + ret =3D qio_channel_read(ioc, (char *)&cmd, sizeof(cmd), NULL); + if (ret <=3D 0) { + break; + } + + cmd =3D be32_to_cpu(cmd); + switch (cmd) { + case CMD_GET_CAPABILITY: { + ptm_cap cap =3D cpu_to_be64(0x3fff); + qio_channel_write(ioc, (char *)&cap, sizeof(cap), &error_abort= ); + break; + } + case CMD_INIT: { + ptm_init init; + qio_channel_read(ioc, (char *)&init.u.req, sizeof(init.u.req), + &error_abort); + init.u.resp.tpm_result =3D 0; + qio_channel_write(ioc, (char *)&init.u.resp, sizeof(init.u.res= p), + &error_abort); + break; + } + case CMD_SHUTDOWN: { + ptm_res res =3D 0; + qio_channel_write(ioc, (char *)&res, sizeof(res), &error_abort= ); + qio_channel_close(s->tpm_ioc, &error_abort); + g_thread_join(s->emu_tpm_thread); + break; + } + case CMD_STOP: { + ptm_res res =3D 0; + qio_channel_write(ioc, (char *)&res, sizeof(res), &error_abort= ); + break; + } + case CMD_SET_BUFFERSIZE: { + ptm_setbuffersize sbs; + qio_channel_read(ioc, (char *)&sbs.u.req, sizeof(sbs.u.req), + &error_abort); + sbs.u.resp.buffersize =3D sbs.u.req.buffersize ?: cpu_to_be32(= 4096); + sbs.u.resp.tpm_result =3D 0; + sbs.u.resp.minsize =3D cpu_to_be32(128); + sbs.u.resp.maxsize =3D cpu_to_be32(4096); + qio_channel_write(ioc, (char *)&sbs.u.resp, sizeof(sbs.u.resp), + &error_abort); + break; + } + case CMD_SET_LOCALITY: { + ptm_loc loc; + /* Note: this time it's not u.req / u.resp... */ + qio_channel_read(ioc, (char *)&loc, sizeof(loc), &error_abort); + g_assert_cmpint(loc.u.req.loc, =3D=3D, 0); + loc.u.resp.tpm_result =3D 0; + qio_channel_write(ioc, (char *)&loc, sizeof(loc), &error_abort= ); + break; + } + default: + g_debug("unimplemented %u", cmd); + g_assert_not_reached(); + } + } + + object_unref(OBJECT(ioc)); + object_unref(OBJECT(lioc)); + return NULL; +} + +#define TPM_CMD "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00" + +static void tpm_crb_test(const void *data) +{ + const TestState *s =3D data; + uint32_t intfid =3D readl(TPM_CRB_ADDR_BASE + A_CRB_INTF_ID); + uint32_t csize =3D readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_SIZE); + uint64_t caddr =3D readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR); + uint32_t rsize =3D readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_SIZE); + uint64_t raddr =3D readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR); + + g_assert_cmpint(FIELD_EX32(intfid, CRB_INTF_ID, InterfaceType), =3D=3D= , 1); + g_assert_cmpint(FIELD_EX32(intfid, CRB_INTF_ID, InterfaceVersion), =3D= =3D, 1); + g_assert_cmpint(FIELD_EX32(intfid, CRB_INTF_ID, CapLocality), =3D=3D, = 0); + g_assert_cmpint(FIELD_EX32(intfid, CRB_INTF_ID, CapCRBIdleBypass), =3D= =3D, 0); + g_assert_cmpint(FIELD_EX32(intfid, CRB_INTF_ID, CapDataXferSizeSupport= ), + =3D=3D, 3); + g_assert_cmpint(FIELD_EX32(intfid, CRB_INTF_ID, CapFIFO), =3D=3D, 0); + g_assert_cmpint(FIELD_EX32(intfid, CRB_INTF_ID, CapCRB), =3D=3D, 1); + g_assert_cmpint(FIELD_EX32(intfid, CRB_INTF_ID, InterfaceSelector), = =3D=3D, 1); + g_assert_cmpint(FIELD_EX32(intfid, CRB_INTF_ID, RID), =3D=3D, 0); + + g_assert_cmpint(csize, >=3D, 128); + g_assert_cmpint(rsize, >=3D, 128); + g_assert_cmpint(caddr, >, TPM_CRB_ADDR_BASE); + g_assert_cmpint(raddr, >, TPM_CRB_ADDR_BASE); + + memwrite(caddr, TPM_CMD, sizeof(TPM_CMD)); + + uint32_t sts, start =3D 1; + uint64_t end_time =3D g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; + writel(TPM_CRB_ADDR_BASE + A_CRB_CTRL_START, start); + do { + start =3D readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_START); + if ((start & 1) =3D=3D 0) { + break; + } + } while (g_get_monotonic_time() < end_time); + start =3D readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_START); + g_assert_cmpint(start & 1, =3D=3D, 0); + sts =3D readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_STS); + g_assert_cmpint(sts & 1, =3D=3D, 0); + + struct tpm_hdr tpm_msg; + memread(raddr, &tpm_msg, sizeof(tpm_msg)); + g_assert_cmpmem(&tpm_msg, sizeof(tpm_msg), s->tpm_msg, sizeof(*s->tpm_= msg)); +} + +int main(int argc, char **argv) +{ + int ret; + char *args, *tmp_path =3D g_dir_make_tmp("qemu-tpm-crb-test.XXXXXX", N= ULL); + GThread *thread; + TestState test; + + module_call_init(MODULE_INIT_QOM); + g_test_init(&argc, &argv, NULL); + + test.addr =3D g_new0(SocketAddress, 1); + test.addr->type =3D SOCKET_ADDRESS_TYPE_UNIX; + test.addr->u.q_unix.path =3D g_build_filename(tmp_path, "sock", NULL); + g_mutex_init(&test.data_mutex); + g_cond_init(&test.data_cond); + + thread =3D g_thread_new(NULL, emu_ctrl_thread, &test); + test_wait_cond(&test); + + args =3D g_strdup_printf( + "-chardev socket,id=3Dchr,path=3D%s " + "-tpmdev emulator,id=3Ddev,chardev=3Dchr " + "-device tpm-crb,tpmdev=3Ddev", + test.addr->u.q_unix.path); + qtest_start(args); + + qtest_add_data_func("/tpm-crb/test", &test, tpm_crb_test); + ret =3D g_test_run(); + + qtest_end(); + + g_thread_join(thread); + g_unlink(test.addr->u.q_unix.path); + qapi_free_SocketAddress(test.addr); + g_rmdir(tmp_path); + g_free(tmp_path); + g_free(args); + return ret; +} --=20 2.5.5