]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
PCI/IDE: Enumerate Selective Stream IDE capabilities
authorDan Williams <dan.j.williams@intel.com>
Fri, 31 Oct 2025 21:28:54 +0000 (14:28 -0700)
committerDan Williams <dan.j.williams@intel.com>
Tue, 4 Nov 2025 03:27:40 +0000 (19:27 -0800)
Link encryption is a new PCIe feature enumerated by "PCIe r7.0 section
7.9.26 IDE Extended Capability".

It is both a standalone port + endpoint capability, and a building block
for the security protocol defined by "PCIe r7.0 section 11 TEE Device
Interface Security Protocol (TDISP)". That protocol coordinates device
security setup between a platform TSM (TEE Security Manager) and a
device DSM (Device Security Manager). While the platform TSM can
allocate resources like Stream ID and manage keys, it still requires
system software to manage the IDE capability register block.

Add register definitions and basic enumeration in preparation for
Selective IDE Stream establishment. A follow on change selects the new
CONFIG_PCI_IDE symbol. Note that while the IDE specification defines
both a point-to-point "Link Stream" and a Root Port to endpoint
"Selective Stream", only "Selective Stream" is considered for Linux as
that is the predominant mode expected by Trusted Execution Environment
Security Managers (TSMs), and it is the security model that limits the
number of PCI components within the TCB in a PCIe topology with
switches.

Co-developed-by: Alexey Kardashevskiy <aik@amd.com>
Signed-off-by: Alexey Kardashevskiy <aik@amd.com>
Co-developed-by: Xu Yilun <yilun.xu@linux.intel.com>
Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Alexey Kardashevskiy <aik@amd.com>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
Link: https://patch.msgid.link/20251031212902.2256310-3-dan.j.williams@intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/pci/Kconfig
drivers/pci/Makefile
drivers/pci/ide.c [new file with mode: 0644]
drivers/pci/pci.h
drivers/pci/probe.c
include/linux/pci.h
include/uapi/linux/pci_regs.h

index f94f5d384362e543a1e1cfaf7d77240c446131f5..b28423e2057f206e49b34ffe29df58bdd8fc0a9b 100644 (file)
@@ -122,6 +122,9 @@ config XEN_PCIDEV_FRONTEND
 config PCI_ATS
        bool
 
+config PCI_IDE
+       bool
+
 config PCI_DOE
        bool "Enable PCI Data Object Exchange (DOE) support"
        help
index 67647f1880fb8fb0629d680398f5b88d69aac660..6612256fd37d156f050234a7145e3facd3ab0421 100644 (file)
@@ -34,6 +34,7 @@ obj-$(CONFIG_PCI_P2PDMA)      += p2pdma.o
 obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
 obj-$(CONFIG_VGA_ARB)          += vgaarb.o
 obj-$(CONFIG_PCI_DOE)          += doe.o
+obj-$(CONFIG_PCI_IDE)          += ide.o
 obj-$(CONFIG_PCI_DYNAMIC_OF_NODES) += of_property.o
 obj-$(CONFIG_PCI_NPEM)         += npem.o
 obj-$(CONFIG_PCIE_TPH)         += tph.o
