152 lines
3.6 KiB
C
152 lines
3.6 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
#include <linux/acpi.h>
|
|
#include <linux/of.h>
|
|
|
|
#include <asm/topology.h>
|
|
|
|
static int __init parse_dt_topology(void)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* cpu topology table
|
|
*/
|
|
struct cpu_topology cpu_topology[NR_CPUS];
|
|
EXPORT_SYMBOL_GPL(cpu_topology);
|
|
|
|
const struct cpumask *cpu_coregroup_mask(int cpu)
|
|
{
|
|
const cpumask_t *core_mask = cpumask_of_node(cpu_to_node(cpu));
|
|
|
|
/* Find the smaller of NUMA, core or LLC siblings */
|
|
if (cpumask_subset(&cpu_topology[cpu].core_sibling, core_mask)) {
|
|
/* not numa in package, lets use the package siblings */
|
|
core_mask = &cpu_topology[cpu].core_sibling;
|
|
}
|
|
if (cpu_topology[cpu].llc_id != -1) {
|
|
if (cpumask_subset(&cpu_topology[cpu].llc_sibling, core_mask))
|
|
core_mask = &cpu_topology[cpu].llc_sibling;
|
|
}
|
|
|
|
return core_mask;
|
|
}
|
|
|
|
static void update_siblings_masks(int cpuid)
|
|
{
|
|
struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
|
|
int cpu;
|
|
|
|
/* update core and thread sibling masks */
|
|
for_each_online_cpu(cpu) {
|
|
cpu_topo = &cpu_topology[cpu];
|
|
|
|
if (cpuid_topo->llc_id == cpu_topo->llc_id) {
|
|
cpumask_set_cpu(cpu, &cpuid_topo->llc_sibling);
|
|
cpumask_set_cpu(cpuid, &cpu_topo->llc_sibling);
|
|
}
|
|
|
|
if (cpuid_topo->package_id != cpu_topo->package_id)
|
|
continue;
|
|
|
|
cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
|
|
cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
|
|
|
|
if (cpuid_topo->core_id != cpu_topo->core_id)
|
|
continue;
|
|
|
|
cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling);
|
|
cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
|
|
}
|
|
}
|
|
|
|
void store_cpu_topology(int cpuid)
|
|
{
|
|
struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
|
|
|
|
if (cpuid_topo->package_id != -1)
|
|
goto topology_populated;
|
|
|
|
cpuid_topo->core_id = cpu_to_rcid(cpuid) & CORE_ID_MASK;
|
|
cpuid_topo->package_id = rcid_to_package(cpu_to_rcid(cpuid));
|
|
cpuid_topo->llc_id = rcid_to_package(cpuid);
|
|
cpuid_topo->thread_id = (cpu_to_rcid(cpuid) >> THREAD_ID_SHIFT) & THREAD_ID_MASK;
|
|
|
|
pr_debug("CPU%u: socket %d core %d thread %d\n",
|
|
cpuid, cpuid_topo->package_id, cpuid_topo->core_id,
|
|
cpuid_topo->thread_id);
|
|
|
|
topology_populated:
|
|
update_siblings_masks(cpuid);
|
|
}
|
|
|
|
static void clear_cpu_topology(int cpu)
|
|
{
|
|
struct cpu_topology *cpu_topo = &cpu_topology[cpu];
|
|
|
|
cpumask_clear(&cpu_topo->llc_sibling);
|
|
cpumask_set_cpu(cpu, &cpu_topo->llc_sibling);
|
|
|
|
cpumask_clear(&cpu_topo->core_sibling);
|
|
cpumask_set_cpu(cpu, &cpu_topo->core_sibling);
|
|
cpumask_clear(&cpu_topo->thread_sibling);
|
|
cpumask_set_cpu(cpu, &cpu_topo->thread_sibling);
|
|
}
|
|
|
|
static void __init reset_cpu_topology(void)
|
|
{
|
|
int cpu;
|
|
|
|
for_each_possible_cpu(cpu) {
|
|
struct cpu_topology *cpu_topo = &cpu_topology[cpu];
|
|
|
|
cpu_topo->thread_id = -1;
|
|
cpu_topo->core_id = 0;
|
|
cpu_topo->package_id = -1;
|
|
cpu_topo->llc_id = -1;
|
|
|
|
clear_cpu_topology(cpu);
|
|
}
|
|
}
|
|
|
|
void remove_cpu_topology(int cpu)
|
|
{
|
|
int sibling;
|
|
|
|
for_each_cpu(sibling, topology_core_cpumask(cpu))
|
|
cpumask_clear_cpu(cpu, topology_core_cpumask(sibling));
|
|
for_each_cpu(sibling, topology_sibling_cpumask(cpu))
|
|
cpumask_clear_cpu(cpu, topology_sibling_cpumask(sibling));
|
|
for_each_cpu(sibling, topology_llc_cpumask(cpu))
|
|
cpumask_clear_cpu(cpu, topology_llc_cpumask(sibling));
|
|
|
|
clear_cpu_topology(cpu);
|
|
}
|
|
|
|
#ifdef CONFIG_ACPI
|
|
static int __init parse_acpi_topology(void)
|
|
{
|
|
return 0;
|
|
}
|
|
#else
|
|
static inline int __init parse_acpi_topology(void)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
#endif
|
|
|
|
void __init init_cpu_topology(void)
|
|
{
|
|
reset_cpu_topology();
|
|
|
|
/*
|
|
* Discard anything that was parsed if we hit an error so we
|
|
* don't use partial information.
|
|
*/
|
|
if (!acpi_disabled && parse_acpi_topology())
|
|
reset_cpu_topology();
|
|
else if (of_have_populated_dt() && parse_dt_topology())
|
|
reset_cpu_topology();
|
|
}
|