From: Cedric Xing <cedric.xing@intel.com>
To: Dan Williams <dan.j.williams@intel.com>,
"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>,
Dave Hansen <dave.hansen@linux.intel.com>,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>
Cc: linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev,
Cedric Xing <cedric.xing@intel.com>
Subject: [PATCH 4/4] x86/tdx: Expose TDX MRs through TSM sysfs interface
Date: Wed, 12 Feb 2025 20:23:07 -0600 [thread overview]
Message-ID: <20250212-tdx-rtmr-v1-4-9795dc49e132@intel.com> (raw)
In-Reply-To: <20250212-tdx-rtmr-v1-0-9795dc49e132@intel.com>
TDX MRs are made accessible to user mode as files (attributes) in sysfs.
Below shows the directory structure of TDX MRs inside a TDVM.
/sys/kernel/tsm
└── tdx
├── mrconfigid
│ └── sha384
│ └── digest
├── mrowner
│ └── sha384
│ └── digest
├── mrownerconfig
│ └── sha384
│ └── digest
├── mrtd
│ └── sha384
│ └── digest
├── report0
├── reportdata
├── rtmr0
│ └── sha384
│ └── digest
├── rtmr1
│ └── sha384
│ └── digest
├── rtmr2
│ └── sha384
│ └── digest
├── rtmr3
│ └── sha384
│ └── digest
└── servtd_hash
└── sha384
└── digest
The digest attribute/file of each MR contains the MR's current value.
Writing to the digest attribute/file of an RTMR extends the written value
to that RTMR.
The report0 and reportdata attributes offer a simple interface for user
mode applications to request TDREPORTs. These 2 attributes can be
enabled/disabled by setting CONFIG_TDX_GUEST_DRIVER_TSM_REPORT to Y/n.
Signed-off-by: Cedric Xing <cedric.xing@intel.com>
---
drivers/virt/coco/tdx-guest/Kconfig | 15 ++++
drivers/virt/coco/tdx-guest/tdx-guest.c | 119 ++++++++++++++++++++++++++++++++
2 files changed, 134 insertions(+)
diff --git a/drivers/virt/coco/tdx-guest/Kconfig b/drivers/virt/coco/tdx-guest/Kconfig
index 22dd59e19431..effadcfd9918 100644
--- a/drivers/virt/coco/tdx-guest/Kconfig
+++ b/drivers/virt/coco/tdx-guest/Kconfig
@@ -9,3 +9,18 @@ config TDX_GUEST_DRIVER
To compile this driver as module, choose M here. The module will
be called tdx-guest.
+
+if TDX_GUEST_DRIVER
+
+config TDX_GUEST_DRIVER_TSM_REPORT
+ bool "tdx-guest: Enable TSM raw TDREPORT interface"
+ default y
+ help
+ This option adds 2 files, namely report0 and reportdata, to the TSM
+ sysfs directory tree (/sys/kernel/tsm/tdx/).
+
+ To request a TDREPORT, set REPORTDATA by writing to
+ /sys/kernel/tsm/tdx/reportdata, then read
+ /sys/kernel/tsm/tdx/report0.
+
+endif
diff --git a/drivers/virt/coco/tdx-guest/tdx-guest.c b/drivers/virt/coco/tdx-guest/tdx-guest.c
index 224e7dde9cde..c95aa17e728c 100644
--- a/drivers/virt/coco/tdx-guest/tdx-guest.c
+++ b/drivers/virt/coco/tdx-guest/tdx-guest.c
@@ -5,6 +5,8 @@
* Copyright (C) 2022 Intel Corporation
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
@@ -18,6 +20,8 @@
#include <linux/tsm.h>
#include <linux/sizes.h>
+#include <crypto/hash_info.h>
+
#include <uapi/linux/tdx-guest.h>
#include <asm/cpu_device_id.h>
@@ -304,6 +308,114 @@ static const struct tsm_ops tdx_tsm_ops = {
.report_bin_attr_visible = tdx_report_bin_attr_visible,
};
+enum {
+ TDREPORT_reportdata = 128,
+ TDREPORT_tdinfo = 512,
+ TDREPORT_mrtd = TDREPORT_tdinfo + 16,
+ TDREPORT_mrconfigid = TDREPORT_mrtd + 48,
+ TDREPORT_mrowner = TDREPORT_mrconfigid + 48,
+ TDREPORT_mrownerconfig = TDREPORT_mrowner + 48,
+ TDREPORT_rtmr0 = TDREPORT_mrownerconfig + 48,
+ TDREPORT_rtmr1 = TDREPORT_rtmr0 + 48,
+ TDREPORT_rtmr2 = TDREPORT_rtmr1 + 48,
+ TDREPORT_rtmr3 = TDREPORT_rtmr2 + 48,
+ TDREPORT_servtd_hash = TDREPORT_rtmr3 + 48,
+};
+
+static u8 tdx_mr_report[TDX_REPORT_LEN] __aligned(TDX_REPORT_LEN);
+
+#define TDX_MR_(r) .mr_value = tdx_mr_report + TDREPORT_##r, TSM_MR_(r, SHA384)
+static const struct tsm_measurement_register tdx_mrs[] = {
+ { TDX_MR_(rtmr0) | TSM_MR_F_RTMR | TSM_MR_F_W },
+ { TDX_MR_(rtmr1) | TSM_MR_F_RTMR | TSM_MR_F_W },
+ { TDX_MR_(rtmr2) | TSM_MR_F_RTMR | TSM_MR_F_W },
+ { TDX_MR_(rtmr3) | TSM_MR_F_RTMR | TSM_MR_F_W },
+ { TDX_MR_(mrtd) },
+ { TDX_MR_(mrconfigid) },
+ { TDX_MR_(mrowner) },
+ { TDX_MR_(mrownerconfig) },
+ { TDX_MR_(servtd_hash) },
+#ifdef CONFIG_TDX_GUEST_DRIVER_TSM_REPORT
+ { .mr_value = tdx_mr_report, .mr_size = sizeof(tdx_mr_report),
+ .mr_name = "report0", .mr_flags = TSM_MR_F_LIVE | TSM_MR_F_F },
+ { .mr_value = tdx_mr_report + TDREPORT_reportdata,
+ TSM_MR_(reportdata, SHA512) | TSM_MR_F_W | TSM_MR_F_F },
+#endif
+ {}
+};
+#undef TDX_MR_
+
+static int tdx_mr_refresh(struct tsm_measurement *tmr,
+ const struct tsm_measurement_register *mr)
+{
+ u8 *reportdata, *tdreport;
+ int ret;
+
+ reportdata = tdx_mr_report + TDREPORT_reportdata;
+
+ /*
+ * TDCALL requires a GPA as input. Depending on whether this module is
+ * built as a built-in (Y) or a module (M), tdx_mr_report may or may
+ * not be converted to a GPA using virt_to_phys. If not, a directly
+ * mapped buffer must be allocated using kmalloc and used as an
+ * intermediary.
+ */
+ if (virt_addr_valid(tdx_mr_report))
+ tdreport = tdx_mr_report;
+ else {
+ tdreport = kmalloc(sizeof(tdx_mr_report), GFP_KERNEL);
+ if (!tdreport)
+ return -ENOMEM;
+
+ reportdata = memcpy(tdreport + TDREPORT_reportdata, reportdata,
+ TDX_REPORTDATA_LEN);
+ }
+
+ ret = tdx_mcall_get_report0(reportdata, tdreport);
+ if (ret)
+ pr_err("GetReport call failed\n");
+
+ if (tdreport != tdx_mr_report) {
+ memcpy(tdx_mr_report, tdreport, sizeof(tdx_mr_report));
+ kfree(tdreport);
+ }
+
+ return ret;
+}
+
+static int tdx_mr_extend(struct tsm_measurement *tmr,
+ const struct tsm_measurement_register *mr, const u8 *data)
+{
+ u8 *buf;
+ int ret;
+
+ if (virt_addr_valid(data))
+ buf = (u8 *)data;
+ else {
+ buf = kmalloc(64, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ memcpy(buf, data, mr->mr_size);
+ }
+
+ ret = tdx_mcall_rtmr_extend((u8)(mr - tmr->mrs), buf);
+ if (ret)
+ pr_err("Extending RTMR%ld failed\n", mr - tmr->mrs);
+
+ if (buf != data)
+ kfree(buf);
+
+ return ret;
+}
+
+static struct tsm_measurement tdx_measurement = {
+ .name = "tdx",
+ .mrs = tdx_mrs,
+ .refresh = tdx_mr_refresh,
+ .extend = tdx_mr_extend,
+};
+
static int __init tdx_guest_init(void)
{
int ret;
@@ -326,8 +438,14 @@ static int __init tdx_guest_init(void)
if (ret)
goto free_quote;
+ ret = tsm_register_measurement(&tdx_measurement);
+ if (ret)
+ goto unregister_tsm;
+
return 0;
+unregister_tsm:
+ tsm_unregister(&tdx_tsm_ops);
free_quote:
free_quote_buf(quote_data);
free_misc:
@@ -339,6 +457,7 @@ module_init(tdx_guest_init);
static void __exit tdx_guest_exit(void)
{
+ tsm_unregister_measurement(&tdx_measurement);
tsm_unregister(&tdx_tsm_ops);
free_quote_buf(quote_data);
misc_deregister(&tdx_misc_dev);
--
2.43.0
next prev parent reply other threads:[~2025-02-13 2:23 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-13 2:23 [PATCH 0/4] tsm: Unified Measurement Register ABI for TVMs Cedric Xing
2025-02-13 2:23 ` [PATCH 1/4] tsm: Add TVM Measurement Register support Cedric Xing
2025-02-14 0:55 ` kernel test robot
2025-02-17 0:17 ` Huang, Kai
2025-02-17 10:44 ` Huang, Kai
2025-02-17 20:57 ` Xing, Cedric
2025-02-18 9:14 ` Huang, Kai
2025-02-18 18:13 ` Xing, Cedric
2025-02-18 1:10 ` Sathyanarayanan Kuppuswamy
2025-02-20 1:01 ` Xing, Cedric
2025-02-13 2:23 ` [PATCH 2/4] tsm: Add TSM measurement sample code Cedric Xing
2025-02-13 2:23 ` [PATCH 3/4] x86/tdx: Add tdx_mcall_rtmr_extend() interface Cedric Xing
2025-02-17 0:40 ` Huang, Kai
2025-02-17 20:58 ` Xing, Cedric
2025-02-17 21:39 ` Sathyanarayanan Kuppuswamy
2025-02-13 2:23 ` Cedric Xing [this message]
2025-02-13 4:50 ` [PATCH 0/4] tsm: Unified Measurement Register ABI for TVMs Dave Hansen
2025-02-13 16:21 ` Xing, Cedric
2025-02-13 16:58 ` Dave Hansen
2025-02-13 21:50 ` Xing, Cedric
2025-02-13 23:19 ` Dave Hansen
2025-02-14 16:19 ` Xing, Cedric
2025-02-14 16:26 ` Dave Hansen
2025-02-14 21:59 ` Xing, Cedric
2025-02-18 16:25 ` Dan Middleton
2025-02-18 16:57 ` Dave Hansen
2025-02-18 23:57 ` Dionna Amalie Glaze
2025-02-19 0:41 ` Dave Hansen
2025-02-19 3:21 ` Dionna Amalie Glaze
2025-02-19 13:29 ` James Bottomley
2025-02-19 15:24 ` Dan Middleton
2025-02-19 20:53 ` James Bottomley
2025-02-19 22:25 ` Xing, Cedric
2025-02-19 23:02 ` Dan Williams
2025-05-02 1:45 ` Dan Williams
2025-02-18 14:49 ` Mikko Ylinen
2025-02-19 4:04 ` Xing, Cedric
2025-02-19 11:31 ` Huang, Kai
2025-02-20 4:37 ` Xing, Cedric
2025-02-19 14:03 ` Mikko Ylinen
2025-02-20 5:07 ` Xing, Cedric
2025-02-18 1:10 ` Sathyanarayanan Kuppuswamy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250212-tdx-rtmr-v1-4-9795dc49e132@intel.com \
--to=cedric.xing@intel.com \
--cc=bp@alien8.de \
--cc=dan.j.williams@intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=hpa@zytor.com \
--cc=kirill.shutemov@linux.intel.com \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®