Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm64/arm64/identcpu.c
Show All 37 Lines | |||||
#include <sys/sbuf.h> | #include <sys/sbuf.h> | ||||
#include <sys/smp.h> | #include <sys/smp.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#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/elf.h> | #include <machine/elf.h> | ||||
#include <machine/md_var.h> | |||||
#include <machine/undefined.h> | |||||
static void print_cpu_features(u_int cpu); | static void print_cpu_features(u_int cpu); | ||||
static u_long parse_cpu_features_hwcap(void); | static u_long parse_cpu_features_hwcap(void); | ||||
static u_long parse_cpu_features_hwcap2(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 805 Lines • ▼ Show 20 Lines | static struct mrs_field_value id_aa64pfr1_mte[] = { | ||||
MRS_FIELD_VALUE(ID_AA64PFR1_MTE_NONE, ""), | MRS_FIELD_VALUE(ID_AA64PFR1_MTE_NONE, ""), | ||||
MRS_FIELD_VALUE(ID_AA64PFR1_MTE_IMPL_EL0, "MTE EL0"), | MRS_FIELD_VALUE(ID_AA64PFR1_MTE_IMPL_EL0, "MTE EL0"), | ||||
MRS_FIELD_VALUE(ID_AA64PFR1_MTE_IMPL, "MTE"), | MRS_FIELD_VALUE(ID_AA64PFR1_MTE_IMPL, "MTE"), | ||||
MRS_FIELD_VALUE_END, | MRS_FIELD_VALUE_END, | ||||
}; | }; | ||||
static struct mrs_field id_aa64pfr1_fields[] = { | static struct mrs_field id_aa64pfr1_fields[] = { | ||||
MRS_FIELD(ID_AA64PFR1, BT, false, MRS_EXACT, id_aa64pfr1_bt), | MRS_FIELD(ID_AA64PFR1, BT, false, MRS_EXACT, id_aa64pfr1_bt), | ||||
MRS_FIELD(ID_AA64PFR1, SSBS, false, MRS_EXACT, id_aa64pfr1_ssbs), | MRS_FIELD(ID_AA64PFR1, SSBS, false, MRS_LOWER, id_aa64pfr1_ssbs), | ||||
MRS_FIELD(ID_AA64PFR1, MTE, false, MRS_EXACT, id_aa64pfr1_mte), | MRS_FIELD(ID_AA64PFR1, MTE, false, MRS_EXACT, id_aa64pfr1_mte), | ||||
MRS_FIELD_END, | MRS_FIELD_END, | ||||
}; | }; | ||||
struct mrs_user_reg { | struct mrs_user_reg { | ||||
u_int reg; | u_int reg; | ||||
u_int CRm; | u_int CRm; | ||||
u_int Op2; | u_int Op2; | ||||
▲ Show 20 Lines • Show All 240 Lines • ▼ Show 20 Lines | for (i = 0; i < nitems(user_regs); i++) { | ||||
} | } | ||||
CPU_DESC_FIELD(kern_cpu_desc, i) = kern_reg; | CPU_DESC_FIELD(kern_cpu_desc, i) = kern_reg; | ||||
CPU_DESC_FIELD(user_cpu_desc, i) = user_reg; | CPU_DESC_FIELD(user_cpu_desc, i) = user_reg; | ||||
} | } | ||||
} | } | ||||
/* HWCAP */ | /* HWCAP */ | ||||
extern u_long elf_hwcap; | |||||
bool __read_frequently lse_supported = false; | bool __read_frequently lse_supported = false; | ||||
bool __read_frequently icache_aliasing = false; | bool __read_frequently icache_aliasing = false; | ||||
bool __read_frequently icache_vmid = false; | bool __read_frequently icache_vmid = false; | ||||
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 */ | ||||
Show All 13 Lines | 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 */ | /* Exposed to userspace as AT_HWCAP and AT_HWCAP2 */ | ||||
elf_hwcap = parse_cpu_features_hwcap(); | elf_hwcap = parse_cpu_features_hwcap(); | ||||
elf_hwcap2 = parse_cpu_features_hwcap2(); | |||||
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) { | ||||
Show All 20 Lines | |||||
} | } | ||||
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(void) | parse_cpu_features_hwcap(void) | ||||
{ | { | ||||
u_long hwcap = 0; | u_long hwcap = 0; | ||||
switch (ID_AA64ISAR0_TS_VAL(user_cpu_desc.id_aa64isar0)) { | |||||
case ID_AA64ISAR0_TS_CondM_8_4: | |||||
case ID_AA64ISAR0_TS_CondM_8_5: | |||||
hwcap |= HWCAP_FLAGM; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
if (ID_AA64ISAR0_DP_VAL(user_cpu_desc.id_aa64isar0) == | if (ID_AA64ISAR0_DP_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_DP_IMPL) | ID_AA64ISAR0_DP_IMPL) | ||||
hwcap |= HWCAP_ASIMDDP; | hwcap |= HWCAP_ASIMDDP; | ||||
if (ID_AA64ISAR0_SM4_VAL(user_cpu_desc.id_aa64isar0) == | if (ID_AA64ISAR0_SM4_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_SM4_IMPL) | ID_AA64ISAR0_SM4_IMPL) | ||||
hwcap |= HWCAP_SM4; | hwcap |= HWCAP_SM4; | ||||
if (ID_AA64ISAR0_SM3_VAL(user_cpu_desc.id_aa64isar0) == | if (ID_AA64ISAR0_SM3_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_SM3_IMPL) | ID_AA64ISAR0_SM3_IMPL) | ||||
hwcap |= HWCAP_SM3; | hwcap |= HWCAP_SM3; | ||||
if (ID_AA64ISAR0_SHA3_VAL(user_cpu_desc.id_aa64isar0) == | |||||
ID_AA64ISAR0_SHA3_IMPL) | |||||
hwcap |= HWCAP_SHA3; | |||||
if (ID_AA64ISAR0_RDM_VAL(user_cpu_desc.id_aa64isar0) == | if (ID_AA64ISAR0_RDM_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_RDM_IMPL) | ID_AA64ISAR0_RDM_IMPL) | ||||
hwcap |= HWCAP_ASIMDRDM; | hwcap |= HWCAP_ASIMDRDM; | ||||
if (ID_AA64ISAR0_Atomic_VAL(user_cpu_desc.id_aa64isar0) == | if (ID_AA64ISAR0_Atomic_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_Atomic_IMPL) | ID_AA64ISAR0_Atomic_IMPL) | ||||
hwcap |= HWCAP_ATOMICS; | hwcap |= HWCAP_ATOMICS; | ||||
if (ID_AA64ISAR0_CRC32_VAL(user_cpu_desc.id_aa64isar0) == | if (ID_AA64ISAR0_CRC32_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_CRC32_BASE) | ID_AA64ISAR0_CRC32_BASE) | ||||
hwcap |= HWCAP_CRC32; | hwcap |= HWCAP_CRC32; | ||||
switch (ID_AA64ISAR0_SHA2_VAL(user_cpu_desc.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(user_cpu_desc.id_aa64isar0)) | if (ID_AA64ISAR0_SHA1_VAL(user_cpu_desc.id_aa64isar0) == | ||||
ID_AA64ISAR0_SHA1_BASE) | |||||
hwcap |= HWCAP_SHA1; | hwcap |= HWCAP_SHA1; | ||||
switch (ID_AA64ISAR0_AES_VAL(user_cpu_desc.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(user_cpu_desc.id_aa64isar1) == | if (ID_AA64ISAR1_SB_VAL(user_cpu_desc.id_aa64isar1) == | ||||
ID_AA64ISAR1_LRCPC_RCPC_8_3) | ID_AA64ISAR1_SB_IMPL) | ||||
hwcap |= HWCAP_SB; | |||||
switch (ID_AA64ISAR1_LRCPC_VAL(user_cpu_desc.id_aa64isar1)) { | |||||
case ID_AA64ISAR1_LRCPC_RCPC_8_3: | |||||
hwcap |= HWCAP_LRCPC; | hwcap |= HWCAP_LRCPC; | ||||
break; | |||||
case ID_AA64ISAR1_LRCPC_RCPC_8_4: | |||||
hwcap |= HWCAP_LRCPC | HWCAP_ILRCPC; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
if (ID_AA64ISAR1_FCMA_VAL(user_cpu_desc.id_aa64isar1) == | if (ID_AA64ISAR1_FCMA_VAL(user_cpu_desc.id_aa64isar1) == | ||||
ID_AA64ISAR1_FCMA_IMPL) | ID_AA64ISAR1_FCMA_IMPL) | ||||
hwcap |= HWCAP_FCMA; | hwcap |= HWCAP_FCMA; | ||||
if (ID_AA64ISAR1_JSCVT_VAL(user_cpu_desc.id_aa64isar1) == | if (ID_AA64ISAR1_JSCVT_VAL(user_cpu_desc.id_aa64isar1) == | ||||
ID_AA64ISAR1_JSCVT_IMPL) | ID_AA64ISAR1_JSCVT_IMPL) | ||||
hwcap |= HWCAP_JSCVT; | hwcap |= HWCAP_JSCVT; | ||||
Show All 23 Lines | case ID_AA64PFR0_FP_IMPL: | ||||
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; | ||||
} | } | ||||
if (ID_AA64PFR1_SSBS_VAL(user_cpu_desc.id_aa64pfr1) == | |||||
ID_AA64PFR1_SSBS_PSTATE_MSR) | |||||
hwcap |= HWCAP_SSBS; | |||||
return (hwcap); | return (hwcap); | ||||
} | |||||
static u_long | |||||
parse_cpu_features_hwcap2(void) | |||||
{ | |||||
u_long hwcap2 = 0; | |||||
if (ID_AA64ISAR0_RNDR_VAL(user_cpu_desc.id_aa64isar0) == | |||||
ID_AA64ISAR0_RNDR_IMPL) | |||||
hwcap2 |= HWCAP2_RNG; | |||||
if (ID_AA64ISAR0_TS_VAL(user_cpu_desc.id_aa64isar0) == | |||||
ID_AA64ISAR0_TS_CondM_8_5) | |||||
hwcap2 |= HWCAP2_FLAGM2; | |||||
if (ID_AA64ISAR1_I8MM_VAL(user_cpu_desc.id_aa64isar1) == | |||||
ID_AA64ISAR1_I8MM_IMPL) | |||||
hwcap2 |= HWCAP2_I8MM; | |||||
if (ID_AA64ISAR1_DGH_VAL(user_cpu_desc.id_aa64isar1) == | |||||
ID_AA64ISAR1_DGH_IMPL) | |||||
hwcap2 |= HWCAP2_DGH; | |||||
if (ID_AA64ISAR1_BF16_VAL(user_cpu_desc.id_aa64isar1) == | |||||
ID_AA64ISAR1_BF16_IMPL) | |||||
hwcap2 |= HWCAP2_BF16; | |||||
if (ID_AA64ISAR1_FRINTTS_VAL(user_cpu_desc.id_aa64isar1) == | |||||
ID_AA64ISAR1_FRINTTS_IMPL) | |||||
hwcap2 |= HWCAP2_FRINT; | |||||
if (ID_AA64ISAR1_DPB_VAL(user_cpu_desc.id_aa64isar1) == | |||||
ID_AA64ISAR1_DPB_DCCVADP) | |||||
hwcap2 |= HWCAP2_DCPODP; | |||||
if (ID_AA64PFR1_BT_VAL(user_cpu_desc.id_aa64pfr1) == | |||||
ID_AA64PFR1_BT_IMPL) | |||||
hwcap2 |= HWCAP2_BTI; | |||||
return (hwcap2); | |||||
} | } | ||||
static void | static void | ||||
print_ctr_fields(struct sbuf *sb, uint64_t reg, void *arg) | print_ctr_fields(struct sbuf *sb, uint64_t reg, void *arg) | ||||
{ | { | ||||
sbuf_printf(sb, "%u byte D-cacheline,", CTR_DLINE_SIZE(reg)); | sbuf_printf(sb, "%u byte D-cacheline,", CTR_DLINE_SIZE(reg)); | ||||
sbuf_printf(sb, "%u byte I-cacheline,", CTR_ILINE_SIZE(reg)); | sbuf_printf(sb, "%u byte I-cacheline,", CTR_ILINE_SIZE(reg)); | ||||
▲ Show 20 Lines • Show All 371 Lines • Show Last 20 Lines |