Skip to content

Commit c9c229b

Browse files
authored
Merge pull request #569 from bgoglin/cxldax
CXLDevice attributes in DAX and NUMA nodes
2 parents 32117b9 + aa26f29 commit c9c229b

File tree

2 files changed

+84
-3
lines changed

2 files changed

+84
-3
lines changed

doc/hwloc.doxy

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,6 +2127,11 @@ and GID #1 of port #3.
21272127
These info attributes are attached to objects specified in parentheses.
21282128

21292129
<dl>
2130+
<dt>CXLDevice (NUMA Nodes or DAX Memory OS devices)</dt>
2131+
<dd>The PCI/CXL bus ID of a device whose CXL Type-3 memory is exposed here.
2132+
There may be multiple instances of this attributes if multiple device memories
2133+
are interleaved.
2134+
</dd>
21302135
<dt>DAXDevice (NUMA Nodes)</dt>
21312136
<dd>The name of the Linux DAX device that was used to expose a non-volatile
21322137
memory region as a volatile NUMA node.

hwloc/topology-linux.c

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3690,6 +3690,69 @@ read_node_mscaches(struct hwloc_topology *topology,
36903690
return 0;
36913691
}
36923692

3693+
static int
3694+
annotate_cxl_dax(hwloc_obj_t obj, unsigned region, int root_fd)
3695+
{
3696+
char path[300];
3697+
unsigned i;
3698+
3699+
for(i=0; ; i++) {
3700+
char decoder[20]; /* "decoderX.Y" */
3701+
char decoderpath[256], *endpoint;
3702+
char uportpath[256], *pcirootbus, *pcibdf;
3703+
unsigned pcidomain, pcibus, pcidevice, pcifunc;
3704+
char *slash, *end;
3705+
int err;
3706+
3707+
/* read the i-th decoder name from file target<i> */
3708+
snprintf(path, sizeof(path), "/sys/bus/cxl/devices/region%u/target%u", region, i);
3709+
if (hwloc_read_path_by_length(path, decoder, sizeof(decoder), root_fd) < 0)
3710+
break;
3711+
end = strchr(decoder, '\n');
3712+
if (end)
3713+
*end = '\0';
3714+
hwloc_debug("hwloc/dax/cxl: found decoder `%s' for region#%u target#%u\n", decoder, region, i);
3715+
3716+
/* get the endpoint symlink which ends with "/portT/endpointX/decoderY.X/" */
3717+
snprintf(path, sizeof(path), "/sys/bus/cxl/devices/%s", decoder);
3718+
err = hwloc_readlink(path, decoderpath, sizeof(decoderpath), root_fd);
3719+
if (err < 0)
3720+
break;
3721+
endpoint = strstr(decoderpath, "endpoint");
3722+
if (!endpoint)
3723+
break;
3724+
slash = strchr(endpoint, '/');
3725+
if (!slash)
3726+
break;
3727+
*slash = '\0';
3728+
hwloc_debug("hwloc/dax/cxl: found endpoint `%s'\n", endpoint);
3729+
3730+
/* get the PCI in the endpointX/uport symlink "../../../pci<busid>/<BDFs>../memX" */
3731+
snprintf(path, sizeof(path), "/sys/bus/cxl/devices/%s/uport", endpoint);
3732+
err = hwloc_readlink(path, uportpath, sizeof(uportpath), root_fd);
3733+
if (err < 0)
3734+
break;
3735+
hwloc_debug("hwloc/dax/cxl: lookind for BDF at the end of uport `%s'\n", uportpath);
3736+
pcirootbus = strstr(uportpath, "/pci");
3737+
if (!pcirootbus)
3738+
break;
3739+
slash = pcirootbus + 11; /* "/pciXXXX:YY/" */
3740+
if (*slash != '/')
3741+
break;
3742+
pcibdf = NULL;
3743+
while (sscanf(slash, "/%x:%x:%x.%x/", &pcidomain, &pcibus, &pcidevice, &pcifunc) == 4) {
3744+
pcibdf = slash+1;
3745+
slash += 13;
3746+
}
3747+
*slash = '\0';
3748+
if (pcibdf) {
3749+
hwloc_obj_add_info(obj, "CXLDevice", pcibdf);
3750+
}
3751+
}
3752+
3753+
return 0;
3754+
}
3755+
36933756
static int
36943757
dax_is_kmem(const char *name, int fsroot_fd)
36953758
{
@@ -3705,7 +3768,7 @@ annotate_dax_parent(hwloc_obj_t obj, const char *name, int fsroot_fd)
37053768
{
37063769
char daxpath[300];
37073770
char link[PATH_MAX];
3708-
char *begin, *end;
3771+
char *begin, *end, *region;
37093772
const char *type;
37103773
int err;
37113774

@@ -3719,7 +3782,11 @@ annotate_dax_parent(hwloc_obj_t obj, const char *name, int fsroot_fd)
37193782
* ../../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region2/dax2.0/dax2.0/ for NVDIMMs
37203783
* ../../../devices/platform/e820_pmem/ndbus0/region0/dax0.0/dax0.0/ for fake NVM (memmap=size!start kernel parameter)
37213784
* ../../../devices/platform/hmem.0/dax0.0/ for "soft-reserved" specific-purpose memory
3785+
* ../../../devices/platform/ACPI0017:00/root0/decoder0.0/region0/dax_region0/dax0.0/ for CXL RAM
3786+
* ../../../devices/platform/ACPI0017:00/root0/nvdimm-bridge0/ndbus0/region0/dax0.0/dax0.0/ for CXL PMEM
37223787
*/
3788+
3789+
/* remove beginning and end of link to populate DAXParent */
37233790
begin = link;
37243791
/* remove the starting ".." (likely multiple) */
37253792
while (!strncmp(begin, "../", 3))
@@ -3729,9 +3796,9 @@ annotate_dax_parent(hwloc_obj_t obj, const char *name, int fsroot_fd)
37293796
begin += 8;
37303797
if (!strncmp(begin, "platform/", 9))
37313798
begin += 9;
3732-
/* remove the ending "daxX.Y" (either one or two) */
3799+
/* stop at the ending "/daxX.Y" */
37333800
end = strstr(begin, name);
3734-
if (end) {
3801+
if (end && end != begin && end[-1] == '/') {
37353802
*end = '\0';
37363803
if (end != begin && end[-1] == '/')
37373804
end[-1] = '\0';
@@ -3741,6 +3808,15 @@ annotate_dax_parent(hwloc_obj_t obj, const char *name, int fsroot_fd)
37413808
type = strstr(begin, "ndbus") ? "NVM" : "SPM";
37423809
hwloc_obj_add_info(obj, "DAXType", type);
37433810

3811+
/* try to get some CXL info from the region */
3812+
region = strstr(begin, "/region");
3813+
if (region) {
3814+
unsigned i = strtoul(region+7, &end, 10);
3815+
if (end != region+7)
3816+
annotate_cxl_dax(obj, i, fsroot_fd);
3817+
}
3818+
3819+
/* insert DAXParent last because it's likely less useful than others */
37443820
hwloc_obj_add_info(obj, "DAXParent", begin);
37453821

37463822
/*

0 commit comments

Comments
 (0)