The branch stable/14 has been updated by andrew:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=2210c15b08b9f70054d4de46a5a8566d395e0abe

commit 2210c15b08b9f70054d4de46a5a8566d395e0abe
Author:     Andrew Turner <[email protected]>
AuthorDate: 2025-09-04 14:45:09 +0000
Commit:     Andrew Turner <[email protected]>
CommitDate: 2026-01-14 21:14:12 +0000

    arm64: Support managing features from loader
    
    Allow the user to enable/disable supported cpu features/errata from a
    known tunable. This will allow the user to disable features, e.g. to
    work around broken firmware. It can also be used to enable workarounds
    for rare errata.
    
    Reviewed by:    imp
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D52358
    
    (cherry picked from commit 4bc68fa98f68211ee7943d77cfc91f60ccb5880d)
---
 sys/arm64/arm64/cpu_feat.c   | 22 +++++++++++++++++++++-
 sys/arm64/include/cpu_feat.h | 27 ++++++++++++++++++++++++++-
 2 files changed, 47 insertions(+), 2 deletions(-)

diff --git a/sys/arm64/arm64/cpu_feat.c b/sys/arm64/arm64/cpu_feat.c
index fd1b8429295f..986d5079e980 100644
--- a/sys/arm64/arm64/cpu_feat.c
+++ b/sys/arm64/arm64/cpu_feat.c
@@ -40,10 +40,13 @@ static cpu_feat_errata_check_fn cpu_feat_check_cb = NULL;
 void
 enable_cpu_feat(uint32_t stage)
 {
+       char tunable[32];
        struct cpu_feat **featp, *feat;
        uint32_t midr;
        u_int errata_count, *errata_list;
        cpu_feat_errata errata_status;
+       cpu_feat_en check_status;
+       bool val;
 
        MPASS((stage & ~CPU_FEAT_STAGE_MASK) == 0);
 
@@ -60,9 +63,26 @@ enable_cpu_feat(uint32_t stage)
                    PCPU_GET(cpuid) != 0)
                        continue;
 
-               if (feat->feat_check != NULL && !feat->feat_check(feat, midr))
+               if (feat->feat_check != NULL)
                        continue;
 
+               check_status = feat->feat_check(feat, midr);
+               /* Ignore features that are not present */
+               if (check_status == FEAT_ALWAYS_DISABLE)
+                       continue;
+
+               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)
+                               continue;
+                       /* If enabled by the tunable then enable it */
+               } else if (check_status == FEAT_DEFAULT_DISABLE) {
+                       /* No tunable set and disabled by default */
+                       continue;
+               }
+
                /*
                 * Check if the feature has any errata that may need a
                 * workaround applied (or it is to install the workaround for
diff --git a/sys/arm64/include/cpu_feat.h b/sys/arm64/include/cpu_feat.h
index f62f3e334dc1..6a554b6baedf 100644
--- a/sys/arm64/include/cpu_feat.h
+++ b/sys/arm64/include/cpu_feat.h
@@ -40,6 +40,31 @@ typedef enum {
                                /* kernel component. */
 } cpu_feat_errata;
 
+typedef enum {
+       /*
+        * Don't implement the feature or erratum wrokarount,
+        * e.g. the feature is not implemented or erratum is
+        * for another CPU.
+        */
+       FEAT_ALWAYS_DISABLE,
+
+       /*
+        * Disable by default, but allow the user to enable,
+        * e.g. For a rare erratum with a workaround, Arm
+        * Category B (rare) or similar.
+        */
+       FEAT_DEFAULT_DISABLE,
+
+       /*
+        * Enabled by default, bit allow the user to disable,
+        * e.g. For a common erratum with a workaround, Arm
+        * Category A or B or similar.
+        */
+       FEAT_DEFAULT_ENABLE,
+
+       /* We could add FEAT_ALWAYS_ENABLE if a need was found. */
+} cpu_feat_en;
+
 #define        CPU_FEAT_STAGE_MASK     0x00000001
 #define        CPU_FEAT_EARLY_BOOT     0x00000000
 #define        CPU_FEAT_AFTER_DEV      0x00000001
@@ -50,7 +75,7 @@ typedef enum {
 
 struct cpu_feat;
 
-typedef bool (cpu_feat_check)(const struct cpu_feat *, u_int);
+typedef cpu_feat_en (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 bool (cpu_feat_enable)(const struct cpu_feat *, cpu_feat_errata,

Reply via email to