diff --git a/hwloc/topology-x86.c b/hwloc/topology-x86.c index 55e1fcfab..78837862a 100644 --- a/hwloc/topology-x86.c +++ b/hwloc/topology-x86.c @@ -40,6 +40,7 @@ struct hwloc_x86_backend_data_s { char *src_cpuiddump_path; int is_knl; int is_hybrid; + int has_power_efficiency_ranking; int found_die_ids; int found_complex_ids; int found_unit_ids; @@ -232,6 +233,7 @@ struct procinfo { unsigned hybridcoretype; unsigned hybridnativemodel; + unsigned power_efficiency_ranking; }; enum cpuid_type { @@ -583,9 +585,44 @@ static void read_extended_topo(struct hwloc_x86_backend_data_s *data, struct pro id); infos->apicid = apic_id; infos->otherids[level] = UINT_MAX; +if (leaf == 0x80000026 && apic_id == 0) { + printf("HybridCPU info at level %u\n", apic_type); + printf(" AsymmetricCores = %u\n", (eax & 0x80000000)>>31); + printf(" HeteroCoreTyopology = %u\n", (eax & 0x40000000)>>30); + printf(" EffRankingAvailable = %u\n", (eax & 0x20000000)>>29); + printf(" CoreType = %u\n", (ebx >> 28) & 0xf); + printf(" Model = %u\n", (ebx >> 24) & 0xf); + printf(" EffRanking = %u\n", (ebx >> 16) & 0xff); +} switch (apic_type) { case 1: threadid = id; + if (leaf == 0x80000026) { + /* AMD 0x80000026 also reports more info about cores. + * bit eax[31] = "AsymmetricCores" = set if cores are asymmetric (different numbers of threads per core) + * => doesn't seem needed in hwloc. + */ + + if (eax & 0x40000000) { + /* HeterogeneousCoreTopology: + * When set, not all instances at the current hierarchy + * level have the same Core Type topology + */ + data->is_hybrid = 1; + } + + if (eax & 0x20000000) { + /* EfficiencyRankingAvailable */ + data->has_power_efficiency_ranking = 1; + /* "a core with a lower value has intrinsically better power, + * but potentially lower performance potential vs cores with a higher value." + */ + infos->power_efficiency_ranking = (ebx >> 16) & 0xff; + } + + infos->hybridcoretype = (ebx >> 28) & 0xf; /* 0 = P, 1 = E */ + infos->hybridnativemodel = (ebx >> 24) & 0xf; /* 0 = Zen4 */ + } break; case 2: infos->ids[CORE] = id; @@ -1413,10 +1450,8 @@ look_procs(struct hwloc_backend *backend, struct procinfo *infos, unsigned long if (data->apicid_unique) { summarize(backend, infos, flags); - if (data->is_hybrid - && !(topology->flags & HWLOC_TOPOLOGY_FLAG_NO_CPUKINDS)) { - /* use hybrid info for cpukinds */ - if (cpuid_type == intel) { + if (!(topology->flags & HWLOC_TOPOLOGY_FLAG_NO_CPUKINDS)) { + if (data->is_hybrid && cpuid_type == intel) { /* Hybrid Intel */ hwloc_bitmap_t atomset = hwloc_bitmap_alloc(); hwloc_bitmap_t coreset = hwloc_bitmap_alloc(); @@ -1454,6 +1489,75 @@ look_procs(struct hwloc_backend *backend, struct procinfo *infos, unsigned long } else { hwloc_bitmap_free(coreset); } + + } else if (data->is_hybrid && cpuid_type == amd) { + /* Hybrid AMD */ + hwloc_bitmap_t Pset = hwloc_bitmap_alloc(); + hwloc_bitmap_t Eset = hwloc_bitmap_alloc(); + for(i=0; ihas_power_efficiency_ranking && cpuid_type == amd) { + /* AMD Power Efficiency Ranking */ + hwloc_bitmap_t rankings = hwloc_bitmap_alloc(); + if (!rankings) { + fprintf(stderr, "[hwloc/x86/cpukinds] failed to allocated rankings bitmap.\n"); + } else { + /* list existing rankings */ + for(i=0; i 1) { + while (!hwloc_bitmap_iszero(rankings)) { + unsigned ranking = hwloc_bitmap_first(rankings); + hwloc_bitmap_t rankset = hwloc_bitmap_alloc(); + if (!rankset) { + fprintf(stderr, "[hwloc/x86/cpukinds] failed to allocated rankset bitmap.\n"); + break; + } else { + for(i=0; iis_knl = 0; data->is_hybrid = 0; + data->has_power_efficiency_ranking = 0; data->apicid_set = hwloc_bitmap_alloc(); data->apicid_unique = 1; data->src_cpuiddump_path = NULL;