1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright 2022-2024 Rivos, Inc
6 #ifndef _ASM_CPUFEATURE_H
7 #define _ASM_CPUFEATURE_H
9 #include <linux/bitmap.h>
10 #include <linux/jump_label.h>
11 #include <asm/hwcap.h>
12 #include <asm/alternative-macros.h>
13 #include <asm/errno.h>
16 * These are probed via a device_initcall(), via either the SBI or directly
17 * from the corresponding CSRs.
19 struct riscv_cpuinfo
{
20 unsigned long mvendorid
;
21 unsigned long marchid
;
25 struct riscv_isainfo
{
26 DECLARE_BITMAP(isa
, RISCV_ISA_EXT_MAX
);
29 DECLARE_PER_CPU(struct riscv_cpuinfo
, riscv_cpuinfo
);
31 /* Per-cpu ISA extensions. */
32 extern struct riscv_isainfo hart_isa
[NR_CPUS
];
34 void riscv_user_isa_enable(void);
36 #define _RISCV_ISA_EXT_DATA(_name, _id, _subset_exts, _subset_exts_size, _validate) { \
40 .subset_ext_ids = _subset_exts, \
41 .subset_ext_size = _subset_exts_size, \
42 .validate = _validate \
45 #define __RISCV_ISA_EXT_DATA(_name, _id) _RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, NULL)
47 #define __RISCV_ISA_EXT_DATA_VALIDATE(_name, _id, _validate) \
48 _RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, _validate)
50 /* Used to declare pure "lasso" extension (Zk for instance) */
51 #define __RISCV_ISA_EXT_BUNDLE(_name, _bundled_exts) \
52 _RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \
53 ARRAY_SIZE(_bundled_exts), NULL)
55 /* Used to declare extensions that are a superset of other extensions (Zvbb for instance) */
56 #define __RISCV_ISA_EXT_SUPERSET(_name, _id, _sub_exts) \
57 _RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), NULL)
58 #define __RISCV_ISA_EXT_SUPERSET_VALIDATE(_name, _id, _sub_exts, _validate) \
59 _RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate)
61 #if defined(CONFIG_RISCV_MISALIGNED)
62 bool check_unaligned_access_emulated_all_cpus(void);
63 void unaligned_emulation_finish(void);
64 bool unaligned_ctl_available(void);
65 DECLARE_PER_CPU(long, misaligned_access_speed
);
67 static inline bool unaligned_ctl_available(void)
73 #if defined(CONFIG_RISCV_PROBE_UNALIGNED_ACCESS)
74 DECLARE_STATIC_KEY_FALSE(fast_unaligned_access_speed_key
);
76 static __always_inline
bool has_fast_unaligned_accesses(void)
78 return static_branch_likely(&fast_unaligned_access_speed_key
);
81 static __always_inline
bool has_fast_unaligned_accesses(void)
83 if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
))
90 unsigned long riscv_get_elf_hwcap(void);
92 struct riscv_isa_ext_data
{
93 const unsigned int id
;
96 const unsigned int *subset_ext_ids
;
97 const unsigned int subset_ext_size
;
98 int (*validate
)(const struct riscv_isa_ext_data
*data
, const unsigned long *isa_bitmap
);
101 extern const struct riscv_isa_ext_data riscv_isa_ext
[];
102 extern const size_t riscv_isa_ext_count
;
103 extern bool riscv_isa_fallback
;
105 unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap
);
107 #define STANDARD_EXT 0
109 bool __riscv_isa_extension_available(const unsigned long *isa_bitmap
, unsigned int bit
);
110 #define riscv_isa_extension_available(isa_bitmap, ext) \
111 __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
113 static __always_inline
bool __riscv_has_extension_likely(const unsigned long vendor
,
114 const unsigned long ext
)
116 asm goto(ALTERNATIVE("j %l[l_no]", "nop", %[vendor
], %[ext
], 1)
118 : [vendor
] "i" (vendor
), [ext
] "i" (ext
)
127 static __always_inline
bool __riscv_has_extension_unlikely(const unsigned long vendor
,
128 const unsigned long ext
)
130 asm goto(ALTERNATIVE("nop", "j %l[l_yes]", %[vendor
], %[ext
], 1)
132 : [vendor
] "i" (vendor
), [ext
] "i" (ext
)
141 static __always_inline
bool riscv_has_extension_unlikely(const unsigned long ext
)
143 compiletime_assert(ext
< RISCV_ISA_EXT_MAX
, "ext must be < RISCV_ISA_EXT_MAX");
145 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE
))
146 return __riscv_has_extension_unlikely(STANDARD_EXT
, ext
);
148 return __riscv_isa_extension_available(NULL
, ext
);
151 static __always_inline
bool riscv_has_extension_likely(const unsigned long ext
)
153 compiletime_assert(ext
< RISCV_ISA_EXT_MAX
, "ext must be < RISCV_ISA_EXT_MAX");
155 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE
))
156 return __riscv_has_extension_likely(STANDARD_EXT
, ext
);
158 return __riscv_isa_extension_available(NULL
, ext
);
161 static __always_inline
bool riscv_cpu_has_extension_likely(int cpu
, const unsigned long ext
)
163 compiletime_assert(ext
< RISCV_ISA_EXT_MAX
, "ext must be < RISCV_ISA_EXT_MAX");
165 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE
) &&
166 __riscv_has_extension_likely(STANDARD_EXT
, ext
))
169 return __riscv_isa_extension_available(hart_isa
[cpu
].isa
, ext
);
172 static __always_inline
bool riscv_cpu_has_extension_unlikely(int cpu
, const unsigned long ext
)
174 compiletime_assert(ext
< RISCV_ISA_EXT_MAX
, "ext must be < RISCV_ISA_EXT_MAX");
176 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE
) &&
177 __riscv_has_extension_unlikely(STANDARD_EXT
, ext
))
180 return __riscv_isa_extension_available(hart_isa
[cpu
].isa
, ext
);