Merge branch 'work.splice_read' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / arch / arm64 / include / asm / cpufeature.h
index 7099f26..758d74f 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef __ASM_CPUFEATURE_H
 #define __ASM_CPUFEATURE_H
 
+#include <linux/jump_label.h>
+
 #include <asm/hwcap.h>
 #include <asm/sysreg.h>
 
@@ -37,8 +39,9 @@
 #define ARM64_WORKAROUND_CAVIUM_27456          12
 #define ARM64_HAS_32BIT_EL0                    13
 #define ARM64_HYP_OFFSET_LOW                   14
+#define ARM64_MISMATCHED_CACHE_LINE_SIZE       15
 
-#define ARM64_NCAPS                            15
+#define ARM64_NCAPS                            16
 
 #ifndef __ASSEMBLY__
 
@@ -63,7 +66,7 @@ struct arm64_ftr_bits {
        enum ftr_type   type;
        u8              shift;
        u8              width;
-       s64             safe_val; /* safe value for discrete features */
+       s64             safe_val; /* safe value for FTR_EXACT features */
 };
 
 /*
@@ -72,13 +75,14 @@ struct arm64_ftr_bits {
  * @sys_val            Safe value across the CPUs (system view)
  */
 struct arm64_ftr_reg {
-       u32                     sys_id;
-       const char              *name;
-       u64                     strict_mask;
-       u64                     sys_val;
-       struct arm64_ftr_bits   *ftr_bits;
+       const char                      *name;
+       u64                             strict_mask;
+       u64                             sys_val;
+       const struct arm64_ftr_bits     *ftr_bits;
 };
 
+extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
+
 /* scope of capability check */
 enum {
        SCOPE_SYSTEM,
@@ -109,6 +113,7 @@ struct arm64_cpu_capabilities {
 };
 
 extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
+extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
 
 bool this_cpu_has_cap(unsigned int cap);
 
@@ -121,16 +126,21 @@ static inline bool cpus_have_cap(unsigned int num)
 {
        if (num >= ARM64_NCAPS)
                return false;
-       return test_bit(num, cpu_hwcaps);
+       if (__builtin_constant_p(num))
+               return static_branch_unlikely(&cpu_hwcap_keys[num]);
+       else
+               return test_bit(num, cpu_hwcaps);
 }
 
 static inline void cpus_set_cap(unsigned int num)
 {
-       if (num >= ARM64_NCAPS)
+       if (num >= ARM64_NCAPS) {
                pr_warn("Attempt to set an illegal CPU capability (%d >= %d)\n",
                        num, ARM64_NCAPS);
-       else
+       } else {
                __set_bit(num, cpu_hwcaps);
+               static_branch_enable(&cpu_hwcap_keys[num]);
+       }
 }
 
 static inline int __attribute_const__
@@ -157,7 +167,7 @@ cpuid_feature_extract_unsigned_field(u64 features, int field)
        return cpuid_feature_extract_unsigned_field_width(features, field, 4);
 }
 
-static inline u64 arm64_ftr_mask(struct arm64_ftr_bits *ftrp)
+static inline u64 arm64_ftr_mask(const struct arm64_ftr_bits *ftrp)
 {
        return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift);
 }
@@ -170,7 +180,7 @@ cpuid_feature_extract_field(u64 features, int field, bool sign)
                cpuid_feature_extract_unsigned_field(features, field);
 }
 
-static inline s64 arm64_ftr_value(struct arm64_ftr_bits *ftrp, u64 val)
+static inline s64 arm64_ftr_value(const struct arm64_ftr_bits *ftrp, u64 val)
 {
        return (s64)cpuid_feature_extract_field(val, ftrp->shift, ftrp->sign);
 }
@@ -193,11 +203,11 @@ void __init setup_cpu_features(void);
 void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
                            const char *info);
 void enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps);
-void check_local_cpu_errata(void);
-void __init enable_errata_workarounds(void);
+void check_local_cpu_capabilities(void);
 
-void verify_local_cpu_errata(void);
-void verify_local_cpu_capabilities(void);
+void update_cpu_errata_workarounds(void);
+void __init enable_errata_workarounds(void);
+void verify_local_cpu_errata_workarounds(void);
 
 u64 read_system_reg(u32 id);