Author: andrew
Date: Wed Dec 30 17:36:34 2015
New Revision: 292954
URL: https://svnweb.freebsd.org/changeset/base/292954

Log:
  Decode and print the ID_AA64* registers on boot. These registers hold
  information on what the core supports. In most cases these will be
  identical across most CPUs in the SoC, however there may be the case where,
  with a big.LITTLE setup they may differ. In this case we print the
  decoded data on all CPUs.
  
  Reviewed by:  kib
  Sponsored by: ABT Systems Ltd
  Differential Revision:        https://reviews.freebsd.org/D4725

Modified:
  head/sys/arm64/arm64/identcpu.c
  head/sys/arm64/arm64/mp_machdep.c
  head/sys/arm64/include/armreg.h
  head/sys/arm64/include/cpu.h

Modified: head/sys/arm64/arm64/identcpu.c
==============================================================================
--- head/sys/arm64/arm64/identcpu.c     Wed Dec 30 17:10:03 2015        
(r292953)
+++ head/sys/arm64/arm64/identcpu.c     Wed Dec 30 17:36:34 2015        
(r292954)
@@ -37,9 +37,12 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 #include <sys/systm.h>
 
+#include <machine/atomic.h>
 #include <machine/cpu.h>
 #include <machine/cpufunc.h>
 
+static int ident_lock;
+
 char machine[] = "arm64";
 
 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0,
