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 @@ -54,6 +54,21 @@ SET_FOREACH(featp, cpu_feat_set) { feat = *featp; + /* Read any tunable the user may have set */ + if (stage == CPU_FEAT_EARLY_BOOT && PCPU_GET(cpuid) == 0) { + snprintf(tunable, sizeof(tunable), "hw.feat.%s", + feat->feat_name); + if (TUNABLE_BOOL_FETCH(tunable, &val)) { + if (val) { + feat->feat_flags |= + CPU_FEAT_USER_ENABLED; + } else { + feat->feat_flags |= + CPU_FEAT_USER_DISABLED; + } + } + } + /* Run the enablement code at the correct stage of boot */ if ((feat->feat_flags & CPU_FEAT_STAGE_MASK) != stage) continue; @@ -71,17 +86,17 @@ if (check_status == FEAT_ALWAYS_DISABLE) goto next; - snprintf(tunable, sizeof(tunable), "hw.feat.%s", - feat->feat_name); - if (TUNABLE_BOOL_FETCH(tunable, &val)) { - /* Is the feature disabled by the tunable? */ - if (!val) - goto next; - /* If enabled by the tunable then enable it */ - } else if (check_status == FEAT_DEFAULT_DISABLE) { - /* No tunable set and disabled by default */ + /* The user disabled the feature */ + if ((feat->feat_flags & CPU_FEAT_USER_DISABLED) != 0) + goto next; + + /* + * The feature was disabled by default and the user + * didn't enable it then skip. + */ + if (check_status == FEAT_DEFAULT_DISABLE && + (feat->feat_flags & CPU_FEAT_USER_ENABLED) == 0) goto next; - } /* * Check if the feature has any errata that may need a 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 @@ -73,6 +73,9 @@ #define CPU_FEAT_PER_CPU 0x00000000 #define CPU_FEAT_SYSTEM 0x00000010 +#define CPU_FEAT_USER_ENABLED 0x40000000 +#define CPU_FEAT_USER_DISABLED 0x80000000 + struct cpu_feat; typedef cpu_feat_en (cpu_feat_check)(const struct cpu_feat *, u_int);