]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
feat(cpufeat): extend check_feature() to deal with min/max
authorAndre Przywara <andre.przywara@arm.com>
Wed, 1 Feb 2023 11:46:31 +0000 (11:46 +0000)
committerAndre Przywara <andre.przywara@arm.com>
Mon, 27 Feb 2023 18:04:14 +0000 (18:04 +0000)
So far the check_feature() function compares the subfield of a CPU ID
register against 0, to learn if a feature is enabled or not.
This is problematic for checks that require a certain revision of a
feature, so we should check against a minimum version number instead.
On top of that we might need to add code to support newer versions of a
feature, so we should be alerted if new hardware introduces a higher
number.

Extend the check_feature() function to take two extra arguments: the
minimum version, and the greatest currently known number.
Then make sure that the CPU ID field is in this range.

Change-Id: I425b68535a2ba9eafd31854e74d142183b521cd5
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
common/feat_detect.c

index a8c40f70d776a3668f22369ac14c4af2f27f6ac4..cbe78c057f9c9f65a457a6e6f39eec47218453ee 100644 (file)
@@ -36,19 +36,28 @@ static inline void feature_panic(char *feat_name)
 /*******************************************************************************
  * Function : check_feature
  * Check for a valid combination of build time flags (ENABLE_FEAT_xxx) and
- * feature availability on the hardware.
- * Panics if a feature is forcefully enabled, but not available on the PE.
+ * feature availability on the hardware. <min> is the smallest feature
+ * ID field value that is required for that feature.
+ * Triggers a panic later if a feature is forcefully enabled, but not
+ * available on the PE. Also will panic if the hardware feature ID field
+ * is larger than the maximum known and supported number, specified by <max>.
  *
  * We force inlining here to let the compiler optimise away the whole check
  * if the feature is disabled at build time (FEAT_STATE_DISABLED).
  ******************************************************************************/
 static inline void __attribute((__always_inline__))
-check_feature(int state, unsigned long field, const char *feat_name)
+check_feature(int state, unsigned long field, const char *feat_name,
+             unsigned int min, unsigned int max)
 {
-       if (state == FEAT_STATE_ALWAYS && field == 0U) {
+       if (state == FEAT_STATE_ALWAYS && field < min) {
                ERROR("FEAT_%s not supported by the PE\n", feat_name);
                tainted = true;
        }
+       if (state >= FEAT_STATE_ALWAYS && field > max) {
+               ERROR("FEAT_%s is version %ld, but is only known up to version %d\n",
+                     feat_name, field, max);
+               tainted = true;
+       }
 }
 
 /******************************************
@@ -312,7 +321,8 @@ void detect_arch_features(void)
 
        /* v8.4 features */
        read_feat_dit();
-       check_feature(ENABLE_FEAT_AMUv1, read_feat_amu_id_field(), "AMUv1");
+       check_feature(ENABLE_FEAT_AMUv1, read_feat_amu_id_field(),
+                     "AMUv1", 1, 2);
        read_feat_mpam();
        read_feat_nv2();
        read_feat_sel2();
@@ -326,12 +336,12 @@ void detect_arch_features(void)
 
        /* v8.6 features */
        read_feat_amuv1p1();
-       check_feature(ENABLE_FEAT_FGT, read_feat_fgt_id_field(), "FGT");
+       check_feature(ENABLE_FEAT_FGT, read_feat_fgt_id_field(), "FGT", 1, 1);
        read_feat_ecv();
        read_feat_twed();
 
        /* v8.7 features */
-       check_feature(ENABLE_FEAT_HCX, read_feat_hcx_id_field(), "HCX");
+       check_feature(ENABLE_FEAT_HCX, read_feat_hcx_id_field(), "HCX", 1, 1);
 
        /* v9.0 features */
        read_feat_brbe();