From owner-svn-src-all@freebsd.org Wed Dec 30 17:36:36 2015 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4FC77A56CFF; Wed, 30 Dec 2015 17:36:36 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1BD0C1AE9; Wed, 30 Dec 2015 17:36:36 +0000 (UTC) (envelope-from andrew@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id tBUHaZuR056140; Wed, 30 Dec 2015 17:36:35 GMT (envelope-from andrew@FreeBSD.org) Received: (from andrew@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id tBUHaZlp056136; Wed, 30 Dec 2015 17:36:35 GMT (envelope-from andrew@FreeBSD.org) Message-Id: <201512301736.tBUHaZlp056136@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: andrew set sender to andrew@FreeBSD.org using -f From: Andrew Turner Date: Wed, 30 Dec 2015 17:36:35 +0000 (UTC) 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 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 30 Dec 2015 17:36:36 -0000 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 #include +#include #include #include +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)]