@@ -56,6 +59,7 @@ SYSCTL_STRING(_hw, HW_MACHINE, machine, 
  * Aff0 - CPU number in Aff1 cluster
  */
 uint64_t __cpu_affinity[MAXCPU];
+static u_int cpu_aff_levels;
 
 struct cpu_desc {
        u_int           cpu_impl;
@@ -64,9 +68,32 @@ struct cpu_desc {
        u_int           cpu_revision;
        const char      *cpu_impl_name;
        const char      *cpu_part_name;
+
+       uint64_t        mpidr;
+       uint64_t        id_aa64afr0;
+       uint64_t        id_aa64afr1;
+       uint64_t        id_aa64dfr0;
+       uint64_t        id_aa64dfr1;
+       uint64_t        id_aa64isar0;
+       uint64_t        id_aa64isar1;
+       uint64_t        id_aa64mmfr0;
+       uint64_t        id_aa64mmfr1;
+       uint64_t        id_aa64pfr0;
+       uint64_t        id_aa64pfr1;
 };
 
 struct cpu_desc cpu_desc[MAXCPU];
+static u_int cpu_print_regs;
+#define        PRINT_ID_AA64_AFR0      0x00000001
+#define        PRINT_ID_AA64_AFR1      0x00000002
+#define        PRINT_ID_AA64_DFR0      0x00000004
+#define        PRINT_ID_AA64_DFR1      0x00000008
+#define        PRINT_ID_AA64_ISAR0     0x00000010
+#define        PRINT_ID_AA64_ISAR1     0x00000020
+#define        PRINT_ID_AA64_MMFR0     0x00000040
+#define        PRINT_ID_AA64_MMFR1     0x00000080
+#define        PRINT_ID_AA64_PFR0      0x00000100
+#define        PRINT_ID_AA64_PFR1      0x00000200
 
 struct cpu_parts {
        u_int           part_id;
@@ -124,7 +151,398 @@ const struct cpu_implementers cpu_implem
        CPU_IMPLEMENTER_NONE,
 };
 
-void identify_cpu(void);
+void
+print_cpu_features(u_int cpu)
+{
+       int printed;
+
+       printf("CPU%3d: %s %s r%dp%d", cpu, cpu_desc[cpu].cpu_impl_name,
+           cpu_desc[cpu].cpu_part_name, cpu_desc[cpu].cpu_variant,
+           cpu_desc[cpu].cpu_revision);
+
+       printf(" affinity:");
+       switch(cpu_aff_levels) {
+       default:
+       case 4:
+               printf(" %2d", CPU_AFF3(cpu_desc[cpu].mpidr));
+               /* FALLTHROUGH */
+       case 3:
+               printf(" %2d", CPU_AFF2(cpu_desc[cpu].mpidr));
+               /* FALLTHROUGH */
+       case 2:
+               printf(" %2d", CPU_AFF1(cpu_desc[cpu].mpidr));
+               /* FALLTHROUGH */
+       case 1:
+       case 0: /* On UP this will be zero */
+               printf(" %2d", CPU_AFF0(cpu_desc[cpu].mpidr));
+               break;
+       }
+       printf("\n");
+
+       if (cpu != 0 && cpu_print_regs == 0)
+               return;
+
+#define SEP_STR        ((printed++) == 0) ? "" : ","
+
+       /* AArch64 Instruction Set Attribute Register 0 */
+       if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR0) != 0) {
+               printed = 0;
+               printf(" Instruction Set Attributes 0 = <");
+               switch (ID_AA64ISAR0_AES(cpu_desc[cpu].id_aa64isar0)) {
+               case ID_AA64ISAR0_AES_NONE:
+                       break;
+               case ID_AA64ISAR0_AES_BASE:
+                       printf("%sAES", SEP_STR);
+                       break;
+               case ID_AA64ISAR0_AES_PMULL:
+                       printf("%sAES+PMULL", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown AES", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64ISAR0_SHA1(cpu_desc[cpu].id_aa64isar0)) {
+               case ID_AA64ISAR0_SHA1_NONE:
+                       break;
+               case ID_AA64ISAR0_SHA1_BASE:
+                       printf("%sSHA1", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown SHA1", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64ISAR0_SHA2(cpu_desc[cpu].id_aa64isar0)) {
+               case ID_AA64ISAR0_SHA2_NONE:
+                       break;
+               case ID_AA64ISAR0_SHA2_BASE:
+                       printf("%sSHA2", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown SHA2", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64ISAR0_CRC32(cpu_desc[cpu].id_aa64isar0)) {
+               case ID_AA64ISAR0_CRC32_NONE:
+                       break;
+               case ID_AA64ISAR0_CRC32_BASE:
+                       printf("%sCRC32", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown CRC32", SEP_STR);
+                       break;
+               }
+
+               if ((cpu_desc[cpu].id_aa64isar0 & ~ID_AA64ISAR0_MASK) != 0)
+                       printf("%s%#lx", SEP_STR,
+                           cpu_desc[cpu].id_aa64isar0 & ~ID_AA64ISAR0_MASK);
+
+               printf(">\n");
+       }
+
+       /* AArch64 Instruction Set Attribute Register 1 */
+       if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR1) != 0) {
+               printf(" Instruction Set Attributes 1 = <%#lx>\n",
+                   cpu_desc[cpu].id_aa64isar1);
+       }
+
+       /* AArch64 Processor Feature Register 0 */
+       if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_PFR0) != 0) {
+               printed = 0;
+               printf("         Processor Features 0 = <");
+               switch (ID_AA64PFR0_GIC(cpu_desc[cpu].id_aa64pfr0)) {
+               case ID_AA64PFR0_GIC_CPUIF_NONE:
+                       break;
+               case ID_AA64PFR0_GIC_CPUIF_EN:
+                       printf("%sGIC", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown GIC interface", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64PFR0_ADV_SIMD(cpu_desc[cpu].id_aa64pfr0)) {
+               case ID_AA64PFR0_ADV_SIMD_NONE:
+                       break;
+               case ID_AA64PFR0_ADV_SIMD_IMPL:
+                       printf("%sAdvSIMD", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown AdvSIMD", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64PFR0_FP(cpu_desc[cpu].id_aa64pfr0)) {
+               case ID_AA64PFR0_FP_NONE:
+                       break;
+               case ID_AA64PFR0_FP_IMPL:
+                       printf("%sFloat", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown Float", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64PFR0_EL3(cpu_desc[cpu].id_aa64pfr0)) {
+               case ID_AA64PFR0_EL3_NONE:
+                       printf("%sNo EL3", SEP_STR);
+                       break;
+               case ID_AA64PFR0_EL3_64:
+                       printf("%sEL3", SEP_STR);
+                       break;
+               case ID_AA64PFR0_EL3_64_32:
+                       printf("%sEL3 32", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown EL3", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64PFR0_EL2(cpu_desc[cpu].id_aa64pfr0)) {
+               case ID_AA64PFR0_EL2_NONE:
+                       printf("%sNo EL2", SEP_STR);
+                       break;
+               case ID_AA64PFR0_EL2_64:
+                       printf("%sEL2", SEP_STR);
+                       break;
+               case ID_AA64PFR0_EL2_64_32:
+                       printf("%sEL2 32", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown EL2", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64PFR0_EL1(cpu_desc[cpu].id_aa64pfr0)) {
+               case ID_AA64PFR0_EL1_64:
+                       printf("%sEL1", SEP_STR);
+                       break;
+               case ID_AA64PFR0_EL1_64_32:
+                       printf("%sEL1 32", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown EL1", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64PFR0_EL0(cpu_desc[cpu].id_aa64pfr0)) {
+               case ID_AA64PFR0_EL0_64:
+                       printf("%sEL0", SEP_STR);
+                       break;
+               case ID_AA64PFR0_EL0_64_32:
+                       printf("%sEL0 32", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown EL0", SEP_STR);
+                       break;
+               }
+
+               if ((cpu_desc[cpu].id_aa64pfr0 & ~ID_AA64PFR0_MASK) != 0)
+                       printf("%s%#lx", SEP_STR,
+                           cpu_desc[cpu].id_aa64pfr0 & ~ID_AA64PFR0_MASK);
+
+               printf(">\n");
+       }
+
+       /* AArch64 Processor Feature Register 1 */
+       if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_PFR1) != 0) {
+               printf("         Processor Features 1 = <%#lx>\n",
+                   cpu_desc[cpu].id_aa64pfr1);
+       }
+
+       /* AArch64 Memory Model Feature Register 0 */
+       if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR0) != 0) {
+               printed = 0;
+               printf("      Memory Model Features 0 = <");
+               switch (ID_AA64MMFR0_TGRAN4(cpu_desc[cpu].id_aa64mmfr0)) {
+               case ID_AA64MMFR0_TGRAN4_NONE:
+                       break;
+               case ID_AA64MMFR0_TGRAN4_IMPL:
+                       printf("%s4k Granule", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown 4k Granule", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64MMFR0_TGRAN16(cpu_desc[cpu].id_aa64mmfr0)) {
+               case ID_AA64MMFR0_TGRAN16_NONE:
+                       break;
+               case ID_AA64MMFR0_TGRAN16_IMPL:
+                       printf("%s16k Granule", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown 16k Granule", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64MMFR0_TGRAN64(cpu_desc[cpu].id_aa64mmfr0)) {
+               case ID_AA64MMFR0_TGRAN64_NONE:
+                       break;
+               case ID_AA64MMFR0_TGRAN64_IMPL:
+                       printf("%s64k Granule", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown 64k Granule", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64MMFR0_BIGEND(cpu_desc[cpu].id_aa64mmfr0)) {
+               case ID_AA64MMFR0_BIGEND_FIXED:
+                       break;
+               case ID_AA64MMFR0_BIGEND_MIXED:
+                       printf("%sMixedEndian", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown Endian switching", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64MMFR0_BIGEND_EL0(cpu_desc[cpu].id_aa64mmfr0)) {
+               case ID_AA64MMFR0_BIGEND_EL0_FIXED:
+                       break;
+               case ID_AA64MMFR0_BIGEND_EL0_MIXED:
+                       printf("%sEL0 MixEndian", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown EL0 Endian switching", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64MMFR0_S_NS_MEM(cpu_desc[cpu].id_aa64mmfr0)) {
+               case ID_AA64MMFR0_S_NS_MEM_NONE:
+                       break;
+               case ID_AA64MMFR0_S_NS_MEM_DISTINCT:
+                       printf("%sS/NS Mem", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown S/NS Mem", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64MMFR0_ASID_BITS(cpu_desc[cpu].id_aa64mmfr0)) {
+               case ID_AA64MMFR0_ASID_BITS_8:
+                       printf("%s8bit ASID", SEP_STR);
+                       break;
+               case ID_AA64MMFR0_ASID_BITS_16:
+                       printf("%s16bit ASID", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown ASID", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64MMFR0_PA_RANGE(cpu_desc[cpu].id_aa64mmfr0)) {
+               case ID_AA64MMFR0_PA_RANGE_4G:
+                       printf("%s4GB PA", SEP_STR);
+                       break;
+               case ID_AA64MMFR0_PA_RANGE_64G:
+                       printf("%s64GB PA", SEP_STR);
+                       break;
+               case ID_AA64MMFR0_PA_RANGE_1T:
+                       printf("%s1TB PA", SEP_STR);
+                       break;
+               case ID_AA64MMFR0_PA_RANGE_4T:
+                       printf("%s4TB PA", SEP_STR);
+                       break;
+               case ID_AA64MMFR0_PA_RANGE_16T:
+                       printf("%s16TB PA", SEP_STR);
+                       break;
+               case ID_AA64MMFR0_PA_RANGE_256T:
+                       printf("%s256TB PA", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown PA Range", SEP_STR);
+                       break;
+               }
+
+               if ((cpu_desc[cpu].id_aa64mmfr0 & ~ID_AA64MMFR0_MASK) != 0)
+                       printf("%s%#lx", SEP_STR,
+                           cpu_desc[cpu].id_aa64mmfr0 & ~ID_AA64MMFR0_MASK);
+               printf(">\n");
+       }
+
+       /* AArch64 Memory Model Feature Register 1 */
+       if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR1) != 0) {
+               printf("      Memory Model Features 1 = <%#lx>\n",
+                   cpu_desc[cpu].id_aa64mmfr1);
+       }
+
+       /* AArch64 Debug Feature Register 0 */
+       if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_DFR0) != 0) {
+               printed = 0;
+               printf("             Debug Features 0 = <");
+               printf("%s%lu CTX Breakpoints", SEP_STR,
+                   ID_AA64DFR0_CTX_CMPS(cpu_desc[cpu].id_aa64dfr0));
+
+               printf("%s%lu Watchpoints", SEP_STR,
+                   ID_AA64DFR0_WRPS(cpu_desc[cpu].id_aa64dfr0));
+
+               printf("%s%lu Breakpoints", SEP_STR,
+                   ID_AA64DFR0_BRPS(cpu_desc[cpu].id_aa64dfr0));
+
+               switch (ID_AA64DFR0_PMU_VER(cpu_desc[cpu].id_aa64dfr0)) {
+               case ID_AA64DFR0_PMU_VER_NONE:
+                       break;
+               case ID_AA64DFR0_PMU_VER_3:
+                       printf("%sPMUv3", SEP_STR);
+                       break;
+               case ID_AA64DFR0_PMU_VER_IMPL:
+                       printf("%sImplementation defined PMU", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown PMU", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64DFR0_TRACE_VER(cpu_desc[cpu].id_aa64dfr0)) {
+               case ID_AA64DFR0_TRACE_VER_NONE:
+                       break;
+               case ID_AA64DFR0_TRACE_VER_IMPL:
+                       printf("%sTrace", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown Trace", SEP_STR);
+                       break;
+               }
+
+               switch (ID_AA64DFR0_DEBUG_VER(cpu_desc[cpu].id_aa64dfr0)) {
+               case ID_AA64DFR0_DEBUG_VER_8:
+                       printf("%sDebug v8", SEP_STR);
+                       break;
+               default:
+                       printf("%sUnknown Debug", SEP_STR);
+                       break;
+               }
+
+               if (cpu_desc[cpu].id_aa64dfr0 & ~ID_AA64DFR0_MASK)
+                       printf("%s%#lx", SEP_STR,
+                           cpu_desc[cpu].id_aa64dfr0 & ~ID_AA64DFR0_MASK);
+               printf(">\n");
+       }
+
+       /* AArch64 Memory Model Feature Register 1 */
+       if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_DFR1) != 0) {
+               printf("             Debug Features 1 = <%#lx>\n",
+                   cpu_desc[cpu].id_aa64dfr1);
+       }
+
+       /* AArch64 Auxiliary Feature Register 0 */
+       if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_AFR0) != 0) {
+               printf("         Auxiliary Features 0 = <%#lx>\n",
+                   cpu_desc[cpu].id_aa64afr0);
+       }
+
+       /* AArch64 Auxiliary Feature Register 1 */
+       if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_AFR1) != 0) {
+               printf("         Auxiliary Features 1 = <%#lx>\n",
+                   cpu_desc[cpu].id_aa64afr1);
+       }
+
+#undef SEP_STR
+}
 
 void
 identify_cpu(void)
@@ -133,7 +551,6 @@ identify_cpu(void)
        u_int impl_id;
        u_int part_id;
        u_int cpu;
-       uint64_t mpidr;
        size_t i;
        const struct cpu_parts *cpu_partsp = NULL;
 
@@ -171,19 +588,77 @@ identify_cpu(void)
        cpu_desc[cpu].cpu_variant = CPU_VAR(midr);
 
        /* Save affinity for current CPU */
-       mpidr = get_mpidr();
-       CPU_AFFINITY(cpu) = mpidr & CPU_AFF_MASK;
+       cpu_desc[cpu].mpidr = get_mpidr();
+       CPU_AFFINITY(cpu) = cpu_desc[cpu].mpidr & CPU_AFF_MASK;
 
-       /* Print details for boot CPU or if we want verbose output */
-       if (cpu == 0 || bootverbose) {
-               printf("CPU(%d): %s %s r%dp%d\n", cpu,
-                   cpu_desc[cpu].cpu_impl_name,
-                   cpu_desc[cpu].cpu_part_name,
-                   cpu_desc[cpu].cpu_variant,
-                   cpu_desc[cpu].cpu_revision);
-       }
+       cpu_desc[cpu].id_aa64dfr0 = READ_SPECIALREG(id_aa64dfr0_el1);
+       cpu_desc[cpu].id_aa64dfr1 = READ_SPECIALREG(id_aa64dfr1_el1);
+       cpu_desc[cpu].id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1);
+       cpu_desc[cpu].id_aa64isar1 = READ_SPECIALREG(id_aa64isar1_el1);
+       cpu_desc[cpu].id_aa64mmfr0 = READ_SPECIALREG(id_aa64mmfr0_el1);
+       cpu_desc[cpu].id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1);
+       cpu_desc[cpu].id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1);
+       cpu_desc[cpu].id_aa64pfr1 = READ_SPECIALREG(id_aa64pfr1_el1);
+
+       if (cpu != 0) {
+               /*
+                * This code must run on one cpu at a time, but we are
+                * not scheduling on the current core so implement a
+                * simple spinlock.
+                */
+               while (atomic_cmpset_acq_int(&ident_lock, 0, 1) == 0)
+                       __asm __volatile("wfe" ::: "memory");
+
+               switch (cpu_aff_levels) {
+               case 0:
+                       if (CPU_AFF0(cpu_desc[cpu].mpidr) !=
+                           CPU_AFF0(cpu_desc[0].mpidr))
+                               cpu_aff_levels = 1;
+                       /* FALLTHROUGH */
+               case 1:
+                       if (CPU_AFF1(cpu_desc[cpu].mpidr) !=
+                           CPU_AFF1(cpu_desc[0].mpidr))
+                               cpu_aff_levels = 2;
+                       /* FALLTHROUGH */
+               case 2:
+                       if (CPU_AFF2(cpu_desc[cpu].mpidr) !=
+                           CPU_AFF2(cpu_desc[0].mpidr))
+                               cpu_aff_levels = 3;
+                       /* FALLTHROUGH */
+               case 3:
+                       if (CPU_AFF3(cpu_desc[cpu].mpidr) !=
+                           CPU_AFF3(cpu_desc[0].mpidr))
+                               cpu_aff_levels = 4;
+                       break;
+               }
 
-       if (bootverbose)
-               printf("CPU%u affinity: %u.%u.%u.%u\n", 0, CPU_AFF0(mpidr),
-                   CPU_AFF1(mpidr), CPU_AFF2(mpidr), CPU_AFF3(mpidr));
+               if (cpu_desc[cpu].id_aa64afr0 != cpu_desc[0].id_aa64afr0)
+                       cpu_print_regs |= PRINT_ID_AA64_AFR0;
+               if (cpu_desc[cpu].id_aa64afr1 != cpu_desc[0].id_aa64afr1)
+                       cpu_print_regs |= PRINT_ID_AA64_AFR1;
+
+               if (cpu_desc[cpu].id_aa64dfr0 != cpu_desc[0].id_aa64dfr0)
+                       cpu_print_regs |= PRINT_ID_AA64_DFR0;
+               if (cpu_desc[cpu].id_aa64dfr1 != cpu_desc[0].id_aa64dfr1)
+                       cpu_print_regs |= PRINT_ID_AA64_DFR1;
+
+               if (cpu_desc[cpu].id_aa64isar0 != cpu_desc[0].id_aa64isar0)
+                       cpu_print_regs |= PRINT_ID_AA64_ISAR0;
+               if (cpu_desc[cpu].id_aa64isar1 != cpu_desc[0].id_aa64isar1)
+                       cpu_print_regs |= PRINT_ID_AA64_ISAR1;
+
+               if (cpu_desc[cpu].id_aa64mmfr0 != cpu_desc[0].id_aa64mmfr0)
+                       cpu_print_regs |= PRINT_ID_AA64_MMFR0;
+               if (cpu_desc[cpu].id_aa64mmfr1 != cpu_desc[0].id_aa64mmfr1)
+                       cpu_print_regs |= PRINT_ID_AA64_MMFR1;
+
+               if (cpu_desc[cpu].id_aa64pfr0 != cpu_desc[0].id_aa64pfr0)
+                       cpu_print_regs |= PRINT_ID_AA64_PFR0;
+               if (cpu_desc[cpu].id_aa64pfr1 != cpu_desc[0].id_aa64pfr1)
+                       cpu_print_regs |= PRINT_ID_AA64_PFR1;
+
+               /* Wake up the other CPUs */
+               atomic_store_rel_int(&ident_lock, 0);
+               __asm __volatile("sev" ::: "memory");
+       }
 }

