* [PATCH 0/2] PCI/CXL: Distinguish CXL capabilities in MCAP
@ 2026-08-16 8:49 peng.guo
2026-08-16 8:49 ` [PATCH 1/2] PCI: Add MMIO Capabilities Register Block definitions peng.guo
2026-08-16 8:49 ` [PATCH 2/2] cxl/core: Skip non-CXL capabilities in MCAP peng.guo
0 siblings, 2 replies; 7+ messages in thread
From: peng.guo @ 2026-08-16 8:49 UTC (permalink / raw)
To: linux-cxl
Cc: linux-pci, linux-kernel, bhelgaas, dave, jic23, dave.jiang,
alison.schofield, vishal.l.verma, ira.weiny, djbw, johnny.li,
jingzhong.yang, engguopeng, pguo
From: pguo <peng.guo@montage-tech.com>
When MMPT is enabled, a device may expose PCI-SIG-defined MMPT
capabilities alongside CXL-defined capabilities in the same MMIO
Capabilities Register Block (MCAP).
MCAP capability IDs are scoped by Vendor ID, but the CXL capability
parser currently matches entries using only their capability IDs. This
can cause MMPT entries to be interpreted as CXL register blocks.
Add the generic PCI MCAP register definitions, then update the CXL
parser to process only capabilities carrying the CXL Vendor ID.
Patch 1 adds the PCI MCAP array and capability header definitions.
Patch 2 filters non-CXL capabilities before interpreting their IDs.
The fix has been tested on a CXL device with MMPT enabled and prevents
both the Mailbox and Status capability misidentification.
pguo (2):
PCI: Add MMIO Capabilities Register Block definitions
cxl/core: Skip non-CXL capabilities in MCAP
drivers/cxl/core/regs.c | 8 +++++++-
include/uapi/linux/pci_regs.h | 21 +++++++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/2] PCI: Add MMIO Capabilities Register Block definitions
2026-08-16 8:49 [PATCH 0/2] PCI/CXL: Distinguish CXL capabilities in MCAP peng.guo
@ 2026-08-16 8:49 ` peng.guo
2026-08-16 9:15 ` sashiko-bot
2026-08-16 11:19 ` Lukas Wunner
2026-08-16 8:49 ` [PATCH 2/2] cxl/core: Skip non-CXL capabilities in MCAP peng.guo
1 sibling, 2 replies; 7+ messages in thread
From: peng.guo @ 2026-08-16 8:49 UTC (permalink / raw)
To: linux-cxl
Cc: linux-pci, linux-kernel, bhelgaas, dave, jic23, dave.jiang,
alison.schofield, vishal.l.verma, ira.weiny, djbw, johnny.li,
jingzhong.yang, engguopeng, pguo
From: pguo <peng.guo@montage-tech.com>
The PCIe Management Message Passthrough via MMIO Mailbox ECN defines
the MMIO Capabilities Register Block (MCAP). MCAP contains an array
header followed by capability headers that describe the ID, version,
location, size, and vendor of each MMIO capability.
Add definitions for the MCAP array and capability headers so that
subsystem drivers can distinguish capabilities with overlapping IDs
by using the Vendor ID field.
Signed-off-by: pguo <peng.guo@montage-tech.com>
---
include/uapi/linux/pci_regs.h | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 14f634ab9350..5fe6bc711526 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -1338,6 +1338,27 @@
#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))
+/* MMIO Capabilities Register Block (MCAP) */
+#define PCI_MCAP_ARRAY_1 0x00
+#define PCI_MCAP_ARRAY_ID __GENMASK(15, 0)
+#define PCI_MCAP_ARRAY_VERSION __GENMASK(23, 16)
+#define PCI_MCAP_ARRAY_TYPE __GENMASK(27, 24)
+#define PCI_MCAP_ARRAY_TYPE_CLASS_CODE 0x0
+#define PCI_MCAP_ARRAY_2 0x04
+#define PCI_MCAP_ARRAY_COUNT __GENMASK(15, 0)
+
+#define PCI_MCAP_HDR_SIZEOF 0x10
+#define PCI_MCAP_HDR_BASE(n) ((n) * PCI_MCAP_HDR_SIZEOF)
+#define PCI_MCAP_HDR_REG_1 0x00
+#define PCI_MCAP_CAP_ID __GENMASK(15, 0)
+#define PCI_MCAP_CAP_VERSION __GENMASK(23, 16)
+#define PCI_MCAP_HDR_REG_2 0x04
+#define PCI_MCAP_HDR_OFFSET __GENMASK(31, 0)
+#define PCI_MCAP_HDR_REG_3 0x08
+#define PCI_MCAP_HDR_LENGTH __GENMASK(31, 0)
+#define PCI_MCAP_HDR_REG_4 0x0c
+#define PCI_MCAP_HDR_VENDOR_ID __GENMASK(15, 0)
+
/*
* Compute Express Link (CXL r4.0, sec 8.1)
*
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/2] cxl/core: Skip non-CXL capabilities in MCAP
2026-08-16 8:49 [PATCH 0/2] PCI/CXL: Distinguish CXL capabilities in MCAP peng.guo
2026-08-16 8:49 ` [PATCH 1/2] PCI: Add MMIO Capabilities Register Block definitions peng.guo
@ 2026-08-16 8:49 ` peng.guo
2026-08-16 9:19 ` sashiko-bot
2026-08-16 11:22 ` Lukas Wunner
1 sibling, 2 replies; 7+ messages in thread
From: peng.guo @ 2026-08-16 8:49 UTC (permalink / raw)
To: linux-cxl
Cc: linux-pci, linux-kernel, bhelgaas, dave, jic23, dave.jiang,
alison.schofield, vishal.l.verma, ira.weiny, djbw, johnny.li,
jingzhong.yang, engguopeng, pguo
From: pguo <peng.guo@montage-tech.com>
When MMPT is enabled, a CXL device may expose both CXL-defined capabilities
and PCIe Management Message Passthrough (MMPT) capabilities in the same
MMIO Capabilities Register Block (MCAP).
The CXL capability parser currently identifies entries using only the
capability ID. Since capability IDs are scoped by Vendor ID, a
PCI-SIG-defined capability may have the same ID as a CXL-defined
capability. This causes non-CXL entries, including MMPT and MMIO Mailbox,
to be interpreted as CXL register blocks.
The MMPT register block may be interpreted as a CXL mailbox. This
causes mailbox initialization to fail with:
cxl_pci 0000:3b:00.0: Mailbox is too small (64b)
Check the MCAP Vendor ID before interpreting an entry as a CXL-defined
capability. This prevents PCI-SIG-defined MMPT capabilities from being
mistaken for CXL mailbox capabilities.
Fixes: 8adaf747c9f0 ("cxl/mem: Find device capabilities")
Suggested-by: Johnny <johnny.li@montage-tech.com>
Signed-off-by: pguo <peng.guo@montage-tech.com>
---
drivers/cxl/core/regs.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
index 93710cf4f0a6..79edb7bac8eb 100644
--- a/drivers/cxl/core/regs.c
+++ b/drivers/cxl/core/regs.c
@@ -134,7 +134,13 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base,
for (cap = 1; cap <= cap_count; cap++) {
struct cxl_reg_map *rmap;
u32 offset, length;
- u16 cap_id;
+ u16 cap_id, vendor_id;
+
+ vendor_id = FIELD_GET(PCI_MCAP_HDR_VENDOR_ID,
+ readl(base + PCI_MCAP_HDR_BASE(cap) +
+ PCI_MCAP_HDR_REG_4));
+ if (vendor_id != PCI_VENDOR_ID_CXL)
+ continue;
cap_id = FIELD_GET(CXLDEV_CAP_HDR_CAP_ID_MASK,
readl(base + cap * 0x10));
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] PCI: Add MMIO Capabilities Register Block definitions
2026-08-16 8:49 ` [PATCH 1/2] PCI: Add MMIO Capabilities Register Block definitions peng.guo
@ 2026-08-16 9:15 ` sashiko-bot
2026-08-16 11:19 ` Lukas Wunner
1 sibling, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-08-16 9:15 UTC (permalink / raw)
To: peng.guo; +Cc: linux-pci, linux-cxl
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The PCI_MCAP_HDR_BASE(n) macro incorrectly calculates the capability header base offset by omitting the 8-byte MCAP Array Header size.
--
--- Patch [1]: [PATCH 1/2] PCI: Add MMIO Capabilities Register Block definitions ---
commit 20bc3890e7eab9f1dcc6c8e26abf81734aa23ac0
Author: pguo <peng.guo@montage-tech.com>
PCI: Add MMIO Capabilities Register Block definitions
This commit adds definitions for the PCIe Management Message Passthrough
via MMIO Mailbox ECN. It introduces the MMIO Capabilities Register Block
array and capability headers.
> diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
> --- a/include/uapi/linux/pci_regs.h
> +++ b/include/uapi/linux/pci_regs.h
[ ... ]
> +/* MMIO Capabilities Register Block (MCAP) */
> +#define PCI_MCAP_ARRAY_1 0x00
> +#define PCI_MCAP_ARRAY_ID __GENMASK(15, 0)
> +#define PCI_MCAP_ARRAY_VERSION __GENMASK(23, 16)
> +#define PCI_MCAP_ARRAY_TYPE __GENMASK(27, 24)
> +#define PCI_MCAP_ARRAY_TYPE_CLASS_CODE 0x0
> +#define PCI_MCAP_ARRAY_2 0x04
> +#define PCI_MCAP_ARRAY_COUNT __GENMASK(15, 0)
> +
> +#define PCI_MCAP_HDR_SIZEOF 0x10
> +#define PCI_MCAP_HDR_BASE(n) ((n) * PCI_MCAP_HDR_SIZEOF)
[Severity: Medium]
Does this macro calculation correctly account for the MCAP Array Header size?
Since PCI_MCAP_ARRAY_1 and PCI_MCAP_ARRAY_2 occupy the first 8 bytes of the
block, calculating PCI_MCAP_HDR_BASE(0) as 0x00 causes the capability
headers to directly overlap with the array header registers instead of
starting at the correct offset.
Should this macro include an 8-byte offset for the array header?
> +#define PCI_MCAP_HDR_REG_1 0x00
> +#define PCI_MCAP_CAP_ID __GENMASK(15, 0)
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260816084957.3316727-1-peng.guo@montage-tech.com?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] cxl/core: Skip non-CXL capabilities in MCAP
2026-08-16 8:49 ` [PATCH 2/2] cxl/core: Skip non-CXL capabilities in MCAP peng.guo
@ 2026-08-16 9:19 ` sashiko-bot
2026-08-16 11:22 ` Lukas Wunner
1 sibling, 0 replies; 7+ messages in thread
From: sashiko-bot @ 2026-08-16 9:19 UTC (permalink / raw)
To: peng.guo; +Cc: linux-cxl, linux-pci
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [High] The strict Vendor ID check in `cxl_probe_device_regs` incorrectly rejects valid capabilities on legacy CXL 2.0/3.0 devices.
Pre-existing issues:
- [High] Missing bounds checking on untrusted device-provided capability count can lead to out-of-bounds MMIO reads.
- [High] Unvalidated device-provided capability offsets allow arbitrary physical memory mapping.
--
--- Patch [2]: [PATCH 2/2] cxl/core: Skip non-CXL capabilities in MCAP ---
commit 6cdac110087d8d1e0117e2bb4680d99d50fc28fe
Author: pguo <peng.guo@montage-tech.com>
cxl/core: Skip non-CXL capabilities in MCAP
This commit adds a check for the MCAP Vendor ID before interpreting an entry
as a CXL-defined capability. It intends to prevent non-CXL entries, such as
MMPT and MMIO Mailbox, from being misidentified as CXL register blocks.
> diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
> index 20c2d9fbcfe7d..854a8bb4c4f35 100644
> --- a/drivers/cxl/core/regs.c
> +++ b/drivers/cxl/core/regs.c
> @@ -135,7 +135,13 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base,
> for (cap = 1; cap <= cap_count; cap++) {
[Severity: High]
This is a pre-existing issue, but does this loop lack bounds checking against
the mapped MMIO region size?
The cap_count is extracted from the device-provided capability array register
and can be as large as 65535.
Since base points to an ioremap region bounded by the remaining PCIe BAR size,
a large untrusted cap_count could cause the offset calculations within the
loop to exceed the mapped boundaries, leading to out-of-bounds MMIO reads.
> struct cxl_reg_map *rmap;
> u32 offset, length;
> - u16 cap_id;
> + u16 cap_id, vendor_id;
> +
> + vendor_id = FIELD_GET(PCI_MCAP_HDR_VENDOR_ID,
> + readl(base + PCI_MCAP_HDR_BASE(cap) +
> + PCI_MCAP_HDR_REG_4));
> + if (vendor_id != PCI_VENDOR_ID_CXL)
> + continue;
[Severity: High]
Does this strict check break legacy CXL 2.0 and 3.0 devices?
For pre-MCAP legacy devices, the offset for the Vendor ID in the capability
header is reserved and defined to read as zero.
Because this check unconditionally rejects any capability that doesn't
explicitly match PCI_VENDOR_ID_CXL, it will skip all valid capabilities
whose Vendor ID evaluates to zero.
Will this cause device probing to fail entirely for legacy hardware?
>
> cap_id = FIELD_GET(CXLDEV_CAP_HDR_CAP_ID_MASK,
> readl(base + cap * 0x10));
> offset = readl(base + cap * 0x10 + 0x4);
> length = readl(base + cap * 0x10 + 0x8);
[Severity: High]
This is a pre-existing issue, but are the offset and length values validated
against the PCIe BAR boundaries?
These fields are read directly from untrusted device MMIO. Later, in
cxl_map_device_regs(), they are used to calculate the physical address for
mapping:
cxl_map_device_regs()
addr = phys_addr + mi->rmap->offset;
length = mi->rmap->size;
*(mi->addr) = devm_cxl_iomap_block(host, addr, length);
Could a crafted offset and length allow the device to force the host kernel
to map and interact with arbitrary physical memory outside the device's BAR?
>
> rmap = NULL;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260816084957.3316727-1-peng.guo@montage-tech.com?part=2
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] PCI: Add MMIO Capabilities Register Block definitions
2026-08-16 8:49 ` [PATCH 1/2] PCI: Add MMIO Capabilities Register Block definitions peng.guo
2026-08-16 9:15 ` sashiko-bot
@ 2026-08-16 11:19 ` Lukas Wunner
1 sibling, 0 replies; 7+ messages in thread
From: Lukas Wunner @ 2026-08-16 11:19 UTC (permalink / raw)
To: peng.guo
Cc: linux-cxl, linux-pci, linux-kernel, bhelgaas, dave, jic23,
dave.jiang, alison.schofield, vishal.l.verma, ira.weiny, djbw,
johnny.li, jingzhong.yang, engguopeng
On Sun, Aug 16, 2026 at 04:49:56PM +0800, peng.guo@montage-tech.com wrote:
> The PCIe Management Message Passthrough via MMIO Mailbox ECN defines
> the MMIO Capabilities Register Block (MCAP). MCAP contains an array
> header followed by capability headers that describe the ID, version,
> location, size, and vendor of each MMIO capability.
That ECN went into PCIe r6.2. For ECNs that are already part of the
PCIe Base Spec, it's better to cite the section in the latest spec
revision, i.e. PCIe r7.0 sec 6.35, rather than the ECN that originally
introduced the feature. Reviewers (like me) generally have the latest
spec revision at hand, but not every ECN.
Otherwise this is
Reviewed-by: Lukas Wunner <lukas@wunner.de>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] cxl/core: Skip non-CXL capabilities in MCAP
2026-08-16 8:49 ` [PATCH 2/2] cxl/core: Skip non-CXL capabilities in MCAP peng.guo
2026-08-16 9:19 ` sashiko-bot
@ 2026-08-16 11:22 ` Lukas Wunner
1 sibling, 0 replies; 7+ messages in thread
From: Lukas Wunner @ 2026-08-16 11:22 UTC (permalink / raw)
To: peng.guo
Cc: linux-cxl, linux-pci, linux-kernel, bhelgaas, dave, jic23,
dave.jiang, alison.schofield, vishal.l.verma, ira.weiny, djbw,
johnny.li, jingzhong.yang, engguopeng
On Sun, Aug 16, 2026 at 04:49:57PM +0800, peng.guo@montage-tech.com wrote:
> +++ b/drivers/cxl/core/regs.c
> @@ -134,7 +134,13 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base,
> for (cap = 1; cap <= cap_count; cap++) {
> struct cxl_reg_map *rmap;
> u32 offset, length;
> - u16 cap_id;
> + u16 cap_id, vendor_id;
> +
Nit: Move the u16 line above the u32 line to maintain inverse Christmas
tree convention.
Thanks,
Lukas
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-08-16 11:22 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-16 8:49 [PATCH 0/2] PCI/CXL: Distinguish CXL capabilities in MCAP peng.guo
2026-08-16 8:49 ` [PATCH 1/2] PCI: Add MMIO Capabilities Register Block definitions peng.guo
2026-08-16 9:15 ` sashiko-bot
2026-08-16 11:19 ` Lukas Wunner
2026-08-16 8:49 ` [PATCH 2/2] cxl/core: Skip non-CXL capabilities in MCAP peng.guo
2026-08-16 9:19 ` sashiko-bot
2026-08-16 11:22 ` Lukas Wunner
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.