Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/riscv/include/asm/cpufeature.h
26471 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
/* 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
155