arm64: Remove fixmap include fragility
[linux-2.6-block.git] / arch / arm64 / kernel / cpuinfo.c
CommitLineData
df857416
MR
1/*
2 * Record and handle CPU attributes.
3 *
4 * Copyright (C) 2014 ARM Ltd.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17#include <asm/arch_timer.h>
18#include <asm/cachetype.h>
19#include <asm/cpu.h>
20#include <asm/cputype.h>
e116a375 21#include <asm/cpufeature.h>
df857416 22
59ccc0d4 23#include <linux/bitops.h>
80c517b0 24#include <linux/bug.h>
df857416 25#include <linux/init.h>
127161aa 26#include <linux/kernel.h>
12d11817 27#include <linux/personality.h>
80c517b0 28#include <linux/preempt.h>
59ccc0d4 29#include <linux/printk.h>
12d11817
SP
30#include <linux/seq_file.h>
31#include <linux/sched.h>
df857416 32#include <linux/smp.h>
92e788b7 33#include <linux/delay.h>
df857416
MR
34
35/*
36 * In case the boot CPU is hotpluggable, we record its initial state and
37 * current state separately. Certain system registers may contain different
38 * values depending on configuration at or after reset.
39 */
40DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
41static struct cpuinfo_arm64 boot_cpu_data;
42
59ccc0d4
MR
43static char *icache_policy_str[] = {
44 [ICACHE_POLICY_RESERVED] = "RESERVED/UNKNOWN",
45 [ICACHE_POLICY_AIVIVT] = "AIVIVT",
46 [ICACHE_POLICY_VIPT] = "VIPT",
47 [ICACHE_POLICY_PIPT] = "PIPT",
48};
49
50unsigned long __icache_flags;
51
9299b247 52static const char *const hwcap_str[] = {
12d11817
SP
53 "fp",
54 "asimd",
55 "evtstrm",
56 "aes",
57 "pmull",
58 "sha1",
59 "sha2",
60 "crc32",
61 "atomics",
62 NULL
63};
64
65#ifdef CONFIG_COMPAT
9299b247 66static const char *const compat_hwcap_str[] = {
12d11817
SP
67 "swp",
68 "half",
69 "thumb",
70 "26bit",
71 "fastmult",
72 "fpa",
73 "vfp",
74 "edsp",
75 "java",
76 "iwmmxt",
77 "crunch",
78 "thumbee",
79 "neon",
80 "vfpv3",
81 "vfpv3d16",
82 "tls",
83 "vfpv4",
84 "idiva",
85 "idivt",
86 "vfpd32",
87 "lpae",
88 "evtstrm"
89};
90
9299b247 91static const char *const compat_hwcap2_str[] = {
12d11817
SP
92 "aes",
93 "pmull",
94 "sha1",
95 "sha2",
96 "crc32",
97 NULL
98};
99#endif /* CONFIG_COMPAT */
100
101static int c_show(struct seq_file *m, void *v)
102{
103 int i, j;
104
105 for_each_online_cpu(i) {
106 struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
107 u32 midr = cpuinfo->reg_midr;
108
109 /*
110 * glibc reads /proc/cpuinfo to determine the number of
111 * online processors, looking for lines beginning with
112 * "processor". Give glibc what it expects.
113 */
114 seq_printf(m, "processor\t: %d\n", i);
115
92e788b7
YS
116 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
117 loops_per_jiffy / (500000UL/HZ),
118 loops_per_jiffy / (5000UL/HZ) % 100);
119
12d11817
SP
120 /*
121 * Dump out the common processor features in a single line.
122 * Userspace should read the hwcaps with getauxval(AT_HWCAP)
123 * rather than attempting to parse this, but there's a body of
124 * software which does already (at least for 32-bit).
125 */
126 seq_puts(m, "Features\t:");
127 if (personality(current->personality) == PER_LINUX32) {
128#ifdef CONFIG_COMPAT
129 for (j = 0; compat_hwcap_str[j]; j++)
130 if (compat_elf_hwcap & (1 << j))
131 seq_printf(m, " %s", compat_hwcap_str[j]);
132
133 for (j = 0; compat_hwcap2_str[j]; j++)
134 if (compat_elf_hwcap2 & (1 << j))
135 seq_printf(m, " %s", compat_hwcap2_str[j]);
136#endif /* CONFIG_COMPAT */
137 } else {
138 for (j = 0; hwcap_str[j]; j++)
139 if (elf_hwcap & (1 << j))
140 seq_printf(m, " %s", hwcap_str[j]);
141 }
142 seq_puts(m, "\n");
143
144 seq_printf(m, "CPU implementer\t: 0x%02x\n",
145 MIDR_IMPLEMENTOR(midr));
146 seq_printf(m, "CPU architecture: 8\n");
147 seq_printf(m, "CPU variant\t: 0x%x\n", MIDR_VARIANT(midr));
148 seq_printf(m, "CPU part\t: 0x%03x\n", MIDR_PARTNUM(midr));
149 seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr));
150 }
151
152 return 0;
153}
154
155static void *c_start(struct seq_file *m, loff_t *pos)
156{
157 return *pos < 1 ? (void *)1 : NULL;
158}
159
160static void *c_next(struct seq_file *m, void *v, loff_t *pos)
161{
162 ++*pos;
163 return NULL;
164}
165
166static void c_stop(struct seq_file *m, void *v)
167{
168}
169
170const struct seq_operations cpuinfo_op = {
171 .start = c_start,
172 .next = c_next,
173 .stop = c_stop,
174 .show = c_show
175};
176
59ccc0d4
MR
177static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
178{
179 unsigned int cpu = smp_processor_id();
180 u32 l1ip = CTR_L1IP(info->reg_ctr);
181
169c018d
AB
182 if (l1ip != ICACHE_POLICY_PIPT) {
183 /*
184 * VIPT caches are non-aliasing if the VA always equals the PA
185 * in all bit positions that are covered by the index. This is
186 * the case if the size of a way (# of sets * line size) does
187 * not exceed PAGE_SIZE.
188 */
189 u32 waysize = icache_get_numsets() * icache_get_linesize();
190
191 if (l1ip != ICACHE_POLICY_VIPT || waysize > PAGE_SIZE)
192 set_bit(ICACHEF_ALIASING, &__icache_flags);
193 }
a3a80544 194 if (l1ip == ICACHE_POLICY_AIVIVT)
59ccc0d4
MR
195 set_bit(ICACHEF_AIVIVT, &__icache_flags);
196
ea171967 197 pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
59ccc0d4
MR
198}
199
df857416
MR
200static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
201{
202 info->reg_cntfrq = arch_timer_get_cntfrq();
203 info->reg_ctr = read_cpuid_cachetype();
0f54b14e 204 info->reg_dczid = read_cpuid(SYS_DCZID_EL0);
df857416
MR
205 info->reg_midr = read_cpuid_id();
206
0f54b14e
JM
207 info->reg_id_aa64dfr0 = read_cpuid(SYS_ID_AA64DFR0_EL1);
208 info->reg_id_aa64dfr1 = read_cpuid(SYS_ID_AA64DFR1_EL1);
209 info->reg_id_aa64isar0 = read_cpuid(SYS_ID_AA64ISAR0_EL1);
210 info->reg_id_aa64isar1 = read_cpuid(SYS_ID_AA64ISAR1_EL1);
211 info->reg_id_aa64mmfr0 = read_cpuid(SYS_ID_AA64MMFR0_EL1);
212 info->reg_id_aa64mmfr1 = read_cpuid(SYS_ID_AA64MMFR1_EL1);
406e3087 213 info->reg_id_aa64mmfr2 = read_cpuid(SYS_ID_AA64MMFR2_EL1);
0f54b14e
JM
214 info->reg_id_aa64pfr0 = read_cpuid(SYS_ID_AA64PFR0_EL1);
215 info->reg_id_aa64pfr1 = read_cpuid(SYS_ID_AA64PFR1_EL1);
216
217 info->reg_id_dfr0 = read_cpuid(SYS_ID_DFR0_EL1);
218 info->reg_id_isar0 = read_cpuid(SYS_ID_ISAR0_EL1);
219 info->reg_id_isar1 = read_cpuid(SYS_ID_ISAR1_EL1);
220 info->reg_id_isar2 = read_cpuid(SYS_ID_ISAR2_EL1);
221 info->reg_id_isar3 = read_cpuid(SYS_ID_ISAR3_EL1);
222 info->reg_id_isar4 = read_cpuid(SYS_ID_ISAR4_EL1);
223 info->reg_id_isar5 = read_cpuid(SYS_ID_ISAR5_EL1);
224 info->reg_id_mmfr0 = read_cpuid(SYS_ID_MMFR0_EL1);
225 info->reg_id_mmfr1 = read_cpuid(SYS_ID_MMFR1_EL1);
226 info->reg_id_mmfr2 = read_cpuid(SYS_ID_MMFR2_EL1);
227 info->reg_id_mmfr3 = read_cpuid(SYS_ID_MMFR3_EL1);
228 info->reg_id_pfr0 = read_cpuid(SYS_ID_PFR0_EL1);
229 info->reg_id_pfr1 = read_cpuid(SYS_ID_PFR1_EL1);
230
231 info->reg_mvfr0 = read_cpuid(SYS_MVFR0_EL1);
232 info->reg_mvfr1 = read_cpuid(SYS_MVFR1_EL1);
233 info->reg_mvfr2 = read_cpuid(SYS_MVFR2_EL1);
80639d4a 234
59ccc0d4 235 cpuinfo_detect_icache_policy(info);
e116a375
AP
236
237 check_local_cpu_errata();
df857416
MR
238}
239
240void cpuinfo_store_cpu(void)
241{
242 struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data);
243 __cpuinfo_store_cpu(info);
3086d391 244 update_cpu_features(smp_processor_id(), info, &boot_cpu_data);
df857416
MR
245}
246
247void __init cpuinfo_store_boot_cpu(void)
248{
249 struct cpuinfo_arm64 *info = &per_cpu(cpu_data, 0);
250 __cpuinfo_store_cpu(info);
251
252 boot_cpu_data = *info;
3c739b57 253 init_cpu_features(&boot_cpu_data);
df857416 254}