|
@@ -0,0 +1,95 @@
|
|
|
+/*
|
|
|
+ * arch/arm64/kernel/topology.c
|
|
|
+ *
|
|
|
+ * Copyright (C) 2011,2013,2014 Linaro Limited.
|
|
|
+ *
|
|
|
+ * Based on the arm32 version written by Vincent Guittot in turn based on
|
|
|
+ * arch/sh/kernel/topology.c
|
|
|
+ *
|
|
|
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
|
+ * License. See the file "COPYING" in the main directory of this archive
|
|
|
+ * for more details.
|
|
|
+ */
|
|
|
+
|
|
|
+#include <linux/cpu.h>
|
|
|
+#include <linux/cpumask.h>
|
|
|
+#include <linux/init.h>
|
|
|
+#include <linux/percpu.h>
|
|
|
+#include <linux/node.h>
|
|
|
+#include <linux/nodemask.h>
|
|
|
+#include <linux/sched.h>
|
|
|
+
|
|
|
+#include <asm/topology.h>
|
|
|
+
|
|
|
+/*
|
|
|
+ * cpu topology table
|
|
|
+ */
|
|
|
+struct cpu_topology cpu_topology[NR_CPUS];
|
|
|
+EXPORT_SYMBOL_GPL(cpu_topology);
|
|
|
+
|
|
|
+const struct cpumask *cpu_coregroup_mask(int cpu)
|
|
|
+{
|
|
|
+ return &cpu_topology[cpu].core_sibling;
|
|
|
+}
|
|
|
+
|
|
|
+static void update_siblings_masks(unsigned int cpuid)
|
|
|
+{
|
|
|
+ struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
|
|
|
+ int cpu;
|
|
|
+
|
|
|
+ if (cpuid_topo->cluster_id == -1) {
|
|
|
+ /*
|
|
|
+ * DT does not contain topology information for this cpu
|
|
|
+ * reset it to default behaviour
|
|
|
+ */
|
|
|
+ pr_debug("CPU%u: No topology information configured\n", cpuid);
|
|
|
+ cpuid_topo->core_id = 0;
|
|
|
+ cpumask_set_cpu(cpuid, &cpuid_topo->core_sibling);
|
|
|
+ cpumask_set_cpu(cpuid, &cpuid_topo->thread_sibling);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* update core and thread sibling masks */
|
|
|
+ for_each_possible_cpu(cpu) {
|
|
|
+ cpu_topo = &cpu_topology[cpu];
|
|
|
+
|
|
|
+ if (cpuid_topo->cluster_id != cpu_topo->cluster_id)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
|
|
|
+ if (cpu != cpuid)
|
|
|
+ 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);
|
|
|
+ if (cpu != cpuid)
|
|
|
+ cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void store_cpu_topology(unsigned int cpuid)
|
|
|
+{
|
|
|
+ update_siblings_masks(cpuid);
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * init_cpu_topology is called at boot when only one cpu is running
|
|
|
+ * which prevent simultaneous write access to cpu_topology array
|
|
|
+ */
|
|
|
+void __init init_cpu_topology(void)
|
|
|
+{
|
|
|
+ unsigned int cpu;
|
|
|
+
|
|
|
+ /* init core mask and power*/
|
|
|
+ for_each_possible_cpu(cpu) {
|
|
|
+ struct cpu_topology *cpu_topo = &cpu_topology[cpu];
|
|
|
+
|
|
|
+ cpu_topo->thread_id = -1;
|
|
|
+ cpu_topo->core_id = -1;
|
|
|
+ cpu_topo->cluster_id = -1;
|
|
|
+ cpumask_clear(&cpu_topo->core_sibling);
|
|
|
+ cpumask_clear(&cpu_topo->thread_sibling);
|
|
|
+ }
|
|
|
+}
|