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