Merge tag 'kvm-x86-misc-6.9' of https://github.com/kvm-x86/linux into HEAD
[linux-2.6-block.git] / arch / riscv / include / asm / cpufeature.h
CommitLineData
ff77cf5b
EG
1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Copyright 2022-2023 Rivos, Inc
4 */
5
6#ifndef _ASM_CPUFEATURE_H
7#define _ASM_CPUFEATURE_H
8
82e9c66e 9#include <linux/bitmap.h>
e72c4333 10#include <linux/jump_label.h>
82e9c66e 11#include <asm/hwcap.h>
e72c4333
XW
12#include <asm/alternative-macros.h>
13#include <asm/errno.h>
82e9c66e 14
ff77cf5b
EG
15/*
16 * These are probed via a device_initcall(), via either the SBI or directly
17 * from the corresponding CSRs.
18 */
19struct riscv_cpuinfo {
20 unsigned long mvendorid;
21 unsigned long marchid;
22 unsigned long mimpid;
23};
24
82e9c66e
EG
25struct riscv_isainfo {
26 DECLARE_BITMAP(isa, RISCV_ISA_EXT_MAX);
27};
28
ff77cf5b
EG
29DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);
30
62a31d6e
EG
31DECLARE_PER_CPU(long, misaligned_access_speed);
32
82e9c66e
EG
33/* Per-cpu ISA extensions. */
34extern struct riscv_isainfo hart_isa[NR_CPUS];
35
43c16d51 36void riscv_user_isa_enable(void);
584ea656 37
71c54b3d
CL
38#ifdef CONFIG_RISCV_MISALIGNED
39bool unaligned_ctl_available(void);
40bool check_unaligned_access_emulated(int cpu);
41void unaligned_emulation_finish(void);
42#else
43static inline bool unaligned_ctl_available(void)
44{
45 return false;
46}
47
48static inline bool check_unaligned_access_emulated(int cpu)
49{
50 return false;
51}
52
53static inline void unaligned_emulation_finish(void) {}
54#endif
55
e72c4333
XW
56unsigned long riscv_get_elf_hwcap(void);
57
58struct riscv_isa_ext_data {
59 const unsigned int id;
60 const char *name;
61 const char *property;
0d8295ed
EG
62 const unsigned int *subset_ext_ids;
63 const unsigned int subset_ext_size;
e72c4333
XW
64};
65
66extern const struct riscv_isa_ext_data riscv_isa_ext[];
67extern const size_t riscv_isa_ext_count;
68extern bool riscv_isa_fallback;
69
70unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
71
0d8295ed 72bool __riscv_isa_extension_available(const unsigned long *isa_bitmap, unsigned int bit);
e72c4333
XW
73#define riscv_isa_extension_available(isa_bitmap, ext) \
74 __riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_##ext)
75
76static __always_inline bool
77riscv_has_extension_likely(const unsigned long ext)
78{
79 compiletime_assert(ext < RISCV_ISA_EXT_MAX,
80 "ext must be < RISCV_ISA_EXT_MAX");
81
82 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
4356e9f8 83 asm goto(
e72c4333
XW
84 ALTERNATIVE("j %l[l_no]", "nop", 0, %[ext], 1)
85 :
86 : [ext] "i" (ext)
87 :
88 : l_no);
89 } else {
90 if (!__riscv_isa_extension_available(NULL, ext))
91 goto l_no;
92 }
93
94 return true;
95l_no:
96 return false;
97}
98
99static __always_inline bool
100riscv_has_extension_unlikely(const unsigned long ext)
101{
102 compiletime_assert(ext < RISCV_ISA_EXT_MAX,
103 "ext must be < RISCV_ISA_EXT_MAX");
104
105 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE)) {
4356e9f8 106 asm goto(
e72c4333
XW
107 ALTERNATIVE("nop", "j %l[l_yes]", 0, %[ext], 1)
108 :
109 : [ext] "i" (ext)
110 :
111 : l_yes);
112 } else {
113 if (__riscv_isa_extension_available(NULL, ext))
114 goto l_yes;
115 }
116
117 return false;
118l_yes:
119 return true;
120}
121
122static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsigned long ext)
123{
124 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_likely(ext))
125 return true;
126
127 return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
128}
129
130static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsigned long ext)
131{
132 if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_unlikely(ext))
133 return true;
134
135 return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
136}
137
2ce5729f
CJ
138DECLARE_STATIC_KEY_FALSE(fast_misaligned_access_speed_key);
139
ff77cf5b 140#endif