Skip to content

Commit 68df568

Browse files
committed
x86: build cpukinds from AMD CPUID leaf 0x80000026
Use coretype to build "AMD-ECore" and "AMD-Pcore" kinds. Use power efficiency rankings to build kinds with native efficiencies. Signed-off-by: Brice Goglin <[email protected]>
1 parent cacc5c3 commit 68df568

File tree

1 file changed

+100
-4
lines changed

1 file changed

+100
-4
lines changed

hwloc/topology-x86.c

Lines changed: 100 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

237239
enum 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

Comments
 (0)