Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+140 -20
+30
Documentation/ABI/testing/sysfs-bus-pci
··· 655 655 (WO) Write the name of the TSM device that was specified 656 656 to 'connect' to teardown the connection. 657 657 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 + 658 688 What: /sys/bus/pci/devices/.../authenticated 659 689 Contact: linux-pci@vger.kernel.org 660 690 Description:
+110 -20
drivers/pci/tsm.c
··· 151 151 } 152 152 } 153 153 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 + 154 173 static int probe_fn(struct pci_dev *pdev, void *dsm) 155 174 { 156 175 struct pci_dev *dsm_dev = dsm; ··· 178 159 pdev->tsm = ops->probe(dsm_dev->tsm->tsm_dev, pdev); 179 160 pci_dbg(pdev, "setup TSM context: DSM: %s status: %s\n", 180 161 pci_name(dsm_dev), pdev->tsm ? "success" : "failed"); 162 + if (pdev->tsm) 163 + link_sysfs_enable(pdev); 181 164 return 0; 182 165 } 183 166 ··· 288 267 static int remove_fn(struct pci_dev *pdev, void *data) 289 268 { 290 269 tsm_remove(pdev->tsm); 270 + link_sysfs_disable(pdev); 291 271 return 0; 292 272 } 293 273 ··· 490 468 } 491 469 static DEVICE_ATTR_WO(disconnect); 492 470 471 + static ssize_t bound_show(struct device *dev, 472 + struct device_attribute *attr, char *buf) 473 + { 474 + struct pci_dev *pdev = to_pci_dev(dev); 475 + struct pci_tsm_pf0 *tsm_pf0; 476 + struct pci_tsm *tsm; 477 + int rc; 478 + 479 + ACQUIRE(rwsem_read_intr, lock)(&pci_tsm_rwsem); 480 + if ((rc = ACQUIRE_ERR(rwsem_read_intr, &lock))) 481 + return rc; 482 + 483 + tsm = pdev->tsm; 484 + if (!tsm) 485 + return sysfs_emit(buf, "\n"); 486 + tsm_pf0 = to_pci_tsm_pf0(tsm); 487 + 488 + ACQUIRE(mutex_intr, ops_lock)(&tsm_pf0->lock); 489 + if ((rc = ACQUIRE_ERR(mutex_intr, &ops_lock))) 490 + return rc; 491 + 492 + if (!tsm->tdi) 493 + return sysfs_emit(buf, "\n"); 494 + return sysfs_emit(buf, "%s\n", dev_name(&tsm->tsm_dev->dev)); 495 + } 496 + static DEVICE_ATTR_RO(bound); 497 + 498 + static ssize_t dsm_show(struct device *dev, struct device_attribute *attr, 499 + char *buf) 500 + { 501 + struct pci_dev *pdev = to_pci_dev(dev); 502 + struct pci_tsm *tsm; 503 + int rc; 504 + 505 + ACQUIRE(rwsem_read_intr, lock)(&pci_tsm_rwsem); 506 + if ((rc = ACQUIRE_ERR(rwsem_read_intr, &lock))) 507 + return rc; 508 + 509 + tsm = pdev->tsm; 510 + if (!tsm) 511 + return sysfs_emit(buf, "\n"); 512 + 513 + return sysfs_emit(buf, "%s\n", pci_name(tsm->dsm_dev)); 514 + } 515 + static DEVICE_ATTR_RO(dsm); 516 + 493 517 /* The 'authenticated' attribute is exclusive to the presence of a 'link' TSM */ 494 518 static bool pci_tsm_link_group_visible(struct kobject *kobj) 495 519 { 496 520 struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); 497 521 498 - return pci_tsm_link_count && is_pci_tsm_pf0(pdev); 522 + if (!pci_tsm_link_count) 523 + return false; 524 + 525 + if (!pci_is_pcie(pdev)) 526 + return false; 527 + 528 + if (is_pci_tsm_pf0(pdev)) 529 + return true; 530 + 531 + /* 532 + * Show 'authenticated' and other attributes for the managed 533 + * sub-functions of a DSM. 534 + */ 535 + if (pdev->tsm) 536 + return true; 537 + 538 + return false; 499 539 } 500 540 DEFINE_SIMPLE_SYSFS_GROUP_VISIBLE(pci_tsm_link); 501 541 ··· 569 485 struct attribute *attr, int n) 570 486 { 571 487 if (pci_tsm_link_group_visible(kobj)) { 488 + struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); 489 + 490 + if (attr == &dev_attr_bound.attr) { 491 + if (is_pci_tsm_pf0(pdev) && has_tee(pdev)) 492 + return attr->mode; 493 + if (pdev->tsm && has_tee(pdev->tsm->dsm_dev)) 494 + return attr->mode; 495 + } 496 + 497 + if (attr == &dev_attr_dsm.attr) { 498 + if (is_pci_tsm_pf0(pdev)) 499 + return attr->mode; 500 + if (pdev->tsm && has_tee(pdev->tsm->dsm_dev)) 501 + return attr->mode; 502 + } 503 + 572 504 if (attr == &dev_attr_connect.attr || 573 - attr == &dev_attr_disconnect.attr) 574 - return attr->mode; 505 + attr == &dev_attr_disconnect.attr) { 506 + if (is_pci_tsm_pf0(pdev)) 507 + return attr->mode; 508 + } 575 509 } 576 510 577 511 return 0; ··· 604 502 static struct attribute *pci_tsm_attrs[] = { 605 503 &dev_attr_connect.attr, 606 504 &dev_attr_disconnect.attr, 505 + &dev_attr_bound.attr, 506 + &dev_attr_dsm.attr, 607 507 NULL 608 508 }; 609 509 ··· 761 657 } 762 658 EXPORT_SYMBOL_GPL(pci_tsm_pf0_destructor); 763 659 764 - static void pf0_sysfs_enable(struct pci_dev *pdev) 765 - { 766 - bool tee = has_tee(pdev); 767 - 768 - pci_dbg(pdev, "Device Security Manager detected (%s%s%s)\n", 769 - pdev->ide_cap ? "IDE" : "", pdev->ide_cap && tee ? " " : "", 770 - tee ? "TEE" : ""); 771 - 772 - sysfs_update_group(&pdev->dev.kobj, &pci_tsm_auth_attr_group); 773 - sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group); 774 - } 775 - 776 660 int pci_tsm_register(struct tsm_dev *tsm_dev) 777 661 { 778 662 struct pci_dev *pdev = NULL; ··· 781 689 if (is_link_tsm(tsm_dev) && pci_tsm_link_count++ == 0) { 782 690 for_each_pci_dev(pdev) 783 691 if (is_pci_tsm_pf0(pdev)) 784 - pf0_sysfs_enable(pdev); 692 + link_sysfs_enable(pdev); 785 693 } else if (is_devsec_tsm(tsm_dev)) { 786 694 pci_tsm_devsec_count++; 787 695 } ··· 815 723 * skipped if the device itself is being removed since sysfs goes away 816 724 * naturally at that point 817 725 */ 818 - if (is_link_tsm(tsm_dev) && is_pci_tsm_pf0(pdev) && !pci_tsm_link_count) { 819 - sysfs_update_group(&pdev->dev.kobj, &pci_tsm_auth_attr_group); 820 - sysfs_update_group(&pdev->dev.kobj, &pci_tsm_attr_group); 821 - } 726 + if (is_link_tsm(tsm_dev) && is_pci_tsm_pf0(pdev) && !pci_tsm_link_count) 727 + link_sysfs_disable(pdev); 822 728 823 729 /* Nothing else to do if this device never attached to the departing TSM */ 824 730 if (!tsm)