@@ -40,6 +40,7 @@ struct hwloc_x86_backend_data_s {
4040 char * src_cpuiddump_path ;
4141 int is_knl ;
4242 int is_hybrid ;
43+ int has_power_efficiency_ranking ;
4344 int found_die_ids ;
4445 int found_complex_ids ;
4546 int found_unit_ids ;
@@ -232,6 +233,7 @@ struct procinfo {
232233
233234 unsigned hybridcoretype ;
234235 unsigned hybridnativemodel ;
236+ unsigned power_efficiency_ranking ;
235237};
236238
237239enum cpuid_type {
@@ -586,6 +588,32 @@ static void read_extended_topo(struct hwloc_x86_backend_data_s *data, struct pro
586588 switch (apic_type ) {
587589 case 1 :
588590 threadid = id ;
591+ if (leaf == 0x80000026 ) {
592+ /* AMD 0x80000026 also reports more info about cores.
593+ * bit eax[31] = "AsymmetricCores" = set if cores are asymmetric (different numbers of threads per core)
594+ * => doesn't seem needed in hwloc.
595+ */
596+
597+ if (eax & 0x40000000 ) {
598+ /* HeterogeneousCoreTopology:
599+ * When set, not all instances at the current hierarchy
600+ * level have the same Core Type topology
601+ */
602+ data -> is_hybrid = 1 ;
603+ }
604+
605+ if (eax & 0x20000000 ) {
606+ /* EfficiencyRankingAvailable */
607+ data -> has_power_efficiency_ranking = 1 ;
608+ /* "a core with a lower value has intrinsically better power,
609+ * but potentially lower performance potential vs cores with a higher value."
610+ */
611+ infos -> power_efficiency_ranking = (ebx >> 16 ) & 0xff ;
612+ }
613+
614+ infos -> hybridcoretype = (ebx >> 28 ) & 0xf ; /* 0 = P, 1 = E */
615+ infos -> hybridnativemodel = (ebx >> 24 ) & 0xf ; /* 0 = Zen4 */
616+ }
589617 break ;
590618 case 2 :
591619 infos -> ids [CORE ] = id ;
@@ -1413,10 +1441,8 @@ look_procs(struct hwloc_backend *backend, struct procinfo *infos, unsigned long
14131441 if (data -> apicid_unique ) {
14141442 summarize (backend , infos , flags );
14151443
1416- if (data -> is_hybrid
1417- && !(topology -> flags & HWLOC_TOPOLOGY_FLAG_NO_CPUKINDS )) {
1418- /* use hybrid info for cpukinds */
1419- if (cpuid_type == intel ) {
1444+ if (!(topology -> flags & HWLOC_TOPOLOGY_FLAG_NO_CPUKINDS )) {
1445+ if (data -> is_hybrid && cpuid_type == intel ) {
14201446 /* Hybrid Intel */
14211447 hwloc_bitmap_t atomset = hwloc_bitmap_alloc ();
14221448 hwloc_bitmap_t coreset = hwloc_bitmap_alloc ();
@@ -1454,6 +1480,75 @@ look_procs(struct hwloc_backend *backend, struct procinfo *infos, unsigned long
14541480 } else {
14551481 hwloc_bitmap_free (coreset );
14561482 }
1483+
1484+ } else if (data -> is_hybrid && cpuid_type == amd ) {
1485+ /* Hybrid AMD */
1486+ hwloc_bitmap_t Pset = hwloc_bitmap_alloc ();
1487+ hwloc_bitmap_t Eset = hwloc_bitmap_alloc ();
1488+ for (i = 0 ; i < nbprocs ; i ++ ) {
1489+ if (infos [i ].hybridcoretype == 0x0 )
1490+ hwloc_bitmap_set (Pset , i );
1491+ else if (infos [i ].hybridcoretype == 0x1 )
1492+ hwloc_bitmap_set (Eset , i );
1493+ }
1494+ /* register AMD-ECore set if any */
1495+ if (!hwloc_bitmap_iszero (Eset )) {
1496+ struct hwloc_infos_s _infos ;
1497+ struct hwloc_info_s infoattr ;
1498+ infoattr .name = (char * ) "CoreType" ;
1499+ infoattr .value = (char * ) "AMD-ECore" ;
1500+ _infos .array = & infoattr ;
1501+ _infos .count = 1 ;
1502+ _infos .allocated = 0 ;
1503+ hwloc_internal_cpukinds_register (topology , Eset , HWLOC_CPUKIND_EFFICIENCY_UNKNOWN , & _infos , 0 );
1504+ /* the cpuset is given to the callee */
1505+ } else {
1506+ hwloc_bitmap_free (Eset );
1507+ }
1508+ /* register AMD-PCore set if any */
1509+ if (!hwloc_bitmap_iszero (Pset )) {
1510+ struct hwloc_infos_s _infos ;
1511+ struct hwloc_info_s infoattr ;
1512+ infoattr .name = (char * ) "CoreType" ;
1513+ infoattr .value = (char * ) "AMD-PCore" ;
1514+ _infos .array = & infoattr ;
1515+ _infos .count = 1 ;
1516+ _infos .allocated = 0 ;
1517+ hwloc_internal_cpukinds_register (topology , Pset , HWLOC_CPUKIND_EFFICIENCY_UNKNOWN , & _infos , 0 );
1518+ /* the cpuset is given to the callee */
1519+ } else {
1520+ hwloc_bitmap_free (Pset );
1521+ }
1522+ }
1523+
1524+ if (data -> has_power_efficiency_ranking && cpuid_type == amd ) {
1525+ /* AMD Power Efficiency Ranking */
1526+ hwloc_bitmap_t rankings = hwloc_bitmap_alloc ();
1527+ if (!rankings ) {
1528+ fprintf (stderr , "[hwloc/x86/cpukinds] failed to allocated rankings bitmap.\n" );
1529+ } else {
1530+ /* list existing rankings */
1531+ for (i = 0 ; i < nbprocs ; i ++ )
1532+ hwloc_bitmap_set (rankings , infos [i ].power_efficiency_ranking );
1533+ if (hwloc_bitmap_weight (rankings ) > 1 ) {
1534+ while (!hwloc_bitmap_iszero (rankings )) {
1535+ unsigned ranking = hwloc_bitmap_first (rankings );
1536+ hwloc_bitmap_t rankset = hwloc_bitmap_alloc ();
1537+ if (!rankset ) {
1538+ fprintf (stderr , "[hwloc/x86/cpukinds] failed to allocated rankset bitmap.\n" );
1539+ break ;
1540+ } else {
1541+ for (i = 0 ; i < nbprocs ; i ++ )
1542+ if (infos [i ].power_efficiency_ranking == (unsigned ) ranking )
1543+ hwloc_bitmap_set (rankset , i );
1544+ hwloc_internal_cpukinds_register (topology , rankset , ranking , NULL , 0 );
1545+ /* the cpuset is given to the callee */
1546+ }
1547+ hwloc_bitmap_clr (rankings , ranking );
1548+ }
1549+ }
1550+ hwloc_bitmap_free (rankings );
1551+ }
14571552 }
14581553 }
14591554 } else {
@@ -1896,6 +1991,7 @@ hwloc_x86_component_instantiate(struct hwloc_topology *topology,
18961991 data = HWLOC_BACKEND_PRIVATE_DATA (backend );
18971992 data -> is_knl = 0 ;
18981993 data -> is_hybrid = 0 ;
1994+ data -> has_power_efficiency_ranking = 0 ;
18991995 data -> apicid_set = hwloc_bitmap_alloc ();
19001996 data -> apicid_unique = 1 ;
19011997 data -> src_cpuiddump_path = NULL ;
0 commit comments