diff --git a/drivers/pci/ide.c b/drivers/pci/ide.c
new file mode 100644 (file)
index 0000000..26866ed
--- /dev/null
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2024-2025 Intel Corporation. All rights reserved. */
+
+/* PCIe r7.0 section 6.33 Integrity & Data Encryption (IDE) */
+
+#define dev_fmt(fmt) "PCI/IDE: " fmt
+#include <linux/bitfield.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+
+#include "pci.h"
+
+static int __sel_ide_offset(u16 ide_cap, u8 nr_link_ide, u8 stream_index,
+                           u8 nr_ide_mem)
+{
+       u32 offset = ide_cap + PCI_IDE_LINK_STREAM_0 +
+                    nr_link_ide * PCI_IDE_LINK_BLOCK_SIZE;
+
+       /*
+        * Assume a constant number of address association resources per stream
+        * index
+        */
+       return offset + stream_index * PCI_IDE_SEL_BLOCK_SIZE(nr_ide_mem);
+}
+
+void pci_ide_init(struct pci_dev *pdev)
+{
+       u16 nr_link_ide, nr_ide_mem, nr_streams;
+       u16 ide_cap;
+       u32 val;
+
+       if (!pci_is_pcie(pdev))
+               return;
+
+       ide_cap = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_IDE);
+       if (!ide_cap)
+               return;
+
+       pci_read_config_dword(pdev, ide_cap + PCI_IDE_CAP, &val);
+       if ((val & PCI_IDE_CAP_SELECTIVE) == 0)
+               return;
+
+       /*
+        * Require endpoint IDE capability to be paired with IDE Root Port IDE
+        * capability.
+        */
+       if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ENDPOINT) {
+               struct pci_dev *rp = pcie_find_root_port(pdev);
+
+               if (!rp->ide_cap)
+                       return;
+       }
+
+       pdev->ide_cfg = FIELD_GET(PCI_IDE_CAP_SEL_CFG, val);
+       pdev->ide_tee_limit = FIELD_GET(PCI_IDE_CAP_TEE_LIMITED, val);
+
+       if (val & PCI_IDE_CAP_LINK)
+               nr_link_ide = 1 + FIELD_GET(PCI_IDE_CAP_LINK_TC_NUM, val);
+       else
+               nr_link_ide = 0;
+
+       nr_ide_mem = 0;
+       nr_streams = 1 + FIELD_GET(PCI_IDE_CAP_SEL_NUM, val);
+       for (u16 i = 0; i < nr_streams; i++) {
+               int pos = __sel_ide_offset(ide_cap, nr_link_ide, i, nr_ide_mem);
+               int nr_assoc;
+               u32 val;
+
+               pci_read_config_dword(pdev, pos + PCI_IDE_SEL_CAP, &val);
+
+               /*
+                * Let's not entertain streams that do not have a constant
+                * number of address association blocks
+                */
+               nr_assoc = FIELD_GET(PCI_IDE_SEL_CAP_ASSOC_NUM, val);
+               if (i && (nr_assoc != nr_ide_mem)) {
+                       pci_info(pdev, "Unsupported Selective Stream %d capability, SKIP the rest\n", i);
+                       nr_streams = i;
+                       break;
+               }
+
+               nr_ide_mem = nr_assoc;
+       }
+
+       pdev->ide_cap = ide_cap;
+       pdev->nr_link_ide = nr_link_ide;
+       pdev->nr_ide_mem = nr_ide_mem;
+}
index 4492b809094b5794bd94dfbc20102cb208c3fa2f..86ef13e7cece14491ee12938057762926fb4c2d9 100644 (file)
@@ -613,6 +613,12 @@ static inline void pci_doe_sysfs_init(struct pci_dev *pdev) { }
 static inline void pci_doe_sysfs_teardown(struct pci_dev *pdev) { }
 #endif
 
+#ifdef CONFIG_PCI_IDE
+void pci_ide_init(struct pci_dev *dev);
+#else
+static inline void pci_ide_init(struct pci_dev *dev) { }
+#endif
+
 /**
  * pci_dev_set_io_state - Set the new error state if possible.
  *
index 0ce98e18b5a876afe72af35a9f4a44d598e8d500..4c55020f3ddf6bdf35c9238f2bf5a86bf6d803eb 100644 (file)
@@ -2667,6 +2667,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
        pci_doe_init(dev);              /* Data Object Exchange */
        pci_tph_init(dev);              /* TLP Processing Hints */
        pci_rebar_init(dev);            /* Resizable BAR */
+       pci_ide_init(dev);              /* Link Integrity and Data Encryption */
 
        pcie_report_downtraining(dev);
        pci_init_reset_methods(dev);
