Merge branch 'x86-topology-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 topology updates from Ingo Molnar: "Implement multi-die topology support on Intel CPUs and expose the die topology to user-space tooling, by Len Brown, Kan Liang and Zhang Rui. These changes should have no effect on the kernel's existing understanding of topologies, i.e. there should be no behavioral impact on cache, NUMA, scheduler, perf and other topologies and overall system performance" * 'x86-topology-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/x86/intel/rapl: Cosmetic rename internal variables in response to multi-die/pkg support perf/x86/intel/uncore: Cosmetic renames in response to multi-die/pkg support hwmon/coretemp: Cosmetic: Rename internal variables to zones from packages thermal/x86_pkg_temp_thermal: Cosmetic: Rename internal variables to zones from packages perf/x86/intel/cstate: Support multi-die/package perf/x86/intel/rapl: Support multi-die/package perf/x86/intel/uncore: Support multi-die/package topology: Create core_cpus and die_cpus sysfs attributes topology: Create package_cpus sysfs attribute hwmon/coretemp: Support multi-die/package powercap/intel_rapl: Update RAPL domain name and debug messages thermal/x86_pkg_temp_thermal: Support multi-die/package powercap/intel_rapl: Support multi-die/package powercap/intel_rapl: Simplify rapl_find_package() x86/topology: Define topology_logical_die_id() x86/topology: Define topology_die_id() cpu/topology: Export die_id x86/topology: Create topology_max_die_per_package() x86/topology: Add CPUID.1F multi-die/package support
This commit is contained in:
@@ -1322,6 +1322,7 @@ static void validate_apic_and_package_id(struct cpuinfo_x86 *c)
|
||||
cpu, apicid, c->initial_apicid);
|
||||
}
|
||||
BUG_ON(topology_update_package_map(c->phys_proc_id, cpu));
|
||||
BUG_ON(topology_update_die_map(c->cpu_die_id, cpu));
|
||||
#else
|
||||
c->logical_proc_id = 0;
|
||||
#endif
|
||||
|
@@ -15,33 +15,66 @@
|
||||
/* leaf 0xb SMT level */
|
||||
#define SMT_LEVEL 0
|
||||
|
||||
/* leaf 0xb sub-leaf types */
|
||||
/* extended topology sub-leaf types */
|
||||
#define INVALID_TYPE 0
|
||||
#define SMT_TYPE 1
|
||||
#define CORE_TYPE 2
|
||||
#define DIE_TYPE 5
|
||||
|
||||
#define LEAFB_SUBTYPE(ecx) (((ecx) >> 8) & 0xff)
|
||||
#define BITS_SHIFT_NEXT_LEVEL(eax) ((eax) & 0x1f)
|
||||
#define LEVEL_MAX_SIBLINGS(ebx) ((ebx) & 0xffff)
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned int __max_die_per_package __read_mostly = 1;
|
||||
EXPORT_SYMBOL(__max_die_per_package);
|
||||
|
||||
/*
|
||||
* Check if given CPUID extended toplogy "leaf" is implemented
|
||||
*/
|
||||
static int check_extended_topology_leaf(int leaf)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
|
||||
cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Return best CPUID Extended Toplogy Leaf supported
|
||||
*/
|
||||
static int detect_extended_topology_leaf(struct cpuinfo_x86 *c)
|
||||
{
|
||||
if (c->cpuid_level >= 0x1f) {
|
||||
if (check_extended_topology_leaf(0x1f) == 0)
|
||||
return 0x1f;
|
||||
}
|
||||
|
||||
if (c->cpuid_level >= 0xb) {
|
||||
if (check_extended_topology_leaf(0xb) == 0)
|
||||
return 0xb;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int detect_extended_topology_early(struct cpuinfo_x86 *c)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
int leaf;
|
||||
|
||||
if (c->cpuid_level < 0xb)
|
||||
return -1;
|
||||
|
||||
cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
/*
|
||||
* check if the cpuid leaf 0xb is actually implemented.
|
||||
*/
|
||||
if (ebx == 0 || (LEAFB_SUBTYPE(ecx) != SMT_TYPE))
|
||||
leaf = detect_extended_topology_leaf(c);
|
||||
if (leaf < 0)
|
||||
return -1;
|
||||
|
||||
set_cpu_cap(c, X86_FEATURE_XTOPOLOGY);
|
||||
|
||||
cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
|
||||
/*
|
||||
* initial apic id, which also represents 32-bit extended x2apic id.
|
||||
*/
|
||||
@@ -52,7 +85,7 @@ int detect_extended_topology_early(struct cpuinfo_x86 *c)
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for extended topology enumeration cpuid leaf 0xb and if it
|
||||
* Check for extended topology enumeration cpuid leaf, and if it
|
||||
* exists, use it for populating initial_apicid and cpu topology
|
||||
* detection.
|
||||
*/
|
||||
@@ -60,22 +93,28 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned int eax, ebx, ecx, edx, sub_index;
|
||||
unsigned int ht_mask_width, core_plus_mask_width;
|
||||
unsigned int ht_mask_width, core_plus_mask_width, die_plus_mask_width;
|
||||
unsigned int core_select_mask, core_level_siblings;
|
||||
unsigned int die_select_mask, die_level_siblings;
|
||||
int leaf;
|
||||
|
||||
if (detect_extended_topology_early(c) < 0)
|
||||
leaf = detect_extended_topology_leaf(c);
|
||||
if (leaf < 0)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Populate HT related information from sub-leaf level 0.
|
||||
*/
|
||||
cpuid_count(0xb, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
|
||||
cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx);
|
||||
c->initial_apicid = edx;
|
||||
core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
|
||||
core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
|
||||
die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
|
||||
die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
|
||||
|
||||
sub_index = 1;
|
||||
do {
|
||||
cpuid_count(0xb, sub_index, &eax, &ebx, &ecx, &edx);
|
||||
cpuid_count(leaf, sub_index, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
/*
|
||||
* Check for the Core type in the implemented sub leaves.
|
||||
@@ -83,23 +122,34 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
|
||||
if (LEAFB_SUBTYPE(ecx) == CORE_TYPE) {
|
||||
core_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
|
||||
core_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
|
||||
break;
|
||||
die_level_siblings = core_level_siblings;
|
||||
die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
|
||||
}
|
||||
if (LEAFB_SUBTYPE(ecx) == DIE_TYPE) {
|
||||
die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
|
||||
die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
|
||||
}
|
||||
|
||||
sub_index++;
|
||||
} while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE);
|
||||
|
||||
core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width;
|
||||
die_select_mask = (~(-1 << die_plus_mask_width)) >>
|
||||
core_plus_mask_width;
|
||||
|
||||
c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid, ht_mask_width)
|
||||
& core_select_mask;
|
||||
c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, core_plus_mask_width);
|
||||
c->cpu_core_id = apic->phys_pkg_id(c->initial_apicid,
|
||||
ht_mask_width) & core_select_mask;
|
||||
c->cpu_die_id = apic->phys_pkg_id(c->initial_apicid,
|
||||
core_plus_mask_width) & die_select_mask;
|
||||
c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid,
|
||||
die_plus_mask_width);
|
||||
/*
|
||||
* Reinit the apicid, now that we have extended initial_apicid.
|
||||
*/
|
||||
c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
|
||||
|
||||
c->x86_max_cores = (core_level_siblings / smp_num_siblings);
|
||||
__max_die_per_package = (die_level_siblings / core_level_siblings);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user