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 11/15] PCI/TSM: Add device interface security RUN support
Date: Sun, 5 Jul 2026 15:08:15 -0700 [thread overview]
Message-ID: <20260705220819.2472765-12-djbw@kernel.org> (raw)
In-Reply-To: <20260705220819.2472765-1-djbw@kernel.org>
The final device-side operation of the PCIe Trusted Execution Environment
(TEE) Device Interface Security Protocol (TDISP) state machine is to ask
the TSM to flip the device from LOCKED to RUN.
The story so far in the security lifecycle of the device is that the VMM
setup an SPDM session and link encryption with the device's physical
function0. The VMM then assigned either that physical function or other
virtual function of that device to a VM. The VM asked the TSM to transition
the device from TDISP UNLOCKED->LOCKED. With the device LOCKED the VM is
enabled to validate signed fresh evidence of the device's configuration and
expected MMIO mappings.
The VM now accepts the device to transition it from LOCKED to RUN.
Implement a sysfs trigger to flip the device to private operation and plumb
that to a 'struct pci_tsm_ops::run()' operation.
Note that the RUN state only allows the device to be accessed via private
MMIO. DMA enable is a separate step triggered at pci_dma_configure() time.
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 | 13 ++++
include/linux/pci-tsm.h | 12 +++-
drivers/pci/tsm/core.c | 89 ++++++++++++++++++++++++-
3 files changed, 110 insertions(+), 4 deletions(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index 1ed77b9402a6..c2a5c4fe9373 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -732,3 +732,16 @@ Description:
'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.
+
+What: /sys/bus/pci/devices/.../tsm/accept
+Contact: linux-coco@lists.linux.dev
+Description:
+ (RW) Write "1" (or any boolean "true" string) to this file to
+ request that TSM transition the device from the TDISP LOCKED
+ state to the RUN state and arrange the for the secure IOMMU to
+ accept requests with T=1 in the PCIe packet header (TLP)
+ targeting private memory. Per TDISP the only exits from the RUN
+ state are via an explicit unlock request or an event that
+ transitions the device to the ERROR state. 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/include/linux/pci-tsm.h b/include/linux/pci-tsm.h
index 326471f1e01a..371a7e300a64 100644
--- a/include/linux/pci-tsm.h
+++ b/include/linux/pci-tsm.h
@@ -70,15 +70,18 @@ struct pci_tsm_ops {
* pci_tsm') for follow-on security state transitions from the
* LOCKED state
* @unlock: destroy TSM context and return device to UNLOCKED state
+ * @run: Move a device to the RUN state / prepare to enable DMA
*
* Context: @lock and @unlock run under pci_tsm_rwsem held for write to
- * sync with TSM unregistration and each other. All operations run under
- * the device lock for mutual exclusion with driver attach and detach.
+ * sync with TSM unregistration and each other. @run runs under
+ * pci_tsm_rwsem held for read. 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,
struct pci_dev *pdev);
void (*unlock)(struct pci_tsm *tsm);
+ int (*run)(struct pci_dev *pdev);
);
int (*refresh_evidence)(struct pci_tsm *tsm, const void *nonce,
@@ -97,6 +100,9 @@ struct pci_tdi {
u32 tdi_id;
};
+/* Private operation acknowledged, future ioremap will use private alias */
+#define PCI_TSM_F_ACCEPT (1UL << 0)
+
/**
* struct pci_tsm - Core TSM context for a given PCIe endpoint
* @pdev: Back ref to device function, distinguishes type of pci_tsm context
@@ -104,6 +110,7 @@ struct pci_tdi {
* @tsm_dev: PCI TEE Security Manager device for Link Confidentiality or Device
* Function Security operations
* @tdi: TDI context established by the @bind link operation
+ * @flags: Convey TDISP availabilty and / or state
* @evidence: cached evidence from SPDM session establishment (connect), or
* TDISP bind (lock)
*
@@ -130,6 +137,7 @@ struct pci_tsm {
struct tsm_dev *tsm_dev;
struct pci_tdi *tdi;
struct device_evidence *evidence;
+ unsigned long flags;
};
/**
diff --git a/drivers/pci/tsm/core.c b/drivers/pci/tsm/core.c
index 590e19f6c2b8..1f09ab4e8d4c 100644
--- a/drivers/pci/tsm/core.c
+++ b/drivers/pci/tsm/core.c
@@ -552,6 +552,89 @@ static ssize_t dsm_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(dsm);
+/**
+ * pci_tsm_accept() - accept a device for private MMIO operation
+ * @pdev: PCI device to accept
+ *
+ * "Accept" transitions the device interface to the RUN state, it is
+ * only suitable to make that transition from a known idle (no active
+ * DMA / MMIO mappings) state. The "driver detached" state is a coarse
+ * way to assert that requirement.
+ */
+static int pci_tsm_accept(struct pci_dev *pdev)
+{
+ int rc;
+
+ ACQUIRE(rwsem_read_intr, lock)(&pci_tsm_rwsem);
+ if ((rc = ACQUIRE_ERR(rwsem_read_intr, &lock)))
+ return rc;
+
+ if (!pdev->tsm)
+ 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;
+
+ if (test_bit(PCI_TSM_F_ACCEPT, &pdev->tsm->flags))
+ return 0;
+
+ rc = to_pci_tsm_ops(pdev->tsm)->run(pdev);
+ if (rc)
+ return rc;
+
+ set_bit(PCI_TSM_F_ACCEPT, &pdev->tsm->flags);
+
+ return 0;
+}
+
+static ssize_t accept_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ bool accept;
+ int rc;
+
+ rc = kstrtobool(buf, &accept);
+ if (rc)
+ return rc;
+
+ /*
+ * TDISP can only go from RUN to UNLOCKED/ERROR, so there is no
+ * 'unaccept' verb.
+ */
+ if (!accept)
+ return -EINVAL;
+
+ rc = pci_tsm_accept(pdev);
+ if (rc)
+ return rc;
+
+ return len;
+}
+
+static ssize_t accept_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ bool accept = false;
+ int rc;
+
+ ACQUIRE(rwsem_read_intr, lock)(&pci_tsm_rwsem);
+ if ((rc = ACQUIRE_ERR(rwsem_read_intr, &lock)))
+ return rc;
+
+ /* Unlocked == Unaccepted */
+ if (pdev->tsm)
+ accept = test_bit(PCI_TSM_F_ACCEPT, &pdev->tsm->flags);
+
+ return sysfs_emit(buf, "%d\n", accept);
+}
+static DEVICE_ATTR_RW(accept);
+
/**
* pci_tsm_unlock() - Transition TDI from LOCKED/RUN to UNLOCKED
* @pdev: TDI device to unlock
@@ -568,9 +651,9 @@ static void pci_tsm_unlock(struct pci_dev *pdev)
"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;
+ /* implicit clear of PCI_TSM_F_ACCEPT */
}
static int pci_tsm_lock(struct pci_dev *pdev, struct tsm_dev *tsm_dev)
@@ -735,7 +818,8 @@ static umode_t pci_tsm_attr_visible(struct kobject *kobj,
}
if (pci_tsm_devsec_group_visible(kobj)) {
- if (attr == &dev_attr_lock.attr ||
+ if (attr == &dev_attr_accept.attr ||
+ attr == &dev_attr_lock.attr ||
attr == &dev_attr_unlock.attr)
return attr->mode;
}
@@ -755,6 +839,7 @@ static struct attribute *pci_tsm_attrs[] = {
&dev_attr_disconnect.attr,
&dev_attr_bound.attr,
&dev_attr_dsm.attr,
+ &dev_attr_accept.attr,
&dev_attr_lock.attr,
&dev_attr_unlock.attr,
NULL
--
2.54.0
next prev parent reply other threads:[~2026-07-05 22:08 UTC|newest]
Thread overview: 20+ 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:08 ` [PATCH 02/15] tools: ynl: Teach pyynl to handle blobs Dan Williams
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:08 ` [PATCH 04/15] device core: Introduce "device evidence" over netlink Dan Williams
2026-07-05 22:08 ` [PATCH 05/15] device core: Add "device evidence" 'validate' command Dan Williams
2026-07-05 22:08 ` [PATCH 06/15] PCI/TSM: Add device evidence support Dan Williams
2026-07-05 22:08 ` [PATCH 07/15] modules: Document the global async_probe parameter Dan Williams
2026-07-05 22:08 ` [PATCH 08/15] device core: Initial device trust infrastructure Dan Williams
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-06 13:49 ` Jason Gunthorpe
2026-07-05 22:08 ` [PATCH 10/15] PCI/TSM: Add device interface security LOCKED support Dan Williams
2026-07-05 22:08 ` Dan Williams [this message]
2026-07-05 22:08 ` [PATCH 12/15] PCI/TSM: Add device interface security DMA enable/disable Dan Williams
2026-07-05 22:08 ` [PATCH 13/15] PCI, device core: Add private memory access for DEVICE_TRUST_TCB Dan Williams
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:08 ` [PATCH 15/15] PCI/TSM: Add relative MMIO offset support? Dan Williams
2026-07-06 12:51 ` [PATCH 00/15] Device Evidence and Trust for PCI Security Protocol (TDISP) 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-12-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox