Skip to content

Commit

Permalink
x86: use the hybrid leaf to build a cpukinds based on the core type
Browse files Browse the repository at this point in the history
Signed-off-by: Brice Goglin <Brice.Goglin@inria.fr>
  • Loading branch information
bgoglin committed Nov 19, 2020
1 parent 03560bf commit 22ca5a8
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 4 deletions.
1 change: 1 addition & 0 deletions NEWS
Expand Up @@ -21,6 +21,7 @@ Version 2.4.0
-------------
* API
+ Add hwloc/cpukinds.h for reporting information about hybrid CPUs.
- Use x86 CPUID hybrid leaf to identify Intel Atom and Core cores.
* Backends
+ Properly handle Linux kernel 5.10+ exposing ACPI HMAT information
with knowledge of Generic Initiators.
Expand Down
51 changes: 49 additions & 2 deletions hwloc/topology-x86.c
Expand Up @@ -181,6 +181,7 @@ enum hwloc_x86_disc_flags {

#define has_topoext(features) ((features)[6] & (1 << 22))
#define has_x2apic(features) ((features)[4] & (1 << 21))
#define has_hybrid(features) ((features)[18] & (1 << 15))

struct cacheinfo {
hwloc_obj_cache_type_t type;
Expand Down Expand Up @@ -217,6 +218,9 @@ struct procinfo {
unsigned cpustepping;
unsigned cpumodelnumber;
unsigned cpufamilynumber;

unsigned hybridcoretype;
unsigned hybridnativemodel;
};

enum cpuid_type {
Expand Down Expand Up @@ -681,6 +685,15 @@ static void look_proc(struct hwloc_backend *backend, struct procinfo *infos, uns
}
}

if (highest_cpuid >= 0x1a && has_hybrid(features)) {
/* Get hybrid cpu information from cpuid 0x1a */
eax = 0x1a;
ecx = 0;
cpuid_or_from_dump(&eax, &ebx, &ecx, &edx, src_cpuiddump);
infos->hybridcoretype = eax >> 24;
infos->hybridnativemodel = eax & 0xffffff;
}

/*********************************************************************************
* Get the hierarchy of thread, core, die, package, etc. from CPU-specific leaves
*/
Expand Down Expand Up @@ -1280,8 +1293,41 @@ look_procs(struct hwloc_backend *backend, struct procinfo *infos, unsigned long
hwloc_bitmap_free(orig_cpuset);
}

if (data->apicid_unique)
if (data->apicid_unique) {
summarize(backend, infos, flags);

if (has_hybrid(features)) {
/* use hybrid info for cpukinds */
hwloc_bitmap_t atomset = hwloc_bitmap_alloc();
hwloc_bitmap_t coreset = hwloc_bitmap_alloc();
for(i=0; i<nbprocs; i++) {
if (infos[i].hybridcoretype == 0x20)
hwloc_bitmap_set(atomset, i);
else if (infos[i].hybridcoretype == 0x40)
hwloc_bitmap_set(coreset, i);
}
/* register IntelAtom set if any */
if (!hwloc_bitmap_iszero(atomset)) {
struct hwloc_info_s infoattr;
infoattr.name = (char *) "CoreType";
infoattr.value = (char *) "IntelAtom";
hwloc_internal_cpukinds_register(topology, atomset, HWLOC_CPUKIND_EFFICIENCY_UNKNOWN, &infoattr, 1, 0);
/* the cpuset is given to the callee */
} else {
hwloc_bitmap_free(atomset);
}
/* register IntelCore set if any */
if (!hwloc_bitmap_iszero(coreset)) {
struct hwloc_info_s infoattr;
infoattr.name = (char *) "CoreType";
infoattr.value = (char *) "IntelCore";
hwloc_internal_cpukinds_register(topology, coreset, HWLOC_CPUKIND_EFFICIENCY_UNKNOWN, &infoattr, 1, 0);
/* the cpuset is given to the callee */
} else {
hwloc_bitmap_free(coreset);
}
}
}
/* if !data->apicid_unique, do nothing and return success, so that the caller does nothing either */

return 0;
Expand Down Expand Up @@ -1360,7 +1406,7 @@ int hwloc_look_x86(struct hwloc_backend *backend, unsigned long flags)
unsigned highest_cpuid;
unsigned highest_ext_cpuid;
/* This stores cpuid features with the same indexing as Linux */
unsigned features[10] = { 0 };
unsigned features[19] = { 0 };
struct procinfo *infos = NULL;
enum cpuid_type cpuid_type = unknown;
hwloc_x86_os_state_t os_state;
Expand Down Expand Up @@ -1460,6 +1506,7 @@ int hwloc_look_x86(struct hwloc_backend *backend, unsigned long flags)
ecx = 0;
cpuid_or_from_dump(&eax, &ebx, &ecx, &edx, src_cpuiddump);
features[9] = ebx;
features[18] = edx;
}

if (cpuid_type != intel && highest_ext_cpuid >= 0x80000001) {
Expand Down
4 changes: 2 additions & 2 deletions include/hwloc/cpukinds.h
Expand Up @@ -36,7 +36,7 @@ extern "C" {
* may be obtained with hwloc_cpukinds_get_by_cpuset().
*
* Each set is described by an abstracted efficiency value and
* an array of info attributes.
* an array of info attributes (for instance the "CoreType").
*
* A higher efficiency value means intrinsic greater performance
* (and possibly less performance/power efficiency).
Expand Down Expand Up @@ -99,7 +99,7 @@ hwloc_cpukinds_get_by_cpuset(hwloc_topology_t topology,
* the efficiency of all kinds is set to \c -1,
* and kinds are reported in no specific order.
*
* The array of info attributes
* The array of info attributes (for instance the "CoreType")
* and its length are returned in \p infos or \p nr_infos.
* The array belongs to the topology, it should not be freed or modified.
*
Expand Down

0 comments on commit 22ca5a8

Please sign in to comment.