aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2015-03-27 09:09:23 -0400
committerWill Deacon <will.deacon@arm.com>2015-03-30 06:03:43 -0400
commit359b706473b47da3c93bd99fd10d798fe411ab67 (patch)
tree2b0727207e192f5fe08b39bc55d6263a7a2cd01b
parentfef7f2b2010381c795ae43743ad31931cc58f5ad (diff)
arm64: Extract feature parsing code from cpu_errata.c
As we detect more architectural features at runtime, it makes sense to reuse the existing framework whilst avoiding to call a feature an erratum... This patch extract the core capability parsing, moves it into a new file (cpufeature.c), and let the CPU errata detection code use it. Reviewed-by: Andre Przywara <andre.przywara@arm.com> Acked-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arch/arm64/include/asm/cpufeature.h15
-rw-r--r--arch/arm64/kernel/Makefile2
-rw-r--r--arch/arm64/kernel/cpu_errata.c36
-rw-r--r--arch/arm64/kernel/cpufeature.c47
-rw-r--r--arch/arm64/kernel/cpuinfo.c1
5 files changed, 68 insertions, 33 deletions
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index b6c16d5f622f..6ae35d160464 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -28,6 +28,18 @@
28 28
29#ifndef __ASSEMBLY__ 29#ifndef __ASSEMBLY__
30 30
31struct arm64_cpu_capabilities {
32 const char *desc;
33 u16 capability;
34 bool (*matches)(const struct arm64_cpu_capabilities *);
35 union {
36 struct { /* To be used for erratum handling only */
37 u32 midr_model;
38 u32 midr_range_min, midr_range_max;
39 };
40 };
41};
42
31extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS); 43extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
32 44
33static inline bool cpu_have_feature(unsigned int num) 45static inline bool cpu_have_feature(unsigned int num)
@@ -51,7 +63,10 @@ static inline void cpus_set_cap(unsigned int num)
51 __set_bit(num, cpu_hwcaps); 63 __set_bit(num, cpu_hwcaps);
52} 64}
53 65
66void check_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
67 const char *info);
54void check_local_cpu_errata(void); 68void check_local_cpu_errata(void);
69void check_local_cpu_features(void);
55bool cpu_supports_mixed_endian_el0(void); 70bool cpu_supports_mixed_endian_el0(void);
56bool system_supports_mixed_endian_el0(void); 71bool system_supports_mixed_endian_el0(void);
57 72
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index d5e70747c7a2..b12e15b80516 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -17,7 +17,7 @@ arm64-obj-y := debug-monitors.o entry.o irq.o fpsimd.o \
17 sys.o stacktrace.o time.o traps.o io.o vdso.o \ 17 sys.o stacktrace.o time.o traps.o io.o vdso.o \
18 hyp-stub.o psci.o psci-call.o cpu_ops.o insn.o \ 18 hyp-stub.o psci.o psci-call.o cpu_ops.o insn.o \
19 return_address.o cpuinfo.o cpu_errata.o \ 19 return_address.o cpuinfo.o cpu_errata.o \
20 alternative.o cacheinfo.o 20 cpufeature.o alternative.o cacheinfo.o
21 21
22arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \ 22arm64-obj-$(CONFIG_COMPAT) += sys32.o kuser32.o signal32.o \
23 sys_compat.o entry32.o \ 23 sys_compat.o entry32.o \
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index fa62637e63a8..a66f4fa4d541 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -16,8 +16,6 @@
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 17 */
18 18
19#define pr_fmt(fmt) "alternatives: " fmt
20
21#include <linux/types.h> 19#include <linux/types.h>
22#include <asm/cpu.h> 20#include <asm/cpu.h>
23#include <asm/cputype.h> 21#include <asm/cputype.h>
@@ -26,27 +24,11 @@
26#define MIDR_CORTEX_A53 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) 24#define MIDR_CORTEX_A53 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
27#define MIDR_CORTEX_A57 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) 25#define MIDR_CORTEX_A57 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
28 26
29/*
30 * Add a struct or another datatype to the union below if you need
31 * different means to detect an affected CPU.
32 */
33struct arm64_cpu_capabilities {
34 const char *desc;
35 u16 capability;
36 bool (*is_affected)(struct arm64_cpu_capabilities *);
37 union {
38 struct {
39 u32 midr_model;
40 u32 midr_range_min, midr_range_max;
41 };
42 };
43};
44
45#define CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \ 27#define CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \
46 MIDR_ARCHITECTURE_MASK) 28 MIDR_ARCHITECTURE_MASK)
47 29
48static bool __maybe_unused 30static bool __maybe_unused
49is_affected_midr_range(struct arm64_cpu_capabilities *entry) 31is_affected_midr_range(const struct arm64_cpu_capabilities *entry)
50{ 32{
51 u32 midr = read_cpuid_id(); 33 u32 midr = read_cpuid_id();
52 34
@@ -59,12 +41,12 @@ is_affected_midr_range(struct arm64_cpu_capabilities *entry)
59} 41}
60 42
61#define MIDR_RANGE(model, min, max) \ 43#define MIDR_RANGE(model, min, max) \
62 .is_affected = is_affected_midr_range, \ 44 .matches = is_affected_midr_range, \
63 .midr_model = model, \ 45 .midr_model = model, \
64 .midr_range_min = min, \ 46 .midr_range_min = min, \
65 .midr_range_max = max 47 .midr_range_max = max
66 48
67struct arm64_cpu_capabilities arm64_errata[] = { 49const struct arm64_cpu_capabilities arm64_errata[] = {
68#if defined(CONFIG_ARM64_ERRATUM_826319) || \ 50#if defined(CONFIG_ARM64_ERRATUM_826319) || \
69 defined(CONFIG_ARM64_ERRATUM_827319) || \ 51 defined(CONFIG_ARM64_ERRATUM_827319) || \
70 defined(CONFIG_ARM64_ERRATUM_824069) 52 defined(CONFIG_ARM64_ERRATUM_824069)
@@ -97,15 +79,5 @@ struct arm64_cpu_capabilities arm64_errata[] = {
97 79
98void check_local_cpu_errata(void) 80void check_local_cpu_errata(void)
99{ 81{
100 struct arm64_cpu_capabilities *cpus = arm64_errata; 82 check_cpu_capabilities(arm64_errata, "enabling workaround for");
101 int i;
102
103 for (i = 0; cpus[i].desc; i++) {
104 if (!cpus[i].is_affected(&cpus[i]))
105 continue;
106
107 if (!cpus_have_cap(cpus[i].capability))
108 pr_info("enabling workaround for %s\n", cpus[i].desc);
109 cpus_set_cap(cpus[i].capability);
110 }
111} 83}
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
new file mode 100644
index 000000000000..3d9967e43d89
--- /dev/null
+++ b/arch/arm64/kernel/cpufeature.c
@@ -0,0 +1,47 @@
1/*
2 * Contains CPU feature definitions
3 *
4 * Copyright (C) 2015 ARM Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#define pr_fmt(fmt) "alternatives: " fmt
20
21#include <linux/types.h>
22#include <asm/cpu.h>
23#include <asm/cpufeature.h>
24
25static const struct arm64_cpu_capabilities arm64_features[] = {
26 {},
27};
28
29void check_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
30 const char *info)
31{
32 int i;
33
34 for (i = 0; caps[i].desc; i++) {
35 if (!caps[i].matches(&caps[i]))
36 continue;
37
38 if (!cpus_have_cap(caps[i].capability))
39 pr_info("%s %s\n", info, caps[i].desc);
40 cpus_set_cap(caps[i].capability);
41 }
42}
43
44void check_local_cpu_features(void)
45{
46 check_cpu_capabilities(arm64_features, "detected feature");
47}
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 929855691dae..75d5a867e7fb 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -236,6 +236,7 @@ static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
236 cpuinfo_detect_icache_policy(info); 236 cpuinfo_detect_icache_policy(info);
237 237
238 check_local_cpu_errata(); 238 check_local_cpu_errata();
239 check_local_cpu_features();
239 update_cpu_features(info); 240 update_cpu_features(info);
240} 241}
241 242