1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright 2022-2024 Rivos, Inc 4 */ 5 6 #ifndef _ASM_CPUFEATURE_H 7 #define _ASM_CPUFEATURE_H 8 9 #include <linux/bitmap.h> 10 #include <linux/jump_label.h> 11 #include <linux/workqueue.h> 12 #include <linux/kconfig.h> 13 #include <linux/percpu-defs.h> 14 #include <linux/threads.h> 15 #include <asm/hwcap.h> 16 #include <asm/cpufeature-macros.h> 17 18 /* 19 * These are probed via a device_initcall(), via either the SBI or directly 20 * from the corresponding CSRs. 21 */ 22 struct riscv_cpuinfo { 23 unsigned long mvendorid; 24 unsigned long marchid; 25 unsigned long mimpid; 26 }; 27 28 struct riscv_isainfo { 29 DECLARE_BITMAP(isa, RISCV_ISA_EXT_MAX); 30 }; 31 32 DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo); 33 34 /* Per-cpu ISA extensions. */ 35 extern struct riscv_isainfo hart_isa[NR_CPUS]; 36 37 extern u32 thead_vlenb_of; 38 39 void __init riscv_user_isa_enable(void); 40 41 #define _RISCV_ISA_EXT_DATA(_name, _id, _subset_exts, _subset_exts_size, _validate) { \ 42 .name = #_name, \ 43 .property = #_name, \ 44 .id = _id, \ 45 .subset_ext_ids = _subset_exts, \ 46 .subset_ext_size = _subset_exts_size, \ 47 .validate = _validate \ 48 } 49 50 #define __RISCV_ISA_EXT_DATA(_name, _id) _RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, NULL) 51 52 #define __RISCV_ISA_EXT_DATA_VALIDATE(_name, _id, _validate) \ 53 _RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, _validate) 54 55 /* Used to declare pure "lasso" extension (Zk for instance) */ 56 #define __RISCV_ISA_EXT_BUNDLE(_name, _bundled_exts) \ 57 _RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \ 58 ARRAY_SIZE(_bundled_exts), NULL) 59 #define __RISCV_ISA_EXT_BUNDLE_VALIDATE(_name, _bundled_exts, _validate) \ 60 _RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \ 61 ARRAY_SIZE(_bundled_exts), _validate) 62 63 /* Used to declare extensions that are a superset of other extensions (Zvbb for instance) */ 64 #define __RISCV_ISA_EXT_SUPERSET(_name, _id, _sub_exts) \ 65 _RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), NULL) 66 #define __RISCV_ISA_EXT_SUPERSET_VALIDATE(_name, _id, _sub_exts, _validate) \ 67 _RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate) 68 69 bool __init check_unaligned_access_emulated_all_cpus(void); 70 void unaligned_access_init(void); 71 int cpu_online_unaligned_access_init(unsigned int cpu); 72 #if defined(CONFIG_RISCV_SCALAR_MISALIGNED) 73 void unaligned_emulation_finish(void); 74 bool unaligned_ctl_available(void); 75 #else 76 static inline bool unaligned_ctl_available(void) 77 { 78 return false; 79 } 80 #endif 81 82 #if defined(CONFIG_RISCV_MISALIGNED) 83 DECLARE_PER_CPU(long, misaligned_access_speed); 84 bool misaligned_traps_can_delegate(void); 85 #else 86 static inline bool misaligned_traps_can_delegate(void) 87 { 88 return false; 89 } 90 #endif 91 92 bool __init check_vector_unaligned_access_emulated_all_cpus(void); 93 #if defined(CONFIG_RISCV_VECTOR_MISALIGNED) 94 void check_vector_unaligned_access_emulated(struct work_struct *work __always_unused); 95 DECLARE_PER_CPU(long, vector_misaligned_access); 96 #endif 97 98 #if defined(CONFIG_RISCV_PROBE_UNALIGNED_ACCESS) 99 DECLARE_STATIC_KEY_FALSE(fast_unaligned_access_speed_key); 100 101 static __always_inline bool has_fast_unaligned_accesses(void) 102 { 103 return static_branch_likely(&fast_unaligned_access_speed_key); 104 } 105 #else 106 static __always_inline bool has_fast_unaligned_accesses(void) 107 { 108 if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) 109 return true; 110 else 111 return false; 112 } 113 #endif 114 115 unsigned long riscv_get_elf_hwcap(void); 116 117 struct riscv_isa_ext_data { 118 const unsigned int id; 119 const char *name; 120 const char *property; 121 const unsigned int *subset_ext_ids; 122 const unsigned int subset_ext_size; 123 int (*validate)(const struct riscv_isa_ext_data *data, const unsigned long *isa_bitmap); 124 }; 125 126 extern const struct riscv_isa_ext_data riscv_isa_ext[]; 127 extern const size_t riscv_isa_ext_count; 128 extern bool riscv_isa_fallback; 129 130 unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap); 131 static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsigned long ext) 132 { 133 compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX"); 134 135 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && 136 __riscv_has_extension_likely(STANDARD_EXT, ext)) 137 return true; 138 139 return __riscv_isa_extension_available(hart_isa[cpu].isa, ext); 140 } 141 142 static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsigned long ext) 143 { 144 compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX"); 145 146 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && 147 __riscv_has_extension_unlikely(STANDARD_EXT, ext)) 148 return true; 149 150 return __riscv_isa_extension_available(hart_isa[cpu].isa, ext); 151 } 152 153 #endif 154