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