index d1fdf81fbe1e427aecbc951fa3fdf65c20450b05..4402ca931124a7b238cc448db155af58c0f29c0a 100644 (file)
@@ -539,6 +539,13 @@ struct pci_dev {
 #endif
 #ifdef CONFIG_PCI_NPEM
        struct npem     *npem;          /* Native PCIe Enclosure Management */
+#endif
+#ifdef CONFIG_PCI_IDE
+       u16             ide_cap;        /* Link Integrity & Data Encryption */
+       u8              nr_ide_mem;     /* Address association resources for streams */
+       u8              nr_link_ide;    /* Link Stream count (Selective Stream offset) */
+       unsigned int    ide_cfg:1;      /* Config cycles over IDE */
+       unsigned int    ide_tee_limit:1; /* Disallow T=0 traffic over IDE */
 #endif
        u16             acs_cap;        /* ACS Capability offset */
        u8              supported_speeds; /* Supported Link Speeds Vector */
index 07e06aafec502af7c12379f7207e2e3321dc2ff1..05bd22d9e352c1cb03eefb76a3864565d3ffd31b 100644 (file)
 #define PCI_EXT_CAP_ID_NPEM    0x29    /* Native PCIe Enclosure Management */
 #define PCI_EXT_CAP_ID_PL_32GT  0x2A    /* Physical Layer 32.0 GT/s */
 #define PCI_EXT_CAP_ID_DOE     0x2E    /* Data Object Exchange */
+#define PCI_EXT_CAP_ID_IDE     0x30    /* Integrity and Data Encryption */
 #define PCI_EXT_CAP_ID_PL_64GT 0x31    /* Physical Layer 64.0 GT/s */
 #define PCI_EXT_CAP_ID_MAX     PCI_EXT_CAP_ID_PL_64GT
 
 #define PCI_DVSEC_CXL_PORT_CTL                         0x0c
 #define PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR              0x00000001
 
+/* Integrity and Data Encryption Extended Capability */
+#define PCI_IDE_CAP                    0x04
+#define  PCI_IDE_CAP_LINK              0x1  /* Link IDE Stream Supported */
+#define  PCI_IDE_CAP_SELECTIVE         0x2  /* Selective IDE Streams Supported */
+#define  PCI_IDE_CAP_FLOWTHROUGH       0x4  /* Flow-Through IDE Stream Supported */
+#define  PCI_IDE_CAP_PARTIAL_HEADER_ENC 0x8  /* Partial Header Encryption Supported */
+#define  PCI_IDE_CAP_AGGREGATION       0x10 /* Aggregation Supported */
+#define  PCI_IDE_CAP_PCRC              0x20 /* PCRC Supported */
+#define  PCI_IDE_CAP_IDE_KM            0x40 /* IDE_KM Protocol Supported */
+#define  PCI_IDE_CAP_SEL_CFG           0x80 /* Selective IDE for Config Request Support */
+#define  PCI_IDE_CAP_ALG               __GENMASK(12, 8) /* Supported Algorithms */
+#define   PCI_IDE_CAP_ALG_AES_GCM_256  0    /* AES-GCM 256 key size, 96b MAC */
+#define  PCI_IDE_CAP_LINK_TC_NUM       __GENMASK(15, 13) /* Link IDE TCs */
+#define  PCI_IDE_CAP_SEL_NUM           __GENMASK(23, 16) /* Supported Selective IDE Streams */
+#define  PCI_IDE_CAP_TEE_LIMITED       0x1000000 /* TEE-Limited Stream Supported */
+#define PCI_IDE_CTL                    0x08
+#define  PCI_IDE_CTL_FLOWTHROUGH_IDE   0x4  /* Flow-Through IDE Stream Enabled */
+
+#define PCI_IDE_LINK_STREAM_0          0xc  /* First Link Stream Register Block */
+#define  PCI_IDE_LINK_BLOCK_SIZE       8
+/* Link IDE Stream block, up to PCI_IDE_CAP_LINK_TC_NUM */
+#define PCI_IDE_LINK_CTL_0             0x00              /* First Link Control Register Offset in block */
+#define  PCI_IDE_LINK_CTL_EN           0x1               /* Link IDE Stream Enable */
+#define  PCI_IDE_LINK_CTL_TX_AGGR_NPR  __GENMASK(3, 2)   /* Tx Aggregation Mode NPR */
+#define  PCI_IDE_LINK_CTL_TX_AGGR_PR   __GENMASK(5, 4)   /* Tx Aggregation Mode PR */
+#define  PCI_IDE_LINK_CTL_TX_AGGR_CPL  __GENMASK(7, 6)   /* Tx Aggregation Mode CPL */
+#define  PCI_IDE_LINK_CTL_PCRC_EN      0x100             /* PCRC Enable */
+#define  PCI_IDE_LINK_CTL_PART_ENC     __GENMASK(13, 10) /* Partial Header Encryption Mode */
+#define  PCI_IDE_LINK_CTL_ALG          __GENMASK(18, 14) /* Selection from PCI_IDE_CAP_ALG */
+#define  PCI_IDE_LINK_CTL_TC           __GENMASK(21, 19) /* Traffic Class */
+#define  PCI_IDE_LINK_CTL_ID           __GENMASK(31, 24) /* Stream ID */
+#define PCI_IDE_LINK_STS_0             0x4               /* First Link Status Register Offset in block */
+#define  PCI_IDE_LINK_STS_STATE                __GENMASK(3, 0)   /* Link IDE Stream State */
+#define  PCI_IDE_LINK_STS_IDE_FAIL     0x80000000        /* IDE fail message received */
+
+/* Selective IDE Stream block, up to PCI_IDE_CAP_SELECTIVE_STREAMS_NUM */
+/* Selective IDE Stream Capability Register */
+#define  PCI_IDE_SEL_CAP               0x00
+#define   PCI_IDE_SEL_CAP_ASSOC_NUM    __GENMASK(3, 0)
+/* Selective IDE Stream Control Register */
+#define  PCI_IDE_SEL_CTL               0x04
+#define   PCI_IDE_SEL_CTL_EN           0x1               /* Selective IDE Stream Enable */
+#define   PCI_IDE_SEL_CTL_TX_AGGR_NPR  __GENMASK(3, 2)   /* Tx Aggregation Mode NPR */
+#define   PCI_IDE_SEL_CTL_TX_AGGR_PR   __GENMASK(5, 4)   /* Tx Aggregation Mode PR */
+#define   PCI_IDE_SEL_CTL_TX_AGGR_CPL  __GENMASK(7, 6)   /* Tx Aggregation Mode CPL */
+#define   PCI_IDE_SEL_CTL_PCRC_EN      0x100             /* PCRC Enable */
+#define   PCI_IDE_SEL_CTL_CFG_EN       0x200             /* Selective IDE for Configuration Requests */
+#define   PCI_IDE_SEL_CTL_PART_ENC     __GENMASK(13, 10) /* Partial Header Encryption Mode */
+#define   PCI_IDE_SEL_CTL_ALG          __GENMASK(18, 14) /* Selection from PCI_IDE_CAP_ALG */
+#define   PCI_IDE_SEL_CTL_TC           __GENMASK(21, 19) /* Traffic Class */
+#define   PCI_IDE_SEL_CTL_DEFAULT      0x400000          /* Default Stream */
+#define   PCI_IDE_SEL_CTL_TEE_LIMITED  0x800000          /* TEE-Limited Stream */
+#define   PCI_IDE_SEL_CTL_ID           __GENMASK(31, 24) /* Stream ID */
+#define   PCI_IDE_SEL_CTL_ID_MAX       255
+/* Selective IDE Stream Status Register */
+#define  PCI_IDE_SEL_STS                0x08
+#define   PCI_IDE_SEL_STS_STATE                 __GENMASK(3, 0) /* Selective IDE Stream State */
+#define   PCI_IDE_SEL_STS_STATE_INSECURE 0
+#define   PCI_IDE_SEL_STS_STATE_SECURE  2
+#define   PCI_IDE_SEL_STS_IDE_FAIL      0x80000000      /* IDE fail message received */
+/* IDE RID Association Register 1 */
+#define  PCI_IDE_SEL_RID_1              0x0c
+#define   PCI_IDE_SEL_RID_1_LIMIT       __GENMASK(23, 8)
+/* IDE RID Association Register 2 */
+#define  PCI_IDE_SEL_RID_2             0x10
+#define   PCI_IDE_SEL_RID_2_VALID      0x1
+#define   PCI_IDE_SEL_RID_2_BASE       __GENMASK(23, 8)
+#define   PCI_IDE_SEL_RID_2_SEG                __GENMASK(31, 24)
+/* Selective IDE Address Association Register Block, up to PCI_IDE_SEL_CAP_ASSOC_NUM */
+#define PCI_IDE_SEL_ADDR_BLOCK_SIZE    12
+#define  PCI_IDE_SEL_ADDR_1(x)         (20 + (x) * PCI_IDE_SEL_ADDR_BLOCK_SIZE)
+#define   PCI_IDE_SEL_ADDR_1_VALID     0x1
+#define   PCI_IDE_SEL_ADDR_1_BASE_LOW  __GENMASK(19, 8)
+#define   PCI_IDE_SEL_ADDR_1_LIMIT_LOW __GENMASK(31, 20)
+/* IDE Address Association Register 2 is "Memory Limit Upper" */
+#define  PCI_IDE_SEL_ADDR_2(x)         (24 + (x) * PCI_IDE_SEL_ADDR_BLOCK_SIZE)
+/* IDE Address Association Register 3 is "Memory Base Upper" */
+#define  PCI_IDE_SEL_ADDR_3(x)         (28 + (x) * PCI_IDE_SEL_ADDR_BLOCK_SIZE)
+#define PCI_IDE_SEL_BLOCK_SIZE(nr_assoc)  (20 + PCI_IDE_SEL_ADDR_BLOCK_SIZE * (nr_assoc))
+
 #endif /* LINUX_PCI_REGS_H */