]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - arch/arm64/kernel/cpuinfo.c
UBUNTU: Ubuntu-4.15.0-96.97
[mirror_ubuntu-bionic-kernel.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>
02f7760e 18#include <asm/cache.h>
df857416
MR
19#include <asm/cpu.h>
20#include <asm/cputype.h>
e116a375 21#include <asm/cpufeature.h>
2e0f2478 22#include <asm/fpsimd.h>
df857416 23
59ccc0d4 24#include <linux/bitops.h>
80c517b0 25#include <linux/bug.h>
e47b020a
CM
26#include <linux/compat.h>
27#include <linux/elf.h>
df857416 28#include <linux/init.h>
127161aa 29#include <linux/kernel.h>
12d11817 30#include <linux/personality.h>
80c517b0 31#include <linux/preempt.h>
59ccc0d4 32#include <linux/printk.h>
12d11817
SP
33#include <linux/seq_file.h>
34#include <linux/sched.h>
df857416 35#include <linux/smp.h>
92e788b7 36#include <linux/delay.h>
df857416
MR
37
38/*
39 * In case the boot CPU is hotpluggable, we record its initial state and
40 * current state separately. Certain system registers may contain different
41 * values depending on configuration at or after reset.
42 */
43DEFINE_PER_CPU(struct cpuinfo_arm64, cpu_data);
44static struct cpuinfo_arm64 boot_cpu_data;
45
59ccc0d4 46static char *icache_policy_str[] = {
155433cb
WD
47 [0 ... ICACHE_POLICY_PIPT] = "RESERVED/UNKNOWN",
48 [ICACHE_POLICY_VIPT] = "VIPT",
49 [ICACHE_POLICY_PIPT] = "PIPT",
dda288d7 50 [ICACHE_POLICY_VPIPT] = "VPIPT",
59ccc0d4
MR
51};
52
53unsigned long __icache_flags;
54
9299b247 55static const char *const hwcap_str[] = {
12d11817
SP
56 "fp",
57 "asimd",
58 "evtstrm",
59 "aes",
60 "pmull",
61 "sha1",
62 "sha2",
63 "crc32",
64 "atomics",
bf500618
SP
65 "fphp",
66 "asimdhp",
77c97b4e 67 "cpuid",
f92f5ce0 68 "asimdrdm",
c8c3798d 69 "jscvt",
cb567e79 70 "fcma",
c651aae5 71 "lrcpc",
7aac405e 72 "dcpop",
f5e035f8
SP
73 "sha3",
74 "sm3",
75 "sm4",
76 "asimddp",
77 "sha512",
43994d82 78 "sve",
fb0e26e9 79 "asimdfhm",
a060f8f2
SP
80 "dit",
81 "uscat",
82 "ilrcpc",
83 "flagm",
2a3135c3 84 "ssbs",
12d11817
SP
85 NULL
86};
87
88#ifdef CONFIG_COMPAT
9299b247 89static const char *const compat_hwcap_str[] = {
12d11817
SP
90 "swp",
91 "half",
92 "thumb",
93 "26bit",
94 "fastmult",
95 "fpa",
96 "vfp",
97 "edsp",
98 "java",
99 "iwmmxt",
100 "crunch",
101 "thumbee",
102 "neon",
103 "vfpv3",
104 "vfpv3d16",
105 "tls",
106 "vfpv4",
107 "idiva",
108 "idivt",
109 "vfpd32",
110 "lpae",
f228b494
JG
111 "evtstrm",
112 NULL
12d11817
SP
113};
114
9299b247 115static const char *const compat_hwcap2_str[] = {
12d11817
SP
116 "aes",
117 "pmull",
118 "sha1",
119 "sha2",
120 "crc32",
121 NULL
122};
123#endif /* CONFIG_COMPAT */
124
125static int c_show(struct seq_file *m, void *v)
126{
127 int i, j;
e47b020a 128 bool compat = personality(current->personality) == PER_LINUX32;
12d11817
SP
129
130 for_each_online_cpu(i) {
131 struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
132 u32 midr = cpuinfo->reg_midr;
133
134 /*
135 * glibc reads /proc/cpuinfo to determine the number of
136 * online processors, looking for lines beginning with
137 * "processor". Give glibc what it expects.
138 */
139 seq_printf(m, "processor\t: %d\n", i);
e47b020a
CM
140 if (compat)
141 seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
142 MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
12d11817 143
92e788b7
YS
144 seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
145 loops_per_jiffy / (500000UL/HZ),
146 loops_per_jiffy / (5000UL/HZ) % 100);
147
12d11817
SP
148 /*
149 * Dump out the common processor features in a single line.
150 * Userspace should read the hwcaps with getauxval(AT_HWCAP)
151 * rather than attempting to parse this, but there's a body of
152 * software which does already (at least for 32-bit).
153 */
154 seq_puts(m, "Features\t:");
e47b020a 155 if (compat) {
12d11817
SP
156#ifdef CONFIG_COMPAT
157 for (j = 0; compat_hwcap_str[j]; j++)
158 if (compat_elf_hwcap & (1 << j))
159 seq_printf(m, " %s", compat_hwcap_str[j]);
160
161 for (j = 0; compat_hwcap2_str[j]; j++)
162 if (compat_elf_hwcap2 & (1 << j))
163 seq_printf(m, " %s", compat_hwcap2_str[j]);
164#endif /* CONFIG_COMPAT */
165 } else {
166 for (j = 0; hwcap_str[j]; j++)
167 if (elf_hwcap & (1 << j))
168 seq_printf(m, " %s", hwcap_str[j]);
169 }
170 seq_puts(m, "\n");
171
172 seq_printf(m, "CPU implementer\t: 0x%02x\n",
173 MIDR_IMPLEMENTOR(midr));
174 seq_printf(m, "CPU architecture: 8\n");
175 seq_printf(m, "CPU variant\t: 0x%x\n", MIDR_VARIANT(midr));
176 seq_printf(m, "CPU part\t: 0x%03x\n", MIDR_PARTNUM(midr));
177 seq_printf(m, "CPU revision\t: %d\n\n", MIDR_REVISION(midr));
178 }
179
180 return 0;
181}
182
183static void *c_start(struct seq_file *m, loff_t *pos)
184{
185 return *pos < 1 ? (void *)1 : NULL;
186}
187
188static void *c_next(struct seq_file *m, void *v, loff_t *pos)
189{
190 ++*pos;
191 return NULL;
192}
193
194static void c_stop(struct seq_file *m, void *v)
195{
196}
197
198const struct seq_operations cpuinfo_op = {
199 .start = c_start,
200 .next = c_next,
201 .stop = c_stop,
202 .show = c_show
203};
204
f8d9f924
SC
205
206static struct kobj_type cpuregs_kobj_type = {
207 .sysfs_ops = &kobj_sysfs_ops,
208};
209
210/*
211 * The ARM ARM uses the phrase "32-bit register" to describe a register
212 * whose upper 32 bits are RES0 (per C5.1.1, ARM DDI 0487A.i), however
213 * no statement is made as to whether the upper 32 bits will or will not
214 * be made use of in future, and between ARM DDI 0487A.c and ARM DDI
215 * 0487A.d CLIDR_EL1 was expanded from 32-bit to 64-bit.
216 *
217 * Thus, while both MIDR_EL1 and REVIDR_EL1 are described as 32-bit
218 * registers, we expose them both as 64 bit values to cater for possible
219 * future expansion without an ABI break.
220 */
221#define kobj_to_cpuinfo(kobj) container_of(kobj, struct cpuinfo_arm64, kobj)
222#define CPUREGS_ATTR_RO(_name, _field) \
223 static ssize_t _name##_show(struct kobject *kobj, \
224 struct kobj_attribute *attr, char *buf) \
225 { \
226 struct cpuinfo_arm64 *info = kobj_to_cpuinfo(kobj); \
227 \
228 if (info->reg_midr) \
229 return sprintf(buf, "0x%016x\n", info->reg_##_field); \
230 else \
231 return 0; \
232 } \
233 static struct kobj_attribute cpuregs_attr_##_name = __ATTR_RO(_name)
234
235CPUREGS_ATTR_RO(midr_el1, midr);
236CPUREGS_ATTR_RO(revidr_el1, revidr);
237
238static struct attribute *cpuregs_id_attrs[] = {
239 &cpuregs_attr_midr_el1.attr,
240 &cpuregs_attr_revidr_el1.attr,
241 NULL
242};
243
70a62ad1 244static const struct attribute_group cpuregs_attr_group = {
f8d9f924
SC
245 .attrs = cpuregs_id_attrs,
246 .name = "identification"
247};
248
a7ce95e1 249static int cpuid_cpu_online(unsigned int cpu)
f8d9f924
SC
250{
251 int rc;
252 struct device *dev;
253 struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu);
254
255 dev = get_cpu_device(cpu);
256 if (!dev) {
257 rc = -ENODEV;
258 goto out;
259 }
260 rc = kobject_add(&info->kobj, &dev->kobj, "regs");
261 if (rc)
262 goto out;
263 rc = sysfs_create_group(&info->kobj, &cpuregs_attr_group);
264 if (rc)
265 kobject_del(&info->kobj);
266out:
267 return rc;
268}
269
a7ce95e1 270static int cpuid_cpu_offline(unsigned int cpu)
f8d9f924
SC
271{
272 struct device *dev;
273 struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu);
274
275 dev = get_cpu_device(cpu);
276 if (!dev)
277 return -ENODEV;
278 if (info->kobj.parent) {
279 sysfs_remove_group(&info->kobj, &cpuregs_attr_group);
280 kobject_del(&info->kobj);
281 }
282
283 return 0;
284}
285
f8d9f924
SC
286static int __init cpuinfo_regs_init(void)
287{
a7ce95e1 288 int cpu, ret;
f8d9f924
SC
289
290 for_each_possible_cpu(cpu) {
291 struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu);
292
293 kobject_init(&info->kobj, &cpuregs_kobj_type);
f8d9f924 294 }
f8d9f924 295
a7ce95e1
AMG
296 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "arm64/cpuinfo:online",
297 cpuid_cpu_online, cpuid_cpu_offline);
298 if (ret < 0) {
299 pr_err("cpuinfo: failed to register hotplug callbacks.\n");
300 return ret;
301 }
f8d9f924
SC
302 return 0;
303}
59ccc0d4
MR
304static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info)
305{
306 unsigned int cpu = smp_processor_id();
307 u32 l1ip = CTR_L1IP(info->reg_ctr);
308
3689c75a
WD
309 switch (l1ip) {
310 case ICACHE_POLICY_PIPT:
311 break;
dda288d7
WD
312 case ICACHE_POLICY_VPIPT:
313 set_bit(ICACHEF_VPIPT, &__icache_flags);
314 break;
3689c75a 315 default:
3689c75a
WD
316 /* Fallthrough */
317 case ICACHE_POLICY_VIPT:
318 /* Assume aliasing */
319 set_bit(ICACHEF_ALIASING, &__icache_flags);
320 }
59ccc0d4 321
ea171967 322 pr_info("Detected %s I-cache on CPU%d\n", icache_policy_str[l1ip], cpu);
59ccc0d4
MR
323}
324
df857416
MR
325static void __cpuinfo_store_cpu(struct cpuinfo_arm64 *info)
326{
327 info->reg_cntfrq = arch_timer_get_cntfrq();
328 info->reg_ctr = read_cpuid_cachetype();
1cc6ed90 329 info->reg_dczid = read_cpuid(DCZID_EL0);
df857416 330 info->reg_midr = read_cpuid_id();
f8d9f924 331 info->reg_revidr = read_cpuid(REVIDR_EL1);
df857416 332
1cc6ed90
MR
333 info->reg_id_aa64dfr0 = read_cpuid(ID_AA64DFR0_EL1);
334 info->reg_id_aa64dfr1 = read_cpuid(ID_AA64DFR1_EL1);
335 info->reg_id_aa64isar0 = read_cpuid(ID_AA64ISAR0_EL1);
336 info->reg_id_aa64isar1 = read_cpuid(ID_AA64ISAR1_EL1);
337 info->reg_id_aa64mmfr0 = read_cpuid(ID_AA64MMFR0_EL1);
338 info->reg_id_aa64mmfr1 = read_cpuid(ID_AA64MMFR1_EL1);
339 info->reg_id_aa64mmfr2 = read_cpuid(ID_AA64MMFR2_EL1);
340 info->reg_id_aa64pfr0 = read_cpuid(ID_AA64PFR0_EL1);
341 info->reg_id_aa64pfr1 = read_cpuid(ID_AA64PFR1_EL1);
2e0f2478 342 info->reg_id_aa64zfr0 = read_cpuid(ID_AA64ZFR0_EL1);
1cc6ed90 343
a6dc3cd7
SP
344 /* Update the 32bit ID registers only if AArch32 is implemented */
345 if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
346 info->reg_id_dfr0 = read_cpuid(ID_DFR0_EL1);
347 info->reg_id_isar0 = read_cpuid(ID_ISAR0_EL1);
348 info->reg_id_isar1 = read_cpuid(ID_ISAR1_EL1);
349 info->reg_id_isar2 = read_cpuid(ID_ISAR2_EL1);
350 info->reg_id_isar3 = read_cpuid(ID_ISAR3_EL1);
351 info->reg_id_isar4 = read_cpuid(ID_ISAR4_EL1);
352 info->reg_id_isar5 = read_cpuid(ID_ISAR5_EL1);
353 info->reg_id_mmfr0 = read_cpuid(ID_MMFR0_EL1);
354 info->reg_id_mmfr1 = read_cpuid(ID_MMFR1_EL1);
355 info->reg_id_mmfr2 = read_cpuid(ID_MMFR2_EL1);
356 info->reg_id_mmfr3 = read_cpuid(ID_MMFR3_EL1);
357 info->reg_id_pfr0 = read_cpuid(ID_PFR0_EL1);
358 info->reg_id_pfr1 = read_cpuid(ID_PFR1_EL1);
359
360 info->reg_mvfr0 = read_cpuid(MVFR0_EL1);
361 info->reg_mvfr1 = read_cpuid(MVFR1_EL1);
362 info->reg_mvfr2 = read_cpuid(MVFR2_EL1);
363 }
80639d4a 364
2e0f2478
DM
365 if (IS_ENABLED(CONFIG_ARM64_SVE) &&
366 id_aa64pfr0_sve(info->reg_id_aa64pfr0))
367 info->reg_zcr = read_zcr_features();
368
59ccc0d4 369 cpuinfo_detect_icache_policy(info);
df857416
MR
370}
371
372void cpuinfo_store_cpu(void)
373{
374 struct cpuinfo_arm64 *info = this_cpu_ptr(&cpu_data);
375 __cpuinfo_store_cpu(info);
3086d391 376 update_cpu_features(smp_processor_id(), info, &boot_cpu_data);
df857416
MR
377}
378
379void __init cpuinfo_store_boot_cpu(void)
380{
381 struct cpuinfo_arm64 *info = &per_cpu(cpu_data, 0);
382 __cpuinfo_store_cpu(info);
383
384 boot_cpu_data = *info;
3c739b57 385 init_cpu_features(&boot_cpu_data);
df857416 386}
f8d9f924
SC
387
388device_initcall(cpuinfo_regs_init);