@@ -39,6 +39,7 @@ struct hwloc_x86_backend_data_s {
3939 char * src_cpuiddump_path ;
4040 int is_knl ;
4141 int is_hybrid ;
42+ int has_power_efficiency_ranking ;
4243 int found_die_ids ;
4344 int found_complex_ids ;
4445 int found_unit_ids ;
@@ -231,6 +232,7 @@ struct procinfo {
231232
232233 unsigned hybridcoretype ;
233234 unsigned hybridnativemodel ;
235+ unsigned power_efficiency_ranking ;
234236};
235237
236238enum cpuid_type {
@@ -581,6 +583,32 @@ static void read_extended_topo(struct hwloc_x86_backend_data_s *data, struct pro
581583 switch (apic_type ) {
582584 case 1 :
583585 threadid = id ;
586+ if (leaf == 0x80000026 ) {
587+ /* AMD 0x80000026 also reports more info about cores.
588+ * bit eax[31] = "AsymmetricCores" = set if cores are asymmetric (different numbers of threads per core)
589+ * => doesn't seem needed in hwloc.
590+ */
591+
592+ if (eax & 0x40000000 ) {
593+ /* HeterogeneousCoreTopology:
594+ * When set, not all instances at the current hierarchy
595+ * level have the same Core Type topology
596+ */
597+ data -> is_hybrid = 1 ;
598+ }
599+
600+ if (eax & 0x20000000 ) {
601+ /* EfficiencyRankingAvailable */
602+ data -> has_power_efficiency_ranking = 1 ;
603+ /* "a core with a lower value has intrinsically better power,
604+ * but potentially lower performance potential vs cores with a higher value."
605+ */
606+ infos -> power_efficiency_ranking = (ebx >> 16 & 0xff );
607+ }
608+
609+ infos -> hybridcoretype = (ebx >> 28 ) & 0xf ; /* 0 = P, 1 = E */
610+ infos -> hybridnativemodel = (ebx >> 24 ) & 0xf ; /* 0 = Zen4 */
611+ }
584612 break ;
585613 case 2 :
586614 infos -> ids [CORE ] = id ;
@@ -1405,10 +1433,8 @@ look_procs(struct hwloc_backend *backend, struct procinfo *infos, unsigned long
14051433 if (data -> apicid_unique ) {
14061434 summarize (backend , infos , flags );
14071435
1408- if (data -> is_hybrid
1409- && !(topology -> flags & HWLOC_TOPOLOGY_FLAG_NO_CPUKINDS )) {
1410- /* use hybrid info for cpukinds */
1411- if (cpuid_type == intel ) {
1436+ if (!(topology -> flags & HWLOC_TOPOLOGY_FLAG_NO_CPUKINDS )) {
1437+ if (data -> is_hybrid && cpuid_type == intel ) {
14121438 /* Hybrid Intel */
14131439 hwloc_bitmap_t atomset = hwloc_bitmap_alloc ();
14141440 hwloc_bitmap_t coreset = hwloc_bitmap_alloc ();
@@ -1438,9 +1464,71 @@ look_procs(struct hwloc_backend *backend, struct procinfo *infos, unsigned long
14381464 } else {
14391465 hwloc_bitmap_free (coreset );
14401466 }
1467+
1468+ } else if (data -> is_hybrid && cpuid_type == amd ) {
1469+ /* Hybrid AMD */
1470+ hwloc_bitmap_t Pset = hwloc_bitmap_alloc ();
1471+ hwloc_bitmap_t Eset = hwloc_bitmap_alloc ();
1472+ for (i = 0 ; i < nbprocs ; i ++ ) {
1473+ if (infos [i ].hybridcoretype == 0x0 )
1474+ hwloc_bitmap_set (Pset , i );
1475+ else if (infos [i ].hybridcoretype == 0x1 )
1476+ hwloc_bitmap_set (Eset , i );
1477+ }
1478+ /* register AMD-ECore set if any */
1479+ if (!hwloc_bitmap_iszero (Eset )) {
1480+ struct hwloc_info_s infoattr ;
1481+ infoattr .name = (char * ) "CoreType" ;
1482+ infoattr .value = (char * ) "AMD-ECore" ;
1483+ hwloc_internal_cpukinds_register (topology , Eset , HWLOC_CPUKIND_EFFICIENCY_UNKNOWN , & infoattr , 1 , 0 );
1484+ /* the cpuset is given to the callee */
1485+ } else {
1486+ hwloc_bitmap_free (Eset );
1487+ }
1488+ /* register AMD-PCore set if any */
1489+ if (!hwloc_bitmap_iszero (Pset )) {
1490+ struct hwloc_info_s infoattr ;
1491+ infoattr .name = (char * ) "CoreType" ;
1492+ infoattr .value = (char * ) "AMD-PCore" ;
1493+ hwloc_internal_cpukinds_register (topology , Pset , HWLOC_CPUKIND_EFFICIENCY_UNKNOWN , & infoattr , 1 , 0 );
1494+ /* the cpuset is given to the callee */
1495+ } else {
1496+ hwloc_bitmap_free (Pset );
1497+ }
1498+ }
1499+
1500+ if (data -> has_power_efficiency_ranking && cpuid_type == amd ) {
1501+ /* AMD Power Efficiency Ranking */
1502+ hwloc_bitmap_t rankings = hwloc_bitmap_alloc ();
1503+ if (!rankings ) {
1504+ fprintf (stderr , "[hwloc/x86/cpukinds] failed to allocated rankings bitmap.\n" );
1505+ } else {
1506+ /* list existing rankings */
1507+ for (i = 0 ; i < nbprocs ; i ++ )
1508+ hwloc_bitmap_set (rankings , infos [i ].power_efficiency_ranking );
1509+ if (hwloc_bitmap_weight (rankings ) > 1 ) {
1510+ while (!hwloc_bitmap_iszero (rankings )) {
1511+ unsigned ranking = hwloc_bitmap_first (rankings );
1512+ hwloc_bitmap_t rankset = hwloc_bitmap_alloc ();
1513+ if (!rankset ) {
1514+ fprintf (stderr , "[hwloc/x86/cpukinds] failed to allocated rankset bitmap.\n" );
1515+ break ;
1516+ } else {
1517+ for (i = 0 ; i < nbprocs ; i ++ )
1518+ if (infos [i ].power_efficiency_ranking == (unsigned ) ranking )
1519+ hwloc_bitmap_set (rankset , i );
1520+ hwloc_internal_cpukinds_register (topology , rankset , ranking , NULL , 0 , 0 );
1521+ /* the cpuset is given to the callee */
1522+ }
1523+ hwloc_bitmap_clr (rankings , ranking );
1524+ }
1525+ }
1526+ hwloc_bitmap_free (rankings );
1527+ }
14411528 }
14421529 }
14431530 }
1531+
14441532 /* if !data->apicid_unique, do nothing and return success, so that the caller does nothing either */
14451533
14461534 return 0 ;
@@ -1886,6 +1974,7 @@ hwloc_x86_component_instantiate(struct hwloc_topology *topology,
18861974 /* default values */
18871975 data -> is_knl = 0 ;
18881976 data -> is_hybrid = 0 ;
1977+ data -> has_power_efficiency_ranking = 0 ;
18891978 data -> apicid_set = hwloc_bitmap_alloc ();
18901979 data -> apicid_unique = 1 ;
18911980 data -> src_cpuiddump_path = NULL ;
0 commit comments