xref: /linux/arch/riscv/kvm/isa.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
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_ISA_EXT_ARR(A),
21 	KVM_ISA_EXT_ARR(C),
22 	KVM_ISA_EXT_ARR(D),
23 	KVM_ISA_EXT_ARR(F),
24 	KVM_ISA_EXT_ARR(H),
25 	KVM_ISA_EXT_ARR(I),
26 	KVM_ISA_EXT_ARR(M),
27 	KVM_ISA_EXT_ARR(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(ZICFILP),
69 	KVM_ISA_EXT_ARR(ZICFISS),
70 	KVM_ISA_EXT_ARR(ZICNTR),
71 	KVM_ISA_EXT_ARR(ZICOND),
72 	KVM_ISA_EXT_ARR(ZICSR),
73 	KVM_ISA_EXT_ARR(ZIFENCEI),
74 	KVM_ISA_EXT_ARR(ZIHINTNTL),
75 	KVM_ISA_EXT_ARR(ZIHINTPAUSE),
76 	KVM_ISA_EXT_ARR(ZIHPM),
77 	KVM_ISA_EXT_ARR(ZILSD),
78 	KVM_ISA_EXT_ARR(ZIMOP),
79 	KVM_ISA_EXT_ARR(ZKND),
80 	KVM_ISA_EXT_ARR(ZKNE),
81 	KVM_ISA_EXT_ARR(ZKNH),
82 	KVM_ISA_EXT_ARR(ZKR),
83 	KVM_ISA_EXT_ARR(ZKSED),
84 	KVM_ISA_EXT_ARR(ZKSH),
85 	KVM_ISA_EXT_ARR(ZKT),
86 	KVM_ISA_EXT_ARR(ZTSO),
87 	KVM_ISA_EXT_ARR(ZVBB),
88 	KVM_ISA_EXT_ARR(ZVBC),
89 	KVM_ISA_EXT_ARR(ZVFBFMIN),
90 	KVM_ISA_EXT_ARR(ZVFBFWMA),
91 	KVM_ISA_EXT_ARR(ZVFH),
92 	KVM_ISA_EXT_ARR(ZVFHMIN),
93 	KVM_ISA_EXT_ARR(ZVKB),
94 	KVM_ISA_EXT_ARR(ZVKG),
95 	KVM_ISA_EXT_ARR(ZVKNED),
96 	KVM_ISA_EXT_ARR(ZVKNHA),
97 	KVM_ISA_EXT_ARR(ZVKNHB),
98 	KVM_ISA_EXT_ARR(ZVKSED),
99 	KVM_ISA_EXT_ARR(ZVKSH),
100 	KVM_ISA_EXT_ARR(ZVKT),
101 };
102 
103 unsigned long kvm_riscv_base2isa_ext(unsigned long base_ext)
104 {
105 	unsigned long i;
106 
107 	for (i = 0; i < KVM_RISCV_ISA_EXT_MAX; i++) {
108 		if (kvm_isa_ext_arr[i] == base_ext)
109 			return i;
110 	}
111 
112 	return KVM_RISCV_ISA_EXT_MAX;
113 }
114 
115 int __kvm_riscv_isa_check_host(unsigned long kvm_ext, unsigned long *base_ext)
116 {
117 	unsigned long host_ext;
118 
119 	if (kvm_ext >= KVM_RISCV_ISA_EXT_MAX ||
120 	    kvm_ext >= ARRAY_SIZE(kvm_isa_ext_arr))
121 		return -ENOENT;
122 
123 	kvm_ext = array_index_nospec(kvm_ext, ARRAY_SIZE(kvm_isa_ext_arr));
124 	switch (kvm_isa_ext_arr[kvm_ext]) {
125 	case RISCV_ISA_EXT_SMNPM:
126 		/*
127 		 * Pointer masking effective in (H)S-mode is provided by the
128 		 * Smnpm extension, so that extension is reported to the guest,
129 		 * even though the CSR bits for configuring VS-mode pointer
130 		 * masking on the host side are part of the Ssnpm extension.
131 		 */
132 		host_ext = RISCV_ISA_EXT_SSNPM;
133 		break;
134 	default:
135 		host_ext = kvm_isa_ext_arr[kvm_ext];
136 		break;
137 	}
138 
139 	if (!__riscv_isa_extension_available(NULL, host_ext))
140 		return -ENOENT;
141 
142 	if (base_ext)
143 		*base_ext = kvm_isa_ext_arr[kvm_ext];
144 
145 	return 0;
146 }
147 
148 bool kvm_riscv_isa_enable_allowed(unsigned long ext)
149 {
150 	switch (ext) {
151 	case KVM_RISCV_ISA_EXT_H:
152 		return false;
153 	case KVM_RISCV_ISA_EXT_SSCOFPMF:
154 		/* Sscofpmf depends on interrupt filtering defined in ssaia */
155 		return !kvm_riscv_isa_check_host(SSAIA);
156 	case KVM_RISCV_ISA_EXT_SVADU:
157 		/*
158 		 * The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero.
159 		 * Guest OS can use Svadu only when host OS enable Svadu.
160 		 */
161 		return arch_has_hw_pte_young();
162 	case KVM_RISCV_ISA_EXT_V:
163 		return riscv_v_vstate_ctrl_user_allowed();
164 	default:
165 		break;
166 	}
167 
168 	return true;
169 }
170 
171 bool kvm_riscv_isa_disable_allowed(unsigned long ext)
172 {
173 	switch (ext) {
174 	/* Extensions which don't have any mechanism to disable */
175 	case KVM_RISCV_ISA_EXT_A:
176 	case KVM_RISCV_ISA_EXT_C:
177 	case KVM_RISCV_ISA_EXT_I:
178 	case KVM_RISCV_ISA_EXT_M:
179 	/* There is not architectural config bit to disable sscofpmf completely */
180 	case KVM_RISCV_ISA_EXT_SSCOFPMF:
181 	case KVM_RISCV_ISA_EXT_SSNPM:
182 	case KVM_RISCV_ISA_EXT_SSTC:
183 	case KVM_RISCV_ISA_EXT_SVINVAL:
184 	case KVM_RISCV_ISA_EXT_SVNAPOT:
185 	case KVM_RISCV_ISA_EXT_SVVPTC:
186 	case KVM_RISCV_ISA_EXT_ZAAMO:
187 	case KVM_RISCV_ISA_EXT_ZABHA:
188 	case KVM_RISCV_ISA_EXT_ZACAS:
189 	case KVM_RISCV_ISA_EXT_ZALASR:
190 	case KVM_RISCV_ISA_EXT_ZALRSC:
191 	case KVM_RISCV_ISA_EXT_ZAWRS:
192 	case KVM_RISCV_ISA_EXT_ZBA:
193 	case KVM_RISCV_ISA_EXT_ZBB:
194 	case KVM_RISCV_ISA_EXT_ZBC:
195 	case KVM_RISCV_ISA_EXT_ZBKB:
196 	case KVM_RISCV_ISA_EXT_ZBKC:
197 	case KVM_RISCV_ISA_EXT_ZBKX:
198 	case KVM_RISCV_ISA_EXT_ZBS:
199 	case KVM_RISCV_ISA_EXT_ZCA:
200 	case KVM_RISCV_ISA_EXT_ZCB:
201 	case KVM_RISCV_ISA_EXT_ZCD:
202 	case KVM_RISCV_ISA_EXT_ZCF:
203 	case KVM_RISCV_ISA_EXT_ZCMOP:
204 	case KVM_RISCV_ISA_EXT_ZFA:
205 	case KVM_RISCV_ISA_EXT_ZFBFMIN:
206 	case KVM_RISCV_ISA_EXT_ZFH:
207 	case KVM_RISCV_ISA_EXT_ZFHMIN:
208 	case KVM_RISCV_ISA_EXT_ZICBOP:
209 	case KVM_RISCV_ISA_EXT_ZICCRSE:
210 	case KVM_RISCV_ISA_EXT_ZICNTR:
211 	case KVM_RISCV_ISA_EXT_ZICOND:
212 	case KVM_RISCV_ISA_EXT_ZICSR:
213 	case KVM_RISCV_ISA_EXT_ZIFENCEI:
214 	case KVM_RISCV_ISA_EXT_ZIHINTNTL:
215 	case KVM_RISCV_ISA_EXT_ZIHINTPAUSE:
216 	case KVM_RISCV_ISA_EXT_ZIHPM:
217 	case KVM_RISCV_ISA_EXT_ZIMOP:
218 	case KVM_RISCV_ISA_EXT_ZKND:
219 	case KVM_RISCV_ISA_EXT_ZKNE:
220 	case KVM_RISCV_ISA_EXT_ZKNH:
221 	case KVM_RISCV_ISA_EXT_ZKR:
222 	case KVM_RISCV_ISA_EXT_ZKSED:
223 	case KVM_RISCV_ISA_EXT_ZKSH:
224 	case KVM_RISCV_ISA_EXT_ZKT:
225 	case KVM_RISCV_ISA_EXT_ZTSO:
226 	case KVM_RISCV_ISA_EXT_ZVBB:
227 	case KVM_RISCV_ISA_EXT_ZVBC:
228 	case KVM_RISCV_ISA_EXT_ZVFBFMIN:
229 	case KVM_RISCV_ISA_EXT_ZVFBFWMA:
230 	case KVM_RISCV_ISA_EXT_ZVFH:
231 	case KVM_RISCV_ISA_EXT_ZVFHMIN:
232 	case KVM_RISCV_ISA_EXT_ZVKB:
233 	case KVM_RISCV_ISA_EXT_ZVKG:
234 	case KVM_RISCV_ISA_EXT_ZVKNED:
235 	case KVM_RISCV_ISA_EXT_ZVKNHA:
236 	case KVM_RISCV_ISA_EXT_ZVKNHB:
237 	case KVM_RISCV_ISA_EXT_ZVKSED:
238 	case KVM_RISCV_ISA_EXT_ZVKSH:
239 	case KVM_RISCV_ISA_EXT_ZVKT:
240 		return false;
241 	/* Extensions which can be disabled using Smstateen */
242 	case KVM_RISCV_ISA_EXT_SSAIA:
243 		return riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN);
244 	case KVM_RISCV_ISA_EXT_SVADE:
245 		/*
246 		 * The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero.
247 		 * Svade can't be disabled unless we support Svadu.
248 		 */
249 		return arch_has_hw_pte_young();
250 	default:
251 		break;
252 	}
253 
254 	return true;
255 }
256