@@ -3690,6 +3690,69 @@ read_node_mscaches(struct hwloc_topology *topology,
3690
3690
return 0 ;
3691
3691
}
3692
3692
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
+
3693
3756
static int
3694
3757
dax_is_kmem (const char * name , int fsroot_fd )
3695
3758
{
@@ -3705,7 +3768,7 @@ annotate_dax_parent(hwloc_obj_t obj, const char *name, int fsroot_fd)
3705
3768
{
3706
3769
char daxpath [300 ];
3707
3770
char link [PATH_MAX ];
3708
- char * begin , * end ;
3771
+ char * begin , * end , * region ;
3709
3772
const char * type ;
3710
3773
int err ;
3711
3774
@@ -3719,7 +3782,11 @@ annotate_dax_parent(hwloc_obj_t obj, const char *name, int fsroot_fd)
3719
3782
* ../../../devices/LNXSYSTM:00/LNXSYBUS:00/ACPI0012:00/ndbus0/region2/dax2.0/dax2.0/ for NVDIMMs
3720
3783
* ../../../devices/platform/e820_pmem/ndbus0/region0/dax0.0/dax0.0/ for fake NVM (memmap=size!start kernel parameter)
3721
3784
* ../../../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
3722
3787
*/
3788
+
3789
+ /* remove beginning and end of link to populate DAXParent */
3723
3790
begin = link ;
3724
3791
/* remove the starting ".." (likely multiple) */
3725
3792
while (!strncmp (begin , "../" , 3 ))
@@ -3729,9 +3796,9 @@ annotate_dax_parent(hwloc_obj_t obj, const char *name, int fsroot_fd)
3729
3796
begin += 8 ;
3730
3797
if (!strncmp (begin , "platform/" , 9 ))
3731
3798
begin += 9 ;
3732
- /* remove the ending "daxX.Y" (either one or two) */
3799
+ /* stop at the ending "/ daxX.Y" */
3733
3800
end = strstr (begin , name );
3734
- if (end ) {
3801
+ if (end && end != begin && end [ -1 ] == '/' ) {
3735
3802
* end = '\0' ;
3736
3803
if (end != begin && end [-1 ] == '/' )
3737
3804
end [-1 ] = '\0' ;
@@ -3741,6 +3808,15 @@ annotate_dax_parent(hwloc_obj_t obj, const char *name, int fsroot_fd)
3741
3808
type = strstr (begin , "ndbus" ) ? "NVM" : "SPM" ;
3742
3809
hwloc_obj_add_info (obj , "DAXType" , type );
3743
3810
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 */
3744
3820
hwloc_obj_add_info (obj , "DAXParent" , begin );
3745
3821
3746
3822
/*
0 commit comments