Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski...
[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",
bf500618
SP
62 "fphp",
63 "asimdhp",
12d11817
SP
64 NULL
65};
66
67#ifdef CONFIG_COMPAT
9299b247 68static const char *const compat_hwcap_str[] = {
12d11817
SP
69 "swp",
70 "half",
71 "thumb",
72 "26bit",
73 "fastmult",
74 "fpa",
75 "vfp",
76 "edsp",
77 "java",
78 "iwmmxt",
79 "crunch",
80 "thumbee",
81 "neon",
82 "vfpv3",
83 "vfpv3d16",
84 "tls",
85 "vfpv4",
86 "idiva",
87 "idivt",
88 "vfpd32",
89 "lpae",
f228b494
JG
90 "evtstrm",
91 NULL
12d11817
SP
92};
93
9299b247 94static const char *const compat_hwcap2_str[] = {
12d11817
SP
95 "aes",
96 "pmull",
97 "sha1",
98 "sha2",
99 "crc32",
100 NULL
101};
102#endif /* CONFIG_COMPAT */
103
104static int c_show(struct seq_file *m, void *v)
105{
106 int i, j;
107
108 for_each_online_cpu(i) {
109 struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
110 u32 midr = cpuinfo->reg_midr;
111
112 /*
113 * glibc reads /proc/cpuinfo to determine the number of
114 * online processors, looking for lines beginning with
115 * "processor". Give glibc what it expects.
116 */
117 seq_printf(m, "processor\t: %d\n", i);
118
92e788b7
YS
119 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
120 loops_per_jiffy / (500000UL/HZ),
121 loops_per_jiffy / (5000UL/HZ) % 100);
122
12d11817
SP
123 /*
124 * Dump out the common processor features in a single line.
125 * Userspace should read the hwcaps with getauxval(AT_HWCAP)
126 * rather than attempting to parse this, but there's a body of
127 * software which does already (at least for 32-bit).
128 */
129 seq_puts(m, "Features\t:");
130 if (personality(current->personality) == PER_LINUX32) {
131#ifdef CONFIG_COMPAT
132 for (j = 0; compat_hwcap_str[j]; j++)
133 if (compat_elf_hwcap & (1 << j))
134 seq_printf(m, " %s", compat_hwcap_str[j]);
135
136 for (j = 0; compat_hwcap2_str[j]; j++)
137 if (compat_elf_hwcap2 & (1 << j))
138 seq_printf(m, " %s", compat_hwcap2_str[j]);
139#endif /* CONFIG_COMPAT */
140 } else {
141 for (j = 0; hwcap_str[j]; j++)
142 if (elf_hwcap & (1 << j))
143 seq_printf(m, " %s", hwcap_str[j]);
144 }
145 seq_puts(m, "\n");
146
147 seq_printf(m, "CPU implementer\t: 0x%02x\n",
148 MIDR_IMPLEMENTOR(midr));
149 seq_printf(m, "CPU architecture: 8\n");
150 seq_printf(m, "CPU variant\t: 0x%x\n", MIDR_VARIANT(midr));
151 seq_printf(m, "CPU part\t: 0x%03x\n", MIDR_PARTNUM(midr));
152 seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr));
153 }
154
155 return 0;
156}
157
158static void *c_start(struct seq_file *m, loff_t *pos)
159{
160 return *pos < 1 ? (void *)1 : NULL;
161}
162
163static void *c_next(struct seq_file *m, void *v, loff_t *pos)
164{
165 ++*pos;
166 return NULL;
167}
168
169static void c_stop(struct seq_file *m, void *v)
170{
171}
172
173const struct seq_operations cpuinfo_op = {
174 .start = c_start,
175 .next = c_next,
176 .stop = c_stop,
177 .show = c_show
178};
179
59ccc0d4
MR
180static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
181{
182 unsigned int cpu = smp_processor_id();
183 u32 l1ip = CTR_L1IP(info->reg_ctr);
184
169c018d
AB
185 if (l1ip != ICACHE_POLICY_PIPT) {
186 /*
187 * VIPT caches are non-aliasing if the VA always equals the PA
188 * in all bit positions that are covered by the index. This is
189 * the case if the size of a way (# of sets * line size) does
190 * not exceed PAGE_SIZE.
191 */
192 u32 waysize = icache_get_numsets() * icache_get_linesize();
193
194 if (l1ip != ICACHE_POLICY_VIPT || waysize > PAGE_SIZE)
195 set_bit(ICACHEF_ALIASING, &__icache_flags);
196 }
a3a80544 197 if (l1ip == ICACHE_POLICY_AIVIVT)
59ccc0d4
MR
198 set_bit(ICACHEF_AIVIVT, &__icache_flags);
199
ea171967 200 pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
59ccc0d4
MR
201}
202
df857416
MR
203static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
204{
205 info->reg_cntfrq = arch_timer_get_cntfrq();
206 info->reg_ctr = read_cpuid_cachetype();
1cc6ed90 207 info->reg_dczid = read_cpuid(DCZID_EL0);
df857416
MR
208 info->reg_midr = read_cpuid_id();
209
1cc6ed90
MR
210 info->reg_id_aa64dfr0 = read_cpuid(ID_AA64DFR0_EL1);
211 info->reg_id_aa64dfr1 = read_cpuid(ID_AA64DFR1_EL1);
212 info->reg_id_aa64isar0 = read_cpuid(ID_AA64ISAR0_EL1);
213 info->reg_id_aa64isar1 = read_cpuid(ID_AA64ISAR1_EL1);
214 info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1);
215 info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1);
216 info->reg_id_aa64mmfr2 = read_cpuid(ID_AA64MMFR2_EL1);
217 info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1);
218 info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1);
219
a6dc3cd7
SP
220 /* Update the 32bit ID registers only if AArch32 is implemented */
221 if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
222 info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
223 info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
224 info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
225 info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
226 info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
227 info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
228 info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
229 info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
230 info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
231 info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
232 info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
233 info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
234 info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
235
236 info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
237 info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
238 info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
239 }
80639d4a 240
59ccc0d4 241 cpuinfo_detect_icache_policy(info);
e116a375
AP
242
243 check_local_cpu_errata();
df857416
MR
244}
245
246void cpuinfo_store_cpu(void)
247{
248 struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data);
249 __cpuinfo_store_cpu(info);
3086d391 250 update_cpu_features(smp_processor_id(), info, &boot_cpu_data);
df857416
MR
251}
252
253void __init cpuinfo_store_boot_cpu(void)
254{
255 struct cpuinfo_arm64 *info = &per_cpu(cpu_data, 0);
256 __cpuinfo_store_cpu(info);
257
258 boot_cpu_data = *info;
3c739b57 259 init_cpu_features(&boot_cpu_data);
df857416 260}