diff options
| author | Dan Williams <dan.j.williams@intel.com> | 2025-11-12 18:14:46 -0800 |
|---|---|---|
| committer | Dan Williams <dan.j.williams@intel.com> | 2025-11-14 15:06:57 -0800 |
| commit | f7ae6d4ec6520a901787cbab273983e96d8516da (patch) | |
| tree | f472f35a21dc0ce1b95bac96d54209484966bb45 | |
| parent | c316c75d57fbb34e2305690813f4dbec9311f2b0 (diff) | |
PCI/TSM: Add 'dsm' and 'bound' attributes for dependent functions
PCI/TSM sysfs for physical function 0 devices, i.e. the "DSM" (Device
Security Manager), contains the 'connect' and 'disconnect' attributes.
After a successful 'connect' operation the DSM, its dependent functions
(SR-IOV virtual functions, non-zero multi-functions, or downstream
endpoints of a switch DSM) are candidates for being transitioned into a
TDISP (TEE Device Interface Security Protocol) operational state, via
pci_tsm_bind(). At present sysfs is blind to which devices are capable of
TDISP operation and it is ambiguous which functions are serviced by which
DSMs.
Add a 'dsm' attribute to identify a function's DSM device, and add a
'bound' attribute to identify when a function has entered a TDISP
operational state.
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Lukas Wunner <lukas@wunner.de>
Cc: Samuel Ortiz <sameo@rivosinc.com>
Cc: Alexey Kardashevskiy <aik@amd.com>
Cc: Xu Yilun <yilun.xu@linux.intel.com>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Link: https://patch.msgid.link/20251113021446.436830-9-dan.j.williams@intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
| -rw-r--r-- | Documentation/ABI/testing/sysfs-bus-pci | 30 | ||||
| -rw-r--r-- | drivers/pci/tsm.c | 130 |
2 files changed, 140 insertions, 20 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci index 6ffe02f854d6..b767db2c52cb 100644 --- a/Documentation/ABI/testing/sysfs-bus-pci +++ b/Documentation/ABI/testing/sysfs-bus-pci @@ -655,6 +655,36 @@ Description: (WO) Write the name of the TSM device that was specified to 'connect' to teardown the connection. +What: /sys/bus/pci/devices/.../tsm/dsm +Contact: linux-coco@lists.linux.dev +Description: (RO) Return PCI device name of this device's DSM (Device + Security Manager). When a device is in the connected state it + indicates that the platform TSM (TEE Security Manager) has made + a secure-session connection with a device's DSM. A DSM is always + physical function 0 and when the device supports TDISP (TEE + Device Interface Security Protocol) its managed functions also + populate this tsm/dsm attribute. The managed functions of a DSM + are SR-IOV (Single Root I/O Virtualization) virtual functions, + non-zero functions of a multi-function device, or downstream + endpoints depending on whether the DSM is an SR-IOV physical + function, function0 of a multi-function device, or an upstream + PCIe switch port. This is a "link" TSM attribute, see + Documentation/ABI/testing/sysfs-class-tsm. + +What: /sys/bus/pci/devices/.../tsm/bound +Contact: linux-coco@lists.linux.dev +Description: (RO) Return the device name of the TSM when the device is in a + TDISP (TEE Device Interface Security Protocol) operational state + (LOCKED, RUN, or ERROR, not UNLOCKED). Bound devices consume + platform TSM resources and depend on the device's configuration + (e.g. BME (Bus Master Enable) and MSE (Memory Space Enable) + among other settings) to remain stable for the duration of the + bound state. This attribute is only visible for devices that + support TDISP operation, and it is only populated after + successful connect and TSM bind. The TSM bind operation is + initiated by VFIO/IOMMUFD. This is a "link" TSM attribute, see + Documentation/ABI/testing/sysfs-class-tsm. + What: /sys/bus/pci/devices/.../authenticated Contact: linux-pci@vger.kernel.org Description: diff --git a/drivers/pci/tsm.c b/drivers/pci/tsm.c index 5e57501f693e..5fdcd7f2e820 100644 --- a/drivers/pci/tsm.c +++ b/drivers/pci/tsm.c @@ -151,6 +151,25 @@ static void pci_tsm_walk_fns_reverse(struct pci_dev *pdev, } } +static void link_sysfs_disable(struct pci_dev *pdev) +{ + sysfs_update_group(&pdev->dev.kobj, &pci_tsm_auth_attr_group); + sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group); +} + +static void link_sysfs_enable(struct pci_dev *pdev) +{ + bool tee = has_tee(pdev); + + pci_dbg(pdev, "%s Security Manager detected (%s%s%s)\n", + pdev->tsm ? "Device" : "Platform TEE", + pdev->ide_cap ? "IDE" : "", pdev->ide_cap && tee ? " " : "", + tee ? "TEE" : ""); + + sysfs_update_group(&pdev->dev.kobj, &pci_tsm_auth_attr_group); + sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group); +} + static int probe_fn(struct pci_dev *pdev, void *dsm) { struct pci_dev *dsm_dev = dsm; @@ -159,6 +178,8 @@ static int probe_fn(struct pci_dev *pdev, void *dsm) pdev->tsm = ops->probe(dsm_dev->tsm->tsm_dev, pdev); pci_dbg(pdev, "setup TSM context: DSM: %s status: %s\n", pci_name(dsm_dev), pdev->tsm ? "success" : "failed"); + if (pdev->tsm) + link_sysfs_enable(pdev); return 0; } @@ -267,6 +288,7 @@ static DEVICE_ATTR_RW(connect); static int remove_fn(struct pci_dev *pdev, void *data) { tsm_remove(pdev->tsm); + link_sysfs_disable(pdev); return 0; } @@ -468,12 +490,74 @@ static ssize_t disconnect_store(struct device *dev, } static DEVICE_ATTR_WO(disconnect); +static ssize_t bound_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct pci_tsm_pf0 *tsm_pf0; + struct pci_tsm *tsm; + int rc; + + ACQUIRE(rwsem_read_intr, lock)(&pci_tsm_rwsem); + if ((rc = ACQUIRE_ERR(rwsem_read_intr, &lock))) + return rc; + + tsm = pdev->tsm; + if (!tsm) + return sysfs_emit(buf, "\n"); + tsm_pf0 = to_pci_tsm_pf0(tsm); + + ACQUIRE(mutex_intr, ops_lock)(&tsm_pf0->lock); + if ((rc = ACQUIRE_ERR(mutex_intr, &ops_lock))) + return rc; + + if (!tsm->tdi) + return sysfs_emit(buf, "\n"); + return sysfs_emit(buf, "%s\n", dev_name(&tsm->tsm_dev->dev)); +} +static DEVICE_ATTR_RO(bound); + +static ssize_t dsm_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct pci_tsm *tsm; + int rc; + + ACQUIRE(rwsem_read_intr, lock)(&pci_tsm_rwsem); + if ((rc = ACQUIRE_ERR(rwsem_read_intr, &lock))) + return rc; + + tsm = pdev->tsm; + if (!tsm) + return sysfs_emit(buf, "\n"); + + return sysfs_emit(buf, "%s\n", pci_name(tsm->dsm_dev)); +} +static DEVICE_ATTR_RO(dsm); + /* The 'authenticated' attribute is exclusive to the presence of a 'link' TSM */ static bool pci_tsm_link_group_visible(struct kobject *kobj) { struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); - return pci_tsm_link_count && is_pci_tsm_pf0(pdev); + if (!pci_tsm_link_count) + return false; + + if (!pci_is_pcie(pdev)) + return false; + + if (is_pci_tsm_pf0(pdev)) + return true; + + /* + * Show 'authenticated' and other attributes for the managed + * sub-functions of a DSM. + */ + if (pdev->tsm) + return true; + + return false; } DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(pci_tsm_link); @@ -485,9 +569,27 @@ static umode_t pci_tsm_attr_visible(struct kobject *kobj, struct attribute *attr, int n) { if (pci_tsm_link_group_visible(kobj)) { + struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); + + if (attr == &dev_attr_bound.attr) { + if (is_pci_tsm_pf0(pdev) && has_tee(pdev)) + return attr->mode; + if (pdev->tsm && has_tee(pdev->tsm->dsm_dev)) + return attr->mode; + } + + if (attr == &dev_attr_dsm.attr) { + if (is_pci_tsm_pf0(pdev)) + return attr->mode; + if (pdev->tsm && has_tee(pdev->tsm->dsm_dev)) + return attr->mode; + } + if (attr == &dev_attr_connect.attr || - attr == &dev_attr_disconnect.attr) - return attr->mode; + attr == &dev_attr_disconnect.attr) { + if (is_pci_tsm_pf0(pdev)) + return attr->mode; + } } return 0; @@ -502,6 +604,8 @@ DEFINE_SYSFS_GROUP_VISIBLE(pci_tsm); static struct attribute *pci_tsm_attrs[] = { &dev_attr_connect.attr, &dev_attr_disconnect.attr, + &dev_attr_bound.attr, + &dev_attr_dsm.attr, NULL }; @@ -657,18 +761,6 @@ void pci_tsm_pf0_destructor(struct pci_tsm_pf0 *pf0_tsm) } EXPORT_SYMBOL_GPL(pci_tsm_pf0_destructor); -static void pf0_sysfs_enable(struct pci_dev *pdev) -{ - bool tee = has_tee(pdev); - - pci_dbg(pdev, "Device Security Manager detected (%s%s%s)\n", - pdev->ide_cap ? "IDE" : "", pdev->ide_cap && tee ? " " : "", - tee ? "TEE" : ""); - - sysfs_update_group(&pdev->dev.kobj, &pci_tsm_auth_attr_group); - sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group); -} - int pci_tsm_register(struct tsm_dev *tsm_dev) { struct pci_dev *pdev = NULL; @@ -689,7 +781,7 @@ int pci_tsm_register(struct tsm_dev *tsm_dev) if (is_link_tsm(tsm_dev) && pci_tsm_link_count++ == 0) { for_each_pci_dev(pdev) if (is_pci_tsm_pf0(pdev)) - pf0_sysfs_enable(pdev); + link_sysfs_enable(pdev); } else if (is_devsec_tsm(tsm_dev)) { pci_tsm_devsec_count++; } @@ -723,10 +815,8 @@ static void __pci_tsm_destroy(struct pci_dev *pdev, struct tsm_dev *tsm_dev) * skipped if the device itself is being removed since sysfs goes away * naturally at that point */ - if (is_link_tsm(tsm_dev) && is_pci_tsm_pf0(pdev) && !pci_tsm_link_count) { - sysfs_update_group(&pdev->dev.kobj, &pci_tsm_auth_attr_group); - sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group); - } + if (is_link_tsm(tsm_dev) && is_pci_tsm_pf0(pdev) && !pci_tsm_link_count) + link_sysfs_disable(pdev); /* Nothing else to do if this device never attached to the departing TSM */ if (!tsm) |
