Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 30 Dec 2015 17:36:35 +0000 (UTC)
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r292954 - in head/sys/arm64: arm64 include
Message-ID:  <201512301736.tBUHaZlp056136@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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)]



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201512301736.tBUHaZlp056136>