diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -892,16 +892,17 @@ return (ID_AA64ISAR2_WFxT_VAL(id_aa64isar2) != ID_AA64ISAR2_WFxT_NONE); } -static void +static bool wfxt_enable(const struct cpu_feat *feat __unused, cpu_feat_errata errata_status __unused, u_int *errata_list __unused, u_int errata_count __unused) { /* will be called if wfxt_check returns true */ enable_wfxt = true; + return (true); } -CPU_FEAT(feat_wfxt, +CPU_FEAT(feat_wfxt, "WFE and WFI instructions with timeout", wfxt_check, NULL, wfxt_enable, CPU_FEAT_AFTER_DEV | CPU_FEAT_SYSTEM); #endif diff --git a/sys/arm64/arm64/cpu_feat.c b/sys/arm64/arm64/cpu_feat.c --- a/sys/arm64/arm64/cpu_feat.c +++ b/sys/arm64/arm64/cpu_feat.c @@ -32,6 +32,8 @@ #include #include +SYSCTL_NODE(_hw, OID_AUTO, feat, CTLFLAG_RD, 0, "CPU features/errata"); + /* TODO: Make this a list if we ever grow a callback other than smccc_errata */ static cpu_feat_errata_check_fn cpu_feat_check_cb = NULL; @@ -97,8 +99,9 @@ /* Shouldn't be possible */ MPASS(errata_status != ERRATA_UNKNOWN); - feat->feat_enable(feat, errata_status, errata_list, - errata_count); + if (feat->feat_enable(feat, errata_status, errata_list, + errata_count)) + feat->feat_enabled = true; } } diff --git a/sys/arm64/arm64/identcpu.c b/sys/arm64/arm64/identcpu.c --- a/sys/arm64/arm64/identcpu.c +++ b/sys/arm64/arm64/identcpu.c @@ -2320,7 +2320,7 @@ return (false); } -static void +static bool user_ctr_enable(const struct cpu_feat *feat __unused, cpu_feat_errata errata_status, u_int *errata_list, u_int errata_count) { @@ -2356,9 +2356,11 @@ WRITE_SPECIALREG(sctlr_el1, READ_SPECIALREG(sctlr_el1) & ~SCTLR_UCT); isb(); + + return (true); } -CPU_FEAT(trap_ctr, +CPU_FEAT(trap_ctr, "Trap CTR_EL0", user_ctr_check, user_ctr_has_errata, user_ctr_enable, CPU_FEAT_AFTER_DEV | CPU_FEAT_PER_CPU); diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -182,7 +182,7 @@ return (ID_AA64MMFR1_PAN_VAL(id_aa64mfr1) != ID_AA64MMFR1_PAN_NONE); } -static void +static bool pan_enable(const struct cpu_feat *feat __unused, cpu_feat_errata errata_status __unused, u_int *errata_list __unused, u_int errata_count __unused) @@ -200,9 +200,11 @@ ".arch_extension pan \n" "msr pan, #1 \n" ".arch_extension nopan \n"); + + return (true); } -CPU_FEAT(feat_pan, +CPU_FEAT(feat_pan, "Privileged access never", pan_check, NULL, pan_enable, CPU_FEAT_EARLY_BOOT | CPU_FEAT_PER_CPU); diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -1695,7 +1695,7 @@ return (false); } -static void +static bool pmap_dbm_enable(const struct cpu_feat *feat __unused, cpu_feat_errata errata_status, u_int *errata_list __unused, u_int errata_count) @@ -1704,7 +1704,7 @@ /* Skip if there is an erratum affecting DBM */ if (errata_status != ERRATA_NONE) - return; + return (false); tcr = READ_SPECIALREG(tcr_el1) | TCR_HD; WRITE_SPECIALREG(tcr_el1, tcr); @@ -1714,9 +1714,11 @@ __asm __volatile("tlbi vmalle1"); dsb(nsh); isb(); + + return (true); } -CPU_FEAT(feat_hafdbs, +CPU_FEAT(feat_hafdbs, "Hardware management of the Access flag and dirty state", pmap_dbm_check, pmap_dbm_has_errata, pmap_dbm_enable, CPU_FEAT_AFTER_DEV | CPU_FEAT_PER_CPU); diff --git a/sys/arm64/arm64/ptrauth.c b/sys/arm64/arm64/ptrauth.c --- a/sys/arm64/arm64/ptrauth.c +++ b/sys/arm64/arm64/ptrauth.c @@ -141,7 +141,7 @@ return (false); } -static void +static bool ptrauth_enable(const struct cpu_feat *feat __unused, cpu_feat_errata errata_status __unused, u_int *errata_list __unused, u_int errata_count __unused) @@ -153,9 +153,11 @@ elf64_addr_mask_14.code |= PAC_ADDR_MASK_14; elf64_addr_mask_14.data |= PAC_ADDR_MASK_14; #endif + + return (true); } -CPU_FEAT(feat_pauth, +CPU_FEAT(feat_pauth, "Pointer Authentication", ptrauth_check, NULL, ptrauth_enable, CPU_FEAT_EARLY_BOOT | CPU_FEAT_SYSTEM); diff --git a/sys/arm64/include/cpu_feat.h b/sys/arm64/include/cpu_feat.h --- a/sys/arm64/include/cpu_feat.h +++ b/sys/arm64/include/cpu_feat.h @@ -29,6 +29,7 @@ #define _MACHINE_CPU_FEAT_H_ #include +#include typedef enum { ERRATA_UNKNOWN, /* Unknown erratum */ @@ -52,7 +53,7 @@ typedef bool (cpu_feat_check)(const struct cpu_feat *, u_int); typedef bool (cpu_feat_has_errata)(const struct cpu_feat *, u_int, u_int **, u_int *); -typedef void (cpu_feat_enable)(const struct cpu_feat *, cpu_feat_errata, +typedef bool (cpu_feat_enable)(const struct cpu_feat *, cpu_feat_errata, u_int *, u_int); struct cpu_feat { @@ -61,18 +62,24 @@ cpu_feat_has_errata *feat_has_errata; cpu_feat_enable *feat_enable; uint32_t feat_flags; + bool feat_enabled; }; SET_DECLARE(cpu_feat_set, struct cpu_feat); -#define CPU_FEAT(name, check, has_errata, enable, flags) \ +SYSCTL_DECL(_hw_feat); + +#define CPU_FEAT(name, descr, check, has_errata, enable, flags) \ static struct cpu_feat name = { \ .feat_name = #name, \ .feat_check = check, \ .feat_has_errata = has_errata, \ .feat_enable = enable, \ .feat_flags = flags, \ + .feat_enabled = false, \ }; \ -DATA_SET(cpu_feat_set, name) +DATA_SET(cpu_feat_set, name); \ +SYSCTL_BOOL(_hw_feat, OID_AUTO, name, CTLFLAG_RD, &name.feat_enabled, \ + 0, descr) /* * Allow drivers to mark an erratum as worked around, e.g. the Errata