Power aware scheduling needs the cpu topology information to improve the
cpu scheduler decision making. sched_mc and sched_smt will use the topology
information.
For ARM64, we can get the topology from the MPIDR register which defines the
the affinity of processors.
This patch is mainly based on arch/arm/kernel/topology.c written by
Vincent Guittot, and replaced the topology array with per cpu variable.
v2:
Make the changelog easier to understand.
Use 'u64' for MPIDR value on arm64.
Some typo fix.
v3:
Rebased the patch on the latest linaro acpi git tree.
Put store_cpu_topology(cpu) before set_cpu_online(cpu, true) to make
the system boot without problem.
Signed-off-by: Hanjun Guo <hanjun.guo(a)linaro.org>
---
arch/arm64/Kconfig | 25 ++++++++
arch/arm64/include/asm/cputype.h | 11 ++++
arch/arm64/include/asm/topology.h | 35 +++++++++++
arch/arm64/kernel/Makefile | 5 +-
arch/arm64/kernel/smp.c | 6 ++
arch/arm64/kernel/topology.c | 120 +++++++++++++++++++++++++++++++++++++
6 files changed, 198 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index ae80184..b0fd1aa 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -150,6 +150,31 @@ config SMP
If you don't know what to do here, say N.
+config ARM64_CPU_TOPOLOGY
+ bool "Support cpu topology definition"
+ depends on SMP && ARM64
+ default y
+ help
+ Support ARM64 cpu topology definition. The MPIDR register defines
+ affinity between processors which is then used to describe the cpu
+ topology of an ARM64 System.
+
+config SCHED_MC
+ bool "Multi-core scheduler support"
+ depends on ARM64_CPU_TOPOLOGY
+ help
+ Multi-core scheduler support improves the CPU scheduler's decision
+ making when dealing with multi-core CPU chips at a cost of slightly
+ increased overhead in some places. If unsure say N here.
+
+config SCHED_SMT
+ bool "SMT scheduler support"
+ depends on ARM64_CPU_TOPOLOGY
+ help
+ Improves the CPU scheduler's decision making when dealing with
+ MultiThreading at a cost of slightly increased overhead in some
+ places. If unsure say N here.
+
config NR_CPUS
int "Maximum number of CPUs (2-32)"
range 2 32
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 5fe138e..58a595f 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -30,6 +30,17 @@
#define MPIDR_HWID_BITMASK 0xff00ffffff
+#define MPIDR_SMP_BITMASK (0x1 << 30)
+#define MPIDR_MT_BITMASK (0x1 << 24)
+
+#define MPIDR_LEVEL_BITS 8
+#define MPIDR_LEVEL_MASK ((1 << MPIDR_LEVEL_BITS) - 1)
+
+#define MPIDR_AFFINITY_LEVEL_0(mpidr) ((mpidr) & MPIDR_LEVEL_MASK)
+#define MPIDR_AFFINITY_LEVEL_1(mpidr) ((mpidr >> 8) & MPIDR_LEVEL_MASK)
+#define MPIDR_AFFINITY_LEVEL_2(mpidr) ((mpidr >> 16) & MPIDR_LEVEL_MASK)
+#define MPIDR_AFFINITY_LEVEL_3(mpidr) ((mpidr >> 32) & MPIDR_LEVEL_MASK)
+
#define read_cpuid(reg) ({ \
u64 __val; \
asm("mrs %0, " reg : "=r" (__val)); \
diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h
index 22c9421..06440d4 100644
--- a/arch/arm64/include/asm/topology.h
+++ b/arch/arm64/include/asm/topology.h
@@ -1,8 +1,43 @@
#ifndef _ASM_ARM64_TOPOLOGY_H
#define _ASM_ARM64_TOPOLOGY_H
+#ifdef CONFIG_ARM64_CPU_TOPOLOGY
+
+#include <linux/cpumask.h>
+
+struct cputopo_arm64 {
+ int thread_id;
+ int core_id;
+ int socket_id;
+ cpumask_t thread_sibling;
+ cpumask_t core_sibling;
+};
+
+DECLARE_PER_CPU(struct cputopo_arm64, cpu_topology);
+
+#define cpu_topo(cpu) per_cpu(cpu_topology, cpu)
+
+#define topology_physical_package_id(cpu) (cpu_topo(cpu).socket_id)
+#define topology_core_id(cpu) (cpu_topo(cpu).core_id)
+#define topology_core_cpumask(cpu) (&cpu_topo(cpu).core_sibling)
+#define topology_thread_cpumask(cpu) (&cpu_topo(cpu).thread_sibling)
+
+#define mc_capable() (cpu_topo(0).socket_id != -1)
+#define smt_capable() (cpu_topo(0).thread_id != -1)
+
+void init_cpu_topology(void);
+void store_cpu_topology(unsigned int cpuid);
+const struct cpumask *cpu_coregroup_mask(int cpu);
void arch_fix_phys_package_id(int num, u32 slot);
+#else
+
+static inline void arch_fix_phys_package_id(int num, u32 slot) {}
+static inline void init_cpu_topology(void) { }
+static inline void store_cpu_topology(unsigned int cpuid) { }
+
+#endif
+
#include <asm-generic/topology.h>
#endif /* _ASM_ARM64_TOPOLOGY_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index c5e29d5..a47c359 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -18,6 +18,7 @@ arm64-obj-$(CONFIG_SMP) += smp.o smp_spin_table.o smp_psci.o
arm64-obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o
arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+arm64-obj-$(CONFIG_ARM64_CPU_TOPOLOGY) += topology.o
obj-y += $(arm64-obj-y) vdso/
obj-m += $(arm64-obj-m)
@@ -27,7 +28,3 @@ extra-y := $(head-y) vmlinux.lds
# vDSO - this must be built first to generate the symbol offsets
$(call objectify,$(arm64-obj-y)): $(obj)/vdso/vdso-offsets.h
$(obj)/vdso/vdso-offsets.h: $(obj)/vdso
-
-# Hack for now
-obj-y += topology.o
-
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 1049238..b923cfc 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -39,6 +39,7 @@
#include <asm/atomic.h>
#include <asm/cacheflush.h>
#include <asm/cputype.h>
+#include <asm/topology.h>
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -199,6 +200,8 @@ asmlinkage void secondary_start_kernel(void)
raw_spin_lock(&boot_lock);
raw_spin_unlock(&boot_lock);
+ store_cpu_topology(cpu);
+
/*
* OK, now it's safe to let the boot CPU continue. Wait for
* the CPU migration code to notice that the CPU is online
@@ -408,6 +411,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
int cpu, err;
unsigned int ncores = num_possible_cpus();
+ init_cpu_topology();
+ store_cpu_topology(smp_processor_id());
+
/*
* are we trying to boot more cores than exist?
*/
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 5c8e69c..947fcc2 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -1,3 +1,16 @@
+/*
+ * arch/arm64/kernel/topology.c
+ *
+ * Copyright (C) 2013 Linaro Limited.
+ * Written by: Hanjun Guo
+ *
+ * based on arch/arm/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/export.h>
@@ -13,6 +26,113 @@
#include <asm/topology.h>
#include <asm/cpu.h>
+DEFINE_PER_CPU(struct cputopo_arm64, cpu_topology);
+
+const struct cpumask *cpu_coregroup_mask(int cpu)
+{
+ return &cpu_topo(cpu).core_sibling;
+}
+
+void update_siblings_masks(unsigned int cpuid)
+{
+ struct cputopo_arm64 *topo, *cpuid_topo = &cpu_topo(cpuid);
+ int cpu;
+
+ /* update core and thread sibling masks */
+ for_each_possible_cpu(cpu) {
+ topo = &cpu_topo(cpu);
+
+ if (cpuid_topo->socket_id != topo->socket_id)
+ continue;
+
+ cpumask_set_cpu(cpuid, &topo->core_sibling);
+ if (cpu != cpuid)
+ cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
+
+ if (cpuid_topo->core_id != topo->core_id)
+ continue;
+
+ cpumask_set_cpu(cpuid, &topo->thread_sibling);
+ if (cpu != cpuid)
+ cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
+ }
+ smp_wmb();
+}
+
+/*
+ * store_cpu_topology is called at boot when only one cpu is running
+ * and with the mutex cpu_hotplug.lock locked, when several cpus have booted,
+ * which prevents simultaneous write access to cpu_topology array
+ */
+void store_cpu_topology(unsigned int cpuid)
+{
+ struct cputopo_arm64 *cpuid_topo = &cpu_topo(cpuid);
+ u64 mpidr;
+
+ /* If the cpu topology has been already set, just return */
+ if (cpuid_topo->core_id != -1)
+ return;
+
+ mpidr = read_cpuid_mpidr();
+
+ /* create cpu topology mapping */
+ if (!(mpidr & MPIDR_SMP_BITMASK)) {
+ /*
+ * This is a multiprocessor system
+ * multiprocessor format & multiprocessor mode field are set
+ */
+
+ if (mpidr & MPIDR_MT_BITMASK) {
+ /* core performance interdependency */
+ cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL_0(mpidr);
+ cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL_1(mpidr);
+ cpuid_topo->socket_id = MPIDR_AFFINITY_LEVEL_2(mpidr);
+ } else {
+ /* largely independent cores */
+ cpuid_topo->thread_id = -1;
+ cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL_0(mpidr);
+ cpuid_topo->socket_id = MPIDR_AFFINITY_LEVEL_1(mpidr);
+ }
+ } else {
+ /*
+ * This is an uniprocessor system
+ * we are in multiprocessor format but uniprocessor system
+ * or in the old uniprocessor format
+ */
+ cpuid_topo->thread_id = -1;
+ cpuid_topo->core_id = 0;
+ cpuid_topo->socket_id = -1;
+ }
+
+ update_siblings_masks(cpuid);
+
+ pr_info("CPU%u: thread %d, cpu %d, socket %d, mpidr 0x%llx\n",
+ cpuid, cpu_topo(cpuid).thread_id,
+ cpu_topo(cpuid).core_id,
+ cpu_topo(cpuid).socket_id, mpidr);
+}
+
+/*
+ * 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 */
+ for_each_possible_cpu(cpu) {
+ struct cputopo_arm64 *topo = &cpu_topo(cpu);
+
+ topo->thread_id = -1;
+ topo->core_id = -1;
+ topo->socket_id = -1;
+ cpumask_clear(&topo->core_sibling);
+ cpumask_clear(&topo->thread_sibling);
+ }
+ smp_wmb();
+}
+
void arch_fix_phys_package_id(int num, u32 slot)
{
}
--
1.7.9.5
From: Al Stone <ahs3(a)redhat.com>
No one should be using an RSDT any longer; they are
essentially deprecated and no longer useful. This
patch simply removes the table definitions from the
currently defined platforms.
Al Stone (2):
ASL: exynos5250-arndale.acpi: Remove deprecated RSDT table
ASL: foundation-v8.acpi: Remove deprecated RSDT files
platforms/exynos5250-arndale.acpi/rsdt.asl | 20 --------------------
platforms/foundation-v8.acpi/rsdt.asl | 20 --------------------
2 files changed, 40 deletions(-)
delete mode 100644 platforms/exynos5250-arndale.acpi/rsdt.asl
delete mode 100644 platforms/foundation-v8.acpi/rsdt.asl
--
1.8.1.4
From: Al Stone <ahs3(a)redhat.com>
The prior version of this created a "dummy" platform; I did not
think that specific enough so the platform is now called "loadtest".
What this patch to acpi-asl does is define only the ACPI tables that
are absolutely required to determine if ACPI will initialize properly
during kernel boot. These tables contain essentially *no* configuration
information and should not.
Changes for v2:
-- rename "dummy" to "loadtest"
-- reduce tables to bare minimum (including removing the RSDT
which has been deprecated)
Al Stone (1):
ASL : loadtest.acpi : add in a minimal table set that can be used
for testing of core ACPI table loading
platforms/loadtest.acpi/.gitignore | 3 +
platforms/loadtest.acpi/dsdt.asl | 17 +++
platforms/loadtest.acpi/facp.asl | 167 ++++++++++++++++++++++++++++++
platforms/loadtest.acpi/facs.asl | 21 ++++
platforms/loadtest.acpi/loadtest.manifest | 13 +++
platforms/loadtest.acpi/rsdp.asl | 17 +++
platforms/loadtest.acpi/xsdt.asl | 23 ++++
7 files changed, 261 insertions(+)
create mode 100644 platforms/loadtest.acpi/.gitignore
create mode 100644 platforms/loadtest.acpi/dsdt.asl
create mode 100644 platforms/loadtest.acpi/facp.asl
create mode 100644 platforms/loadtest.acpi/facs.asl
create mode 100644 platforms/loadtest.acpi/loadtest.manifest
create mode 100644 platforms/loadtest.acpi/rsdp.asl
create mode 100644 platforms/loadtest.acpi/xsdt.asl
--
1.8.1.4
Hi,
First two patches are cleanups for some stuff in Makefiles.
The next two patches add the ability to relocate a block to a fixed physical
address and the ability to use this from the makefile.
An example for armv8 booting from our modified bootwrapper is.
make PADDR=0x88100000 foundation-v8.acpi
Near the top of the output from mab you will see the output.
> relocating blob to 0x88100000
I shall be sending a patch soon to remove the in kernel re-location code as
it is no longer needed and gets in the way of UEFI support.
Thanks
Graeme