Annotation of src/sys/arch/aarch64/aarch64/cpu.c, Revision 1.56.2.1
1.56.2.1! thorpej 1: /* $NetBSD: cpu.c,v 1.57 2020/12/11 18:03:33 skrll Exp $ */
1.1 ryo 2:
3: /*
4: * Copyright (c) 2017 Ryo Shimizu <ryo@nerv.org>
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26: * POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29: #include <sys/cdefs.h>
1.56.2.1! thorpej 30: __KERNEL_RCSID(1, "$NetBSD: cpu.c,v 1.57 2020/12/11 18:03:33 skrll Exp $");
1.1 ryo 31:
32: #include "locators.h"
1.2 ryo 33: #include "opt_arm_debug.h"
34: #include "opt_fdt.h"
1.1 ryo 35: #include "opt_multiprocessor.h"
36:
37: #include <sys/param.h>
1.2 ryo 38: #include <sys/atomic.h>
1.35 skrll 39: #include <sys/cpu.h>
1.1 ryo 40: #include <sys/device.h>
41: #include <sys/kmem.h>
1.14 ryo 42: #include <sys/reboot.h>
1.45 riastrad 43: #include <sys/rndsource.h>
1.13 mrg 44: #include <sys/sysctl.h>
1.35 skrll 45: #include <sys/systm.h>
1.1 ryo 46:
1.53 riastrad 47: #include <crypto/aes/aes_impl.h>
1.49 riastrad 48: #include <crypto/aes/arch/arm/aes_armv8.h>
1.50 riastrad 49: #include <crypto/aes/arch/arm/aes_neon.h>
1.54 riastrad 50: #include <crypto/chacha/chacha_impl.h>
51: #include <crypto/chacha/arch/arm/chacha_neon.h>
1.49 riastrad 52:
1.1 ryo 53: #include <aarch64/armreg.h>
54: #include <aarch64/cpu.h>
1.42 jmcneill 55: #include <aarch64/cpu_counter.h>
1.1 ryo 56: #include <aarch64/machdep.h>
57:
1.56.2.1! thorpej 58: #include <arm/cpufunc.h>
1.34 mrg 59: #include <arm/cpu_topology.h>
1.2 ryo 60: #ifdef FDT
61: #include <arm/fdt/arm_fdtvar.h>
62: #endif
63:
1.4 skrll 64: #ifdef VERBOSE_INIT_ARM
65: #define VPRINTF(...) printf(__VA_ARGS__)
66: #else
1.12 skrll 67: #define VPRINTF(...) __nothing
1.4 skrll 68: #endif
69:
1.1 ryo 70: void cpu_attach(device_t, cpuid_t);
1.2 ryo 71: static void identify_aarch64_model(uint32_t, char *, size_t);
1.6 ryo 72: static void cpu_identify(device_t self, struct cpu_info *);
1.2 ryo 73: static void cpu_identify1(device_t self, struct cpu_info *);
1.1 ryo 74: static void cpu_identify2(device_t self, struct cpu_info *);
1.42 jmcneill 75: static void cpu_init_counter(struct cpu_info *);
1.13 mrg 76: static void cpu_setup_id(struct cpu_info *);
77: static void cpu_setup_sysctl(device_t, struct cpu_info *);
1.45 riastrad 78: static void cpu_setup_rng(device_t, struct cpu_info *);
1.49 riastrad 79: static void cpu_setup_aes(device_t, struct cpu_info *);
1.54 riastrad 80: static void cpu_setup_chacha(device_t, struct cpu_info *);
1.1 ryo 81:
1.2 ryo 82: #ifdef MULTIPROCESSOR
83: #define NCPUINFO MAXCPUS
84: #else
85: #define NCPUINFO 1
86: #endif /* MULTIPROCESSOR */
87:
1.6 ryo 88: /*
89: * Our exported CPU info;
90: * these will be refered from secondary cpus in the middle of hatching.
91: */
92: struct cpu_info cpu_info_store[NCPUINFO] = {
93: [0] = {
94: .ci_cpl = IPL_HIGH,
95: .ci_curlwp = &lwp0
96: }
97: };
98:
1.1 ryo 99: void
100: cpu_attach(device_t dv, cpuid_t id)
101: {
102: struct cpu_info *ci;
1.6 ryo 103: const int unit = device_unit(dv);
1.1 ryo 104:
1.6 ryo 105: if (unit == 0) {
1.1 ryo 106: ci = curcpu();
1.6 ryo 107: ci->ci_cpuid = id;
1.13 mrg 108: cpu_setup_id(ci);
1.1 ryo 109: } else {
110: #ifdef MULTIPROCESSOR
1.14 ryo 111: if ((boothowto & RB_MD1) != 0) {
112: aprint_naive("\n");
113: aprint_normal(": multiprocessor boot disabled\n");
114: return;
115: }
116:
1.6 ryo 117: KASSERT(unit < MAXCPUS);
118: ci = &cpu_info_store[unit];
119:
1.1 ryo 120: ci->ci_cpl = IPL_HIGH;
121: ci->ci_cpuid = id;
1.13 mrg 122: /* ci_id is stored by own cpus when hatching */
1.2 ryo 123:
1.6 ryo 124: cpu_info[ncpu] = ci;
1.23 jmcneill 125: if (cpu_hatched_p(unit) == 0) {
1.1 ryo 126: ci->ci_dev = dv;
127: dv->dv_private = ci;
1.6 ryo 128: ci->ci_index = -1;
1.1 ryo 129:
130: aprint_naive(": disabled\n");
1.2 ryo 131: aprint_normal(": disabled (unresponsive)\n");
1.1 ryo 132: return;
133: }
1.2 ryo 134: #else /* MULTIPROCESSOR */
1.1 ryo 135: aprint_naive(": disabled\n");
136: aprint_normal(": disabled (uniprocessor kernel)\n");
137: return;
1.2 ryo 138: #endif /* MULTIPROCESSOR */
139: }
140:
1.1 ryo 141: ci->ci_dev = dv;
142: dv->dv_private = ci;
143:
1.48 riastrad 144: ci->ci_kfpu_spl = -1;
145:
1.34 mrg 146: arm_cpu_do_topology(ci);
1.33 mrg 147: cpu_identify(ci->ci_dev, ci);
1.26 mlelstv 148:
1.1 ryo 149: #ifdef MULTIPROCESSOR
1.6 ryo 150: if (unit != 0) {
1.1 ryo 151: mi_cpu_attach(ci);
1.2 ryo 152: return;
1.1 ryo 153: }
1.2 ryo 154: #endif /* MULTIPROCESSOR */
1.1 ryo 155:
1.15 ryo 156: set_cpufuncs();
1.1 ryo 157: fpu_attach(ci);
158:
1.2 ryo 159: cpu_identify1(dv, ci);
1.40 skrll 160:
161: /* aarch64_getcacheinfo(0) was called by locore.S */
1.6 ryo 162: aarch64_printcacheinfo(dv);
1.1 ryo 163: cpu_identify2(dv, ci);
1.13 mrg 164:
1.42 jmcneill 165: cpu_init_counter(ci);
166:
1.13 mrg 167: cpu_setup_sysctl(dv, ci);
1.45 riastrad 168: cpu_setup_rng(dv, ci);
1.49 riastrad 169: cpu_setup_aes(dv, ci);
1.54 riastrad 170: cpu_setup_chacha(dv, ci);
1.1 ryo 171: }
172:
173: struct cpuidtab {
174: uint32_t cpu_partnum;
175: const char *cpu_name;
1.43 jmcneill 176: const char *cpu_vendor;
1.1 ryo 177: const char *cpu_architecture;
178: };
179:
180: #define CPU_PARTMASK (CPU_ID_IMPLEMENTOR_MASK | CPU_ID_PARTNO_MASK)
181:
182: const struct cpuidtab cpuids[] = {
1.43 jmcneill 183: { CPU_ID_CORTEXA35R0 & CPU_PARTMASK, "Cortex-A35", "Arm", "v8-A" },
184: { CPU_ID_CORTEXA53R0 & CPU_PARTMASK, "Cortex-A53", "Arm", "v8-A" },
185: { CPU_ID_CORTEXA57R0 & CPU_PARTMASK, "Cortex-A57", "Arm", "v8-A" },
186: { CPU_ID_CORTEXA55R1 & CPU_PARTMASK, "Cortex-A55", "Arm", "v8.2-A+" },
187: { CPU_ID_CORTEXA65R0 & CPU_PARTMASK, "Cortex-A65", "Arm", "v8.2-A+" },
188: { CPU_ID_CORTEXA72R0 & CPU_PARTMASK, "Cortex-A72", "Arm", "v8-A" },
189: { CPU_ID_CORTEXA73R0 & CPU_PARTMASK, "Cortex-A73", "Arm", "v8-A" },
190: { CPU_ID_CORTEXA75R2 & CPU_PARTMASK, "Cortex-A75", "Arm", "v8.2-A+" },
191: { CPU_ID_CORTEXA76R3 & CPU_PARTMASK, "Cortex-A76", "Arm", "v8.2-A+" },
192: { CPU_ID_CORTEXA76AER1 & CPU_PARTMASK, "Cortex-A76AE", "Arm", "v8.2-A+" },
193: { CPU_ID_CORTEXA77R0 & CPU_PARTMASK, "Cortex-A77", "Arm", "v8.2-A+" },
194: { CPU_ID_NVIDIADENVER2 & CPU_PARTMASK, "Denver2", "NVIDIA", "v8-A" },
195: { CPU_ID_EMAG8180 & CPU_PARTMASK, "eMAG", "Ampere", "v8-A" },
196: { CPU_ID_NEOVERSEE1R1 & CPU_PARTMASK, "Neoverse E1", "Arm", "v8.2-A+" },
197: { CPU_ID_NEOVERSEN1R3 & CPU_PARTMASK, "Neoverse N1", "Arm", "v8.2-A+" },
198: { CPU_ID_THUNDERXRX, "ThunderX", "Cavium", "v8-A" },
199: { CPU_ID_THUNDERX81XXRX, "ThunderX CN81XX", "Cavium", "v8-A" },
200: { CPU_ID_THUNDERX83XXRX, "ThunderX CN83XX", "Cavium", "v8-A" },
201: { CPU_ID_THUNDERX2RX, "ThunderX2", "Marvell", "v8.1-A" },
1.1 ryo 202: };
203:
204: static void
205: identify_aarch64_model(uint32_t cpuid, char *buf, size_t len)
206: {
207: int i;
208: uint32_t cpupart, variant, revision;
209:
210: cpupart = cpuid & CPU_PARTMASK;
211: variant = __SHIFTOUT(cpuid, CPU_ID_VARIANT_MASK);
212: revision = __SHIFTOUT(cpuid, CPU_ID_REVISION_MASK);
213:
214: for (i = 0; i < __arraycount(cpuids); i++) {
215: if (cpupart == cpuids[i].cpu_partnum) {
1.43 jmcneill 216: snprintf(buf, len, "%s %s r%dp%d (%s)",
217: cpuids[i].cpu_vendor, cpuids[i].cpu_name,
218: variant, revision,
1.1 ryo 219: cpuids[i].cpu_architecture);
220: return;
221: }
222: }
223:
224: snprintf(buf, len, "unknown CPU (ID = 0x%08x)", cpuid);
225: }
226:
227: static void
1.6 ryo 228: cpu_identify(device_t self, struct cpu_info *ci)
1.1 ryo 229: {
230: char model[128];
1.32 martin 231: const char *m;
1.1 ryo 232:
1.13 mrg 233: identify_aarch64_model(ci->ci_id.ac_midr, model, sizeof(model));
1.36 skrll 234: if (ci->ci_index == 0) {
1.32 martin 235: m = cpu_getmodel();
236: if (m == NULL || *m == 0)
237: cpu_setmodel("%s", model);
238: }
1.1 ryo 239:
240: aprint_naive("\n");
1.43 jmcneill 241: aprint_normal(": %s, id 0x%lx\n", model, ci->ci_cpuid);
1.2 ryo 242: }
1.1 ryo 243:
1.2 ryo 244: static void
245: cpu_identify1(device_t self, struct cpu_info *ci)
246: {
1.51 ryo 247: uint64_t ctr, clidr, sctlr; /* for cache */
1.1 ryo 248:
249: /* SCTLR - System Control Register */
250: sctlr = reg_sctlr_el1_read();
251: if (sctlr & SCTLR_I)
1.43 jmcneill 252: aprint_verbose_dev(self, "IC enabled");
1.1 ryo 253: else
1.43 jmcneill 254: aprint_verbose_dev(self, "IC disabled");
1.1 ryo 255:
256: if (sctlr & SCTLR_C)
1.43 jmcneill 257: aprint_verbose(", DC enabled");
1.1 ryo 258: else
1.43 jmcneill 259: aprint_verbose(", DC disabled");
1.1 ryo 260:
261: if (sctlr & SCTLR_A)
1.43 jmcneill 262: aprint_verbose(", Alignment check enabled\n");
1.1 ryo 263: else {
264: switch (sctlr & (SCTLR_SA | SCTLR_SA0)) {
265: case SCTLR_SA | SCTLR_SA0:
1.43 jmcneill 266: aprint_verbose(
1.1 ryo 267: ", EL0/EL1 stack Alignment check enabled\n");
268: break;
269: case SCTLR_SA:
1.43 jmcneill 270: aprint_verbose(", EL1 stack Alignment check enabled\n");
1.1 ryo 271: break;
272: case SCTLR_SA0:
1.43 jmcneill 273: aprint_verbose(", EL0 stack Alignment check enabled\n");
1.1 ryo 274: break;
275: case 0:
1.43 jmcneill 276: aprint_verbose(", Alignment check disabled\n");
1.1 ryo 277: break;
278: }
279: }
280:
281: /*
282: * CTR - Cache Type Register
283: */
284: ctr = reg_ctr_el0_read();
1.51 ryo 285: clidr = reg_clidr_el1_read();
1.43 jmcneill 286: aprint_verbose_dev(self, "Cache Writeback Granule %" PRIu64 "B,"
1.3 christos 287: " Exclusives Reservation Granule %" PRIu64 "B\n",
1.1 ryo 288: __SHIFTOUT(ctr, CTR_EL0_CWG_LINE) * 4,
289: __SHIFTOUT(ctr, CTR_EL0_ERG_LINE) * 4);
290:
1.51 ryo 291: aprint_verbose_dev(self, "Dcache line %ld, Icache line %ld"
292: ", DIC=%lu, IDC=%lu, LoUU=%lu, LoC=%lu, LoUIS=%lu\n",
1.1 ryo 293: sizeof(int) << __SHIFTOUT(ctr, CTR_EL0_DMIN_LINE),
1.51 ryo 294: sizeof(int) << __SHIFTOUT(ctr, CTR_EL0_IMIN_LINE),
295: __SHIFTOUT(ctr, CTR_EL0_DIC),
296: __SHIFTOUT(ctr, CTR_EL0_IDC),
297: __SHIFTOUT(clidr, CLIDR_LOUU),
298: __SHIFTOUT(clidr, CLIDR_LOC),
299: __SHIFTOUT(clidr, CLIDR_LOUIS));
1.1 ryo 300: }
301:
302:
303: /*
304: * identify vfp, etc.
305: */
306: static void
307: cpu_identify2(device_t self, struct cpu_info *ci)
308: {
1.13 mrg 309: struct aarch64_sysctl_cpu_id *id = &ci->ci_id;
310: uint64_t dfr0;
1.1 ryo 311:
1.13 mrg 312: if (!CPU_IS_PRIMARY(ci)) {
313: cpu_setup_id(ci);
314: cpu_setup_sysctl(self, ci);
315: }
1.1 ryo 316:
317: dfr0 = reg_id_aa64dfr0_el1_read();
318:
1.33 mrg 319: aprint_debug_dev(self, "midr=0x%" PRIx32 " mpidr=0x%" PRIx32 "\n",
320: (uint32_t)ci->ci_id.ac_midr, (uint32_t)ci->ci_id.ac_mpidr);
1.43 jmcneill 321: aprint_verbose_dev(self, "revID=0x%" PRIx64, id->ac_revidr);
1.1 ryo 322:
323: /* ID_AA64DFR0_EL1 */
324: switch (__SHIFTOUT(dfr0, ID_AA64DFR0_EL1_PMUVER)) {
325: case ID_AA64DFR0_EL1_PMUVER_V3:
1.43 jmcneill 326: aprint_verbose(", PMCv3");
1.1 ryo 327: break;
328: case ID_AA64DFR0_EL1_PMUVER_NOV3:
1.43 jmcneill 329: aprint_verbose(", PMC");
1.1 ryo 330: break;
331: }
332:
333: /* ID_AA64MMFR0_EL1 */
1.13 mrg 334: switch (__SHIFTOUT(id->ac_aa64mmfr0, ID_AA64MMFR0_EL1_TGRAN4)) {
1.1 ryo 335: case ID_AA64MMFR0_EL1_TGRAN4_4KB:
1.43 jmcneill 336: aprint_verbose(", 4k table");
1.1 ryo 337: break;
338: }
1.13 mrg 339: switch (__SHIFTOUT(id->ac_aa64mmfr0, ID_AA64MMFR0_EL1_TGRAN16)) {
1.1 ryo 340: case ID_AA64MMFR0_EL1_TGRAN16_16KB:
1.43 jmcneill 341: aprint_verbose(", 16k table");
1.1 ryo 342: break;
343: }
1.13 mrg 344: switch (__SHIFTOUT(id->ac_aa64mmfr0, ID_AA64MMFR0_EL1_TGRAN64)) {
1.1 ryo 345: case ID_AA64MMFR0_EL1_TGRAN64_64KB:
1.43 jmcneill 346: aprint_verbose(", 64k table");
1.1 ryo 347: break;
348: }
349:
1.13 mrg 350: switch (__SHIFTOUT(id->ac_aa64mmfr0, ID_AA64MMFR0_EL1_ASIDBITS)) {
1.1 ryo 351: case ID_AA64MMFR0_EL1_ASIDBITS_8BIT:
1.43 jmcneill 352: aprint_verbose(", 8bit ASID");
1.1 ryo 353: break;
354: case ID_AA64MMFR0_EL1_ASIDBITS_16BIT:
1.43 jmcneill 355: aprint_verbose(", 16bit ASID");
1.1 ryo 356: break;
357: }
1.43 jmcneill 358: aprint_verbose("\n");
1.1 ryo 359:
360:
361:
1.43 jmcneill 362: aprint_verbose_dev(self, "auxID=0x%" PRIx64, ci->ci_id.ac_aa64isar0);
1.1 ryo 363:
364: /* PFR0 */
1.47 riastrad 365: switch (__SHIFTOUT(id->ac_aa64pfr0, ID_AA64PFR0_EL1_CSV3)) {
366: case ID_AA64PFR0_EL1_CSV3_IMPL:
367: aprint_verbose(", CSV3");
368: break;
369: }
370: switch (__SHIFTOUT(id->ac_aa64pfr0, ID_AA64PFR0_EL1_CSV2)) {
371: case ID_AA64PFR0_EL1_CSV2_IMPL:
372: aprint_verbose(", CSV2");
373: break;
374: }
1.13 mrg 375: switch (__SHIFTOUT(id->ac_aa64pfr0, ID_AA64PFR0_EL1_GIC)) {
1.1 ryo 376: case ID_AA64PFR0_EL1_GIC_CPUIF_EN:
1.43 jmcneill 377: aprint_verbose(", GICv3");
1.1 ryo 378: break;
379: }
1.13 mrg 380: switch (__SHIFTOUT(id->ac_aa64pfr0, ID_AA64PFR0_EL1_FP)) {
1.56 jmcneill 381: case ID_AA64PFR0_EL1_FP_NONE:
382: break;
383: default:
1.43 jmcneill 384: aprint_verbose(", FP");
1.1 ryo 385: break;
386: }
387:
388: /* ISAR0 */
1.13 mrg 389: switch (__SHIFTOUT(id->ac_aa64isar0, ID_AA64ISAR0_EL1_CRC32)) {
1.1 ryo 390: case ID_AA64ISAR0_EL1_CRC32_CRC32X:
1.43 jmcneill 391: aprint_verbose(", CRC32");
1.1 ryo 392: break;
393: }
1.13 mrg 394: switch (__SHIFTOUT(id->ac_aa64isar0, ID_AA64ISAR0_EL1_SHA1)) {
1.1 ryo 395: case ID_AA64ISAR0_EL1_SHA1_SHA1CPMHSU:
1.43 jmcneill 396: aprint_verbose(", SHA1");
1.1 ryo 397: break;
398: }
1.13 mrg 399: switch (__SHIFTOUT(id->ac_aa64isar0, ID_AA64ISAR0_EL1_SHA2)) {
1.1 ryo 400: case ID_AA64ISAR0_EL1_SHA2_SHA256HSU:
1.43 jmcneill 401: aprint_verbose(", SHA256");
1.1 ryo 402: break;
403: }
1.13 mrg 404: switch (__SHIFTOUT(id->ac_aa64isar0, ID_AA64ISAR0_EL1_AES)) {
1.1 ryo 405: case ID_AA64ISAR0_EL1_AES_AES:
1.43 jmcneill 406: aprint_verbose(", AES");
1.1 ryo 407: break;
408: case ID_AA64ISAR0_EL1_AES_PMUL:
1.43 jmcneill 409: aprint_verbose(", AES+PMULL");
1.1 ryo 410: break;
411: }
1.44 riastrad 412: switch (__SHIFTOUT(id->ac_aa64isar0, ID_AA64ISAR0_EL1_RNDR)) {
413: case ID_AA64ISAR0_EL1_RNDR_RNDRRS:
414: aprint_verbose(", RNDRRS");
415: break;
416: }
1.1 ryo 417:
1.47 riastrad 418: /* PFR0:DIT -- data-independent timing support */
419: switch (__SHIFTOUT(id->ac_aa64pfr0, ID_AA64PFR0_EL1_DIT)) {
420: case ID_AA64PFR0_EL1_DIT_IMPL:
421: aprint_verbose(", DIT");
422: break;
423: }
1.1 ryo 424:
425: /* PFR0:AdvSIMD */
1.13 mrg 426: switch (__SHIFTOUT(id->ac_aa64pfr0, ID_AA64PFR0_EL1_ADVSIMD)) {
1.56 jmcneill 427: case ID_AA64PFR0_EL1_ADV_SIMD_NONE:
428: break;
429: default:
1.43 jmcneill 430: aprint_verbose(", NEON");
1.1 ryo 431: break;
432: }
433:
434: /* MVFR0/MVFR1 */
1.13 mrg 435: switch (__SHIFTOUT(id->ac_mvfr0, MVFR0_FPROUND)) {
1.1 ryo 436: case MVFR0_FPROUND_ALL:
1.43 jmcneill 437: aprint_verbose(", rounding");
1.1 ryo 438: break;
439: }
1.13 mrg 440: switch (__SHIFTOUT(id->ac_mvfr0, MVFR0_FPTRAP)) {
1.1 ryo 441: case MVFR0_FPTRAP_TRAP:
1.43 jmcneill 442: aprint_verbose(", exceptions");
1.1 ryo 443: break;
444: }
1.13 mrg 445: switch (__SHIFTOUT(id->ac_mvfr1, MVFR1_FPDNAN)) {
1.1 ryo 446: case MVFR1_FPDNAN_NAN:
1.43 jmcneill 447: aprint_verbose(", NaN propagation");
1.1 ryo 448: break;
449: }
1.13 mrg 450: switch (__SHIFTOUT(id->ac_mvfr1, MVFR1_FPFTZ)) {
1.1 ryo 451: case MVFR1_FPFTZ_DENORMAL:
1.43 jmcneill 452: aprint_verbose(", denormals");
1.1 ryo 453: break;
454: }
1.13 mrg 455: switch (__SHIFTOUT(id->ac_mvfr0, MVFR0_SIMDREG)) {
1.1 ryo 456: case MVFR0_SIMDREG_16x64:
1.43 jmcneill 457: aprint_verbose(", 16x64bitRegs");
1.1 ryo 458: break;
459: case MVFR0_SIMDREG_32x64:
1.43 jmcneill 460: aprint_verbose(", 32x64bitRegs");
1.1 ryo 461: break;
462: }
1.13 mrg 463: switch (__SHIFTOUT(id->ac_mvfr1, MVFR1_SIMDFMAC)) {
1.1 ryo 464: case MVFR1_SIMDFMAC_FMAC:
1.43 jmcneill 465: aprint_verbose(", Fused Multiply-Add");
1.1 ryo 466: break;
467: }
468:
1.43 jmcneill 469: aprint_verbose("\n");
1.1 ryo 470: }
1.2 ryo 471:
1.13 mrg 472: /*
1.42 jmcneill 473: * Enable the performance counter, then estimate frequency for
474: * the current PE and store the result in cpu_cc_freq.
475: */
476: static void
477: cpu_init_counter(struct cpu_info *ci)
478: {
1.55 jmcneill 479: const uint64_t dfr0 = reg_id_aa64dfr0_el1_read();
480: const u_int pmuver = __SHIFTOUT(dfr0, ID_AA64DFR0_EL1_PMUVER);
481: if (pmuver == ID_AA64DFR0_EL1_PMUVER_NONE) {
482: /* Performance Monitors Extension not implemented. */
483: return;
484: }
485:
1.42 jmcneill 486: reg_pmcr_el0_write(PMCR_E | PMCR_C);
487: reg_pmcntenset_el0_write(PMCNTEN_C);
488:
489: const uint32_t prev = cpu_counter32();
490: delay(100000);
491: ci->ci_data.cpu_cc_freq = (cpu_counter32() - prev) * 10;
492: }
493:
494: /*
1.13 mrg 495: * Fill in this CPUs id data. Must be called from hatched cpus.
496: */
497: static void
498: cpu_setup_id(struct cpu_info *ci)
499: {
500: struct aarch64_sysctl_cpu_id *id = &ci->ci_id;
501:
502: memset(id, 0, sizeof *id);
503:
504: id->ac_midr = reg_midr_el1_read();
505: id->ac_revidr = reg_revidr_el1_read();
506: id->ac_mpidr = reg_mpidr_el1_read();
507:
508: id->ac_aa64dfr0 = reg_id_aa64dfr0_el1_read();
509: id->ac_aa64dfr1 = reg_id_aa64dfr1_el1_read();
510:
511: id->ac_aa64isar0 = reg_id_aa64isar0_el1_read();
512: id->ac_aa64isar1 = reg_id_aa64isar1_el1_read();
513:
514: id->ac_aa64mmfr0 = reg_id_aa64mmfr0_el1_read();
515: id->ac_aa64mmfr1 = reg_id_aa64mmfr1_el1_read();
1.39 maxv 516: id->ac_aa64mmfr2 = reg_id_aa64mmfr2_el1_read();
1.13 mrg 517:
518: id->ac_mvfr0 = reg_mvfr0_el1_read();
519: id->ac_mvfr1 = reg_mvfr1_el1_read();
520: id->ac_mvfr2 = reg_mvfr2_el1_read();
521:
1.52 ryo 522: id->ac_clidr = reg_clidr_el1_read();
523: id->ac_ctr = reg_ctr_el0_read();
524:
1.13 mrg 525: /* Only in ARMv8.2. */
526: id->ac_aa64zfr0 = 0 /* reg_id_aa64zfr0_el1_read() */;
527:
528: id->ac_aa64pfr0 = reg_id_aa64pfr0_el1_read();
529: id->ac_aa64pfr1 = reg_id_aa64pfr1_el1_read();
530: }
531:
532: /*
533: * setup the per-cpu sysctl tree.
534: */
535: static void
536: cpu_setup_sysctl(device_t dv, struct cpu_info *ci)
537: {
538: const struct sysctlnode *cpunode = NULL;
539:
540: sysctl_createv(NULL, 0, NULL, &cpunode,
541: CTLFLAG_PERMANENT,
542: CTLTYPE_NODE, device_xname(dv), NULL,
543: NULL, 0, NULL, 0,
544: CTL_MACHDEP,
545: CTL_CREATE, CTL_EOL);
546:
547: if (cpunode == NULL)
548: return;
549:
550: sysctl_createv(NULL, 0, &cpunode, NULL,
551: CTLFLAG_PERMANENT,
552: CTLTYPE_STRUCT, "cpu_id", NULL,
553: NULL, 0, &ci->ci_id, sizeof(ci->ci_id),
554: CTL_CREATE, CTL_EOL);
555: }
556:
1.45 riastrad 557: static struct krndsource rndrrs_source;
558:
559: static void
560: rndrrs_get(size_t nbytes, void *cookie)
561: {
562: /* Entropy bits per data byte, wild-arse guess. */
563: const unsigned bpb = 4;
564: size_t nbits = nbytes*NBBY;
565: uint64_t x;
566: int error;
567:
568: while (nbits) {
569: /*
570: * x := random 64-bit sample
571: * error := Z bit, set to 1 if sample is bad
572: *
573: * XXX This should be done by marking the function
574: * __attribute__((target("arch=armv8.5-a+rng"))) and
575: * using `mrs %0, rndrrs', but:
576: *
577: * (a) the version of gcc we use doesn't support that,
578: * and
579: * (b) clang doesn't seem to like `rndrrs' itself.
580: *
581: * So we use the numeric encoding for now.
582: */
583: __asm __volatile(""
584: "mrs %0, s3_3_c2_c4_1\n"
585: "cset %w1, eq"
586: : "=r"(x), "=r"(error));
587: if (error)
588: break;
589: rnd_add_data_sync(&rndrrs_source, &x, sizeof(x),
590: bpb*sizeof(x));
591: nbits -= MIN(nbits, bpb*sizeof(x));
592: }
593:
594: explicit_memset(&x, 0, sizeof x);
595: }
596:
597: /*
598: * setup the RNDRRS entropy source
599: */
600: static void
601: cpu_setup_rng(device_t dv, struct cpu_info *ci)
602: {
603: struct aarch64_sysctl_cpu_id *id = &ci->ci_id;
604:
605: /* Probably shared between cores. */
606: if (!CPU_IS_PRIMARY(ci))
607: return;
608:
609: /* Verify that it is supported. */
610: switch (__SHIFTOUT(id->ac_aa64isar0, ID_AA64ISAR0_EL1_RNDR)) {
611: case ID_AA64ISAR0_EL1_RNDR_RNDRRS:
612: break;
613: default:
614: return;
615: }
616:
617: /* Attach it. */
618: rndsource_setcb(&rndrrs_source, rndrrs_get, NULL);
619: rnd_attach_source(&rndrrs_source, "rndrrs", RND_TYPE_RNG,
620: RND_FLAG_DEFAULT|RND_FLAG_HASCB);
621: }
622:
1.49 riastrad 623: /*
624: * setup the AES implementation
625: */
626: static void
627: cpu_setup_aes(device_t dv, struct cpu_info *ci)
628: {
629: struct aarch64_sysctl_cpu_id *id = &ci->ci_id;
630:
1.50 riastrad 631: /* Check for ARMv8.0-AES support. */
1.49 riastrad 632: switch (__SHIFTOUT(id->ac_aa64isar0, ID_AA64ISAR0_EL1_AES)) {
633: case ID_AA64ISAR0_EL1_AES_AES:
634: case ID_AA64ISAR0_EL1_AES_PMUL:
1.50 riastrad 635: aes_md_init(&aes_armv8_impl);
636: return;
637: default:
1.49 riastrad 638: break;
1.50 riastrad 639: }
640:
641: /* Failing that, check for SIMD support. */
642: switch (__SHIFTOUT(id->ac_aa64pfr0, ID_AA64PFR0_EL1_ADVSIMD)) {
643: case ID_AA64PFR0_EL1_ADV_SIMD_IMPL:
644: aes_md_init(&aes_neon_impl);
645: return;
1.49 riastrad 646: default:
1.50 riastrad 647: break;
1.49 riastrad 648: }
649: }
650:
1.54 riastrad 651: /*
652: * setup the ChaCha implementation
653: */
654: static void
655: cpu_setup_chacha(device_t dv, struct cpu_info *ci)
656: {
657: struct aarch64_sysctl_cpu_id *id = &ci->ci_id;
658:
659: /* Check for SIMD support. */
660: switch (__SHIFTOUT(id->ac_aa64pfr0, ID_AA64PFR0_EL1_ADVSIMD)) {
661: case ID_AA64PFR0_EL1_ADV_SIMD_IMPL:
662: chacha_md_init(&chacha_neon_impl);
663: return;
664: default:
665: break;
666: }
667: }
668:
1.2 ryo 669: #ifdef MULTIPROCESSOR
670: void
671: cpu_hatch(struct cpu_info *ci)
672: {
673: KASSERT(curcpu() == ci);
674:
675: mutex_enter(&cpu_hatch_lock);
676:
1.15 ryo 677: set_cpufuncs();
1.2 ryo 678: fpu_attach(ci);
679:
680: cpu_identify1(ci->ci_dev, ci);
1.26 mlelstv 681: aarch64_getcacheinfo(device_unit(ci->ci_dev));
1.6 ryo 682: aarch64_printcacheinfo(ci->ci_dev);
1.2 ryo 683: cpu_identify2(ci->ci_dev, ci);
684:
685: mutex_exit(&cpu_hatch_lock);
686:
1.42 jmcneill 687: cpu_init_counter(ci);
688:
1.2 ryo 689: intr_cpu_init(ci);
690:
691: #ifdef FDT
692: arm_fdt_cpu_hatch(ci);
693: #endif
694: #ifdef MD_CPU_HATCH
695: MD_CPU_HATCH(ci); /* for non-fdt arch? */
696: #endif
697:
1.6 ryo 698: /*
1.41 skrll 699: * clear my bit of arm_cpu_mbox to tell cpu_boot_secondary_processors().
1.6 ryo 700: * there are cpu0,1,2,3, and if cpu2 is unresponsive,
701: * ci_index are each cpu0=0, cpu1=1, cpu2=undef, cpu3=2.
702: * therefore we have to use device_unit instead of ci_index for mbox.
703: */
1.23 jmcneill 704:
1.41 skrll 705: cpu_clr_mbox(device_unit(ci->ci_dev));
1.23 jmcneill 706: }
1.2 ryo 707: #endif /* MULTIPROCESSOR */
CVSweb <webmaster@jp.NetBSD.org>