From: Lu Baolu <baolu.lu@linux.intel.com>
To: iommu@lists.linux.dev, x86@kernel.org,
linux-coco@lists.linux.dev, kvm@vger.kernel.org
Cc: Jason Gunthorpe <jgg@ziepe.ca>, Kevin Tian <kevin.tian@intel.com>,
Kiryl Shutsemau <kas@kernel.org>,
Rick Edgecombe <rick.p.edgecombe@intel.com>,
yilun.xu@linux.intel.com, xiaoyao.li@intel.com,
Chao Gao <chao.gao@intel.com>,
Binbin Wu <binbin.wu@linux.intel.com>,
linux-kernel@vger.kernel.org, Lu Baolu <baolu.lu@linux.intel.com>
Subject: [PATCH v3 7/9] coco/tdx-host: Add skeleton to support PCI link encryption
Date: Thu, 12 Nov 2026 12:30:52 +0800 [thread overview]
Message-ID: <20261112043054.2664857-8-baolu.lu@linux.intel.com> (raw)
In-Reply-To: <20261112043054.2664857-1-baolu.lu@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 only check for TDX Connect support in the TDX Module and
register the Link TSM. The TSM support is basic boilerplate with
operation flows to be added later.
Based on work by Yilun and Dan.
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/virt/coco/tdx-host/Kconfig | 2 +
arch/x86/include/asm/tdx.h | 8 ++
drivers/virt/coco/tdx-host/tdx-host.c | 118 +++++++++++++++++++++++++-
3 files changed, 127 insertions(+), 1 deletion(-)
diff --git a/drivers/virt/coco/tdx-host/Kconfig b/drivers/virt/coco/tdx-host/Kconfig
index 57d0c01a4357..f8c8cc29d46c 100644
--- a/drivers/virt/coco/tdx-host/Kconfig
+++ b/drivers/virt/coco/tdx-host/Kconfig
@@ -1,6 +1,8 @@
config TDX_HOST_SERVICES
tristate
depends on INTEL_TDX_HOST
+ depends on PCI
select FW_LOADER
select FW_UPLOAD
+ select PCI_TSM
default m
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 0ed0062c9b0a..fc284a555984 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -142,6 +142,14 @@ int tdx_topup_pamt_cache(struct tdx_pamt_cache *cache, unsigned long npages);
int tdx_pamt_get(kvm_pfn_t pfn, struct tdx_pamt_cache *cache);
void tdx_pamt_put(kvm_pfn_t pfn);
+static inline bool tdx_supports_tdisp(const struct tdx_sys_info *sysinfo)
+{
+ if (!(sysinfo->features.tdx_features0 & TDX_FEATURES0_TDXCONNECT))
+ return false;
+
+ return false; /* To be enabled when kernel is ready */
+}
+
int tdx_guest_keyid_alloc(void);
u32 tdx_get_nr_guest_keyids(void);
void tdx_guest_keyid_free(unsigned int keyid);
diff --git a/drivers/virt/coco/tdx-host/tdx-host.c b/drivers/virt/coco/tdx-host/tdx-host.c
index e8ed8dfa526e..0908aaaa28ac 100644
--- a/drivers/virt/coco/tdx-host/tdx-host.c
+++ b/drivers/virt/coco/tdx-host/tdx-host.c
@@ -9,10 +9,14 @@
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/sysfs.h>
+#include <linux/pci.h>
+#include <linux/pci-tsm.h>
+#include <linux/tsm.h>
#include <asm/cpu_device_id.h>
#include <asm/seamldr.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),
@@ -20,6 +24,112 @@ static const struct x86_cpu_id tdx_host_ids[] = {
};
MODULE_DEVICE_TABLE(x86cpu, tdx_host_ids);
+struct tdx_tsm_link {
+ struct pci_tsm_pf0 pci;
+};
+
+static struct tdx_tsm_link *to_tdx_tsm_link(struct pci_tsm *tsm)
+{
+ return container_of(tsm, struct tdx_tsm_link, pci.base_tsm);
+}
+
+static int tdx_tsm_link_connect(struct pci_dev *pdev)
+{
+ return -ENXIO;
+}
+
+static void tdx_tsm_link_disconnect(struct pci_dev *pdev)
+{
+}
+
+static struct pci_tsm *tdx_tsm_link_pf0_probe(struct tsm_dev *tsm_dev,
+ struct pci_dev *pdev)
+{
+ int rc;
+
+ struct tdx_tsm_link *tlink __free(kfree) = kzalloc_obj(*tlink);
+ 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_tsm_link_pf0_remove(struct pci_tsm *tsm)
+{
+ struct tdx_tsm_link *tlink = to_tdx_tsm_link(tsm);
+
+ pci_tsm_pf0_destructor(&tlink->pci);
+ kfree(tlink);
+}
+
+static struct pci_tsm *tdx_tsm_link_fn_probe(struct tsm_dev *tsm_dev,
+ struct pci_dev *pdev)
+{
+ int rc;
+
+ struct pci_tsm *pci_tsm __free(kfree) = kzalloc_obj(*pci_tsm);
+ 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_tsm_link_probe(struct tsm_dev *tsm_dev,
+ struct pci_dev *pdev)
+{
+ if (is_pci_tsm_pf0(pdev))
+ return tdx_tsm_link_pf0_probe(tsm_dev, pdev);
+
+ return tdx_tsm_link_fn_probe(tsm_dev, pdev);
+}
+
+static void tdx_tsm_link_remove(struct pci_tsm *tsm)
+{
+ if (is_pci_tsm_pf0(tsm->pdev)) {
+ tdx_tsm_link_pf0_remove(tsm);
+ return;
+ }
+
+ /* for sub-functions */
+ kfree(tsm);
+}
+
+static struct pci_tsm_ops tdx_tsm_link_ops = {
+ .probe = tdx_tsm_link_probe,
+ .remove = tdx_tsm_link_remove,
+ .connect = tdx_tsm_link_connect,
+ .disconnect = tdx_tsm_link_disconnect,
+};
+
+static void unregister_link_tsm(void *link)
+{
+ tsm_unregister(link);
+}
+
+static int tdx_tdisp_init(struct device *dev)
+{
+ const struct tdx_sys_info *sysinfo = tdx_get_sysinfo();
+ struct tsm_dev *link;
+
+ if (!sysinfo || !tdx_supports_tdisp(sysinfo))
+ return 0;
+
+ link = tsm_register(dev, &tdx_tsm_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 ssize_t version_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -204,7 +314,13 @@ static int seamldr_init(struct device *dev)
static int tdx_host_probe(struct faux_device *fdev)
{
- return seamldr_init(&fdev->dev);
+ int ret;
+
+ ret = seamldr_init(&fdev->dev);
+ if (ret)
+ return ret;
+
+ return tdx_tdisp_init(&fdev->dev);
}
static const struct faux_device_ops tdx_host_ops = {
--
2.43.0
next prev parent reply other threads:[~2026-11-12 4:44 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-12 4:30 [PATCH v3 0/9] coco/tdx-host: Introduce trusted DMA initialization support Lu Baolu
2026-11-12 4:30 ` [PATCH v3 1/9] x86/virt/tdx: Add SEAMCALL wrappers for IOMMU setup/clear Lu Baolu
2026-11-12 4:30 ` [PATCH v3 2/9] x86/virt/tdx: Read global metadata for trusted IOMMU Lu Baolu
2026-11-12 4:30 ` [PATCH v3 3/9] x86/virt/tdx: Export Dynamic PAMT helpers to tdx-host Lu Baolu
2026-11-12 4:30 ` [PATCH v3 4/9] iommu/vt-d: Add interface for tdx-host when enabling trusted DMA Lu Baolu
2026-11-12 4:30 ` [PATCH v3 5/9] iommu/vt-d: Block GCMD and ECMD while acquired by the TDX module Lu Baolu
2026-11-12 4:30 ` [PATCH v3 6/9] iommu/vt-d: Refuse system suspend " Lu Baolu
2026-11-12 4:30 ` Lu Baolu [this message]
2026-11-12 4:30 ` [PATCH v3 8/9] coco/tdx-host: Rename tdx-host.c to main.c Lu Baolu
2026-11-12 4:30 ` [PATCH v3 9/9] coco/tdx-host: Enable trusted DMA on IOMMUs on device connect Lu Baolu
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=20261112043054.2664857-8-baolu.lu@linux.intel.com \
--to=baolu.lu@linux.intel.com \
--cc=binbin.wu@linux.intel.com \
--cc=chao.gao@intel.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@ziepe.ca \
--cc=kas@kernel.org \
--cc=kevin.tian@intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=rick.p.edgecombe@intel.com \
--cc=x86@kernel.org \
--cc=xiaoyao.li@intel.com \
--cc=yilun.xu@linux.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
all inboxes | Powered by JetHome®