From patchwork Sat Jul 27 10:42:07 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hanjun Guo X-Patchwork-Id: 18618 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-yh0-f71.google.com (mail-yh0-f71.google.com [209.85.213.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id C57E325AC6 for ; Sat, 27 Jul 2013 10:44:29 +0000 (UTC) Received: by mail-yh0-f71.google.com with SMTP id f64sf513898yha.2 for ; Sat, 27 Jul 2013 03:44:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=mime-version:x-beenthere:x-forwarded-to:x-forwarded-for :delivered-to:from:to:cc:subject:date:message-id:x-mailer :x-gm-message-state:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :x-google-group-id:list-post:list-help:list-archive:list-unsubscribe; bh=V1Cnng/oWcZeqVqehQT8pt+jIRthAtcPtJie9Ck1A3E=; b=PD+8OJ45L9/7qAT9ehpUZC/9hxYKWOKRGHDZDwGjm/2l9OuqgleJxHZ5GaIALfBgf0 wII7XDBx4xinQdico0Snq1tOUzDt7I4PBA6jLm/WmetIi4x2Qb+vfz+8KlnS/fGQP8ce sbKwYi0afPPsASOp6i/14gmAhQWVEq3RlWdfAQWFvH4pbbwdLnmytcPj3dDllT+eJjJG uuIxCKE6MPJlgyvQQ5o/EeT8mtMYH55tO3wh2TZBpr17G0ACC3wiHZHpDmlaGEEKn7YV xYLggsi/5RPQonsHfw5+QfN+A792vQLIvLAX4RZITj7hy2YRvW3xN4eVx9Rc10ZDQdhV HVcQ== X-Received: by 10.236.135.66 with SMTP id t42mr27189386yhi.36.1374921869172; Sat, 27 Jul 2013 03:44:29 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.39.3 with SMTP id l3ls1416782qek.62.gmail; Sat, 27 Jul 2013 03:44:29 -0700 (PDT) X-Received: by 10.220.197.10 with SMTP id ei10mr5394898vcb.68.1374921869041; Sat, 27 Jul 2013 03:44:29 -0700 (PDT) Received: from mail-vb0-f52.google.com (mail-vb0-f52.google.com [209.85.212.52]) by mx.google.com with ESMTPS id tf3si15458656vec.68.2013.07.27.03.44.28 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 27 Jul 2013 03:44:29 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.212.52 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.52; Received: by mail-vb0-f52.google.com with SMTP id f12so1810491vbg.39 for ; Sat, 27 Jul 2013 03:44:28 -0700 (PDT) X-Received: by 10.220.164.138 with SMTP id e10mr5374488vcy.27.1374921868897; Sat, 27 Jul 2013 03:44:28 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.221.11.8 with SMTP id pc8csp26860vcb; Sat, 27 Jul 2013 03:44:28 -0700 (PDT) X-Received: by 10.66.160.132 with SMTP id xk4mr39806370pab.118.1374921867736; Sat, 27 Jul 2013 03:44:27 -0700 (PDT) Received: from mail-pa0-f54.google.com (mail-pa0-f54.google.com [209.85.220.54]) by mx.google.com with ESMTPS id gx9si5677443pac.98.2013.07.27.03.44.27 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 27 Jul 2013 03:44:27 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.54 is neither permitted nor denied by best guess record for domain of hanjun.guo@linaro.org) client-ip=209.85.220.54; Received: by mail-pa0-f54.google.com with SMTP id kx1so3870898pab.13 for ; Sat, 27 Jul 2013 03:44:27 -0700 (PDT) X-Received: by 10.66.218.74 with SMTP id pe10mr51651852pac.177.1374921867068; Sat, 27 Jul 2013 03:44:27 -0700 (PDT) Received: from localhost ([218.17.215.175]) by mx.google.com with ESMTPSA id w8sm8911021pab.12.2013.07.27.03.43.06 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sat, 27 Jul 2013 03:44:26 -0700 (PDT) From: Hanjun Guo To: Catalin Marinas , Will Deacon Cc: Russell King , Vincent Guittot , linux-arm-kernel@lists.infradead.org, patches@linaro.org, linaro-kernel@lists.linaro.org, linux-kernel@vger.kernel.org, linaro-acpi@lists.linaro.org, Al Stone , Graeme Gregory , Naresh Bhat , Tomasz Nowicki , Hanjun Guo Subject: [RFC][PATCH 1/2] ARM64: add cpu topology definition Date: Sat, 27 Jul 2013 18:42:07 +0800 Message-Id: <1374921728-9007-1-git-send-email-hanjun.guo@linaro.org> X-Mailer: git-send-email 1.7.9.5 X-Gm-Message-State: ALoCoQl1HYdTMvtZZ/gzyFI8ZTHdkGTN2UpO2bGdEN55jBzr9MnENC6H3euXpZ81wGijcUtk2Hih X-Original-Sender: hanjun.guo@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.52 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Power aware scheduling needs the cpu topology information to improve the cpu scheduler decision making. 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. Signed-off-by: Hanjun Guo --- arch/arm64/Kconfig | 9 +++ arch/arm64/include/asm/cputype.h | 11 ++++ arch/arm64/include/asm/topology.h | 41 ++++++++++++ arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/smp.c | 6 ++ arch/arm64/kernel/topology.c | 128 +++++++++++++++++++++++++++++++++++++ 6 files changed, 196 insertions(+) create mode 100644 arch/arm64/include/asm/topology.h create mode 100644 arch/arm64/kernel/topology.c diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 9737e97..f0ce91b 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -150,6 +150,15 @@ 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 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..68b55af 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 new file mode 100644 index 0000000..8631808 --- /dev/null +++ b/arch/arm64/include/asm/topology.h @@ -0,0 +1,41 @@ +#ifndef _ASM_ARM64_TOPOLOGY_H +#define _ASM_ARM64_TOPOLOGY_H + +#ifdef CONFIG_ARM64_CPU_TOPOLOGY + +#include + +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); + +#else + +static inline void init_cpu_topology(void) { } +static inline void store_cpu_topology(unsigned int cpuid) { } + +#endif + +#include + +#endif /* _ASM_ARM64_TOPOLOGY_H */ diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 7b4b564..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) diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index fee5cce..197b1da 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -215,6 +216,8 @@ asmlinkage void secondary_start_kernel(void) local_irq_enable(); local_fiq_enable(); + store_cpu_topology(cpu); + /* * OK, it's off to the idle thread for us */ @@ -387,6 +390,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 new file mode 100644 index 0000000..1eb0435 --- /dev/null +++ b/arch/arm64/kernel/topology.c @@ -0,0 +1,128 @@ +/* + * 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 +#include +#include +#include +#include + +#include +#include + +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); + + printk(KERN_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(); +}