Skip to content

Commit f7ae6d4

Browse files
committed
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>
1 parent c316c75 commit f7ae6d4

2 files changed

Lines changed: 140 additions & 20 deletions

File tree

Documentation/ABI/testing/sysfs-bus-pci

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,36 @@ Description:
655655
(WO) Write the name of the TSM device that was specified
656656
to 'connect' to teardown the connection.
657657

658+
What: /sys/bus/pci/devices/.../tsm/dsm
659+
Contact: linux-coco@lists.linux.dev
660+
Description: (RO) Return PCI device name of this device's DSM (Device
661+
Security Manager). When a device is in the connected state it
662+
indicates that the platform TSM (TEE Security Manager) has made
663+
a secure-session connection with a device's DSM. A DSM is always
664+
physical function 0 and when the device supports TDISP (TEE
665+
Device Interface Security Protocol) its managed functions also
666+
populate this tsm/dsm attribute. The managed functions of a DSM
667+
are SR-IOV (Single Root I/O Virtualization) virtual functions,
668+
non-zero functions of a multi-function device, or downstream
669+
endpoints depending on whether the DSM is an SR-IOV physical
670+
function, function0 of a multi-function device, or an upstream
671+
PCIe switch port. This is a "link" TSM attribute, see
672+
Documentation/ABI/testing/sysfs-class-tsm.
673+
674+
What: /sys/bus/pci/devices/.../tsm/bound
675+
Contact: linux-coco@lists.linux.dev
676+
Description: (RO) Return the device name of the TSM when the device is in a
677+
TDISP (TEE Device Interface Security Protocol) operational state
678+
(LOCKED, RUN, or ERROR, not UNLOCKED). Bound devices consume
679+
platform TSM resources and depend on the device's configuration
680+
(e.g. BME (Bus Master Enable) and MSE (Memory Space Enable)
681+
among other settings) to remain stable for the duration of the
682+
bound state. This attribute is only visible for devices that
683+
support TDISP operation, and it is only populated after
684+
successful connect and TSM bind. The TSM bind operation is
685+
initiated by VFIO/IOMMUFD. This is a "link" TSM attribute, see
686+
Documentation/ABI/testing/sysfs-class-tsm.
687+
658688
What: /sys/bus/pci/devices/.../authenticated
659689
Contact: linux-pci@vger.kernel.org
660690
Description:

drivers/pci/tsm.c

Lines changed: 110 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,25 @@ static void pci_tsm_walk_fns_reverse(struct pci_dev *pdev,
151151
}
152152
}
153153

154+
static void link_sysfs_disable(struct pci_dev *pdev)
155+
{
156+
sysfs_update_group(&pdev->dev.kobj, &pci_tsm_auth_attr_group);
157+
sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group);
158+
}
159+
160+
static void link_sysfs_enable(struct pci_dev *pdev)
161+
{
162+
bool tee = has_tee(pdev);
163+
164+
pci_dbg(pdev, "%s Security Manager detected (%s%s%s)\n",
165+
pdev->tsm ? "Device" : "Platform TEE",
166+
pdev->ide_cap ? "IDE" : "", pdev->ide_cap && tee ? " " : "",
167+
tee ? "TEE" : "");
168+
169+
sysfs_update_group(&pdev->dev.kobj, &pci_tsm_auth_attr_group);
170+
sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group);
171+
}
172+
154173
static int probe_fn(struct pci_dev *pdev, void *dsm)
155174
{
156175
struct pci_dev *dsm_dev = dsm;
@@ -159,6 +178,8 @@ static int probe_fn(struct pci_dev *pdev, void *dsm)
159178
pdev->tsm = ops->probe(dsm_dev->tsm->tsm_dev, pdev);
160179
pci_dbg(pdev, "setup TSM context: DSM: %s status: %s\n",
161180
pci_name(dsm_dev), pdev->tsm ? "success" : "failed");
181+
if (pdev->tsm)
182+
link_sysfs_enable(pdev);
162183
return 0;
163184
}
164185

@@ -267,6 +288,7 @@ static DEVICE_ATTR_RW(connect);
267288
static int remove_fn(struct pci_dev *pdev, void *data)
268289
{
269290
tsm_remove(pdev->tsm);
291+
link_sysfs_disable(pdev);
270292
return 0;
271293
}
272294

@@ -468,12 +490,74 @@ static ssize_t disconnect_store(struct device *dev,
468490
}
469491
static DEVICE_ATTR_WO(disconnect);
470492

