Skip to content

Commit fcd2620

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 c2b03ae commit fcd2620

File tree

1 file changed

+93
-4
lines changed

1 file changed

+93
-4
lines changed

hwloc/topology-x86.c

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

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

Comments
 (0)