xref: /openbmc/linux/arch/arm64/kernel/cpu_errata.c (revision c819e2cf)
1 /*
2  * Contains CPU specific errata definitions
3  *
4  * Copyright (C) 2014 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/cputype.h>
24 #include <asm/cpufeature.h>
25 
26 #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)
28 
29 /*
30  * Add a struct or another datatype to the union below if you need
31  * different means to detect an affected CPU.
32  */
33 struct 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 | \
46 			MIDR_ARCHITECTURE_MASK)
47 
48 static bool __maybe_unused
49 is_affected_midr_range(struct arm64_cpu_capabilities *entry)
50 {
51 	u32 midr = read_cpuid_id();
52 
53 	if ((midr & CPU_MODEL_MASK) != entry->midr_model)
54 		return false;
55 
56 	midr &= MIDR_REVISION_MASK | MIDR_VARIANT_MASK;
57 
58 	return (midr >= entry->midr_range_min && midr <= entry->midr_range_max);
59 }
60 
61 #define MIDR_RANGE(model, min, max) \
62 	.is_affected = is_affected_midr_range, \
63 	.midr_model = model, \
64 	.midr_range_min = min, \
65 	.midr_range_max = max
66 
67 struct arm64_cpu_capabilities arm64_errata[] = {
68 #if	defined(CONFIG_ARM64_ERRATUM_826319) || \
69 	defined(CONFIG_ARM64_ERRATUM_827319) || \
70 	defined(CONFIG_ARM64_ERRATUM_824069)
71 	{
72 	/* Cortex-A53 r0p[012] */
73 		.desc = "ARM errata 826319, 827319, 824069",
74 		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
75 		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x02),
76 	},
77 #endif
78 #ifdef CONFIG_ARM64_ERRATUM_819472
79 	{
80 	/* Cortex-A53 r0p[01] */
81 		.desc = "ARM errata 819472",
82 		.capability = ARM64_WORKAROUND_CLEAN_CACHE,
83 		MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x01),
84 	},
85 #endif
86 #ifdef CONFIG_ARM64_ERRATUM_832075
87 	{
88 	/* Cortex-A57 r0p0 - r1p2 */
89 		.desc = "ARM erratum 832075",
90 		.capability = ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE,
91 		MIDR_RANGE(MIDR_CORTEX_A57, 0x00, 0x12),
92 	},
93 #endif
94 	{
95 	}
96 };
97 
98 void check_local_cpu_errata(void)
99 {
100 	struct arm64_cpu_capabilities *cpus = arm64_errata;
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 }
112