xref: /linux/arch/riscv/kvm/isa.c (revision 01f492e1817e858d1712f2489d0afbaa552f417b)
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