Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm64/arm64/identcpu.c
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
#include <machine/atomic.h> | #include <machine/atomic.h> | ||||
#include <machine/cpu.h> | #include <machine/cpu.h> | ||||
#include <machine/cpufunc.h> | #include <machine/cpufunc.h> | ||||
#include <machine/undefined.h> | #include <machine/undefined.h> | ||||
#include <machine/elf.h> | #include <machine/elf.h> | ||||
static void print_cpu_features(u_int cpu); | static void print_cpu_features(u_int cpu); | ||||
static u_long parse_cpu_features_hwcap(u_int cpu); | static u_long parse_cpu_features_hwcap(void); | ||||
char machine[] = "arm64"; | char machine[] = "arm64"; | ||||
#ifdef SCTL_MASK32 | #ifdef SCTL_MASK32 | ||||
extern int adaptive_machine_arch; | extern int adaptive_machine_arch; | ||||
#endif | #endif | ||||
static SYSCTL_NODE(_machdep, OID_AUTO, cache, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | static SYSCTL_NODE(_machdep, OID_AUTO, cache, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | ||||
▲ Show 20 Lines • Show All 1,031 Lines • ▼ Show 20 Lines | if (cpu == 0) { | ||||
kern_reg = CPU_DESC_FIELD(kern_cpu_desc, i); | kern_reg = CPU_DESC_FIELD(kern_cpu_desc, i); | ||||
user_reg = CPU_DESC_FIELD(user_cpu_desc, i); | user_reg = CPU_DESC_FIELD(user_cpu_desc, i); | ||||
} | } | ||||
fields = user_regs[i].fields; | fields = user_regs[i].fields; | ||||
for (j = 0; fields[j].type != 0; j++) { | for (j = 0; fields[j].type != 0; j++) { | ||||
switch (fields[j].type & MRS_TYPE_MASK) { | switch (fields[j].type & MRS_TYPE_MASK) { | ||||
case MRS_EXACT: | case MRS_EXACT: | ||||
user_reg &= ~(0xfu << fields[j].shift); | user_reg &= ~(0xful << fields[j].shift); | ||||
user_reg |= | user_reg |= | ||||
(uint64_t)MRS_EXACT_FIELD(fields[j].type) << | (uint64_t)MRS_EXACT_FIELD(fields[j].type) << | ||||
fields[j].shift; | fields[j].shift; | ||||
break; | break; | ||||
case MRS_LOWER: | case MRS_LOWER: | ||||
user_reg = update_lower_register(user_reg, | user_reg = update_lower_register(user_reg, | ||||
value, fields[j].shift, 4, fields[j].sign); | value, fields[j].shift, 4, fields[j].sign); | ||||
break; | break; | ||||
Show All 19 Lines | |||||
int64_t dcache_line_size; /* The minimum D cache line size */ | int64_t dcache_line_size; /* The minimum D cache line size */ | ||||
int64_t icache_line_size; /* The minimum I cache line size */ | int64_t icache_line_size; /* The minimum I cache line size */ | ||||
int64_t idcache_line_size; /* The minimum cache line size */ | int64_t idcache_line_size; /* The minimum cache line size */ | ||||
static void | static void | ||||
identify_cpu_sysinit(void *dummy __unused) | identify_cpu_sysinit(void *dummy __unused) | ||||
{ | { | ||||
int cpu; | int cpu; | ||||
u_long hwcap; | |||||
bool dic, idc; | bool dic, idc; | ||||
dic = (allow_dic != 0); | dic = (allow_dic != 0); | ||||
idc = (allow_idc != 0); | idc = (allow_idc != 0); | ||||
CPU_FOREACH(cpu) { | CPU_FOREACH(cpu) { | ||||
check_cpu_regs(cpu); | check_cpu_regs(cpu); | ||||
hwcap = parse_cpu_features_hwcap(cpu); | |||||
if (elf_hwcap == 0) | |||||
elf_hwcap = hwcap; | |||||
else | |||||
elf_hwcap &= hwcap; | |||||
if (cpu != 0) | if (cpu != 0) | ||||
update_special_regs(cpu); | update_special_regs(cpu); | ||||
if (CTR_DIC_VAL(cpu_desc[cpu].ctr) == 0) | if (CTR_DIC_VAL(cpu_desc[cpu].ctr) == 0) | ||||
dic = false; | dic = false; | ||||
if (CTR_IDC_VAL(cpu_desc[cpu].ctr) == 0) | if (CTR_IDC_VAL(cpu_desc[cpu].ctr) == 0) | ||||
idc = false; | idc = false; | ||||
} | } | ||||
/* Exposed to userspace as AT_HWCAP */ | |||||
elf_hwcap = parse_cpu_features_hwcap(); | |||||
if (dic && idc) { | if (dic && idc) { | ||||
arm64_icache_sync_range = &arm64_dic_idc_icache_sync_range; | arm64_icache_sync_range = &arm64_dic_idc_icache_sync_range; | ||||
if (bootverbose) | if (bootverbose) | ||||
printf("Enabling DIC & IDC ICache sync\n"); | printf("Enabling DIC & IDC ICache sync\n"); | ||||
} | } | ||||
if ((elf_hwcap & HWCAP_ATOMICS) != 0) { | if ((elf_hwcap & HWCAP_ATOMICS) != 0) { | ||||
lse_supported = true; | lse_supported = true; | ||||
Show All 15 Lines | cpu_features_sysinit(void *dummy __unused) | ||||
u_int cpu; | u_int cpu; | ||||
CPU_FOREACH(cpu) | CPU_FOREACH(cpu) | ||||
print_cpu_features(cpu); | print_cpu_features(cpu); | ||||
} | } | ||||
SYSINIT(cpu_features, SI_SUB_SMP, SI_ORDER_ANY, cpu_features_sysinit, NULL); | SYSINIT(cpu_features, SI_SUB_SMP, SI_ORDER_ANY, cpu_features_sysinit, NULL); | ||||
static u_long | static u_long | ||||
parse_cpu_features_hwcap(u_int cpu) | parse_cpu_features_hwcap(void) | ||||
{ | { | ||||
u_long hwcap = 0; | u_long hwcap = 0; | ||||
if (ID_AA64ISAR0_DP_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_DP_IMPL) | if (ID_AA64ISAR0_DP_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_DP_IMPL) | |||||
hwcap |= HWCAP_ASIMDDP; | hwcap |= HWCAP_ASIMDDP; | ||||
if (ID_AA64ISAR0_SM4_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_SM4_IMPL) | if (ID_AA64ISAR0_SM4_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_SM4_IMPL) | |||||
hwcap |= HWCAP_SM4; | hwcap |= HWCAP_SM4; | ||||
if (ID_AA64ISAR0_SM3_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_SM3_IMPL) | if (ID_AA64ISAR0_SM3_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_SM3_IMPL) | |||||
hwcap |= HWCAP_SM3; | hwcap |= HWCAP_SM3; | ||||
if (ID_AA64ISAR0_RDM_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_RDM_IMPL) | if (ID_AA64ISAR0_RDM_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_RDM_IMPL) | |||||
hwcap |= HWCAP_ASIMDRDM; | hwcap |= HWCAP_ASIMDRDM; | ||||
if (ID_AA64ISAR0_Atomic_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_Atomic_IMPL) | if (ID_AA64ISAR0_Atomic_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_Atomic_IMPL) | |||||
hwcap |= HWCAP_ATOMICS; | hwcap |= HWCAP_ATOMICS; | ||||
if (ID_AA64ISAR0_CRC32_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_CRC32_BASE) | if (ID_AA64ISAR0_CRC32_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_CRC32_BASE) | |||||
hwcap |= HWCAP_CRC32; | hwcap |= HWCAP_CRC32; | ||||
switch (ID_AA64ISAR0_SHA2_VAL(cpu_desc[cpu].id_aa64isar0)) { | switch (ID_AA64ISAR0_SHA2_VAL(user_cpu_desc.id_aa64isar0)) { | ||||
case ID_AA64ISAR0_SHA2_BASE: | case ID_AA64ISAR0_SHA2_BASE: | ||||
hwcap |= HWCAP_SHA2; | hwcap |= HWCAP_SHA2; | ||||
break; | break; | ||||
case ID_AA64ISAR0_SHA2_512: | case ID_AA64ISAR0_SHA2_512: | ||||
hwcap |= HWCAP_SHA2 | HWCAP_SHA512; | hwcap |= HWCAP_SHA2 | HWCAP_SHA512; | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
if (ID_AA64ISAR0_SHA1_VAL(cpu_desc[cpu].id_aa64isar0)) | if (ID_AA64ISAR0_SHA1_VAL(user_cpu_desc.id_aa64isar0)) | ||||
hwcap |= HWCAP_SHA1; | hwcap |= HWCAP_SHA1; | ||||
switch (ID_AA64ISAR0_AES_VAL(cpu_desc[cpu].id_aa64isar0)) { | switch (ID_AA64ISAR0_AES_VAL(user_cpu_desc.id_aa64isar0)) { | ||||
case ID_AA64ISAR0_AES_BASE: | case ID_AA64ISAR0_AES_BASE: | ||||
hwcap |= HWCAP_AES; | hwcap |= HWCAP_AES; | ||||
break; | break; | ||||
case ID_AA64ISAR0_AES_PMULL: | case ID_AA64ISAR0_AES_PMULL: | ||||
hwcap |= HWCAP_PMULL | HWCAP_AES; | hwcap |= HWCAP_PMULL | HWCAP_AES; | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
if (ID_AA64ISAR1_LRCPC_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_LRCPC_RCPC_8_3) | if (ID_AA64ISAR1_LRCPC_VAL(user_cpu_desc.id_aa64isar1) == | ||||
ID_AA64ISAR1_LRCPC_RCPC_8_3) | |||||
hwcap |= HWCAP_LRCPC; | hwcap |= HWCAP_LRCPC; | ||||
if (ID_AA64ISAR1_FCMA_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_FCMA_IMPL) | if (ID_AA64ISAR1_FCMA_VAL(user_cpu_desc.id_aa64isar1) == | ||||
ID_AA64ISAR1_FCMA_IMPL) | |||||
hwcap |= HWCAP_FCMA; | hwcap |= HWCAP_FCMA; | ||||
if (ID_AA64ISAR1_JSCVT_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_JSCVT_IMPL) | if (ID_AA64ISAR1_JSCVT_VAL(user_cpu_desc.id_aa64isar1) == | ||||
ID_AA64ISAR1_JSCVT_IMPL) | |||||
hwcap |= HWCAP_JSCVT; | hwcap |= HWCAP_JSCVT; | ||||
if (ID_AA64ISAR1_DPB_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_DPB_DCCVAP) | if (ID_AA64ISAR1_DPB_VAL(user_cpu_desc.id_aa64isar1) == | ||||
ID_AA64ISAR1_DPB_DCCVAP) | |||||
hwcap |= HWCAP_DCPOP; | hwcap |= HWCAP_DCPOP; | ||||
if (ID_AA64PFR0_SVE_VAL(cpu_desc[cpu].id_aa64pfr0) == ID_AA64PFR0_SVE_IMPL) | if (ID_AA64PFR0_SVE_VAL(user_cpu_desc.id_aa64pfr0) == | ||||
ID_AA64PFR0_SVE_IMPL) | |||||
hwcap |= HWCAP_SVE; | hwcap |= HWCAP_SVE; | ||||
switch (ID_AA64PFR0_AdvSIMD_VAL(cpu_desc[cpu].id_aa64pfr0)) { | switch (ID_AA64PFR0_AdvSIMD_VAL(user_cpu_desc.id_aa64pfr0)) { | ||||
case ID_AA64PFR0_AdvSIMD_IMPL: | case ID_AA64PFR0_AdvSIMD_IMPL: | ||||
hwcap |= HWCAP_ASIMD; | hwcap |= HWCAP_ASIMD; | ||||
break; | break; | ||||
case ID_AA64PFR0_AdvSIMD_HP: | case ID_AA64PFR0_AdvSIMD_HP: | ||||
hwcap |= HWCAP_ASIMD | HWCAP_ASIMDDP; | hwcap |= HWCAP_ASIMD | HWCAP_ASIMDDP; | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
switch (ID_AA64PFR0_FP_VAL(cpu_desc[cpu].id_aa64pfr0)) { | switch (ID_AA64PFR0_FP_VAL(user_cpu_desc.id_aa64pfr0)) { | ||||
case ID_AA64PFR0_FP_IMPL: | case ID_AA64PFR0_FP_IMPL: | ||||
hwcap |= HWCAP_FP; | hwcap |= HWCAP_FP; | ||||
break; | break; | ||||
case ID_AA64PFR0_FP_HP: | case ID_AA64PFR0_FP_HP: | ||||
hwcap |= HWCAP_FP | HWCAP_FPHP; | hwcap |= HWCAP_FP | HWCAP_FPHP; | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 382 Lines • Show Last 20 Lines |