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