cpufeature.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*
  2. * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. */
  8. #ifndef __ASM_CPUFEATURE_H
  9. #define __ASM_CPUFEATURE_H
  10. #include <asm/cpucaps.h>
  11. #include <asm/hwcap.h>
  12. #include <asm/sysreg.h>
  13. /*
  14. * In the arm64 world (as in the ARM world), elf_hwcap is used both internally
  15. * in the kernel and for user space to keep track of which optional features
  16. * are supported by the current system. So let's map feature 'x' to HWCAP_x.
  17. * Note that HWCAP_x constants are bit fields so we need to take the log.
  18. */
  19. #define MAX_CPU_FEATURES (8 * sizeof(elf_hwcap))
  20. #define cpu_feature(x) ilog2(HWCAP_ ## x)
  21. #ifndef __ASSEMBLY__
  22. #include <linux/bug.h>
  23. #include <linux/jump_label.h>
  24. #include <linux/kernel.h>
  25. /*
  26. * CPU feature register tracking
  27. *
  28. * The safe value of a CPUID feature field is dependent on the implications
  29. * of the values assigned to it by the architecture. Based on the relationship
  30. * between the values, the features are classified into 3 types - LOWER_SAFE,
  31. * HIGHER_SAFE and EXACT.
  32. *
  33. * The lowest value of all the CPUs is chosen for LOWER_SAFE and highest
  34. * for HIGHER_SAFE. It is expected that all CPUs have the same value for
  35. * a field when EXACT is specified, failing which, the safe value specified
  36. * in the table is chosen.
  37. */
  38. enum ftr_type {
  39. FTR_EXACT, /* Use a predefined safe value */
  40. FTR_LOWER_SAFE, /* Smaller value is safe */
  41. FTR_HIGHER_SAFE,/* Bigger value is safe */
  42. };
  43. #define FTR_STRICT true /* SANITY check strict matching required */
  44. #define FTR_NONSTRICT false /* SANITY check ignored */
  45. #define FTR_SIGNED true /* Value should be treated as signed */
  46. #define FTR_UNSIGNED false /* Value should be treated as unsigned */
  47. #define FTR_VISIBLE true /* Feature visible to the user space */
  48. #define FTR_HIDDEN false /* Feature is hidden from the user */
  49. struct arm64_ftr_bits {
  50. bool sign; /* Value is signed ? */
  51. bool visible;
  52. bool strict; /* CPU Sanity check: strict matching required ? */
  53. enum ftr_type type;
  54. u8 shift;
  55. u8 width;
  56. s64 safe_val; /* safe value for FTR_EXACT features */
  57. };
  58. /*
  59. * @arm64_ftr_reg - Feature register
  60. * @strict_mask Bits which should match across all CPUs for sanity.
  61. * @sys_val Safe value across the CPUs (system view)
  62. */
  63. struct arm64_ftr_reg {
  64. const char *name;
  65. u64 strict_mask;
  66. u64 user_mask;
  67. u64 sys_val;
  68. u64 user_val;
  69. const struct arm64_ftr_bits *ftr_bits;
  70. };
  71. extern struct arm64_ftr_reg arm64_ftr_reg_ctrel0;
  72. /* scope of capability check */
  73. enum {
  74. SCOPE_SYSTEM,
  75. SCOPE_LOCAL_CPU,
  76. };
  77. struct arm64_cpu_capabilities {
  78. const char *desc;
  79. u16 capability;
  80. int def_scope; /* default scope */
  81. bool (*matches)(const struct arm64_cpu_capabilities *caps, int scope);
  82. int (*enable)(void *); /* Called on all active CPUs */
  83. union {
  84. struct { /* To be used for erratum handling only */
  85. u32 midr_model;
  86. u32 midr_range_min, midr_range_max;
  87. };
  88. struct { /* Feature register checking */
  89. u32 sys_reg;
  90. u8 field_pos;
  91. u8 min_field_value;
  92. u8 hwcap_type;
  93. bool sign;
  94. unsigned long hwcap;
  95. };
  96. };
  97. };
  98. extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
  99. extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
  100. bool this_cpu_has_cap(unsigned int cap);
  101. static inline bool cpu_have_feature(unsigned int num)
  102. {
  103. return elf_hwcap & (1UL << num);
  104. }
  105. /* System capability check for constant caps */
  106. static inline bool cpus_have_const_cap(int num)
  107. {
  108. if (num >= ARM64_NCAPS)
  109. return false;
  110. return static_branch_unlikely(&cpu_hwcap_keys[num]);
  111. }
  112. static inline bool cpus_have_cap(unsigned int num)
  113. {
  114. if (num >= ARM64_NCAPS)
  115. return false;
  116. return test_bit(num, cpu_hwcaps);
  117. }
  118. static inline void cpus_set_cap(unsigned int num)
  119. {
  120. if (num >= ARM64_NCAPS) {
  121. pr_warn("Attempt to set an illegal CPU capability (%d >= %d)\n",
  122. num, ARM64_NCAPS);
  123. } else {
  124. __set_bit(num, cpu_hwcaps);
  125. static_branch_enable(&cpu_hwcap_keys[num]);
  126. }
  127. }
  128. static inline int __attribute_const__
  129. cpuid_feature_extract_signed_field_width(u64 features, int field, int width)
  130. {
  131. return (s64)(features << (64 - width - field)) >> (64 - width);
  132. }
  133. static inline int __attribute_const__
  134. cpuid_feature_extract_signed_field(u64 features, int field)
  135. {
  136. return cpuid_feature_extract_signed_field_width(features, field, 4);
  137. }
  138. static inline unsigned int __attribute_const__
  139. cpuid_feature_extract_unsigned_field_width(u64 features, int field, int width)
  140. {
  141. return (u64)(features << (64 - width - field)) >> (64 - width);
  142. }
  143. static inline unsigned int __attribute_const__
  144. cpuid_feature_extract_unsigned_field(u64 features, int field)
  145. {
  146. return cpuid_feature_extract_unsigned_field_width(features, field, 4);
  147. }
  148. static inline u64 arm64_ftr_mask(const struct arm64_ftr_bits *ftrp)
  149. {
  150. return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift);
  151. }
  152. static inline u64 arm64_ftr_reg_user_value(const struct arm64_ftr_reg *reg)
  153. {
  154. return (reg->user_val | (reg->sys_val & reg->user_mask));
  155. }
  156. static inline int __attribute_const__
  157. cpuid_feature_extract_field_width(u64 features, int field, int width, bool sign)
  158. {
  159. return (sign) ?
  160. cpuid_feature_extract_signed_field_width(features, field, width) :
  161. cpuid_feature_extract_unsigned_field_width(features, field, width);
  162. }
  163. static inline int __attribute_const__
  164. cpuid_feature_extract_field(u64 features, int field, bool sign)
  165. {
  166. return cpuid_feature_extract_field_width(features, field, 4, sign);
  167. }
  168. static inline s64 arm64_ftr_value(const struct arm64_ftr_bits *ftrp, u64 val)
  169. {
  170. return (s64)cpuid_feature_extract_field_width(val, ftrp->shift, ftrp->width, ftrp->sign);
  171. }
  172. static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0)
  173. {
  174. return cpuid_feature_extract_unsigned_field(mmfr0, ID_AA64MMFR0_BIGENDEL_SHIFT) == 0x1 ||
  175. cpuid_feature_extract_unsigned_field(mmfr0, ID_AA64MMFR0_BIGENDEL0_SHIFT) == 0x1;
  176. }
  177. static inline bool id_aa64pfr0_32bit_el0(u64 pfr0)
  178. {
  179. u32 val = cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_EL0_SHIFT);
  180. return val == ID_AA64PFR0_EL0_32BIT_64BIT;
  181. }
  182. void __init setup_cpu_features(void);
  183. void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
  184. const char *info);
  185. void enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps);
  186. void check_local_cpu_capabilities(void);
  187. void update_cpu_errata_workarounds(void);
  188. void __init enable_errata_workarounds(void);
  189. void verify_local_cpu_errata_workarounds(void);
  190. u64 read_system_reg(u32 id);
  191. static inline bool cpu_supports_mixed_endian_el0(void)
  192. {
  193. return id_aa64mmfr0_mixed_endian_el0(read_cpuid(ID_AA64MMFR0_EL1));
  194. }
  195. static inline bool system_supports_32bit_el0(void)
  196. {
  197. return cpus_have_const_cap(ARM64_HAS_32BIT_EL0);
  198. }
  199. static inline bool system_supports_mixed_endian_el0(void)
  200. {
  201. return id_aa64mmfr0_mixed_endian_el0(read_system_reg(SYS_ID_AA64MMFR0_EL1));
  202. }
  203. static inline bool system_supports_fpsimd(void)
  204. {
  205. return !cpus_have_const_cap(ARM64_HAS_NO_FPSIMD);
  206. }
  207. static inline bool system_uses_ttbr0_pan(void)
  208. {
  209. return IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN) &&
  210. !cpus_have_cap(ARM64_HAS_PAN);
  211. }
  212. #endif /* __ASSEMBLY__ */
  213. #endif