summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Mares <mj@ucw.cz>2022-10-30 12:51:17 +0100
committerMartin Mares <mj@ucw.cz>2022-10-30 12:51:17 +0100
commite5eb34c946017291e9c659c224bf0a1646270dad (patch)
tree227247e3e876ac3bd3ad4fe3c345536395e963f8
parent7d4345b1942d013584316cbd042dc983a94c8b14 (diff)
parentfe0df5d38149ae4303300eb429dd501a8bd7da3b (diff)
downloadpciutils-e5eb34c946017291e9c659c224bf0a1646270dad.tar.gz
Merge remote-tracking branch 'jphaws/cxl'
-rw-r--r--lib/header.h83
-rw-r--r--ls-ecaps.c204
2 files changed, 252 insertions, 35 deletions
diff --git a/lib/header.h b/lib/header.h
index 525b910..33ed2be 100644
--- a/lib/header.h
+++ b/lib/header.h
@@ -1068,24 +1068,71 @@
#define PCI_DVSEC_VENDOR_ID_CXL 0x1e98 /* Designated Vendor-Specific Vendor ID for CXL */
#define PCI_DVSEC_ID_CXL 0 /* Designated Vendor-Specific ID for Intel CXL */
-/* PCIe CXL Designated Vendor-Specific Capabilities, Control, Status */
-#define PCI_CXL_CAP 0x0a /* CXL Capability Register */
-#define PCI_CXL_CAP_CACHE 0x0001 /* CXL.cache Protocol Support */
-#define PCI_CXL_CAP_IO 0x0002 /* CXL.io Protocol Support */
-#define PCI_CXL_CAP_MEM 0x0004 /* CXL.mem Protocol Support */
-#define PCI_CXL_CAP_MEM_HWINIT 0x0008 /* CXL.mem Initializes with HW/FW Support */
-#define PCI_CXL_CAP_HDM_CNT(x) (((x) & (3 << 4)) >> 4) /* CXL Number of HDM ranges */
-#define PCI_CXL_CAP_VIRAL 0x4000 /* CXL Viral Handling Support */
-#define PCI_CXL_CTRL 0x0c /* CXL Control Register */
-#define PCI_CXL_CTRL_CACHE 0x0001 /* CXL.cache Protocol Enable */
-#define PCI_CXL_CTRL_IO 0x0002 /* CXL.io Protocol Enable */
-#define PCI_CXL_CTRL_MEM 0x0004 /* CXL.mem Protocol Enable */
-#define PCI_CXL_CTRL_CACHE_SF_COV(x) (((x) & (0x1f << 3)) >> 3) /* Snoop Filter Coverage */
-#define PCI_CXL_CTRL_CACHE_SF_GRAN(x) (((x) & (0x7 << 8)) >> 8) /* Snoop Filter Granularity */
-#define PCI_CXL_CTRL_CACHE_CLN 0x0800 /* CXL.cache Performance Hint on Clean Evictions */
-#define PCI_CXL_CTRL_VIRAL 0x4000 /* CXL Viral Handling Enable */
-#define PCI_CXL_STATUS 0x0e /* CXL Status Register */
-#define PCI_CXL_STATUS_VIRAL 0x4000 /* CXL Viral Handling Status */
+/* PCIe CXL Designated Vendor-Specific Capabilities for Devices: Control, Status */
+#define PCI_CXL_DEV_LEN 0x38 /* CXL Device DVSEC Length */
+#define PCI_CXL_DEV_CAP 0x0a /* CXL Capability Register */
+#define PCI_CXL_DEV_CAP_CACHE 0x0001 /* CXL.cache Protocol Support */
+#define PCI_CXL_DEV_CAP_IO 0x0002 /* CXL.io Protocol Support */
+#define PCI_CXL_DEV_CAP_MEM 0x0004 /* CXL.mem Protocol Support */
+#define PCI_CXL_DEV_CAP_MEM_HWINIT 0x0008 /* CXL.mem Initializes with HW/FW Support */
+#define PCI_CXL_DEV_CAP_HDM_CNT(x) (((x) & (3 << 4)) >> 4) /* CXL Number of HDM ranges */
+#define PCI_CXL_DEV_CAP_VIRAL 0x4000 /* CXL Viral Handling Support */
+#define PCI_CXL_DEV_CTRL 0x0c /* CXL Control Register */
+#define PCI_CXL_DEV_CTRL_CACHE 0x0001 /* CXL.cache Protocol Enable */
+#define PCI_CXL_DEV_CTRL_IO 0x0002 /* CXL.io Protocol Enable */
+#define PCI_CXL_DEV_CTRL_MEM 0x0004 /* CXL.mem Protocol Enable */
+#define PCI_CXL_DEV_CTRL_CACHE_SF_COV(x) (((x) & (0x1f << 3)) >> 3) /* Snoop Filter Coverage */
+#define PCI_CXL_DEV_CTRL_CACHE_SF_GRAN(x) (((x) & (0x7 << 8)) >> 8) /* Snoop Filter Granularity */
+#define PCI_CXL_DEV_CTRL_CACHE_CLN 0x0800 /* CXL.cache Performance Hint on Clean Evictions */
+#define PCI_CXL_DEV_CTRL_VIRAL 0x4000 /* CXL Viral Handling Enable */
+#define PCI_CXL_DEV_STATUS 0x0e /* CXL Status Register */
+#define PCI_CXL_DEV_STATUS_VIRAL 0x4000 /* CXL Viral Handling Status */
+#define PCI_CXL_DEV_STATUS2 0x12
+#define PCI_CXL_DEV_STATUS_CACHE_INV 0x0001
+#define PCI_CXL_DEV_STATUS_RC 0x0002 /* Device Reset Complete */
+#define PCI_CXL_DEV_STATUS_RE 0x0004 /* Device Reset Error */
+#define PCI_CXL_DEV_STATUS_PMC 0x8000 /* Power Management Init Complete */
+#define PCI_CXL_DEV_CAP2 0x16
+#define PCI_CXL_DEV_CAP2_CACHE_UNK 0x0000 /* Cache Size Isn't Reported */
+#define PCI_CXL_DEV_CAP2_CACHE_64K 0x0001 /* Unit Size 64K */
+#define PCI_CXL_DEV_CAP2_CACHE_1M 0x0002 /* Unit Size 1M */
+#define PCI_CXL_DEV_RANGE1_SIZE_HI 0x18
+#define PCI_CXL_DEV_RANGE1_SIZE_LO 0x1c
+#define PCI_CXL_RANGE_VALID 0x0001
+#define PCI_CXL_RANGE_ACTIVE 0x0002
+#define PCI_CXL_RANGE_TYPE(x) (((x) >> 2) & 0x7)
+#define PCI_CXL_RANGE_CLASS(x) (((x) >> 5) & 0x7)
+#define PCI_CXL_RANGE_INTERLEAVE(x) (((x) >> 8) & 0x1f)
+#define PCI_CXL_RANGE_TIMEOUT(x) (((x) >> 13) & 0x7)
+#define PCI_CXL_DEV_RANGE1_BASE_HI 0x20
+#define PCI_CXL_DEV_RANGE1_BASE_LO 0x24
+#define PCI_CXL_DEV_RANGE2_SIZE_HI 0x28
+#define PCI_CXL_DEV_RANGE2_SIZE_LO 0x2c
+#define PCI_CXL_DEV_RANGE2_BASE_HI 0x30
+#define PCI_CXL_DEV_RANGE2_BASE_LO 0x34
+
+/* PCIe CXL 2.0 Designated Vendor-Specific Capabilities for Ports */
+#define PCI_CXL_PORT_EXT_LEN 0x28 /* CXL Extensions DVSEC for Ports Length */
+#define PCI_CXL_PORT_EXT_STATUS 0x0a /* Port Extension Status */
+#define PCI_CXL_PORT_PM_INIT_COMPLETE 0x1 /* Port Power Management Initialization Complete */
+#define PCI_CXL_PORT_CTRL 0x0c /* Port Control Override */
+#define PCI_CXL_PORT_UNMASK_SBR 0x0001 /* Unmask SBR */
+#define PCI_CXL_PORT_UNMASK_LINK 0x0002 /* Unmask Link Disable */
+#define PCI_CXL_PORT_ALT_MEMORY 0x0004 /* Alt Memory and ID Space Enable */
+#define PCI_CXL_PORT_ALT_BME 0x0008 /* Alt BME */
+#define PCI_CXL_PORT_VIRAL_EN 0x4000 /* Viral Enable */
+#define PCI_CXL_PORT_ALT_BUS_BASE 0xe
+#define PCI_CXL_PORT_ALT_BUS_LIMIT 0xf
+#define PCI_CXL_PORT_ALT_MEM_BASE 0x10
+#define PCI_CXL_PORT_ALT_MEM_LIMIT 0x12
+
+/* PCIe CXL 2.0 Designated Vendor-Specific Capabilities for Register Locator */
+#define PCI_CXL_RL_BASE0_LO 0x0c
+#define PCI_CXL_RL_BASE0_HI 0x10
+#define PCI_CXL_RL_BASE1_LO 0x14
+#define PCI_CXL_RL_BASE1_HI 0x18
+#define PCI_CXL_RL_BASE2_LO 0x1c
+#define PCI_CXL_RL_BASE2_HI 0x20
/* Access Control Services */
#define PCI_ACS_CAP 0x04 /* ACS Capability Register */
diff --git a/ls-ecaps.c b/ls-ecaps.c
index 32a2cbc..d8376da 100644
--- a/ls-ecaps.c
+++ b/ls-ecaps.c
@@ -690,30 +690,200 @@ cap_rcec(struct device *d, int where)
}
static void
-cap_dvsec_cxl(struct device *d, int where)
+cxl_range(u64 base, u64 size, int n)
{
- u16 l;
+ u32 interleave[] = { 0, 256, 4096, 512, 1024, 2048, 8192, 16384 };
+ const char *type[] = { "Volatile", "Non-volatile", "CDAT" };
+ const char *class[] = { "DRAM", "Storage", "CDAT" };
+ u16 w;
- printf(": CXL\n");
- if (verbose < 2)
- return;
+ w = (u16) size;
+
+ size &= ~0x0fffffffULL;
+
+ printf("\t\tRange%d: %016"PCI_U64_FMT_X"-%016"PCI_U64_FMT_X"\n", n, base, base + size - 1);
+ printf("\t\t\tValid%c Active%c Type=%s Class=%s interleave=%d timeout=%ds\n",
+ FLAG(w, PCI_CXL_RANGE_VALID), FLAG(w, PCI_CXL_RANGE_ACTIVE),
+ type[PCI_CXL_RANGE_TYPE(w)], class[PCI_CXL_RANGE_CLASS(w)],
+ interleave[PCI_CXL_RANGE_INTERLEAVE(w)],
+ 1 << (PCI_CXL_RANGE_TIMEOUT(w) * 2));
+}
- if (!config_fetch(d, where + PCI_CXL_CAP, 12))
+static void
+dvsec_cxl_device(struct device *d, int where, int rev)
+{
+ u32 cache_size, cache_unit_size, l;
+ u64 range_base, range_size;
+ u16 w;
+
+ /* Legacy 1.1 revs aren't handled */
+ if (rev < 1)
return;
- l = get_conf_word(d, where + PCI_CXL_CAP);
+ w = get_conf_word(d, where + PCI_CXL_DEV_CAP);
printf("\t\tCXLCap:\tCache%c IO%c Mem%c Mem HW Init%c HDMCount %d Viral%c\n",
- FLAG(l, PCI_CXL_CAP_CACHE), FLAG(l, PCI_CXL_CAP_IO), FLAG(l, PCI_CXL_CAP_MEM),
- FLAG(l, PCI_CXL_CAP_MEM_HWINIT), PCI_CXL_CAP_HDM_CNT(l), FLAG(l, PCI_CXL_CAP_VIRAL));
+ FLAG(w, PCI_CXL_DEV_CAP_CACHE), FLAG(w, PCI_CXL_DEV_CAP_IO), FLAG(w, PCI_CXL_DEV_CAP_MEM),
+ FLAG(w, PCI_CXL_DEV_CAP_MEM_HWINIT), PCI_CXL_DEV_CAP_HDM_CNT(w), FLAG(w, PCI_CXL_DEV_CAP_VIRAL));
- l = get_conf_word(d, where + PCI_CXL_CTRL);
+ w = get_conf_word(d, where + PCI_CXL_DEV_CTRL);
printf("\t\tCXLCtl:\tCache%c IO%c Mem%c Cache SF Cov %d Cache SF Gran %d Cache Clean%c Viral%c\n",
- FLAG(l, PCI_CXL_CTRL_CACHE), FLAG(l, PCI_CXL_CTRL_IO), FLAG(l, PCI_CXL_CTRL_MEM),
- PCI_CXL_CTRL_CACHE_SF_COV(l), PCI_CXL_CTRL_CACHE_SF_GRAN(l), FLAG(l, PCI_CXL_CTRL_CACHE_CLN),
- FLAG(l, PCI_CXL_CTRL_VIRAL));
+ FLAG(w, PCI_CXL_DEV_CTRL_CACHE), FLAG(w, PCI_CXL_DEV_CTRL_IO), FLAG(w, PCI_CXL_DEV_CTRL_MEM),
+ PCI_CXL_DEV_CTRL_CACHE_SF_COV(w), PCI_CXL_DEV_CTRL_CACHE_SF_GRAN(w), FLAG(w, PCI_CXL_DEV_CTRL_CACHE_CLN),
+ FLAG(w, PCI_CXL_DEV_CTRL_VIRAL));
+
+ w = get_conf_word(d, where + PCI_CXL_DEV_STATUS);
+ printf("\t\tCXLSta:\tViral%c\n", FLAG(w, PCI_CXL_DEV_STATUS_VIRAL));
+
+ w = get_conf_word(d, where + PCI_CXL_DEV_STATUS2);
+ printf("\t\tCXLSta2:\tResetComplete%c ResetError%c PMComplete%c\n",
+ FLAG(w, PCI_CXL_DEV_STATUS_RC), FLAG(w,PCI_CXL_DEV_STATUS_RE), FLAG(w, PCI_CXL_DEV_STATUS_PMC));
+
+ w = get_conf_word(d, where + PCI_CXL_DEV_CAP2);
+ cache_unit_size = BITS(w, 0, 4);
+ cache_size = BITS(w, 8, 8);
+ switch (cache_unit_size)
+ {
+ case PCI_CXL_DEV_CAP2_CACHE_1M:
+ printf("\t\tCache Size: %08x\n", cache_size * (1<<20));
+ break;
+ case PCI_CXL_DEV_CAP2_CACHE_64K:
+ printf("\t\tCache Size: %08x\n", cache_size * (64<<10));
+ break;
+ case PCI_CXL_DEV_CAP2_CACHE_UNK:
+ printf("\t\tCache Size Not Reported\n");
+ break;
+ default:
+ printf("\t\tCache Size: %d of unknown unit size (%d)\n", cache_size, cache_unit_size);
+ break;
+ }
+
+ l = get_conf_long(d, where + PCI_CXL_DEV_RANGE1_SIZE_HI);
+ range_size = (u64) l << 32;
+ l = get_conf_long(d, where + PCI_CXL_DEV_RANGE1_SIZE_LO);
+ range_size |= l;
+ l = get_conf_long(d, where + PCI_CXL_DEV_RANGE1_BASE_HI);
+ range_base = (u64) l << 32;
+ l = get_conf_long(d, where + PCI_CXL_DEV_RANGE1_BASE_LO);
+ range_base |= l;
+ cxl_range(range_base, range_size, 1);
+
+ l = get_conf_long(d, where + PCI_CXL_DEV_RANGE2_SIZE_HI);
+ range_size = (u64) l << 32;
+ l = get_conf_long(d, where + PCI_CXL_DEV_RANGE2_SIZE_LO);
+ range_size |= l;
+ l = get_conf_long(d, where + PCI_CXL_DEV_RANGE2_BASE_HI);
+ range_base = (u64) l << 32;
+ l = get_conf_long(d, where + PCI_CXL_DEV_RANGE2_BASE_LO);
+ range_base |= l;
+ cxl_range(range_base, range_size, 2);
+}
+
+static void
+dvsec_cxl_port(struct device *d, int where)
+{
+ u16 w, m1, m2;
+ u8 b1, b2;
+
+ w = get_conf_word(d, where + PCI_CXL_PORT_EXT_STATUS);
+ printf("\t\tCXLPortSta:\tPMComplete%c\n", FLAG(w, PCI_CXL_PORT_EXT_STATUS));
+
+ w = get_conf_word(d, where + PCI_CXL_PORT_CTRL);
+ printf("\t\tCXLPortCtl:\tUnmaskSBR%c UnmaskLinkDisable%c AltMem%c AltBME%c ViralEnable%c\n",
+ FLAG(w, PCI_CXL_PORT_UNMASK_SBR), FLAG(w, PCI_CXL_PORT_UNMASK_LINK),
+ FLAG(w, PCI_CXL_PORT_ALT_MEMORY), FLAG(w, PCI_CXL_PORT_ALT_BME),
+ FLAG(w, PCI_CXL_PORT_VIRAL_EN));
+
+ b1 = get_conf_byte(d, where + PCI_CXL_PORT_ALT_BUS_BASE);
+ b2 = get_conf_byte(d, where + PCI_CXL_PORT_ALT_BUS_LIMIT);
+ printf("\t\tAlternateBus:\t%02x-%02x\n", b1, b2);
+ m1 = get_conf_word(d, where + PCI_CXL_PORT_ALT_MEM_BASE);
+ m2 = get_conf_word(d, where + PCI_CXL_PORT_ALT_MEM_LIMIT);
+ printf("\t\tAlternateBus:\t%04x-%04x\n", m1, m2);
+}
+
+static const char *id[] = {
+ "empty",
+ "component registers",
+ "BAR virtualization",
+ "CXL device registers"};
- l = get_conf_word(d, where + PCI_CXL_STATUS);
- printf("\t\tCXLSta:\tViral%c\n", FLAG(l, PCI_CXL_STATUS_VIRAL));
+static inline void
+dvsec_decode_block(uint32_t lo, uint32_t hi, char which)
+{
+ u64 base_hi = hi, base_lo;
+ u8 bir, block_id;
+
+ bir = BITS(lo, 0, 3);
+ block_id = BITS(lo, 8, 8);
+ base_lo = BITS(lo, 16, 16);
+
+ if (!block_id)
+ return;
+
+ printf("\t\tBlock%c\tBIR: bar%d\tID: %s\n", which, bir, id[block_id]);
+ printf("\t\t\tRegisterOffset: %016" PCI_U64_FMT_X "\n", (base_hi << 32ULL) | base_lo << 16);
+}
+
+static void
+dvsec_cxl_register_locator(struct device *d, int where, int len)
+{
+ int i, j;
+
+ for (i = 0xc, j = 1; i < len; i += 8, j++) {
+ dvsec_decode_block(get_conf_long(d, where + i), get_conf_long(d, where + i + 4), j + 0x31);
+ }
+}
+
+static void
+cap_dvsec_cxl(struct device *d, int id, int where)
+{
+ u16 len;
+ u8 rev;
+
+ printf(": CXL\n");
+ if (verbose < 2)
+ return;
+
+ rev = BITS(get_conf_byte(d, where + 0x6), 0, 4);
+
+ switch (id) {
+ case 0:
+ if (!config_fetch(d, where, PCI_CXL_DEV_LEN))
+ return;
+
+ dvsec_cxl_device(d, where, rev);
+ break;
+ case 3:
+ if (!config_fetch(d, where, PCI_CXL_PORT_EXT_LEN))
+ return;
+
+ dvsec_cxl_port(d, where);
+ break;
+ case 8:
+ len = BITS(get_conf_word(d, where + 0x6), 4, 12);
+ if (!config_fetch(d, where, len))
+ return;
+
+ dvsec_cxl_register_locator(d, where, len);
+ break;
+ case 2:
+ printf("\t\tNon-CXL Function Map DVSEC\n");
+ break;
+ case 4:
+ printf("\t\tGPF DVSEC for Port\n");
+ break;
+ case 5:
+ printf("\t\tGPF DVSEC for Device\n");
+ break;
+ case 7:
+ printf("\t\tPCIe DVSEC Flex Bus Port\n");
+ break;
+ case 9:
+ printf("\t\tMLD DVSEC\n");
+ break;
+ default:
+ break;
+ }
}
static void
@@ -734,8 +904,8 @@ cap_dvsec(struct device *d, int where)
u16 id = get_conf_long(d, where + PCI_DVSEC_HEADER2);
printf("Vendor=%04x ID=%04x Rev=%d Len=%d", vendor, id, rev, len);
- if (vendor == PCI_DVSEC_VENDOR_ID_CXL && id == PCI_DVSEC_ID_CXL && len >= 16)
- cap_dvsec_cxl(d, where);
+ if (vendor == PCI_DVSEC_VENDOR_ID_CXL && len >= 16)
+ cap_dvsec_cxl(d, id, where);
else
printf(" <?>\n");
}