From: Xu Yilun <yilun.xu@linux.intel.com>
To: linux-coco@lists.linux.dev, linux-pci@vger.kernel.org
Cc: chao.gao@intel.com, dave.jiang@intel.com,
baolu.lu@linux.intel.com, yilun.xu@linux.intel.com,
yilun.xu@intel.com, zhenzhong.duan@intel.com,
kvm@vger.kernel.org, rick.p.edgecombe@intel.com,
dave.hansen@linux.intel.com, dan.j.williams@intel.com,
kas@kernel.org, x86@kernel.org
Subject: [PATCH v1 03/26] coco/tdx-host: Support Link TSM for TDX host
Date: Mon, 17 Nov 2025 10:22:47 +0800 [thread overview]
Message-ID: <20251117022311.2443900-4-yilun.xu@linux.intel.com> (raw)
In-Reply-To: <20251117022311.2443900-1-yilun.xu@linux.intel.com>
Register a Link TSM instance to support host side TSM operations for
TDISP, when the TDX Connect support bit is set by TDX Module in
tdx_feature0.
This is the main purpose of an independent tdx-host module out of TDX
core. Recall that a TEE Security Manager (TSM) is a platform agent that
speaks the TEE Device Interface Security Protocol (TDISP) to PCIe
devices and manages private memory resources for the platform. An
independent tdx-host module allows for device-security enumeration and
initialization flows to be deferred from other TDX Module initialization
requirements. Crucially, when / if TDX Module init moves earlier in x86
initialization flow this driver is still guaranteed to run after IOMMU
and PCI init (i.e. subsys_initcall() vs device_initcall()).
The ability to unload the module, or unbind the driver is also useful
for debug and coarse grained transitioning between PCI TSM operation and
PCI CMA operation (native kernel PCI device authentication).
For now this is the basic boilerplate with operation flows to be added
later.
Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
Co-developed-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
drivers/virt/coco/tdx-host/Kconfig | 6 +
arch/x86/include/asm/tdx.h | 1 +
drivers/virt/coco/tdx-host/tdx-host.c | 154 +++++++++++++++++++++++++-
3 files changed, 160 insertions(+), 1 deletion(-)
diff --git a/drivers/virt/coco/tdx-host/Kconfig b/drivers/virt/coco/tdx-host/Kconfig
index bf6be0fc0879..026b7d5ea4fa 100644
--- a/drivers/virt/coco/tdx-host/Kconfig
+++ b/drivers/virt/coco/tdx-host/Kconfig
@@ -8,3 +8,9 @@ config TDX_HOST_SERVICES
Say y or m if enabling support for confidential virtual machine
support (CONFIG_INTEL_TDX_HOST). The module is called tdx_host.ko
+
+config TDX_CONNECT
+ bool
+ depends on TDX_HOST_SERVICES
+ depends on PCI_TSM
+ default TDX_HOST_SERVICES
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index b6961e137450..ff77900f067b 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -148,6 +148,7 @@ static __always_inline u64 sc_retry(sc_func_t func, u64 fn,
const char *tdx_dump_mce_info(struct mce *m);
/* Bit definitions of TDX_FEATURES0 metadata field */
+#define TDX_FEATURES0_TDXCONNECT BIT_ULL(6)
#define TDX_FEATURES0_NO_RBP_MOD BIT_ULL(18)
const struct tdx_sys_info *tdx_get_sysinfo(void);
diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-host/tdx-host.c
index ced1c980dc6f..6f21bb2dbeb9 100644
--- a/drivers/virt/coco/tdx-host/tdx-host.c
+++ b/drivers/virt/coco/tdx-host/tdx-host.c
@@ -7,8 +7,13 @@
#include <linux/module.h>
#include <linux/mod_devicetable.h>
+#include <linux/pci.h>
+#include <linux/pci-tsm.h>
+#include <linux/tsm.h>
#include <linux/device/faux.h>
#include <asm/cpu_device_id.h>
+#include <asm/tdx.h>
+#include <asm/tdx_global_metadata.h>
static const struct x86_cpu_id tdx_host_ids[] = {
X86_MATCH_FEATURE(X86_FEATURE_TDX_HOST_PLATFORM, NULL),
@@ -16,6 +21,153 @@ static const struct x86_cpu_id tdx_host_ids[] = {
};
MODULE_DEVICE_TABLE(x86cpu, tdx_host_ids);
+/*
+ * The scope of this pointer is for TDX Connect.
+ * Every feature should evaluate how to get tdx_sysinfo. TDX Connect expects no
+ * tdx_sysinfo change after TDX Module update so could cache it. TDX version
+ * sysfs expects change so should call tdx_get_sysinfo() every time.
+ *
+ * Maybe move TDX Connect to a separate file makes thing clearer.
+ */
+static const struct tdx_sys_info *tdx_sysinfo;
+
+struct tdx_link {
+ struct pci_tsm_pf0 pci;
+};
+
+static struct tdx_link *to_tdx_link(struct pci_tsm *tsm)
+{
+ return container_of(tsm, struct tdx_link, pci.base_tsm);
+}
+
+static int tdx_link_connect(struct pci_dev *pdev)
+{
+ return -ENXIO;
+}
+
+static void tdx_link_disconnect(struct pci_dev *pdev)
+{
+}
+
+static struct pci_tsm *tdx_link_pf0_probe(struct tsm_dev *tsm_dev,
+ struct pci_dev *pdev)
+{
+ int rc;
+
+ struct tdx_link *tlink __free(kfree) =
+ kzalloc(sizeof(*tlink), GFP_KERNEL);
+ if (!tlink)
+ return NULL;
+
+ rc = pci_tsm_pf0_constructor(pdev, &tlink->pci, tsm_dev);
+ if (rc)
+ return NULL;
+
+ return &no_free_ptr(tlink)->pci.base_tsm;
+}
+
+static void tdx_link_pf0_remove(struct pci_tsm *tsm)
+{
+ struct tdx_link *tlink = to_tdx_link(tsm);
+
+ pci_tsm_pf0_destructor(&tlink->pci);
+ kfree(tlink);
+}
+
+static struct pci_tsm *tdx_link_fn_probe(struct tsm_dev *tsm_dev,
+ struct pci_dev *pdev)
+{
+ int rc;
+
+ struct pci_tsm *pci_tsm __free(kfree) =
+ kzalloc(sizeof(*pci_tsm), GFP_KERNEL);
+ if (!pci_tsm)
+ return NULL;
+
+ rc = pci_tsm_link_constructor(pdev, pci_tsm, tsm_dev);
+ if (rc)
+ return NULL;
+
+ return no_free_ptr(pci_tsm);
+}
+
+static struct pci_tsm *tdx_link_probe(struct tsm_dev *tsm_dev, struct pci_dev *pdev)
+{
+ if (is_pci_tsm_pf0(pdev))
+ return tdx_link_pf0_probe(tsm_dev, pdev);
+
+ return tdx_link_fn_probe(tsm_dev, pdev);
+}
+
+static void tdx_link_remove(struct pci_tsm *tsm)
+{
+ if (is_pci_tsm_pf0(tsm->pdev)) {
+ tdx_link_pf0_remove(tsm);
+ return;
+ }
+
+ /* for sub-functions */
+ kfree(tsm);
+}
+
+static struct pci_tsm_ops tdx_link_ops = {
+ .probe = tdx_link_probe,
+ .remove = tdx_link_remove,
+ .connect = tdx_link_connect,
+ .disconnect = tdx_link_disconnect,
+};
+
+static void unregister_link_tsm(void *link)
+{
+ tsm_unregister(link);
+}
+
+static int __maybe_unused tdx_connect_init(struct device *dev)
+{
+ struct tsm_dev *link;
+
+ if (!IS_ENABLED(CONFIG_TDX_CONNECT))
+ return 0;
+
+ /*
+ * With this errata, TDX should use movdir64b to clear private pages
+ * when reclaiming them. See tdx_clear_page().
+ *
+ * Don't expect this errata on any TDX Connect supported platform. TDX
+ * Connect will never call tdx_clear_page().
+ */
+ if (boot_cpu_has_bug(X86_BUG_TDX_PW_MCE))
+ return -ENXIO;
+
+ tdx_sysinfo = tdx_get_sysinfo();
+ if (!tdx_sysinfo)
+ return -ENXIO;
+
+ if (!(tdx_sysinfo->features.tdx_features0 & TDX_FEATURES0_TDXCONNECT))
+ return 0;
+
+ link = tsm_register(dev, &tdx_link_ops);
+ if (IS_ERR(link))
+ return dev_err_probe(dev, PTR_ERR(link),
+ "failed to register TSM\n");
+
+ return devm_add_action_or_reset(dev, unregister_link_tsm, link);
+}
+
+static int tdx_host_probe(struct faux_device *fdev)
+{
+ /*
+ * Only support TDX Connect now. More TDX features could be added here.
+ *
+ * TODO: do tdx_connect_init() when it is fully implemented.
+ */
+ return 0;
+}
+
+static struct faux_device_ops tdx_host_ops = {
+ .probe = tdx_host_probe,
+};
+
static struct faux_device *fdev;
static int __init tdx_host_init(void)
@@ -23,7 +175,7 @@ static int __init tdx_host_init(void)
if (!x86_match_cpu(tdx_host_ids))
return -ENODEV;
- fdev = faux_device_create(KBUILD_MODNAME, NULL, NULL);
+ fdev = faux_device_create(KBUILD_MODNAME, NULL, &tdx_host_ops);
if (!fdev)
return -ENODEV;
--
2.25.1
next prev parent reply other threads:[~2025-11-17 2:38 UTC|newest]
Thread overview: 74+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-17 2:22 [PATCH v1 00/26] PCI/TSM: TDX Connect: SPDM Session and IDE Establishment Xu Yilun
2025-11-17 2:22 ` [PATCH v1 01/26] coco/tdx-host: Introduce a "tdx_host" device Xu Yilun
2025-12-19 11:19 ` Jonathan Cameron
2025-11-17 2:22 ` [PATCH v1 02/26] x86/virt/tdx: Move bit definitions of TDX_FEATURES0 to public header Xu Yilun
2025-11-17 2:22 ` Xu Yilun [this message]
2025-12-19 11:18 ` [PATCH v1 03/26] coco/tdx-host: Support Link TSM for TDX host Jonathan Cameron
2025-11-17 2:22 ` [PATCH v1 04/26] x86/tdx: Move all TDX error defines into <asm/shared/tdx_errno.h> Xu Yilun
2025-11-17 2:22 ` [PATCH v1 05/26] mm: Add __free() support for __free_page() Xu Yilun
2025-12-19 11:22 ` Jonathan Cameron
2025-12-23 9:41 ` Xu Yilun
2025-11-17 2:22 ` [PATCH v1 06/26] x86/virt/tdx: Add tdx_page_array helpers for new TDX Module objects Xu Yilun
2025-11-17 16:41 ` Dave Hansen
2025-11-18 12:47 ` Xu Yilun
2026-02-11 16:24 ` dan.j.williams
2025-11-18 19:09 ` Dave Hansen
2025-11-19 16:20 ` dan.j.williams
2025-11-19 18:05 ` Dave Hansen
2025-11-19 19:10 ` dan.j.williams
2025-11-20 8:34 ` Xu Yilun
2025-11-20 6:28 ` Xu Yilun
2025-12-19 11:32 ` Jonathan Cameron
2025-12-23 10:07 ` Xu Yilun
2026-02-17 7:37 ` Tony Lindgren
2025-11-17 2:22 ` [PATCH v1 07/26] x86/virt/tdx: Read TDX global metadata for TDX Module Extensions Xu Yilun
2025-11-17 16:52 ` Dave Hansen
2025-11-18 13:00 ` Xu Yilun
2025-11-17 2:22 ` [PATCH v1 08/26] x86/virt/tdx: Add tdx_enable_ext() to enable of " Xu Yilun
2025-11-17 17:34 ` Dave Hansen
2025-11-18 17:14 ` Xu Yilun
2025-11-18 18:32 ` Dave Hansen
2025-11-20 6:09 ` Xu Yilun
2025-11-20 15:23 ` Dave Hansen
2025-11-20 18:00 ` dan.j.williams
2025-11-21 12:54 ` Xu Yilun
2025-11-21 15:15 ` Dave Hansen
2025-11-21 15:38 ` Dave Hansen
2025-11-24 10:41 ` Xu Yilun
2025-11-24 10:52 ` Xu Yilun
2025-12-08 10:02 ` Xu Yilun
2025-11-17 2:22 ` [PATCH v1 09/26] ACPICA: Add KEYP table definition Xu Yilun
2025-11-17 2:22 ` [PATCH v1 10/26] acpi: Add KEYP support to fw_table parsing Xu Yilun
2025-12-19 11:44 ` Jonathan Cameron
2025-11-17 2:22 ` [PATCH v1 11/26] iommu/vt-d: Cache max domain ID to avoid redundant calculation Xu Yilun
2025-12-19 11:53 ` Jonathan Cameron
2025-12-23 10:09 ` Xu Yilun
2025-11-17 2:22 ` [PATCH v1 12/26] iommu/vt-d: Reserve the MSB domain ID bit for the TDX module Xu Yilun
2025-12-19 11:51 ` Jonathan Cameron
2025-12-19 11:52 ` Jonathan Cameron
2025-12-23 10:39 ` Xu Yilun
2025-11-17 2:22 ` [PATCH v1 13/26] x86/virt/tdx: Read TDX Connect global metadata for TDX Connect Xu Yilun
2025-11-17 2:22 ` [PATCH v1 14/26] mm: Add __free() support for folio_put() Xu Yilun
2025-12-19 11:55 ` Jonathan Cameron
2025-12-23 10:44 ` Xu Yilun
2025-11-17 2:22 ` [PATCH v1 15/26] x86/virt/tdx: Extend tdx_page_array to support IOMMU_MT Xu Yilun
2025-11-17 19:19 ` Dave Hansen
2025-11-17 2:23 ` [PATCH v1 16/26] x86/virt/tdx: Add a helper to loop on TDX_INTERRUPTED_RESUMABLE Xu Yilun
2025-11-17 2:23 ` [PATCH v1 17/26] x86/virt/tdx: Add SEAMCALL wrappers for trusted IOMMU setup and clear Xu Yilun
2025-11-17 2:23 ` [PATCH v1 18/26] iommu/vt-d: Export a helper to do function for each dmar_drhd_unit Xu Yilun
2025-11-17 2:23 ` [PATCH v1 19/26] coco/tdx-host: Setup all trusted IOMMUs on TDX Connect init Xu Yilun
2025-11-17 2:23 ` [PATCH v1 20/26] coco/tdx-host: Add a helper to exchange SPDM messages through DOE Xu Yilun
2025-11-17 2:23 ` [PATCH v1 21/26] x86/virt/tdx: Add SEAMCALL wrappers for SPDM management Xu Yilun
2025-11-17 2:23 ` [PATCH v1 22/26] coco/tdx-host: Implement SPDM session setup Xu Yilun
2025-11-17 2:23 ` [PATCH v1 23/26] coco/tdx-host: Parse ACPI KEYP table to init IDE for PCI host bridges Xu Yilun
2025-12-19 12:02 ` Jonathan Cameron
2025-11-17 2:23 ` [PATCH v1 24/26] x86/virt/tdx: Add SEAMCALL wrappers for IDE stream management Xu Yilun
2025-11-17 2:23 ` [PATCH v1 25/26] coco/tdx-host: Implement IDE stream setup/teardown Xu Yilun
2025-11-17 2:23 ` [PATCH v1 26/26] coco/tdx-host: Finally enable SPDM session and IDE Establishment Xu Yilun
2025-12-19 12:06 ` Jonathan Cameron
2025-12-23 10:45 ` Xu Yilun
2025-11-17 23:05 ` [PATCH v1 00/26] PCI/TSM: TDX Connect: SPDM Session " Dave Hansen
2025-11-18 1:07 ` Xu Yilun
2025-11-19 15:18 ` Dave Hansen
2025-11-19 15:50 ` dan.j.williams
2025-11-19 16:19 ` Dave Hansen
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=20251117022311.2443900-4-yilun.xu@linux.intel.com \
--to=yilun.xu@linux.intel.com \
--cc=baolu.lu@linux.intel.com \
--cc=chao.gao@intel.com \
--cc=dan.j.williams@intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=dave.jiang@intel.com \
--cc=kas@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-pci@vger.kernel.org \
--cc=rick.p.edgecombe@intel.com \
--cc=x86@kernel.org \
--cc=yilun.xu@intel.com \
--cc=zhenzhong.duan@intel.com \
/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