Modified: head/sys/arm64/arm64/mp_machdep.c
==============================================================================
--- head/sys/arm64/arm64/mp_machdep.c   Wed Dec 30 17:10:03 2015        
(r292953)
+++ head/sys/arm64/arm64/mp_machdep.c   Wed Dec 30 17:36:34 2015        
(r292954)
@@ -175,7 +175,7 @@ arm64_cpu_attach(device_t dev)
 static void
 release_aps(void *dummy __unused)
 {
-       int i;
+       int cpu, i;
 
        /* Setup the IPI handler */
        for (i = 0; i < COUNT_IPI; i++)
@@ -188,8 +188,14 @@ release_aps(void *dummy __unused)
        printf("Release APs\n");
 
        for (i = 0; i < 2000; i++) {
-               if (smp_started)
+               if (smp_started) {
+                       for (cpu = 0; cpu <= mp_maxid; cpu++) {
+                               if (CPU_ABSENT(cpu))
+                                       continue;
+                               print_cpu_features(cpu);
+                       }
                        return;
+               }
                DELAY(1000);
        }
 

Modified: head/sys/arm64/include/armreg.h
==============================================================================
--- head/sys/arm64/include/armreg.h     Wed Dec 30 17:10:03 2015        
(r292953)
+++ head/sys/arm64/include/armreg.h     Wed Dec 30 17:36:34 2015        
(r292954)
@@ -121,19 +121,147 @@
 /* ICC_SRE_EL2 */
 #define        ICC_SRE_EL2_EN          (1U << 3)
 
+/* ID_AA64DFR0_EL1 */
+#define        ID_AA64DFR0_MASK                0xf0f0ffff
+#define        ID_AA64DFR0_DEBUG_VER_SHIFT     0
+#define        ID_AA64DFR0_DEBUG_VER_MASK      (0xf << 
ID_AA64DFR0_DEBUG_VER_SHIFT)
+#define        ID_AA64DFR0_DEBUG_VER(x)        ((x) & 
ID_AA64DFR0_DEBUG_VER_MASK)
+#define         ID_AA64DFR0_DEBUG_VER_8        (0x6 << 
ID_AA64DFR0_DEBUG_VER_SHIFT)
+#define        ID_AA64DFR0_TRACE_VER_SHIFT     4
+#define        ID_AA64DFR0_TRACE_VER_MASK      (0xf << 
ID_AA64DFR0_TRACE_VER_SHIFT)
+#define        ID_AA64DFR0_TRACE_VER(x)        ((x) & 
ID_AA64DFR0_TRACE_VER_MASK)
+#define         ID_AA64DFR0_TRACE_VER_NONE     (0x0 << 
ID_AA64DFR0_TRACE_VER_SHIFT)
+#define         ID_AA64DFR0_TRACE_VER_IMPL     (0x1 << 
ID_AA64DFR0_TRACE_VER_SHIFT)
+#define        ID_AA64DFR0_PMU_VER_SHIFT       8
+#define        ID_AA64DFR0_PMU_VER_MASK        (0xf << 
ID_AA64DFR0_PMU_VER_SHIFT)
+#define        ID_AA64DFR0_PMU_VER(x)          ((x) & ID_AA64DFR0_PMU_VER_MASK)
+#define         ID_AA64DFR0_PMU_VER_NONE       (0x0 << 
ID_AA64DFR0_PMU_VER_SHIFT)
+#define         ID_AA64DFR0_PMU_VER_3          (0x1 << 
ID_AA64DFR0_PMU_VER_SHIFT)
+#define         ID_AA64DFR0_PMU_VER_IMPL       (0xf << 
ID_AA64DFR0_PMU_VER_SHIFT)
+#define        ID_AA64DFR0_BRPS_SHIFT          12
+#define        ID_AA64DFR0_BRPS_MASK           (0xf << ID_AA64DFR0_BRPS_SHIFT)
+#define        ID_AA64DFR0_BRPS(x)             \
+    ((((x) >> ID_AA64DFR0_BRPS_SHIFT) & 0xf) + 1)
+#define        ID_AA64DFR0_WRPS_SHIFT          20
+#define        ID_AA64DFR0_WRPS_MASK           (0xf << ID_AA64DFR0_WRPS_SHIFT)
+#define        ID_AA64DFR0_WRPS(x)             \
+    ((((x) >> ID_AA64DFR0_WRPS_SHIFT) & 0xf) + 1)
+#define        ID_AA64DFR0_CTX_CMPS_SHIFT      28
+#define        ID_AA64DFR0_CTX_CMPS_MASK       (0xf << 
ID_AA64DFR0_CTX_CMPS_SHIFT)
+#define        ID_AA64DFR0_CTX_CMPS(x)         \
+    ((((x) >> ID_AA64DFR0_CTX_CMPS_SHIFT) & 0xf) + 1)
+
+/* ID_AA64ISAR0_EL1 */
+#define        ID_AA64ISAR0_MASK               0x000ffff0
+#define        ID_AA64ISAR0_AES_SHIFT          4
+#define        ID_AA64ISAR0_AES_MASK           (0xf << ID_AA64ISAR0_AES_SHIFT)
+#define        ID_AA64ISAR0_AES(x)             ((x) & ID_AA64ISAR0_AES_MASK)
+#define         ID_AA64ISAR0_AES_NONE          (0x0 << ID_AA64ISAR0_AES_SHIFT)
+#define         ID_AA64ISAR0_AES_BASE          (0x1 << ID_AA64ISAR0_AES_SHIFT)
+#define         ID_AA64ISAR0_AES_PMULL         (0x2 << ID_AA64ISAR0_AES_SHIFT)
+#define        ID_AA64ISAR0_SHA1_SHIFT         8
+#define        ID_AA64ISAR0_SHA1_MASK          (0xf << ID_AA64ISAR0_SHA1_SHIFT)
+#define        ID_AA64ISAR0_SHA1(x)            ((x) & ID_AA64ISAR0_SHA1_MASK)
+#define         ID_AA64ISAR0_SHA1_NONE         (0x0 << ID_AA64ISAR0_SHA1_SHIFT)
+#define         ID_AA64ISAR0_SHA1_BASE         (0x1 << ID_AA64ISAR0_SHA1_SHIFT)
+#define        ID_AA64ISAR0_SHA2_SHIFT         12
+#define        ID_AA64ISAR0_SHA2_MASK          (0xf << ID_AA64ISAR0_SHA2_SHIFT)
+#define        ID_AA64ISAR0_SHA2(x)            ((x) & ID_AA64ISAR0_SHA2_MASK)
+#define         ID_AA64ISAR0_SHA2_NONE         (0x0 << ID_AA64ISAR0_SHA2_SHIFT)
+#define         ID_AA64ISAR0_SHA2_BASE         (0x1 << ID_AA64ISAR0_SHA2_SHIFT)
+#define        ID_AA64ISAR0_CRC32_SHIFT        16
+#define        ID_AA64ISAR0_CRC32_MASK         (0xf << 
ID_AA64ISAR0_CRC32_SHIFT)
+#define        ID_AA64ISAR0_CRC32(x)           ((x) & ID_AA64ISAR0_CRC32_MASK)
+#define         ID_AA64ISAR0_CRC32_NONE        (0x0 << 
ID_AA64ISAR0_CRC32_SHIFT)
+#define         ID_AA64ISAR0_CRC32_BASE        (0x1 << 
ID_AA64ISAR0_CRC32_SHIFT)
+
+/* ID_AA64MMFR0_EL1 */
+#define        ID_AA64MMFR0_MASK               0xffffffff
+#define        ID_AA64MMFR0_PA_RANGE_SHIFT     0
+#define        ID_AA64MMFR0_PA_RANGE_MASK      (0xf << 
ID_AA64MMFR0_PA_RANGE_SHIFT)
+#define        ID_AA64MMFR0_PA_RANGE(x)        ((x) & 
ID_AA64MMFR0_PA_RANGE_MASK)
+#define         ID_AA64MMFR0_PA_RANGE_4G       (0x0 << 
ID_AA64MMFR0_PA_RANGE_SHIFT)
+#define         ID_AA64MMFR0_PA_RANGE_64G      (0x1 << 
ID_AA64MMFR0_PA_RANGE_SHIFT)
+#define         ID_AA64MMFR0_PA_RANGE_1T       (0x2 << 
ID_AA64MMFR0_PA_RANGE_SHIFT)
+#define         ID_AA64MMFR0_PA_RANGE_4T       (0x3 << 
ID_AA64MMFR0_PA_RANGE_SHIFT)
+#define         ID_AA64MMFR0_PA_RANGE_16T      (0x4 << 
ID_AA64MMFR0_PA_RANGE_SHIFT)
+#define         ID_AA64MMFR0_PA_RANGE_256T     (0x5 << 
ID_AA64MMFR0_PA_RANGE_SHIFT)
+#define        ID_AA64MMFR0_ASID_BITS_SHIFT    4
+#define        ID_AA64MMFR0_ASID_BITS_MASK     (0xf << 
ID_AA64MMFR0_ASID_BITS_SHIFT)
+#define        ID_AA64MMFR0_ASID_BITS(x)       ((x) & 
ID_AA64MMFR0_ASID_BITS_MASK)
+#define         ID_AA64MMFR0_ASID_BITS_8       (0x0 << 
ID_AA64MMFR0_ASID_BITS_SHIFT)
+#define         ID_AA64MMFR0_ASID_BITS_16      (0x2 << 
ID_AA64MMFR0_ASID_BITS_SHIFT)
+#define        ID_AA64MMFR0_BIGEND_SHIFT       8
+#define        ID_AA64MMFR0_BIGEND_MASK        (0xf << 
ID_AA64MMFR0_BIGEND_SHIFT)
+#define        ID_AA64MMFR0_BIGEND(x)          ((x) & ID_AA64MMFR0_BIGEND_MASK)
+#define         ID_AA64MMFR0_BIGEND_FIXED      (0x0 << 
ID_AA64MMFR0_BIGEND_SHIFT)
+#define         ID_AA64MMFR0_BIGEND_MIXED      (0x1 << 
ID_AA64MMFR0_BIGEND_SHIFT)
+#define        ID_AA64MMFR0_S_NS_MEM_SHIFT     12
+#define        ID_AA64MMFR0_S_NS_MEM_MASK      (0xf << 
ID_AA64MMFR0_S_NS_MEM_SHIFT)
+#define        ID_AA64MMFR0_S_NS_MEM(x)        ((x) & 
ID_AA64MMFR0_S_NS_MEM_MASK)
+#define         ID_AA64MMFR0_S_NS_MEM_NONE     (0x0 << 
ID_AA64MMFR0_S_NS_MEM_SHIFT)
+#define         ID_AA64MMFR0_S_NS_MEM_DISTINCT (0x1 << 
ID_AA64MMFR0_S_NS_MEM_SHIFT)
+#define        ID_AA64MMFR0_BIGEND_EL0_SHIFT   16
+#define        ID_AA64MMFR0_BIGEND_EL0_MASK    (0xf << 
ID_AA64MMFR0_BIGEND_EL0_SHIFT)
+#define        ID_AA64MMFR0_BIGEND_EL0(x)      ((x) & 
ID_AA64MMFR0_BIGEND_EL0_MASK)
+#define         ID_AA64MMFR0_BIGEND_EL0_FIXED  (0x0 << 
ID_AA64MMFR0_BIGEND_EL0_SHIFT)
+#define         ID_AA64MMFR0_BIGEND_EL0_MIXED  (0x1 << 
ID_AA64MMFR0_BIGEND_EL0_SHIFT)
+#define        ID_AA64MMFR0_TGRAN16_SHIFT      20
+#define        ID_AA64MMFR0_TGRAN16_MASK       (0xf << 
ID_AA64MMFR0_TGRAN16_SHIFT)
+#define        ID_AA64MMFR0_TGRAN16(x)         ((x) & 
ID_AA64MMFR0_TGRAN16_MASK)
+#define         ID_AA64MMFR0_TGRAN16_NONE      (0x0 << 
ID_AA64MMFR0_TGRAN16_SHIFT)
+#define         ID_AA64MMFR0_TGRAN16_IMPL      (0x1 << 
ID_AA64MMFR0_TGRAN16_SHIFT)
+#define        ID_AA64MMFR0_TGRAN64_SHIFT      24
+#define        ID_AA64MMFR0_TGRAN64_MASK       (0xf << 
ID_AA64MMFR0_TGRAN64_SHIFT)
+#define        ID_AA64MMFR0_TGRAN64(x)         ((x) & 
ID_AA64MMFR0_TGRAN64_MASK)
+#define         ID_AA64MMFR0_TGRAN64_IMPL      (0x0 << 
ID_AA64MMFR0_TGRAN64_SHIFT)
+#define         ID_AA64MMFR0_TGRAN64_NONE      (0xf << 
ID_AA64MMFR0_TGRAN64_SHIFT)
+#define        ID_AA64MMFR0_TGRAN4_SHIFT       28
+#define        ID_AA64MMFR0_TGRAN4_MASK        (0xf << 
ID_AA64MMFR0_TGRAN4_SHIFT)
+#define        ID_AA64MMFR0_TGRAN4(x)          ((x) & ID_AA64MMFR0_TGRAN4_MASK)
+#define         ID_AA64MMFR0_TGRAN4_IMPL       (0x0 << 
ID_AA64MMFR0_TGRAN4_SHIFT)
+#define         ID_AA64MMFR0_TGRAN4_NONE       (0xf << 
ID_AA64MMFR0_TGRAN4_SHIFT)
+
 /* ID_AA64PFR0_EL1 */
