Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/riscv/include/asm/cpufeature.h
51658 views
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
extern const struct seq_operations cpuinfo_op;
35
36
/* Per-cpu ISA extensions. */
37
extern struct riscv_isainfo hart_isa[NR_CPUS];
38
39
extern u32 thead_vlenb_of;
40
41
void __init riscv_user_isa_enable(void);
42
43
#define _RISCV_ISA_EXT_DATA(_name, _id, _subset_exts, _subset_exts_size, _validate) { \
44
.name = #_name, \
45
.property = #_name, \
46
.id = _id, \
47
.subset_ext_ids = _subset_exts, \
48
.subset_ext_size = _subset_exts_size, \
49
.validate = _validate \
50
}
51
52
#define __RISCV_ISA_EXT_DATA(_name, _id) _RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, NULL)
53
54
#define __RISCV_ISA_EXT_DATA_VALIDATE(_name, _id, _validate) \
55
_RISCV_ISA_EXT_DATA(_name, _id, NULL, 0, _validate)
56
57
/* Used to declare pure "lasso" extension (Zk for instance) */
58
#define __RISCV_ISA_EXT_BUNDLE(_name, _bundled_exts) \
59
_RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \
60
ARRAY_SIZE(_bundled_exts), NULL)
61
#define __RISCV_ISA_EXT_BUNDLE_VALIDATE(_name, _bundled_exts, _validate) \
62
_RISCV_ISA_EXT_DATA(_name, RISCV_ISA_EXT_INVALID, _bundled_exts, \
63
ARRAY_SIZE(_bundled_exts), _validate)
64
65
/* Used to declare extensions that are a superset of other extensions (Zvbb for instance) */
66
#define __RISCV_ISA_EXT_SUPERSET(_name, _id, _sub_exts) \
67
_RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), NULL)
68
#define __RISCV_ISA_EXT_SUPERSET_VALIDATE(_name, _id, _sub_exts, _validate) \
69
_RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate)
70
71
bool __init check_unaligned_access_emulated_all_cpus(void);
72
void unaligned_access_init(void);
73
int cpu_online_unaligned_access_init(unsigned int cpu);
74
#if defined(CONFIG_RISCV_SCALAR_MISALIGNED)
75
void unaligned_emulation_finish(void);
76
bool unaligned_ctl_available(void);
77
#else
78
static inline bool unaligned_ctl_available(void)
79
{
80
return false;
81
}
82
#endif
83
84
#if defined(CONFIG_RISCV_MISALIGNED)
85
DECLARE_PER_CPU(long, misaligned_access_speed);
86
bool misaligned_traps_can_delegate(void);
87
#else
88
static inline bool misaligned_traps_can_delegate(void)
89
{
90
return false;
91
}
92
#endif
93
94
bool __init check_vector_unaligned_access_emulated_all_cpus(void);
95
#if defined(CONFIG_RISCV_VECTOR_MISALIGNED)
96
void check_vector_unaligned_access_emulated(struct work_struct *work __always_unused);
97
DECLARE_PER_CPU(long, vector_misaligned_access);
98
#endif
99
100
#if defined(CONFIG_RISCV_PROBE_UNALIGNED_ACCESS)
101
DECLARE_STATIC_KEY_FALSE(fast_unaligned_access_speed_key);
102
103
static __always_inline bool has_fast_unaligned_accesses(void)
104
{
105
return static_branch_likely(&fast_unaligned_access_speed_key);
106
}
107
#else
108
static __always_inline bool has_fast_unaligned_accesses(void)
109
{
110
if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
111
return true;
112
else
113
return false;
114
}
115
#endif
116
117
unsigned long riscv_get_elf_hwcap(void);
118
119
struct riscv_isa_ext_data {
120
const unsigned int id;
121
const char *name;
122
const char *property;
123
const unsigned int *subset_ext_ids;
124
const unsigned int subset_ext_size;
125
int (*validate)(const struct riscv_isa_ext_data *data, const unsigned long *isa_bitmap);
126
};
127
128
extern const struct riscv_isa_ext_data riscv_isa_ext[];
129
extern const size_t riscv_isa_ext_count;
130
extern bool riscv_isa_fallback;
131
132
unsigned long riscv_isa_extension_base(const unsigned long *isa_bitmap);
133
static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsigned long ext)
134
{
135
compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
136
137
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) &&
138
__riscv_has_extension_likely(STANDARD_EXT, ext))
139
return true;
140
141
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
142
}
143
144
static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsigned long ext)
145
{
146
compiletime_assert(ext < RISCV_ISA_EXT_MAX, "ext must be < RISCV_ISA_EXT_MAX");
147
148
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) &&
149
__riscv_has_extension_unlikely(STANDARD_EXT, ext))
150
return true;
151
152
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
153
}
154
155
static inline bool cpu_supports_shadow_stack(void)
156
{
157
return (IS_ENABLED(CONFIG_RISCV_USER_CFI) &&
158
riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICFISS));
159
}
160
161
static inline bool cpu_supports_indirect_br_lp_instr(void)
162
{
163
return (IS_ENABLED(CONFIG_RISCV_USER_CFI) &&
164
riscv_has_extension_unlikely(RISCV_ISA_EXT_ZICFILP));
165
}
166
167
#endif
168
169