From: Dan Williams <djbw@kernel.org>
To: linux-coco@lists.linux.dev
Cc: linux-pci@vger.kernel.org, driver-core@lists.linux.dev,
ankita@nvidia.com, Bjorn Helgaas <bhelgaas@google.com>,
Xu Yilun <yilun.xu@linux.intel.com>,
"Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
Subject: [PATCH 10/15] PCI/TSM: Add device interface security LOCKED support
Date: Sun, 5 Jul 2026 15:08:14 -0700 [thread overview]
Message-ID: <20260705220819.2472765-11-djbw@kernel.org> (raw)
In-Reply-To: <20260705220819.2472765-1-djbw@kernel.org>
PCIe Trusted Execution Environment Device Interface Security Protocol
(TDISP) has two distinct sets of operations. The first, already enabled in
driver/pci/tsm.c, enables the VMM to authenticate the physical function
(PCIe Component Measurement and Authentication (CMA)), establish a secure
message passing session (DMTF SPDM), and establish physical link security
(PCIe Integrity and Data Encryption (IDE)). The second set of operations
lets a VM manage the security state of assigned devices (TEE Device
Interfaces (TDIs)). Implement the LOCK/UNLOCK operations in pci_tsm_ops, to
be followed with an operation to transition the interface to RUN.
- lock(): Transition the device to the TDISP LOCKED state. In this state
measurements can validated to ensure that the VM trusts the device's
security manager (DSM).
- unlock(): Transition the device to the TDISP UNLOCKED state.
The device shall not be attached to a driver during these transitions.
Cc: Bjorn Helgaas <bhelgaas@google.com>
Co-developed-by: Xu Yilun <yilun.xu@linux.intel.com>
Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
Co-developed-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
Signed-off-by: Dan Williams <djbw@kernel.org>
---
Documentation/ABI/testing/sysfs-bus-pci | 34 +++-
Documentation/ABI/testing/sysfs-class-tsm | 19 ++
Documentation/driver-api/pci/tsm.rst | 47 +++++
include/linux/pci-tsm.h | 21 ++-
drivers/pci/tsm/core.c | 213 +++++++++++++++++++++-
drivers/virt/coco/tsm-core.c | 43 ++++-
6 files changed, 366 insertions(+), 11 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index b767db2c52cb..1ed77b9402a6 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -647,13 +647,16 @@ Description:
Encryption) establishment. Reads from this attribute return the
name of the connected TSM or the empty string if not
connected. A TSM device signals its readiness to accept PCI
- connection via a KOBJ_CHANGE event.
+ connection via a KOBJ_CHANGE event. This is a "link" TSM
+ attribute, see Documentation/ABI/testing/sysfs-class-tsm.
What: /sys/bus/pci/devices/.../tsm/disconnect
Contact: linux-coco@lists.linux.dev
Description:
(WO) Write the name of the TSM device that was specified
- to 'connect' to teardown the connection.
+ to 'connect' to teardown the connection. This is a
+ "link" TSM attribute, see
+ Documentation/ABI/testing/sysfs-class-tsm.
What: /sys/bus/pci/devices/.../tsm/dsm
Contact: linux-coco@lists.linux.dev
@@ -702,3 +705,30 @@ Description:
When present and the tsm/ attribute directory is present, the
authenticated attribute is an alias for the device 'connect'
state. See the 'tsm/connect' attribute for more details.
+ This is a "link" TSM attribute, see
+ Documentation/ABI/testing/sysfs-class-tsm.
+
+What: /sys/bus/pci/devices/.../tsm/lock
+Contact: linux-coco@lists.linux.dev
+Description:
+ (RW) Write the name of a TSM (TEE Security Manager) device
+ instance to this file to request that the platform transition
+ the PCIe device configuration to the TDISP LOCKED state. This
+ puts the device in a state where security sensitive
+ configuration setting can not be changed without transitioning
+ the device the PCIe TDISP ERROR state. Reads from this attribute
+ return the name of the TSM device instance that has arranged for
+ the device to be locked, or the empty string if not locked. A
+ TSM class device signals its readiness for lock requests via a
+ KOBJ_CHANGE event. Writes fail with EBUSY if this device is
+ bound to a driver. This is a "devsec" TSM attribute, see
+ Documentation/ABI/testing/sysfs-class-tsm. See
+ Documentation/driver-api/pci/tsm.rst for more details.
+
+What: /sys/bus/pci/devices/.../tsm/unlock
+Contact: linux-coco@lists.linux.dev
+Description:
+ (WO) Write the name of the TSM device that was specified to
+ 'lock' to teardown the connection. Writes fail with EBUSY if
+ this device is bound to a driver. This is a "devsec" TSM
+ attribute, see Documentation/ABI/testing/sysfs-class-tsm.
diff --git a/Documentation/ABI/testing/sysfs-class-tsm b/Documentation/ABI/testing/sysfs-class-tsm
index 2949468deaf7..44e8a0bf4dae 100644
--- a/Documentation/ABI/testing/sysfs-class-tsm
+++ b/Documentation/ABI/testing/sysfs-class-tsm
@@ -7,3 +7,22 @@ Description:
signals when the PCI layer is able to support establishment of
link encryption and other device-security features coordinated
through a platform tsm.
+
+What: /sys/class/tsm/tsmN/pci_mode
+Contact: linux-coco@lists.linux.dev
+Description:
+ (RO) A TSM with PCIe TDISP capability can be in one of two
+ modes.
+
+ "link": typically for a hypervisor (VMM) to authenticate,
+ establish a secure session, and setup link
+ encryption.
+
+ "devsec": typically for a confidential guest (TVM) to
+ transition assigned devices through the TDISP
+ state machine UNLOCKED->LOCKED->RUN.
+
+ See the "tsm/" entries in
+ Documentation/ABI/testing/sysfs-bus-pci for the available PCI
+ device attributes when a TSM with the given "pci_mode" is
+ registered.
diff --git a/Documentation/driver-api/pci/tsm.rst b/Documentation/driver-api/pci/tsm.rst
index 232b92bec93f..19df202107fa 100644
--- a/Documentation/driver-api/pci/tsm.rst
+++ b/Documentation/driver-api/pci/tsm.rst
@@ -5,6 +5,53 @@
PCI Trusted Execution Environment Security Manager (TSM)
========================================================
+Overview
+========
+
+A "TSM", as detailed by PCIe r7.0 section 11 "TEE Device Interface
+Security Protocol (TDISP)", is an entity within the platform's Trusted
+Computing Base (TCB) that enforces security policies on the host. It
+serves to mitigate a threat model where devices may be under the control
+of an adversary. The adversarial threats are:
+
+- Identity: Device may be mimicking a legitimate device identity / firmware
+- Physical: link may be under observation, or control (reorder / drop data)
+- Virtual: Device MMIO presented to a guest may not actually map the
+ device, device DMA may be redirected.
+
+In Linux a "tsm" is a broader concept. It is a class device interface to
+mitigate one or more of the above threats. A "tsm driver" registers a
+tsm device that publishes either the 'tsm/connect' or
+'tsm/{lock,accept}' set of attributes for the PCIe device. The typical
+expectation is that 'tsm/{lock,accept}' is published by a guest "tsm
+driver" to mitigate "Virtual" threats. The 'tsm/connect' interface is
+published by a host "tsm driver" to mitigate "Identity" and/or
+"Physical" threats.
+
+Device Interface LOCK
+=====================
+The lock operation facilitated by tsm/lock (see
+Documentation/ABI/testing/sysfs-bus-pci) places the device in a mode
+where any security sensitive changes to the device configuration results
+in the device transitioning to the ERROR state. The device presents
+signed evidence of its LOCK state to the kernel through the tsm driver.
+The relying party is responsible for verifying not only the evidence but
+that the device is trusted to maintain those attested values while
+locked. Accepting the locked configuration moves the device to the RUN
+state where it will accept private (T=1) traffic to its MMIO interface.
+
+Note that the RUN state is necessary, but not sufficient for the device
+to access private host memory (send T=1 DMA). That is only enabled after
+the device's trust level has been elevated to indicate it can operate
+within the TCB.
+
+A device in the RUN state is trusted to cease TCB interactions (send T=1
+DMA / accept T=1 MMIO TLPs) when it is next unlocked or encounters a
+security relevant error. The TSM is responsible for enforcing that the
+device is not unlocked within the interval between evidence collection
+and acceptance, by correlating the evidence from LOCK to the subsequent
+RUN request.
+
Subsystem Interfaces
====================
diff --git a/include/linux/pci-tsm.h b/include/linux/pci-tsm.h
index 8bc16029d31e..326471f1e01a 100644
--- a/include/linux/pci-tsm.h
+++ b/include/linux/pci-tsm.h
@@ -72,7 +72,8 @@ struct pci_tsm_ops {
* @unlock: destroy TSM context and return device to UNLOCKED state
*
* Context: @lock and @unlock run under pci_tsm_rwsem held for write to
- * sync with TSM unregistration and each other
+ * sync with TSM unregistration and each other. All operations run under
+ * the device lock for mutual exclusion with driver attach and detach.
*/
struct_group_tagged(pci_tsm_devsec_ops, devsec_ops,
struct pci_tsm *(*lock)(struct tsm_dev *tsm_dev,
@@ -115,6 +116,13 @@ struct pci_tdi {
* sub-function (SR-IOV virtual function, or non-function0
* multifunction-device), or a downstream endpoint (PCIe upstream switch-port as
* DSM).
+ *
+ * For devsec operations it serves to indicate that the function / TDI has been
+ * locked to a given TSM.
+ *
+ * The common expectation is that there is only ever one TSM, but this is not
+ * enforced. The implementation only enforces that a device can be "connected"
+ * to a TSM instance or "locked" to a different TSM.
*/
struct pci_tsm {
struct pci_dev *pdev;
@@ -136,6 +144,14 @@ struct pci_tsm_pf0 {
struct pci_doe_mb *doe_mb;
};
+/**
+ * struct pci_tsm_devsec - context for tracking private/accepted PCI resources
+ * @base_tsm: generic core "tsm" context
+ */
+struct pci_tsm_devsec {
+ struct pci_tsm base_tsm;
+};
+
/* physical function0 and capable of 'connect' */
static inline bool is_pci_tsm_pf0(struct pci_dev *pdev)
{
@@ -216,6 +232,8 @@ int pci_tsm_link_constructor(struct pci_dev *pdev, struct pci_tsm *tsm,
struct tsm_dev *tsm_dev);
int pci_tsm_pf0_constructor(struct pci_dev *pdev, struct pci_tsm_pf0 *tsm,
struct tsm_dev *tsm_dev);
+int pci_tsm_devsec_constructor(struct pci_dev *pdev, struct pci_tsm_devsec *tsm,
+ struct tsm_dev *tsm_dev);
void pci_tsm_pf0_destructor(struct pci_tsm_pf0 *tsm);
int pci_tsm_doe_transfer(struct pci_dev *pdev, u8 type, const void *req,
size_t req_sz, void *resp, size_t resp_sz);
@@ -230,6 +248,7 @@ static inline const struct pci_tsm_ops *to_pci_tsm_ops(struct pci_tsm *tsm)
{
return tsm->tsm_dev->pci_ops;
}
+struct pci_tsm_devsec *to_pci_tsm_devsec(struct pci_tsm *tsm);
#else
static inline int pci_tsm_register(struct tsm_dev *tsm_dev)
{
diff --git a/drivers/pci/tsm/core.c b/drivers/pci/tsm/core.c
index 220842df42bc..590e19f6c2b8 100644
--- a/drivers/pci/tsm/core.c
+++ b/drivers/pci/tsm/core.c
@@ -9,6 +9,7 @@
#define dev_fmt(fmt) "PCI/TSM: " fmt
#include <linux/bitfield.h>
+#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/pci-doe.h>
#include <linux/pci-tsm.h>
@@ -58,6 +59,26 @@ static struct pci_tsm_pf0 *to_pci_tsm_pf0(struct pci_tsm *tsm)
return container_of(pf0->tsm, struct pci_tsm_pf0, base_tsm);
}
+static inline bool is_devsec(struct pci_dev *pdev)
+{
+ return pdev->tsm && pdev->tsm->dsm_dev == NULL &&
+ pdev->tsm->tdi == NULL;
+}
+
+/* 'struct pci_tsm_devsec' wraps 'struct pci_tsm' when ->tdi == ->dsm == NULL */
+struct pci_tsm_devsec *to_pci_tsm_devsec(struct pci_tsm *tsm)
+{
+ struct pci_dev *pdev = tsm->pdev;
+
+ if (!is_devsec(pdev) || !has_tee(pdev)) {
+ pci_WARN_ONCE(pdev, 1, "invalid context object\n");
+ return NULL;
+ }
+
+ return container_of(tsm, struct pci_tsm_devsec, base_tsm);
+}
+EXPORT_SYMBOL_GPL(to_pci_tsm_devsec);
+
static void tsm_remove(struct pci_tsm *tsm)
{
struct pci_dev *pdev;
@@ -531,6 +552,125 @@ static ssize_t dsm_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(dsm);
+/**
+ * pci_tsm_unlock() - Transition TDI from LOCKED/RUN to UNLOCKED
+ * @pdev: TDI device to unlock
+ *
+ * Returns void, requires all callers to have satisfied dependencies like making
+ * sure the device is locked and detached from its driver.
+ */
+static void pci_tsm_unlock(struct pci_dev *pdev)
+{
+ lockdep_assert_held_write(&pci_tsm_rwsem);
+ device_lock_assert(&pdev->dev);
+
+ if (dev_WARN_ONCE(&pdev->dev, pdev->dev.driver,
+ "unlock attempted on driver attached device\n"))
+ return;
+
+ device_cc_reject(&pdev->dev);
+ to_pci_tsm_ops(pdev->tsm)->unlock(pdev->tsm);
+ pdev->tsm = NULL;
+}
+
+static int pci_tsm_lock(struct pci_dev *pdev, struct tsm_dev *tsm_dev)
+{
+ const struct pci_tsm_ops *ops = tsm_dev->pci_ops;
+ struct pci_tsm *tsm;
+ int rc;
+
+ ACQUIRE(device_intr, lock)(&pdev->dev);
+ if ((rc = ACQUIRE_ERR(device_intr, &lock)))
+ return rc;
+
+ if (pdev->dev.driver)
+ return -EBUSY;
+
+ tsm = ops->lock(tsm_dev, pdev);
+ if (IS_ERR(tsm))
+ return PTR_ERR(tsm);
+
+ pdev->tsm = tsm;
+ return 0;
+}
+
+static ssize_t lock_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ int rc, id;
+
+ rc = sscanf(buf, "tsm%d\n", &id);
+ if (rc != 1)
+ return -EINVAL;
+
+ ACQUIRE(rwsem_write_kill, lock)(&pci_tsm_rwsem);
+ if ((rc = ACQUIRE_ERR(rwsem_write_kill, &lock)))
+ return rc;
+
+ if (pdev->tsm)
+ return -EBUSY;
+
+ struct tsm_dev *tsm_dev __free(put_tsm_dev) = find_tsm_dev(id);
+ if (!is_devsec_tsm(tsm_dev))
+ return -ENXIO;
+
+ rc = pci_tsm_lock(pdev, tsm_dev);
+ if (rc)
+ return rc;
+ return len;
+}
+
+static ssize_t lock_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct tsm_dev *tsm_dev;
+ int rc;
+
+ ACQUIRE(rwsem_read_intr, lock)(&pci_tsm_rwsem);
+ if ((rc = ACQUIRE_ERR(rwsem_read_intr, &lock)))
+ return rc;
+
+ if (!pdev->tsm)
+ return sysfs_emit(buf, "\n");
+
+ tsm_dev = pdev->tsm->tsm_dev;
+ return sysfs_emit(buf, "%s\n", dev_name(&tsm_dev->dev));
+}
+static DEVICE_ATTR_RW(lock);
+
+static ssize_t unlock_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct tsm_dev *tsm_dev;
+ int rc;
+
+ ACQUIRE(rwsem_write_kill, lock)(&pci_tsm_rwsem);
+ if ((rc = ACQUIRE_ERR(rwsem_write_kill, &lock)))
+ return rc;
+
+ if (!pdev->tsm)
+ return -EINVAL;
+
+ tsm_dev = pdev->tsm->tsm_dev;
+ if (!sysfs_streq(buf, dev_name(&tsm_dev->dev)))
+ return -EINVAL;
+
+ ACQUIRE(device_intr, dev_lock)(&pdev->dev);
+ if ((rc = ACQUIRE_ERR(device_intr, &dev_lock)))
+ return rc;
+
+ if (pdev->dev.driver)
+ return -EBUSY;
+
+ pci_tsm_unlock(pdev);
+
+ return len;
+}
+static DEVICE_ATTR_WO(unlock);
+
/* The 'authenticated' attribute is exclusive to the presence of a 'link' TSM */
static bool pci_tsm_link_group_visible(struct kobject *kobj)
{
@@ -556,6 +696,13 @@ static bool pci_tsm_link_group_visible(struct kobject *kobj)
}
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(pci_tsm_link);
+static bool pci_tsm_devsec_group_visible(struct kobject *kobj)
+{
+ struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
+
+ return pci_tsm_devsec_count && has_tee(pdev);
+}
+
/*
* 'link' and 'devsec' TSMs share the same 'tsm/' sysfs group, so the TSM type
* specific attributes need individual visibility checks.
@@ -587,12 +734,19 @@ static umode_t pci_tsm_attr_visible(struct kobject *kobj,
}
}
+ if (pci_tsm_devsec_group_visible(kobj)) {
+ if (attr == &dev_attr_lock.attr ||
+ attr == &dev_attr_unlock.attr)
+ return attr->mode;
+ }
+
return 0;
}
static bool pci_tsm_group_visible(struct kobject *kobj)
{
- return pci_tsm_link_group_visible(kobj);
+ return pci_tsm_link_group_visible(kobj) ||
+ pci_tsm_devsec_group_visible(kobj);
}
DEFINE_SYSFS_GROUP_VISIBLE(pci_tsm);
@@ -601,6 +755,8 @@ static struct attribute *pci_tsm_attrs[] = {
&dev_attr_disconnect.attr,
&dev_attr_bound.attr,
&dev_attr_dsm.attr,
+ &dev_attr_lock.attr,
+ &dev_attr_unlock.attr,
NULL
};
@@ -729,6 +885,29 @@ int pci_tsm_link_constructor(struct pci_dev *pdev, struct pci_tsm *tsm,
}
EXPORT_SYMBOL_GPL(pci_tsm_link_constructor);
+/**
+ * pci_tsm_devsec_constructor() - devsec TSM context initialization
+ * @pdev: The PCI device
+ * @tsm: context to initialize
+ * @tsm_dev: Platform TEE Security Manager, initiator of security operations
+ */
+int pci_tsm_devsec_constructor(struct pci_dev *pdev, struct pci_tsm_devsec *tsm,
+ struct tsm_dev *tsm_dev)
+{
+ struct pci_tsm *pci_tsm = &tsm->base_tsm;
+
+ if (!is_devsec_tsm(tsm_dev))
+ return -EINVAL;
+
+ pci_tsm->dsm_dev = NULL;
+ pci_tsm->tdi = NULL;
+ pci_tsm->pdev = pdev;
+ pci_tsm->tsm_dev = tsm_dev;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_tsm_devsec_constructor);
+
/**
* pci_tsm_pf0_constructor() - common 'struct pci_tsm_pf0' (DSM) initialization
* @pdev: Physical Function 0 PCI device (as indicated by is_pci_tsm_pf0())
@@ -756,6 +935,13 @@ void pci_tsm_pf0_destructor(struct pci_tsm_pf0 *pf0_tsm)
}
EXPORT_SYMBOL_GPL(pci_tsm_pf0_destructor);
+static void devsec_sysfs_enable(struct pci_dev *pdev)
+{
+ pci_dbg(pdev, "TEE I/O Device capability detected (TDISP)\n");
+
+ sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group);
+}
+
int pci_tsm_register(struct tsm_dev *tsm_dev)
{
struct pci_dev *pdev = NULL;
@@ -777,8 +963,10 @@ int pci_tsm_register(struct tsm_dev *tsm_dev)
for_each_pci_dev(pdev)
if (is_pci_tsm_pf0(pdev))
link_sysfs_enable(pdev);
- } else if (is_devsec_tsm(tsm_dev)) {
- pci_tsm_devsec_count++;
+ } else if (is_devsec_tsm(tsm_dev) && pci_tsm_devsec_count++ == 0) {
+ for_each_pci_dev(pdev)
+ if (has_tee(pdev))
+ devsec_sysfs_enable(pdev);
}
return 0;
@@ -813,6 +1001,9 @@ static void __pci_tsm_destroy(struct pci_dev *pdev, struct tsm_dev *tsm_dev)
if (is_link_tsm(tsm_dev) && is_pci_tsm_pf0(pdev) && !pci_tsm_link_count)
link_sysfs_disable(pdev);
+ if (is_devsec_tsm(tsm_dev) && !pci_tsm_devsec_count)
+ sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group);
+
/* Nothing else to do if this device never attached to the departing TSM */
if (!tsm)
return;
@@ -823,10 +1014,18 @@ static void __pci_tsm_destroy(struct pci_dev *pdev, struct tsm_dev *tsm_dev)
else if (tsm_dev != tsm->tsm_dev)
return;
- if (is_link_tsm(tsm_dev) && is_pci_tsm_pf0(pdev))
- pci_tsm_disconnect(pdev);
- else
- pci_tsm_fn_exit(pdev);
+ /* Disconnect DSMs, unlock assigned TDIs, or cleanup DSM subfunctions */
+ if (is_link_tsm(tsm_dev)) {
+ if (is_pci_tsm_pf0(pdev))
+ pci_tsm_disconnect(pdev);
+ else
+ pci_tsm_fn_exit(pdev);
+ }
+
+ if (is_devsec_tsm(tsm_dev) && has_tee(pdev)) {
+ guard(device)(&pdev->dev);
+ pci_tsm_unlock(pdev);
+ }
}
void pci_tsm_destroy(struct pci_dev *pdev)
diff --git a/drivers/virt/coco/tsm-core.c b/drivers/virt/coco/tsm-core.c
index e784993353d8..8e298bda10fc 100644
--- a/drivers/virt/coco/tsm-core.c
+++ b/drivers/virt/coco/tsm-core.c
@@ -9,10 +9,50 @@
#include <linux/cleanup.h>
#include <linux/pci-tsm.h>
+static ssize_t pci_mode_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct tsm_dev *tsm_dev = container_of(dev, struct tsm_dev, dev);
+ const struct pci_tsm_ops *ops = tsm_dev->pci_ops;
+
+ if (ops->connect)
+ return sysfs_emit(buf, "link\n");
+ if (ops->lock)
+ return sysfs_emit(buf, "devsec\n");
+ return sysfs_emit(buf, "none\n");
+}
+static DEVICE_ATTR_RO(pci_mode);
+
+static umode_t tsm_pci_visible(struct kobject *kobj, struct attribute *attr, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct tsm_dev *tsm_dev = container_of(dev, struct tsm_dev, dev);
+
+ if (tsm_dev->pci_ops)
+ return attr->mode;
+ return 0;
+}
+
+static struct attribute *tsm_pci_attrs[] = {
+ &dev_attr_pci_mode.attr,
+ NULL
+};
+
+static const struct attribute_group tsm_pci_group = {
+ .attrs = tsm_pci_attrs,
+ .is_visible = tsm_pci_visible,
+};
+
+static const struct attribute_group *tsm_pci_groups[] = {
+ &tsm_pci_group,
+ NULL
+};
+
static void tsm_release(struct device *);
static const struct class tsm_class = {
.name = "tsm",
- .dev_release = tsm_release
+ .dev_release = tsm_release,
+ .dev_groups = tsm_pci_groups,
};
static DEFINE_IDA(tsm_ida);
@@ -72,6 +112,7 @@ static struct tsm_dev *tsm_register_pci_or_reset(struct tsm_dev *tsm_dev,
device_unregister(&tsm_dev->dev);
return ERR_PTR(rc);
}
+ sysfs_update_group(&tsm_dev->dev.kobj, &tsm_pci_group);
/* Notify TSM userspace that PCI/TSM operations are now possible */
kobject_uevent(&tsm_dev->dev.kobj, KOBJ_CHANGE);
--
2.54.0
next prev parent reply other threads:[~2026-07-05 22:08 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-05 22:08 [PATCH 00/15] Device Evidence and Trust for PCI Security Protocol (TDISP) Dan Williams
2026-07-05 22:08 ` [PATCH 01/15] netlink: specs: Introduce multi-message blobs for SPDM Dan Williams
2026-07-05 22:13 ` sashiko-bot
2026-07-05 22:08 ` [PATCH 02/15] tools: ynl: Teach pyynl to handle blobs Dan Williams
2026-07-05 22:18 ` sashiko-bot
2026-07-05 22:08 ` [PATCH 03/15] tools: ynl: Teach ynl_gen_c to validate and dump 'blob' attributes Dan Williams
2026-07-05 22:20 ` sashiko-bot
2026-07-05 22:08 ` [PATCH 04/15] device core: Introduce "device evidence" over netlink Dan Williams
2026-07-05 22:20 ` sashiko-bot
2026-07-05 22:08 ` [PATCH 05/15] device core: Add "device evidence" 'validate' command Dan Williams
2026-07-05 22:26 ` sashiko-bot
2026-07-05 22:08 ` [PATCH 06/15] PCI/TSM: Add device evidence support Dan Williams
2026-07-05 22:16 ` sashiko-bot
2026-07-05 22:08 ` [PATCH 07/15] modules: Document the global async_probe parameter Dan Williams
2026-07-05 22:15 ` sashiko-bot
2026-07-05 22:08 ` [PATCH 08/15] device core: Initial device trust infrastructure Dan Williams
2026-07-05 22:17 ` sashiko-bot
2026-07-06 13:45 ` Jason Gunthorpe
2026-07-05 22:08 ` [PATCH 09/15] PCI, device core: Move "untrusted" concept to DEVICE_TRUST_ADVERSARY Dan Williams
2026-07-05 22:25 ` sashiko-bot
2026-07-06 13:49 ` Jason Gunthorpe
2026-07-07 13:04 ` Robin Murphy
2026-07-05 22:08 ` Dan Williams [this message]
2026-07-05 22:25 ` [PATCH 10/15] PCI/TSM: Add device interface security LOCKED support sashiko-bot
2026-07-05 22:08 ` [PATCH 11/15] PCI/TSM: Add device interface security RUN support Dan Williams
2026-07-05 22:21 ` sashiko-bot
2026-07-05 22:08 ` [PATCH 12/15] PCI/TSM: Add device interface security DMA enable/disable Dan Williams
2026-07-05 22:25 ` sashiko-bot
2026-07-05 22:08 ` [PATCH 13/15] PCI, device core: Add private memory access for DEVICE_TRUST_TCB Dan Williams
2026-07-05 22:28 ` sashiko-bot
2026-07-06 12:42 ` Aneesh Kumar K.V
2026-07-05 22:08 ` [PATCH 14/15] PCI/TSM: Create MMIO descriptors via TDISP Report Dan Williams
2026-07-05 22:24 ` sashiko-bot
2026-07-05 22:08 ` [PATCH 15/15] PCI/TSM: Add relative MMIO offset support? Dan Williams
2026-07-05 22:25 ` sashiko-bot
2026-07-06 12:51 ` [PATCH 00/15] Device Evidence and Trust for PCI Security Protocol (TDISP) Jason Gunthorpe
2026-07-06 20:55 ` Dan Williams (nvidia)
2026-07-07 12:43 ` Jason Gunthorpe
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=20260705220819.2472765-11-djbw@kernel.org \
--to=djbw@kernel.org \
--cc=aneesh.kumar@kernel.org \
--cc=ankita@nvidia.com \
--cc=bhelgaas@google.com \
--cc=driver-core@lists.linux.dev \
--cc=linux-coco@lists.linux.dev \
--cc=linux-pci@vger.kernel.org \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.