-#define        ID_AA64PFR0_EL0_MASK    (0xf << 0)
-#define        ID_AA64PFR0_EL1_MASK    (0xf << 4)
-#define        ID_AA64PFR0_EL2_MASK    (0xf << 8)
-#define        ID_AA64PFR0_EL3_MASK    (0xf << 12)
-#define        ID_AA64PFR0_FP_MASK     (0xf << 16)
-#define         ID_AA64PFR0_FP_IMPL    (0x0 << 16) /* Floating-point 
implemented */
-#define         ID_AA64PFR0_FP_NONE    (0xf << 16) /* Floating-point not 
implemented */
-#define        ID_AA64PFR0_ADV_SIMD_MASK (0xf << 20)
-#define        ID_AA64PFR0_GIC_SHIFT   (24)
-#define        ID_AA64PFR0_GIC_BITS    (0x4) /* Number of bits in GIC field */
-#define        ID_AA64PFR0_GIC_MASK    (0xf << ID_AA64PFR0_GIC_SHIFT)
-#define         ID_AA64PFR0_GIC_CPUIF_EN (0x1 << ID_AA64PFR0_GIC_SHIFT)
+#define        ID_AA64PFR0_MASK                0x0fffffff
+#define        ID_AA64PFR0_EL0_SHIFT           0
+#define        ID_AA64PFR0_EL0_MASK            (0xf << ID_AA64PFR0_EL0_SHIFT)
+#define        ID_AA64PFR0_EL0(x)              ((x) & ID_AA64PFR0_EL0_MASK)
+#define         ID_AA64PFR0_EL0_64             (1 << ID_AA64PFR0_EL0_SHIFT)
+#define         ID_AA64PFR0_EL0_64_32          (2 << ID_AA64PFR0_EL0_SHIFT)
+#define        ID_AA64PFR0_EL1_SHIFT           4
+#define        ID_AA64PFR0_EL1_MASK            (0xf << ID_AA64PFR0_EL1_SHIFT)
+#define        ID_AA64PFR0_EL1(x)              ((x) & ID_AA64PFR0_EL1_MASK)
+#define         ID_AA64PFR0_EL1_64             (1 << ID_AA64PFR0_EL1_SHIFT)
+#define         ID_AA64PFR0_EL1_64_32          (2 << ID_AA64PFR0_EL1_SHIFT)
+#define        ID_AA64PFR0_EL2_SHIFT           8
+#define        ID_AA64PFR0_EL2_MASK            (0xf << ID_AA64PFR0_EL2_SHIFT)
+#define        ID_AA64PFR0_EL2(x)              ((x) & ID_AA64PFR0_EL2_MASK)
+#define         ID_AA64PFR0_EL2_NONE           (0 << ID_AA64PFR0_EL2_SHIFT)
+#define         ID_AA64PFR0_EL2_64             (1 << ID_AA64PFR0_EL2_SHIFT)
+#define         ID_AA64PFR0_EL2_64_32          (2 << ID_AA64PFR0_EL2_SHIFT)
+#define        ID_AA64PFR0_EL3_SHIFT           12
+#define        ID_AA64PFR0_EL3_MASK            (0xf << ID_AA64PFR0_EL3_SHIFT)
+#define        ID_AA64PFR0_EL3(x)              ((x) & ID_AA64PFR0_EL3_MASK)
+#define         ID_AA64PFR0_EL3_NONE           (0 << ID_AA64PFR0_EL3_SHIFT)
+#define         ID_AA64PFR0_EL3_64             (1 << ID_AA64PFR0_EL3_SHIFT)
+#define         ID_AA64PFR0_EL3_64_32          (2 << ID_AA64PFR0_EL3_SHIFT)
+#define        ID_AA64PFR0_FP_SHIFT            16
+#define        ID_AA64PFR0_FP_MASK             (0xf << ID_AA64PFR0_FP_SHIFT)
+#define        ID_AA64PFR0_FP(x)               ((x) & ID_AA64PFR0_FP_MASK)
+#define         ID_AA64PFR0_FP_IMPL            (0x0 << ID_AA64PFR0_FP_SHIFT)
+#define         ID_AA64PFR0_FP_NONE            (0xf << ID_AA64PFR0_FP_SHIFT)
+#define        ID_AA64PFR0_ADV_SIMD_SHIFT      20
+#define        ID_AA64PFR0_ADV_SIMD_MASK       (0xf << 
ID_AA64PFR0_ADV_SIMD_SHIFT)
+#define        ID_AA64PFR0_ADV_SIMD(x)         ((x) & 
ID_AA64PFR0_ADV_SIMD_MASK)
+#define         ID_AA64PFR0_ADV_SIMD_IMPL      (0x0 << 
ID_AA64PFR0_ADV_SIMD_SHIFT)
+#define         ID_AA64PFR0_ADV_SIMD_NONE      (0xf << 
ID_AA64PFR0_ADV_SIMD_SHIFT)
+#define        ID_AA64PFR0_GIC_BITS            0x4 /* Number of bits in GIC 
field */
+#define        ID_AA64PFR0_GIC_SHIFT           24
+#define        ID_AA64PFR0_GIC_MASK            (0xf << ID_AA64PFR0_GIC_SHIFT)
+#define        ID_AA64PFR0_GIC(x)              ((x) & ID_AA64PFR0_GIC_MASK)
+#define         ID_AA64PFR0_GIC_CPUIF_NONE     (0x0 << ID_AA64PFR0_GIC_SHIFT)
+#define         ID_AA64PFR0_GIC_CPUIF_EN       (0x1 << ID_AA64PFR0_GIC_SHIFT)
 
 /* MAIR_EL1 - Memory Attribute Indirection Register */
 #define        MAIR_ATTR_MASK(idx)     (0xff << ((n)* 8))

Modified: head/sys/arm64/include/cpu.h
==============================================================================
--- head/sys/arm64/include/cpu.h        Wed Dec 30 17:10:03 2015        
(r292953)
+++ head/sys/arm64/include/cpu.h        Wed Dec 30 17:36:34 2015        
(r292954)
@@ -145,6 +145,7 @@ void        cpu_halt(void) __dead2;
 void   cpu_reset(void) __dead2;
 void   fork_trampoline(void);
 void   identify_cpu(void);
+void   print_cpu_features(u_int);
 void   swi_vm(void *v);
 
 #define        CPU_AFFINITY(cpu)       __cpu_affinity[(cpu)]
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to