@@ -132,5 +132,8 @@ static __always_inline u64 hcall_func(u64 exit_reason)
return exit_reason;
}
+/* tdx_tsm driver interfaces */
+extern const struct bus_type tdx_subsys;
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASM_X86_SHARED_TDX_H */
@@ -1099,9 +1099,16 @@ static int init_tdmrs(struct tdmr_info_list *tdmr_list)
return 0;
}
-static const struct bus_type tdx_subsys = {
+static int tdx_uevent(const struct device *dev, struct kobj_uevent_env *env)
+{
+ return add_uevent_var(env, "MODALIAS=%s", dev_name(dev));
+}
+
+const struct bus_type tdx_subsys = {
.name = "tdx",
+ .uevent = tdx_uevent,
};
+EXPORT_SYMBOL_NS_GPL(tdx_subsys, TDX);
struct tdx_tsm {
struct device dev;
@@ -4,3 +4,9 @@
#
config TSM
tristate
+
+config TDX_TSM
+ depends on INTEL_TDX_HOST
+ select PCI_TSM
+ select TSM
+ tristate
@@ -4,3 +4,5 @@
obj-$(CONFIG_TSM) += tsm.o
tsm-y := tsm-core.o
+
+obj-$(CONFIG_TDX_TSM) += tdx_tsm.o
new file mode 100644
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2024 Intel Corporation. All rights reserved. */
+#include <linux/tsm.h>
+#include <linux/pci-tsm.h>
+#include <asm/tdx.h>
+
+static int tdx_tsm_add(struct pci_dev *pdev)
+{
+ return 0;
+}
+
+static void tdx_tsm_del(struct pci_dev *pdev)
+{
+}
+
+static int tdx_tsm_exec(struct pci_dev *pdev, enum pci_tsm_cmd cmd)
+{
+ return -EOPNOTSUPP;
+}
+
+static const struct pci_tsm_ops tdx_pci_tsm_ops = {
+ .add = tdx_tsm_add,
+ .del = tdx_tsm_del,
+ .exec = tdx_tsm_exec,
+};
+
+static void unregister_tsm(void *subsys)
+{
+ tsm_unregister(subsys);
+}
+
+static int tdx_tsm_probe(struct device *dev)
+{
+ struct tsm_subsys *subsys;
+
+ subsys = tsm_register(dev, NULL, &tdx_pci_tsm_ops);
+ if (IS_ERR(subsys)) {
+ dev_err(dev, "failed to register TSM: (%pe)\n", subsys);
+ return PTR_ERR(subsys);
+ }
+
+ return devm_add_action_or_reset(dev, unregister_tsm, subsys);
+}
+
+static struct device_driver tdx_tsm_driver = {
+ .probe = tdx_tsm_probe,
+ .bus = &tdx_subsys,
+ .owner = THIS_MODULE,
+ .name = KBUILD_MODNAME,
+ .mod_name = KBUILD_MODNAME,
+};
+
+static int __init tdx_tsm_init(void)
+{
+ return driver_register(&tdx_tsm_driver);
+}
+module_init(tdx_tsm_init);
+
+static void __exit tdx_tsm_exit(void)
+{
+ driver_unregister(&tdx_tsm_driver);
+}
+module_exit(tdx_tsm_exit);
+
+MODULE_IMPORT_NS(TDX);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("tdx_tsm");
+MODULE_DESCRIPTION("TDX TEE Security Manager");
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. The tdx_tsm driver loads against a device of the same name registered at TDX Module initialization time. The device lives on the "tdx" bus which is a virtual subsystem that hosts the TDX module sysfs ABI. It allows for device-security enumeration and initialization flows to be deferred from TDX Module init time. 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 sysfs attributes and operation flows to be added later. Signed-off-by: Dan Williams <dan.j.williams@intel.com> --- arch/x86/include/asm/shared/tdx.h | 3 ++ arch/x86/virt/vmx/tdx/tdx.c | 9 ++++- drivers/virt/coco/host/Kconfig | 6 +++ drivers/virt/coco/host/Makefile | 2 + drivers/virt/coco/host/tdx_tsm.c | 68 +++++++++++++++++++++++++++++++++++++ 5 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 drivers/virt/coco/host/tdx_tsm.c