linux/arch/arm64/kernel/topology.c
<<
>>
Prefs
   1/*
   2 * arch/arm64/kernel/topology.c
   3 *
   4 * Copyright (C) 2011,2013,2014 Linaro Limited.
   5 *
   6 * Based on the arm32 version written by Vincent Guittot in turn based on
   7 * arch/sh/kernel/topology.c
   8 *
   9 * This file is subject to the terms and conditions of the GNU General Public
  10 * License.  See the file "COPYING" in the main directory of this archive
  11 * for more details.
  12 */
  13
  14#include <linux/acpi.h>
  15#include <linux/arch_topology.h>
  16#include <linux/cacheinfo.h>
  17#include <linux/cpu.h>
  18#include <linux/cpumask.h>
  19#include <linux/init.h>
  20#include <linux/percpu.h>
  21#include <linux/node.h>
  22#include <linux/nodemask.h>
  23#include <linux/of.h>
  24#include <linux/sched.h>
  25#include <linux/sched/topology.h>
  26#include <linux/slab.h>
  27#include <linux/smp.h>
  28#include <linux/string.h>
  29
  30#include <asm/cpu.h>
  31#include <asm/cputype.h>
  32#include <asm/topology.h>
  33
  34static int __init get_cpu_for_node(struct device_node *node)
  35{
  36        struct device_node *cpu_node;
  37        int cpu;
  38
  39        cpu_node = of_parse_phandle(node, "cpu", 0);
  40        if (!cpu_node)
  41                return -1;
  42
  43        cpu = of_cpu_node_to_id(cpu_node);
  44        if (cpu >= 0)
  45                topology_parse_cpu_capacity(cpu_node, cpu);
  46        else
  47                pr_crit("Unable to find CPU node for %pOF\n", cpu_node);
  48
  49        of_node_put(cpu_node);
  50        return cpu;
  51}
  52
  53static int __init parse_core(struct device_node *core, int package_id,
  54                             int core_id)
  55{
  56        char name[10];
  57        bool leaf = true;
  58        int i = 0;
  59        int cpu;
  60        struct device_node *t;
  61
  62        do {
  63                snprintf(name, sizeof(name), "thread%d", i);
  64                t = of_get_child_by_name(core, name);
  65                if (t) {
  66                        leaf = false;
  67                        cpu = get_cpu_for_node(t);
  68                        if (cpu >= 0) {
  69                                cpu_topology[cpu].package_id = package_id;
  70                                cpu_topology[cpu].core_id = core_id;
  71                                cpu_topology[cpu].thread_id = i;
  72                        } else {
  73                                pr_err("%pOF: Can't get CPU for thread\n",
  74                                       t);
  75                                of_node_put(t);
  76                                return -EINVAL;
  77                        }
  78                        of_node_put(t);
  79                }
  80                i++;
  81        } while (t);
  82
  83        cpu = get_cpu_for_node(core);
  84        if (cpu >= 0) {
  85                if (!leaf) {
  86                        pr_err("%pOF: Core has both threads and CPU\n",
  87                               core);
  88                        return -EINVAL;
  89                }
  90
  91                cpu_topology[cpu].package_id = package_id;
  92                cpu_topology[cpu].core_id = core_id;
  93        } else if (leaf) {
  94                pr_err("%pOF: Can't get CPU for leaf core\n", core);
  95                return -EINVAL;
  96        }
  97
  98        return 0;
  99}
 100
 101static int __init parse_cluster(struct device_node *cluster, int depth)
 102{
 103        char name[10];
 104        bool leaf = true;
 105        bool has_cores = false;
 106        struct device_node *c;
 107        static int package_id __initdata;
 108        int core_id = 0;
 109        int i, ret;
 110
 111        /*
 112         * First check for child clusters; we currently ignore any
 113         * information about the nesting of clusters and present the
 114         * scheduler with a flat list of them.
 115         */
 116        i = 0;
 117        do {
 118                snprintf(name, sizeof(name), "cluster%d", i);
 119                c = of_get_child_by_name(cluster, name);
 120                if (c) {
 121                        leaf = false;
 122                        ret = parse_cluster(c, depth + 1);
 123                        of_node_put(c);
 124                        if (ret != 0)
 125                                return ret;
 126                }
 127                i++;
 128        } while (c);
 129
 130        /* Now check for cores */
 131        i = 0;
 132        do {
 133                snprintf(name, sizeof(name), "core%d", i);
 134                c = of_get_child_by_name(cluster, name);
 135                if (c) {
 136                        has_cores = true;
 137
 138                        if (depth == 0) {
 139                                pr_err("%pOF: cpu-map children should be clusters\n",
 140                                       c);
 141                                of_node_put(c);
 142                                return -EINVAL;
 143                        }
 144
 145                        if (leaf) {
 146                                ret = parse_core(c, package_id, core_id++);
 147                        } else {
 148                                pr_err("%pOF: Non-leaf cluster with core %s\n",
 149                                       cluster, name);
 150                                ret = -EINVAL;
 151                        }
 152
 153                        of_node_put(c);
 154                        if (ret != 0)
 155                                return ret;
 156                }
 157                i++;
 158        } while (c);
 159
 160        if (leaf && !has_cores)
 161                pr_warn("%pOF: empty cluster\n", cluster);
 162
 163        if (leaf)
 164                package_id++;
 165
 166        return 0;
 167}
 168
 169static int __init parse_dt_topology(void)
 170{
 171        struct device_node *cn, *map;
 172        int ret = 0;
 173        int cpu;
 174
 175        cn = of_find_node_by_path("/cpus");
 176        if (!cn) {
 177                pr_err("No CPU information found in DT\n");
 178                return 0;
 179        }
 180
 181        /*
 182         * When topology is provided cpu-map is essentially a root
 183         * cluster with restricted subnodes.
 184         */
 185        map = of_get_child_by_name(cn, "cpu-map");
 186        if (!map)
 187                goto out;
 188
 189        ret = parse_cluster(map, 0);
 190        if (ret != 0)
 191                goto out_map;
 192
 193        topology_normalize_cpu_scale();
 194
 195        /*
 196         * Check that all cores are in the topology; the SMP code will
 197         * only mark cores described in the DT as possible.
 198         */
 199        for_each_possible_cpu(cpu)
 200                if (cpu_topology[cpu].package_id == -1)
 201                        ret = -EINVAL;
 202
 203out_map:
 204        of_node_put(map);
 205out:
 206        of_node_put(cn);
 207        return ret;
 208}
 209
 210/*
 211 * cpu topology table
 212 */
 213struct cpu_topology cpu_topology[NR_CPUS];
 214EXPORT_SYMBOL_GPL(cpu_topology);
 215
 216const struct cpumask *cpu_coregroup_mask(int cpu)
 217{
 218        const cpumask_t *core_mask = &cpu_topology[cpu].core_sibling;
 219
 220        if (cpu_topology[cpu].llc_id != -1) {
 221                if (cpumask_subset(&cpu_topology[cpu].llc_siblings, core_mask))
 222                        core_mask = &cpu_topology[cpu].llc_siblings;
 223        }
 224
 225        return core_mask;
 226}
 227
 228static void update_siblings_masks(unsigned int cpuid)
 229{
 230        struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
 231        int cpu;
 232
 233        /* update core and thread sibling masks */
 234        for_each_possible_cpu(cpu) {
 235                cpu_topo = &cpu_topology[cpu];
 236
 237                if (cpuid_topo->llc_id == cpu_topo->llc_id) {
 238                        cpumask_set_cpu(cpu, &cpuid_topo->llc_siblings);
 239                        cpumask_set_cpu(cpuid, &cpu_topo->llc_siblings);
 240                }
 241
 242                if (cpuid_topo->package_id != cpu_topo->package_id)
 243                        continue;
 244
 245                cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
 246                if (cpu != cpuid)
 247                        cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
 248
 249                if (cpuid_topo->core_id != cpu_topo->core_id)
 250                        continue;
 251
 252                cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling);
 253                if (cpu != cpuid)
 254                        cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
 255        }
 256}
 257
 258void store_cpu_topology(unsigned int cpuid)
 259{
 260        struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
 261        u64 mpidr;
 262
 263        if (cpuid_topo->package_id != -1)
 264                goto topology_populated;
 265
 266        mpidr = read_cpuid_mpidr();
 267
 268        /* Uniprocessor systems can rely on default topology values */
 269        if (mpidr & MPIDR_UP_BITMASK)
 270                return;
 271
 272        /* Create cpu topology mapping based on MPIDR. */
 273        if (mpidr & MPIDR_MT_BITMASK) {
 274                /* Multiprocessor system : Multi-threads per core */
 275                cpuid_topo->thread_id  = MPIDR_AFFINITY_LEVEL(mpidr, 0);
 276                cpuid_topo->core_id    = MPIDR_AFFINITY_LEVEL(mpidr, 1);
 277                cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 2) |
 278                                         MPIDR_AFFINITY_LEVEL(mpidr, 3) << 8;
 279        } else {
 280                /* Multiprocessor system : Single-thread per core */
 281                cpuid_topo->thread_id  = -1;
 282                cpuid_topo->core_id    = MPIDR_AFFINITY_LEVEL(mpidr, 0);
 283                cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 1) |
 284                                         MPIDR_AFFINITY_LEVEL(mpidr, 2) << 8 |
 285                                         MPIDR_AFFINITY_LEVEL(mpidr, 3) << 16;
 286        }
 287
 288        pr_debug("CPU%u: cluster %d core %d thread %d mpidr %#016llx\n",
 289                 cpuid, cpuid_topo->package_id, cpuid_topo->core_id,
 290                 cpuid_topo->thread_id, mpidr);
 291
 292topology_populated:
 293        update_siblings_masks(cpuid);
 294}
 295
 296static void __init reset_cpu_topology(void)
 297{
 298        unsigned int cpu;
 299
 300        for_each_possible_cpu(cpu) {
 301                struct cpu_topology *cpu_topo = &cpu_topology[cpu];
 302
 303                cpu_topo->thread_id = -1;
 304                cpu_topo->core_id = 0;
 305                cpu_topo->package_id = -1;
 306
 307                cpu_topo->llc_id = -1;
 308                cpumask_clear(&cpu_topo->llc_siblings);
 309                cpumask_set_cpu(cpu, &cpu_topo->llc_siblings);
 310
 311                cpumask_clear(&cpu_topo->core_sibling);
 312                cpumask_set_cpu(cpu, &cpu_topo->core_sibling);
 313                cpumask_clear(&cpu_topo->thread_sibling);
 314                cpumask_set_cpu(cpu, &cpu_topo->thread_sibling);
 315        }
 316}
 317
 318#ifdef CONFIG_ACPI
 319/*
 320 * Propagate the topology information of the processor_topology_node tree to the
 321 * cpu_topology array.
 322 */
 323static int __init parse_acpi_topology(void)
 324{
 325        bool is_threaded;
 326        int cpu, topology_id;
 327
 328        is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK;
 329
 330        for_each_possible_cpu(cpu) {
 331                int i, cache_id;
 332
 333                topology_id = find_acpi_cpu_topology(cpu, 0);
 334                if (topology_id < 0)
 335                        return topology_id;
 336
 337                if (is_threaded) {
 338                        cpu_topology[cpu].thread_id = topology_id;
 339                        topology_id = find_acpi_cpu_topology(cpu, 1);
 340                        cpu_topology[cpu].core_id   = topology_id;
 341                } else {
 342                        cpu_topology[cpu].thread_id  = -1;
 343                        cpu_topology[cpu].core_id    = topology_id;
 344                }
 345                topology_id = find_acpi_cpu_topology_package(cpu);
 346                cpu_topology[cpu].package_id = topology_id;
 347
 348                i = acpi_find_last_cache_level(cpu);
 349
 350                if (i > 0) {
 351                        /*
 352                         * this is the only part of cpu_topology that has
 353                         * a direct relationship with the cache topology
 354                         */
 355                        cache_id = find_acpi_cpu_cache_topology(cpu, i);
 356                        if (cache_id > 0)
 357                                cpu_topology[cpu].llc_id = cache_id;
 358                }
 359        }
 360
 361        return 0;
 362}
 363
 364#else
 365static inline int __init parse_acpi_topology(void)
 366{
 367        return -EINVAL;
 368}
 369#endif
 370
 371void __init init_cpu_topology(void)
 372{
 373        reset_cpu_topology();
 374
 375        /*
 376         * Discard anything that was parsed if we hit an error so we
 377         * don't use partial information.
 378         */
 379        if (!acpi_disabled && parse_acpi_topology())
 380                reset_cpu_topology();
 381        else if (of_have_populated_dt() && parse_dt_topology())
 382                reset_cpu_topology();
 383}
 384