Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/riscv/kvm/isa.c
170891 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (c) 2026 Qualcomm Technologies, Inc.
4
*/
5
6
#include <linux/cpufeature.h>
7
#include <linux/errno.h>
8
#include <linux/kvm_host.h>
9
#include <linux/nospec.h>
10
#include <linux/pgtable.h>
11
#include <asm/kvm_isa.h>
12
#include <asm/vector.h>
13
14
#define KVM_ISA_EXT_ARR(ext) \
15
[KVM_RISCV_ISA_EXT_##ext] = RISCV_ISA_EXT_##ext
16
17
/* Mapping between KVM ISA Extension ID & guest ISA extension ID */
18
static const unsigned long kvm_isa_ext_arr[] = {
19
/* Single letter extensions (alphabetically sorted) */
20
[KVM_RISCV_ISA_EXT_A] = RISCV_ISA_EXT_a,
21
[KVM_RISCV_ISA_EXT_C] = RISCV_ISA_EXT_c,
22
[KVM_RISCV_ISA_EXT_D] = RISCV_ISA_EXT_d,
23
[KVM_RISCV_ISA_EXT_F] = RISCV_ISA_EXT_f,
24
[KVM_RISCV_ISA_EXT_H] = RISCV_ISA_EXT_h,
25
[KVM_RISCV_ISA_EXT_I] = RISCV_ISA_EXT_i,
26
[KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m,
27
[KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v,
28
/* Multi letter extensions (alphabetically sorted) */
29
KVM_ISA_EXT_ARR(SMNPM),
30
KVM_ISA_EXT_ARR(SMSTATEEN),
31
KVM_ISA_EXT_ARR(SSAIA),
32
KVM_ISA_EXT_ARR(SSCOFPMF),
33
KVM_ISA_EXT_ARR(SSNPM),
34
KVM_ISA_EXT_ARR(SSTC),
35
KVM_ISA_EXT_ARR(SVADE),
36
KVM_ISA_EXT_ARR(SVADU),
37
KVM_ISA_EXT_ARR(SVINVAL),
38
KVM_ISA_EXT_ARR(SVNAPOT),
39
KVM_ISA_EXT_ARR(SVPBMT),
40
KVM_ISA_EXT_ARR(SVVPTC),
41
KVM_ISA_EXT_ARR(ZAAMO),
42
KVM_ISA_EXT_ARR(ZABHA),
43
KVM_ISA_EXT_ARR(ZACAS),
44
KVM_ISA_EXT_ARR(ZALASR),
45
KVM_ISA_EXT_ARR(ZALRSC),
46
KVM_ISA_EXT_ARR(ZAWRS),
47
KVM_ISA_EXT_ARR(ZBA),
48
KVM_ISA_EXT_ARR(ZBB),
49
KVM_ISA_EXT_ARR(ZBC),
50
KVM_ISA_EXT_ARR(ZBKB),
51
KVM_ISA_EXT_ARR(ZBKC),
52
KVM_ISA_EXT_ARR(ZBKX),
53
KVM_ISA_EXT_ARR(ZBS),
54
KVM_ISA_EXT_ARR(ZCA),
55
KVM_ISA_EXT_ARR(ZCB),
56
KVM_ISA_EXT_ARR(ZCD),
57
KVM_ISA_EXT_ARR(ZCF),
58
KVM_ISA_EXT_ARR(ZCLSD),
59
KVM_ISA_EXT_ARR(ZCMOP),
60
KVM_ISA_EXT_ARR(ZFA),
61
KVM_ISA_EXT_ARR(ZFBFMIN),
62
KVM_ISA_EXT_ARR(ZFH),
63
KVM_ISA_EXT_ARR(ZFHMIN),
64
KVM_ISA_EXT_ARR(ZICBOM),
65
KVM_ISA_EXT_ARR(ZICBOP),
66
KVM_ISA_EXT_ARR(ZICBOZ),
67
KVM_ISA_EXT_ARR(ZICCRSE),
68
KVM_ISA_EXT_ARR(ZICNTR),
69
KVM_ISA_EXT_ARR(ZICOND),
70
KVM_ISA_EXT_ARR(ZICSR),
71
KVM_ISA_EXT_ARR(ZIFENCEI),
72
KVM_ISA_EXT_ARR(ZIHINTNTL),
73
KVM_ISA_EXT_ARR(ZIHINTPAUSE),
74
KVM_ISA_EXT_ARR(ZIHPM),
75
KVM_ISA_EXT_ARR(ZILSD),
76
KVM_ISA_EXT_ARR(ZIMOP),
77
KVM_ISA_EXT_ARR(ZKND),
78
KVM_ISA_EXT_ARR(ZKNE),
79
KVM_ISA_EXT_ARR(ZKNH),
80
KVM_ISA_EXT_ARR(ZKR),
81
KVM_ISA_EXT_ARR(ZKSED),
82
KVM_ISA_EXT_ARR(ZKSH),
83
KVM_ISA_EXT_ARR(ZKT),
84
KVM_ISA_EXT_ARR(ZTSO),
85
KVM_ISA_EXT_ARR(ZVBB),
86
KVM_ISA_EXT_ARR(ZVBC),
87
KVM_ISA_EXT_ARR(ZVFBFMIN),
88
KVM_ISA_EXT_ARR(ZVFBFWMA),
89
KVM_ISA_EXT_ARR(ZVFH),
90
KVM_ISA_EXT_ARR(ZVFHMIN),
91
KVM_ISA_EXT_ARR(ZVKB),
92
KVM_ISA_EXT_ARR(ZVKG),
93
KVM_ISA_EXT_ARR(ZVKNED),
94
KVM_ISA_EXT_ARR(ZVKNHA),
95
KVM_ISA_EXT_ARR(ZVKNHB),
96
KVM_ISA_EXT_ARR(ZVKSED),
97
KVM_ISA_EXT_ARR(ZVKSH),
98
KVM_ISA_EXT_ARR(ZVKT),
99
};
100
101
unsigned long kvm_riscv_base2isa_ext(unsigned long base_ext)
102
{
103
unsigned long i;
104
105
for (i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++) {
106
if (kvm_isa_ext_arr[i] == base_ext)
107
return i;
108
}
109
110
return KVM_RISCV_ISA_EXT_MAX;
111
}
112
113
int __kvm_riscv_isa_check_host(unsigned long kvm_ext, unsigned long *base_ext)
114
{
115
unsigned long host_ext;
116
117
if (kvm_ext >= KVM_RISCV_ISA_EXT_MAX ||
118
kvm_ext >= ARRAY_SIZE(kvm_isa_ext_arr))
119
return -ENOENT;
120
121
kvm_ext = array_index_nospec(kvm_ext, ARRAY_SIZE(kvm_isa_ext_arr));
122
switch (kvm_isa_ext_arr[kvm_ext]) {
123
case RISCV_ISA_EXT_SMNPM:
124
/*
125
* Pointer masking effective in (H)S-mode is provided by the
126
* Smnpm extension, so that extension is reported to the guest,
127
* even though the CSR bits for configuring VS-mode pointer
128
* masking on the host side are part of the Ssnpm extension.
129
*/
130
host_ext = RISCV_ISA_EXT_SSNPM;
131
break;
132
default:
133
host_ext = kvm_isa_ext_arr[kvm_ext];
134
break;
135
}
136
137
if (!__riscv_isa_extension_available(NULL, host_ext))
138
return -ENOENT;
139
140
if (base_ext)
141
*base_ext = kvm_isa_ext_arr[kvm_ext];
142
143
return 0;
144
}
145
146
bool kvm_riscv_isa_enable_allowed(unsigned long ext)
147
{
148
switch (ext) {
149
case KVM_RISCV_ISA_EXT_H:
150
return false;
151
case KVM_RISCV_ISA_EXT_SSCOFPMF:
152
/* Sscofpmf depends on interrupt filtering defined in ssaia */
153
return !kvm_riscv_isa_check_host(SSAIA);
154
case KVM_RISCV_ISA_EXT_SVADU:
155
/*
156
* The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero.
157
* Guest OS can use Svadu only when host OS enable Svadu.
158
*/
159
return arch_has_hw_pte_young();
160
case KVM_RISCV_ISA_EXT_V:
161
return riscv_v_vstate_ctrl_user_allowed();
162
default:
163
break;
164
}
165
166
return true;
167
}
168
169
bool kvm_riscv_isa_disable_allowed(unsigned long ext)
170
{
171
switch (ext) {
172
/* Extensions which don't have any mechanism to disable */
173
case KVM_RISCV_ISA_EXT_A:
174
case KVM_RISCV_ISA_EXT_C:
175
case KVM_RISCV_ISA_EXT_I:
176
case KVM_RISCV_ISA_EXT_M:
177
/* There is not architectural config bit to disable sscofpmf completely */
178
case KVM_RISCV_ISA_EXT_SSCOFPMF:
179
case KVM_RISCV_ISA_EXT_SSNPM:
180
case KVM_RISCV_ISA_EXT_SSTC:
181
case KVM_RISCV_ISA_EXT_SVINVAL:
182
case KVM_RISCV_ISA_EXT_SVNAPOT:
183
case KVM_RISCV_ISA_EXT_SVVPTC:
184
case KVM_RISCV_ISA_EXT_ZAAMO:
185
case KVM_RISCV_ISA_EXT_ZABHA:
186
case KVM_RISCV_ISA_EXT_ZACAS:
187
case KVM_RISCV_ISA_EXT_ZALASR:
188
case KVM_RISCV_ISA_EXT_ZALRSC:
189
case KVM_RISCV_ISA_EXT_ZAWRS:
190
case KVM_RISCV_ISA_EXT_ZBA:
191
case KVM_RISCV_ISA_EXT_ZBB:
192
case KVM_RISCV_ISA_EXT_ZBC:
193
case KVM_RISCV_ISA_EXT_ZBKB:
194
case KVM_RISCV_ISA_EXT_ZBKC:
195
case KVM_RISCV_ISA_EXT_ZBKX:
196
case KVM_RISCV_ISA_EXT_ZBS:
197
case KVM_RISCV_ISA_EXT_ZCA:
198
case KVM_RISCV_ISA_EXT_ZCB:
199
case KVM_RISCV_ISA_EXT_ZCD:
200
case KVM_RISCV_ISA_EXT_ZCF:
201
case KVM_RISCV_ISA_EXT_ZCMOP:
202
case KVM_RISCV_ISA_EXT_ZFA:
203
case KVM_RISCV_ISA_EXT_ZFBFMIN:
204
case KVM_RISCV_ISA_EXT_ZFH:
205
case KVM_RISCV_ISA_EXT_ZFHMIN:
206
case KVM_RISCV_ISA_EXT_ZICBOP:
207
case KVM_RISCV_ISA_EXT_ZICCRSE:
208
case KVM_RISCV_ISA_EXT_ZICNTR:
209
case KVM_RISCV_ISA_EXT_ZICOND:
210
case KVM_RISCV_ISA_EXT_ZICSR:
211
case KVM_RISCV_ISA_EXT_ZIFENCEI:
212
case KVM_RISCV_ISA_EXT_ZIHINTNTL:
213
case KVM_RISCV_ISA_EXT_ZIHINTPAUSE:
214
case KVM_RISCV_ISA_EXT_ZIHPM:
215
case KVM_RISCV_ISA_EXT_ZIMOP:
216
case KVM_RISCV_ISA_EXT_ZKND:
217
case KVM_RISCV_ISA_EXT_ZKNE:
218
case KVM_RISCV_ISA_EXT_ZKNH:
219
case KVM_RISCV_ISA_EXT_ZKR:
220
case KVM_RISCV_ISA_EXT_ZKSED:
221
case KVM_RISCV_ISA_EXT_ZKSH:
222
case KVM_RISCV_ISA_EXT_ZKT:
223
case KVM_RISCV_ISA_EXT_ZTSO:
224
case KVM_RISCV_ISA_EXT_ZVBB:
225
case KVM_RISCV_ISA_EXT_ZVBC:
226
case KVM_RISCV_ISA_EXT_ZVFBFMIN:
227
case KVM_RISCV_ISA_EXT_ZVFBFWMA:
228
case KVM_RISCV_ISA_EXT_ZVFH:
229
case KVM_RISCV_ISA_EXT_ZVFHMIN:
230
case KVM_RISCV_ISA_EXT_ZVKB:
231
case KVM_RISCV_ISA_EXT_ZVKG:
232
case KVM_RISCV_ISA_EXT_ZVKNED:
233
case KVM_RISCV_ISA_EXT_ZVKNHA:
234
case KVM_RISCV_ISA_EXT_ZVKNHB:
235
case KVM_RISCV_ISA_EXT_ZVKSED:
236
case KVM_RISCV_ISA_EXT_ZVKSH:
237
case KVM_RISCV_ISA_EXT_ZVKT:
238
return false;
239
/* Extensions which can be disabled using Smstateen */
240
case KVM_RISCV_ISA_EXT_SSAIA:
241
return riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN);
242
case KVM_RISCV_ISA_EXT_SVADE:
243
/*
244
* The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero.
245
* Svade can't be disabled unless we support Svadu.
246
*/
247
return arch_has_hw_pte_young();
248
default:
249
break;
250
}
251
252
return true;
253
}
254
255