493+
static ssize_t bound_show(struct device *dev,
494+
struct device_attribute *attr, char *buf)
495+
{
496+
struct pci_dev *pdev = to_pci_dev(dev);
497+
struct pci_tsm_pf0 *tsm_pf0;
498+
struct pci_tsm *tsm;
499+
int rc;
500+
501+
ACQUIRE(rwsem_read_intr, lock)(&pci_tsm_rwsem);
502+
if ((rc = ACQUIRE_ERR(rwsem_read_intr, &lock)))
503+
return rc;
504+
505+
tsm = pdev->tsm;
506+
if (!tsm)
507+
return sysfs_emit(buf, "\n");
508+
tsm_pf0 = to_pci_tsm_pf0(tsm);
509+
510+
ACQUIRE(mutex_intr, ops_lock)(&tsm_pf0->lock);
511+
if ((rc = ACQUIRE_ERR(mutex_intr, &ops_lock)))
512+
return rc;
513+
514+
if (!tsm->tdi)
515+
return sysfs_emit(buf, "\n");
516+
return sysfs_emit(buf, "%s\n", dev_name(&tsm->tsm_dev->dev));
517+
}
518+
static DEVICE_ATTR_RO(bound);
519+
520+
static ssize_t dsm_show(struct device *dev, struct device_attribute *attr,
521+
char *buf)
522+
{
523+
struct pci_dev *pdev = to_pci_dev(dev);
524+
struct pci_tsm *tsm;
525+
int rc;
526+
527+
ACQUIRE(rwsem_read_intr, lock)(&pci_tsm_rwsem);
528+
if ((rc = ACQUIRE_ERR(rwsem_read_intr, &lock)))
529+
return rc;
530+
531+
tsm = pdev->tsm;
532+
if (!tsm)
533+
return sysfs_emit(buf, "\n");
534+
535+
return sysfs_emit(buf, "%s\n", pci_name(tsm->dsm_dev));
536+
}
537+
static DEVICE_ATTR_RO(dsm);
538+
471539
/* The 'authenticated' attribute is exclusive to the presence of a 'link' TSM */
472540
static bool pci_tsm_link_group_visible(struct kobject *kobj)
473541
{
474542
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
475543

476-
return pci_tsm_link_count && is_pci_tsm_pf0(pdev);
544+
if (!pci_tsm_link_count)
545+
return false;
546+
547+
if (!pci_is_pcie(pdev))
548+
return false;
549+
550+
if (is_pci_tsm_pf0(pdev))
551+
return true;
552+
553+
/*
554+
* Show 'authenticated' and other attributes for the managed
555+
* sub-functions of a DSM.
556+
*/
557+
if (pdev->tsm)
558+
return true;
559+
560+
return false;
477561
}
478562
DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(pci_tsm_link);
479563

@@ -485,9 +569,27 @@ static umode_t pci_tsm_attr_visible(struct kobject *kobj,
485569
struct attribute *attr, int n)
486570
{
487571
if (pci_tsm_link_group_visible(kobj)) {
572+
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
573+
574+
if (attr == &dev_attr_bound.attr) {
575+
if (is_pci_tsm_pf0(pdev) && has_tee(pdev))
576+
return attr->mode;
577+
if (pdev->tsm && has_tee(pdev->tsm->dsm_dev))
578+
return attr->mode;
579+
}
580+
581+
if (attr == &dev_attr_dsm.attr) {
582+
if (is_pci_tsm_pf0(pdev))
583+
return attr->mode;
584+
if (pdev->tsm && has_tee(pdev->tsm->dsm_dev))
585+
return attr->mode;
586+
}
587+
488588
if (attr == &dev_attr_connect.attr ||
489-
attr == &dev_attr_disconnect.attr)
490-
return attr->mode;
589+
attr == &dev_attr_disconnect.attr) {
590+
if (is_pci_tsm_pf0(pdev))
591+
return attr->mode;
592+
}
491593
}
492594

493595
return 0;
@@ -502,6 +604,8 @@ DEFINE_SYSFS_GROUP_VISIBLE(pci_tsm);
502604
static struct attribute *pci_tsm_attrs[] = {
503605
&dev_attr_connect.attr,
504606
&dev_attr_disconnect.attr,
607+
&dev_attr_bound.attr,
608+
&dev_attr_dsm.attr,
505609
NULL
506610
};
507611

@@ -657,18 +761,6 @@ void pci_tsm_pf0_destructor(struct pci_tsm_pf0 *pf0_tsm)
657761
}
658762
EXPORT_SYMBOL_GPL(pci_tsm_pf0_destructor);
659763

660-
static void pf0_sysfs_enable(struct pci_dev *pdev)
661-
{
662-
bool tee = has_tee(pdev);
663-
664-
pci_dbg(pdev, "Device Security Manager detected (%s%s%s)\n",
665-
pdev->ide_cap ? "IDE" : "", pdev->ide_cap && tee ? " " : "",
666-
tee ? "TEE" : "");
667-
668-
sysfs_update_group(&pdev->dev.kobj, &pci_tsm_auth_attr_group);
669-
sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group);
670-
}
671-
672764
int pci_tsm_register(struct tsm_dev *tsm_dev)
673765
{
674766
struct pci_dev *pdev = NULL;
@@ -689,7 +781,7 @@ int pci_tsm_register(struct tsm_dev *tsm_dev)
689781
if (is_link_tsm(tsm_dev) && pci_tsm_link_count++ == 0) {
690782
for_each_pci_dev(pdev)
691783
if (is_pci_tsm_pf0(pdev))
692-
pf0_sysfs_enable(pdev);
784+
link_sysfs_enable(pdev);
693785
} else if (is_devsec_tsm(tsm_dev)) {
694786
pci_tsm_devsec_count++;
695787
}
@@ -723,10 +815,8 @@ static void __pci_tsm_destroy(struct pci_dev *pdev, struct tsm_dev *tsm_dev)
723815
* skipped if the device itself is being removed since sysfs goes away
724816
* naturally at that point
725817
*/
726-
if (is_link_tsm(tsm_dev) && is_pci_tsm_pf0(pdev) && !pci_tsm_link_count) {
727-
sysfs_update_group(&pdev->dev.kobj, &pci_tsm_auth_attr_group);
728-
sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group);
729-
}
818+
if (is_link_tsm(tsm_dev) && is_pci_tsm_pf0(pdev) && !pci_tsm_link_count)
819+
link_sysfs_disable(pdev);
730820

731821
/* Nothing else to do if this device never attached to the departing TSM */
732822
if (!tsm)

0 commit comments

Comments
 (0)