xref: /linux/arch/riscv/kvm/vcpu_sbi.c (revision 3a2c4d55e32ad65efebdb6de44eef3bfa08bb49d)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2019 Western Digital Corporation or its affiliates.
4  *
5  * Authors:
6  *     Atish Patra <atish.patra@wdc.com>
7  */
8 
9 #include <linux/errno.h>
10 #include <linux/err.h>
11 #include <linux/kvm_host.h>
12 #include <asm/sbi.h>
13 #include <asm/kvm_vcpu_sbi.h>
14 
15 #ifndef CONFIG_RISCV_SBI_V01
16 static const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01 = {
17 	.extid_start = -1UL,
18 	.extid_end = -1UL,
19 	.handler = NULL,
20 };
21 #endif
22 
23 #ifndef CONFIG_RISCV_PMU_SBI
24 static const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_pmu = {
25 	.extid_start = -1UL,
26 	.extid_end = -1UL,
27 	.handler = NULL,
28 };
29 #endif
30 
31 struct kvm_riscv_sbi_extension_entry {
32 	enum KVM_RISCV_SBI_EXT_ID ext_idx;
33 	const struct kvm_vcpu_sbi_extension *ext_ptr;
34 };
35 
36 static const struct kvm_riscv_sbi_extension_entry sbi_ext[] = {
37 	{
38 		.ext_idx = KVM_RISCV_SBI_EXT_V01,
39 		.ext_ptr = &vcpu_sbi_ext_v01,
40 	},
41 	{
42 		.ext_idx = KVM_RISCV_SBI_EXT_MAX, /* Can't be disabled */
43 		.ext_ptr = &vcpu_sbi_ext_base,
44 	},
45 	{
46 		.ext_idx = KVM_RISCV_SBI_EXT_TIME,
47 		.ext_ptr = &vcpu_sbi_ext_time,
48 	},
49 	{
50 		.ext_idx = KVM_RISCV_SBI_EXT_IPI,
51 		.ext_ptr = &vcpu_sbi_ext_ipi,
52 	},
53 	{
54 		.ext_idx = KVM_RISCV_SBI_EXT_RFENCE,
55 		.ext_ptr = &vcpu_sbi_ext_rfence,
56 	},
57 	{
58 		.ext_idx = KVM_RISCV_SBI_EXT_SRST,
59 		.ext_ptr = &vcpu_sbi_ext_srst,
60 	},
61 	{
62 		.ext_idx = KVM_RISCV_SBI_EXT_HSM,
63 		.ext_ptr = &vcpu_sbi_ext_hsm,
64 	},
65 	{
66 		.ext_idx = KVM_RISCV_SBI_EXT_PMU,
67 		.ext_ptr = &vcpu_sbi_ext_pmu,
68 	},
69 	{
70 		.ext_idx = KVM_RISCV_SBI_EXT_DBCN,
71 		.ext_ptr = &vcpu_sbi_ext_dbcn,
72 	},
73 	{
74 		.ext_idx = KVM_RISCV_SBI_EXT_SUSP,
75 		.ext_ptr = &vcpu_sbi_ext_susp,
76 	},
77 	{
78 		.ext_idx = KVM_RISCV_SBI_EXT_STA,
79 		.ext_ptr = &vcpu_sbi_ext_sta,
80 	},
81 	{
82 		.ext_idx = KVM_RISCV_SBI_EXT_FWFT,
83 		.ext_ptr = &vcpu_sbi_ext_fwft,
84 	},
85 	{
86 		.ext_idx = KVM_RISCV_SBI_EXT_MPXY,
87 		.ext_ptr = &vcpu_sbi_ext_mpxy,
88 	},
89 	{
90 		.ext_idx = KVM_RISCV_SBI_EXT_EXPERIMENTAL,
91 		.ext_ptr = &vcpu_sbi_ext_experimental,
92 	},
93 	{
94 		.ext_idx = KVM_RISCV_SBI_EXT_VENDOR,
95 		.ext_ptr = &vcpu_sbi_ext_vendor,
96 	},
97 };
98 
99 static const struct kvm_riscv_sbi_extension_entry *
100 riscv_vcpu_get_sbi_ext(struct kvm_vcpu *vcpu, unsigned long idx)
101 {
102 	const struct kvm_riscv_sbi_extension_entry *sext = NULL;
103 
104 	if (idx >= KVM_RISCV_SBI_EXT_MAX)
105 		return NULL;
106 
107 	for (int i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
108 		if (sbi_ext[i].ext_idx == idx) {
109 			sext = &sbi_ext[i];
110 			break;
111 		}
112 	}
113 
114 	return sext;
115 }
116 
117 static bool riscv_vcpu_supports_sbi_ext(struct kvm_vcpu *vcpu, int idx)
118 {
119 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
120 	const struct kvm_riscv_sbi_extension_entry *sext;
121 
122 	sext = riscv_vcpu_get_sbi_ext(vcpu, idx);
123 
124 	return sext && scontext->ext_status[sext->ext_idx] != KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE;
125 }
126 
127 int kvm_riscv_vcpu_sbi_forward_handler(struct kvm_vcpu *vcpu,
128 				       struct kvm_run *run,
129 				       struct kvm_vcpu_sbi_return *retdata)
130 {
131 	struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
132 
133 	vcpu->arch.sbi_context.return_handled = 0;
134 	vcpu->stat.ecall_exit_stat++;
135 	run->exit_reason = KVM_EXIT_RISCV_SBI;
136 	run->riscv_sbi.extension_id = cp->a7;
137 	run->riscv_sbi.function_id = cp->a6;
138 	run->riscv_sbi.args[0] = cp->a0;
139 	run->riscv_sbi.args[1] = cp->a1;
140 	run->riscv_sbi.args[2] = cp->a2;
141 	run->riscv_sbi.args[3] = cp->a3;
142 	run->riscv_sbi.args[4] = cp->a4;
143 	run->riscv_sbi.args[5] = cp->a5;
144 	run->riscv_sbi.ret[0] = SBI_ERR_NOT_SUPPORTED;
145 	run->riscv_sbi.ret[1] = 0;
146 	retdata->uexit = true;
147 	return 0;
148 }
149 
150 void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu,
151 				     struct kvm_run *run,
152 				     u32 type, u64 reason)
153 {
154 	unsigned long i;
155 	struct kvm_vcpu *tmp;
156 
157 	kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
158 		spin_lock(&tmp->arch.mp_state_lock);
159 		WRITE_ONCE(tmp->arch.mp_state.mp_state, KVM_MP_STATE_STOPPED);
160 		spin_unlock(&tmp->arch.mp_state_lock);
161 	}
162 	kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
163 
164 	memset(&run->system_event, 0, sizeof(run->system_event));
165 	run->system_event.type = type;
166 	run->system_event.ndata = 1;
167 	run->system_event.data[0] = reason;
168 	run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
169 }
170 
171 void kvm_riscv_vcpu_sbi_request_reset(struct kvm_vcpu *vcpu,
172 				      unsigned long pc, unsigned long a1)
173 {
174 	spin_lock(&vcpu->arch.reset_state.lock);
175 	vcpu->arch.reset_state.pc = pc;
176 	vcpu->arch.reset_state.a1 = a1;
177 	spin_unlock(&vcpu->arch.reset_state.lock);
178 
179 	kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
180 }
181 
182 void kvm_riscv_vcpu_sbi_load_reset_state(struct kvm_vcpu *vcpu)
183 {
184 	struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
185 	struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
186 	struct kvm_vcpu_reset_state *reset_state = &vcpu->arch.reset_state;
187 
188 	cntx->a0 = vcpu->vcpu_id;
189 
190 	spin_lock(&vcpu->arch.reset_state.lock);
191 	cntx->sepc = reset_state->pc;
192 	cntx->a1 = reset_state->a1;
193 	spin_unlock(&vcpu->arch.reset_state.lock);
194 
195 	cntx->sstatus &= ~SR_SIE;
196 	csr->vsatp = 0;
197 }
198 
199 int kvm_riscv_vcpu_sbi_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
200 {
201 	struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
202 
203 	/* Handle SBI return only once */
204 	if (vcpu->arch.sbi_context.return_handled)
205 		return 0;
206 	vcpu->arch.sbi_context.return_handled = 1;
207 
208 	/* Update return values */
209 	cp->a0 = run->riscv_sbi.ret[0];
210 	cp->a1 = run->riscv_sbi.ret[1];
211 
212 	/* Move to next instruction */
213 	vcpu->arch.guest_context.sepc += 4;
214 
215 	return 0;
216 }
217 
218 static int riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu *vcpu,
219 					 unsigned long reg_num,
220 					 unsigned long reg_val)
221 {
222 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
223 	const struct kvm_riscv_sbi_extension_entry *sext;
224 	const struct kvm_vcpu_sbi_extension *ext;
225 
226 	if (reg_val != 1 && reg_val != 0)
227 		return -EINVAL;
228 
229 	sext = riscv_vcpu_get_sbi_ext(vcpu, reg_num);
230 	if (!sext || scontext->ext_status[sext->ext_idx] == KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE)
231 		return -ENOENT;
232 
233 	ext = sext->ext_ptr;
234 
235 	if (!reg_val && scontext->ext_status[sext->ext_idx] == KVM_RISCV_SBI_EXT_STATUS_ENABLED &&
236 	    ext->reset)
237 		ext->reset(vcpu);
238 
239 	scontext->ext_status[sext->ext_idx] = (reg_val) ?
240 			KVM_RISCV_SBI_EXT_STATUS_ENABLED :
241 			KVM_RISCV_SBI_EXT_STATUS_DISABLED;
242 
243 	return 0;
244 }
245 
246 static int riscv_vcpu_get_sbi_ext_single(struct kvm_vcpu *vcpu,
247 					 unsigned long reg_num,
248 					 unsigned long *reg_val)
249 {
250 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
251 	const struct kvm_riscv_sbi_extension_entry *sext;
252 
253 	sext = riscv_vcpu_get_sbi_ext(vcpu, reg_num);
254 	if (!sext || scontext->ext_status[sext->ext_idx] == KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE)
255 		return -ENOENT;
256 
257 	*reg_val = scontext->ext_status[sext->ext_idx] ==
258 				KVM_RISCV_SBI_EXT_STATUS_ENABLED;
259 
260 	return 0;
261 }
262 
263 static int riscv_vcpu_set_sbi_ext_multi(struct kvm_vcpu *vcpu,
264 					unsigned long reg_num,
265 					unsigned long reg_val, bool enable)
266 {
267 	unsigned long i, ext_id;
268 
269 	if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST)
270 		return -ENOENT;
271 
272 	for_each_set_bit(i, &reg_val, BITS_PER_LONG) {
273 		ext_id = i + reg_num * BITS_PER_LONG;
274 		if (ext_id >= KVM_RISCV_SBI_EXT_MAX)
275 			break;
276 
277 		riscv_vcpu_set_sbi_ext_single(vcpu, ext_id, enable);
278 	}
279 
280 	return 0;
281 }
282 
283 static int riscv_vcpu_get_sbi_ext_multi(struct kvm_vcpu *vcpu,
284 					unsigned long reg_num,
285 					unsigned long *reg_val)
286 {
287 	unsigned long i, ext_id, ext_val;
288 
289 	if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST)
290 		return -ENOENT;
291 
292 	for (i = 0; i < BITS_PER_LONG; i++) {
293 		ext_id = i + reg_num * BITS_PER_LONG;
294 		if (ext_id >= KVM_RISCV_SBI_EXT_MAX)
295 			break;
296 
297 		ext_val = 0;
298 		riscv_vcpu_get_sbi_ext_single(vcpu, ext_id, &ext_val);
299 		if (ext_val)
300 			*reg_val |= KVM_REG_RISCV_SBI_MULTI_MASK(ext_id);
301 	}
302 
303 	return 0;
304 }
305 
306 int kvm_riscv_vcpu_reg_indices_sbi_ext(struct kvm_vcpu *vcpu, u64 __user *uindices)
307 {
308 	unsigned int n = 0;
309 
310 	for (int i = 0; i < KVM_RISCV_SBI_EXT_MAX; i++) {
311 		u64 size = IS_ENABLED(CONFIG_32BIT) ?
312 			   KVM_REG_SIZE_U32 : KVM_REG_SIZE_U64;
313 		u64 reg = KVM_REG_RISCV | size | KVM_REG_RISCV_SBI_EXT |
314 			  KVM_REG_RISCV_SBI_SINGLE | i;
315 
316 		if (!riscv_vcpu_supports_sbi_ext(vcpu, i))
317 			continue;
318 
319 		if (uindices) {
320 			if (put_user(reg, uindices))
321 				return -EFAULT;
322 			uindices++;
323 		}
324 
325 		n++;
326 	}
327 
328 	return n;
329 }
330 
331 int kvm_riscv_vcpu_set_reg_sbi_ext(struct kvm_vcpu *vcpu,
332 				   const struct kvm_one_reg *reg)
333 {
334 	unsigned long __user *uaddr =
335 			(unsigned long __user *)(unsigned long)reg->addr;
336 	unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
337 					    KVM_REG_SIZE_MASK |
338 					    KVM_REG_RISCV_SBI_EXT);
339 	unsigned long reg_val, reg_subtype;
340 
341 	if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
342 		return -EINVAL;
343 
344 	if (vcpu->arch.ran_atleast_once)
345 		return -EBUSY;
346 
347 	reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
348 	reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
349 
350 	if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id)))
351 		return -EFAULT;
352 
353 	switch (reg_subtype) {
354 	case KVM_REG_RISCV_SBI_SINGLE:
355 		return riscv_vcpu_set_sbi_ext_single(vcpu, reg_num, reg_val);
356 	case KVM_REG_RISCV_SBI_MULTI_EN:
357 		return riscv_vcpu_set_sbi_ext_multi(vcpu, reg_num, reg_val, true);
358 	case KVM_REG_RISCV_SBI_MULTI_DIS:
359 		return riscv_vcpu_set_sbi_ext_multi(vcpu, reg_num, reg_val, false);
360 	default:
361 		return -ENOENT;
362 	}
363 
364 	return 0;
365 }
366 
367 int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu,
368 				   const struct kvm_one_reg *reg)
369 {
370 	int rc;
371 	unsigned long __user *uaddr =
372 			(unsigned long __user *)(unsigned long)reg->addr;
373 	unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
374 					    KVM_REG_SIZE_MASK |
375 					    KVM_REG_RISCV_SBI_EXT);
376 	unsigned long reg_val, reg_subtype;
377 
378 	if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
379 		return -EINVAL;
380 
381 	reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
382 	reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
383 
384 	reg_val = 0;
385 	switch (reg_subtype) {
386 	case KVM_REG_RISCV_SBI_SINGLE:
387 		rc = riscv_vcpu_get_sbi_ext_single(vcpu, reg_num, &reg_val);
388 		break;
389 	case KVM_REG_RISCV_SBI_MULTI_EN:
390 	case KVM_REG_RISCV_SBI_MULTI_DIS:
391 		rc = riscv_vcpu_get_sbi_ext_multi(vcpu, reg_num, &reg_val);
392 		if (!rc && reg_subtype == KVM_REG_RISCV_SBI_MULTI_DIS)
393 			reg_val = ~reg_val;
394 		break;
395 	default:
396 		rc = -ENOENT;
397 	}
398 	if (rc)
399 		return rc;
400 
401 	if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
402 		return -EFAULT;
403 
404 	return 0;
405 }
406 
407 int kvm_riscv_vcpu_reg_indices_sbi(struct kvm_vcpu *vcpu, u64 __user *uindices)
408 {
409 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
410 	const struct kvm_riscv_sbi_extension_entry *entry;
411 	const struct kvm_vcpu_sbi_extension *ext;
412 	unsigned long state_reg_count;
413 	int i, j, rc, count = 0;
414 	u64 reg;
415 
416 	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
417 		entry = &sbi_ext[i];
418 		ext = entry->ext_ptr;
419 
420 		if (!ext->get_state_reg_count ||
421 		    scontext->ext_status[entry->ext_idx] != KVM_RISCV_SBI_EXT_STATUS_ENABLED)
422 			continue;
423 
424 		state_reg_count = ext->get_state_reg_count(vcpu);
425 		if (!uindices)
426 			goto skip_put_user;
427 
428 		for (j = 0; j < state_reg_count; j++) {
429 			if (ext->get_state_reg_id) {
430 				rc = ext->get_state_reg_id(vcpu, j, &reg);
431 				if (rc)
432 					return rc;
433 			} else {
434 				reg = KVM_REG_RISCV |
435 				      (IS_ENABLED(CONFIG_32BIT) ?
436 				       KVM_REG_SIZE_U32 : KVM_REG_SIZE_U64) |
437 				      KVM_REG_RISCV_SBI_STATE |
438 				      ext->state_reg_subtype | j;
439 			}
440 
441 			if (put_user(reg, uindices))
442 				return -EFAULT;
443 			uindices++;
444 		}
445 
446 skip_put_user:
447 		count += state_reg_count;
448 	}
449 
450 	return count;
451 }
452 
453 static const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext_withstate(struct kvm_vcpu *vcpu,
454 									    unsigned long subtype)
455 {
456 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
457 	const struct kvm_riscv_sbi_extension_entry *entry;
458 	const struct kvm_vcpu_sbi_extension *ext;
459 	int i;
460 
461 	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
462 		entry = &sbi_ext[i];
463 		ext = entry->ext_ptr;
464 
465 		if (ext->get_state_reg_count &&
466 		    ext->state_reg_subtype == subtype &&
467 		    scontext->ext_status[entry->ext_idx] == KVM_RISCV_SBI_EXT_STATUS_ENABLED)
468 			return ext;
469 	}
470 
471 	return NULL;
472 }
473 
474 int kvm_riscv_vcpu_set_reg_sbi(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
475 {
476 	unsigned long __user *uaddr =
477 			(unsigned long __user *)(unsigned long)reg->addr;
478 	unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
479 					    KVM_REG_SIZE_MASK |
480 					    KVM_REG_RISCV_SBI_STATE);
481 	const struct kvm_vcpu_sbi_extension *ext;
482 	unsigned long reg_subtype;
483 	void *reg_val;
484 	u64 data64;
485 	u32 data32;
486 	u16 data16;
487 	u8 data8;
488 
489 	switch (KVM_REG_SIZE(reg->id)) {
490 	case 1:
491 		reg_val = &data8;
492 		break;
493 	case 2:
494 		reg_val = &data16;
495 		break;
496 	case 4:
497 		reg_val = &data32;
498 		break;
499 	case 8:
500 		reg_val = &data64;
501 		break;
502 	default:
503 		return -EINVAL;
504 	}
505 
506 	if (copy_from_user(reg_val, uaddr, KVM_REG_SIZE(reg->id)))
507 		return -EFAULT;
508 
509 	reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
510 	reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
511 
512 	ext = kvm_vcpu_sbi_find_ext_withstate(vcpu, reg_subtype);
513 	if (!ext || !ext->set_state_reg)
514 		return -EINVAL;
515 
516 	return ext->set_state_reg(vcpu, reg_num, KVM_REG_SIZE(reg->id), reg_val);
517 }
518 
519 int kvm_riscv_vcpu_get_reg_sbi(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
520 {
521 	unsigned long __user *uaddr =
522 			(unsigned long __user *)(unsigned long)reg->addr;
523 	unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
524 					    KVM_REG_SIZE_MASK |
525 					    KVM_REG_RISCV_SBI_STATE);
526 	const struct kvm_vcpu_sbi_extension *ext;
527 	unsigned long reg_subtype;
528 	void *reg_val;
529 	u64 data64;
530 	u32 data32;
531 	u16 data16;
532 	u8 data8;
533 	int ret;
534 
535 	switch (KVM_REG_SIZE(reg->id)) {
536 	case 1:
537 		reg_val = &data8;
538 		break;
539 	case 2:
540 		reg_val = &data16;
541 		break;
542 	case 4:
543 		reg_val = &data32;
544 		break;
545 	case 8:
546 		reg_val = &data64;
547 		break;
548 	default:
549 		return -EINVAL;
550 	}
551 
552 	reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
553 	reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
554 
555 	ext = kvm_vcpu_sbi_find_ext_withstate(vcpu, reg_subtype);
556 	if (!ext || !ext->get_state_reg)
557 		return -EINVAL;
558 
559 	ret = ext->get_state_reg(vcpu, reg_num, KVM_REG_SIZE(reg->id), reg_val);
560 	if (ret)
561 		return ret;
562 
563 	if (copy_to_user(uaddr, reg_val, KVM_REG_SIZE(reg->id)))
564 		return -EFAULT;
565 
566 	return 0;
567 }
568 
569 const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
570 				struct kvm_vcpu *vcpu, unsigned long extid)
571 {
572 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
573 	const struct kvm_riscv_sbi_extension_entry *entry;
574 	const struct kvm_vcpu_sbi_extension *ext;
575 	int i;
576 
577 	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
578 		entry = &sbi_ext[i];
579 		ext = entry->ext_ptr;
580 
581 		if (ext->extid_start <= extid && ext->extid_end >= extid) {
582 			if (entry->ext_idx >= KVM_RISCV_SBI_EXT_MAX ||
583 			    scontext->ext_status[entry->ext_idx] ==
584 						KVM_RISCV_SBI_EXT_STATUS_ENABLED)
585 				return ext;
586 
587 			return NULL;
588 		}
589 	}
590 
591 	return NULL;
592 }
593 
594 int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run)
595 {
596 	int ret = 1;
597 	bool next_sepc = true;
598 	struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
599 	const struct kvm_vcpu_sbi_extension *sbi_ext;
600 	struct kvm_cpu_trap utrap = {0};
601 	struct kvm_vcpu_sbi_return sbi_ret = {
602 		.out_val = 0,
603 		.err_val = 0,
604 		.utrap = &utrap,
605 	};
606 	bool ext_is_v01 = false;
607 
608 	sbi_ext = kvm_vcpu_sbi_find_ext(vcpu, cp->a7);
609 	if (sbi_ext && sbi_ext->handler) {
610 #ifdef CONFIG_RISCV_SBI_V01
611 		if (cp->a7 >= SBI_EXT_0_1_SET_TIMER &&
612 		    cp->a7 <= SBI_EXT_0_1_SHUTDOWN)
613 			ext_is_v01 = true;
614 #endif
615 		ret = sbi_ext->handler(vcpu, run, &sbi_ret);
616 	} else {
617 		/* Return error for unsupported SBI calls */
618 		cp->a0 = SBI_ERR_NOT_SUPPORTED;
619 		goto ecall_done;
620 	}
621 
622 	/*
623 	 * When the SBI extension returns a Linux error code, it exits the ioctl
624 	 * loop and forwards the error to userspace.
625 	 */
626 	if (ret < 0) {
627 		next_sepc = false;
628 		goto ecall_done;
629 	}
630 
631 	/* Handle special error cases i.e trap, exit or userspace forward */
632 	if (sbi_ret.utrap->scause) {
633 		/* No need to increment sepc or exit ioctl loop */
634 		ret = 1;
635 		sbi_ret.utrap->sepc = cp->sepc;
636 		kvm_riscv_vcpu_trap_redirect(vcpu, sbi_ret.utrap);
637 		next_sepc = false;
638 		goto ecall_done;
639 	}
640 
641 	/* Exit ioctl loop or Propagate the error code the guest */
642 	if (sbi_ret.uexit) {
643 		next_sepc = false;
644 		ret = 0;
645 	} else {
646 		cp->a0 = sbi_ret.err_val;
647 		ret = 1;
648 	}
649 ecall_done:
650 	if (next_sepc)
651 		cp->sepc += 4;
652 	/* a1 should only be updated when we continue the ioctl loop */
653 	if (!ext_is_v01 && ret == 1)
654 		cp->a1 = sbi_ret.out_val;
655 
656 	return ret;
657 }
658 
659 void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu)
660 {
661 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
662 	const struct kvm_riscv_sbi_extension_entry *entry;
663 	const struct kvm_vcpu_sbi_extension *ext;
664 	int idx, i;
665 
666 	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
667 		entry = &sbi_ext[i];
668 		ext = entry->ext_ptr;
669 		idx = entry->ext_idx;
670 
671 		if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status))
672 			continue;
673 
674 		if (ext->probe && !ext->probe(vcpu)) {
675 			scontext->ext_status[idx] = KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE;
676 			continue;
677 		}
678 
679 		scontext->ext_status[idx] = ext->default_disabled ?
680 					KVM_RISCV_SBI_EXT_STATUS_DISABLED :
681 					KVM_RISCV_SBI_EXT_STATUS_ENABLED;
682 
683 		if (ext->init && ext->init(vcpu) != 0)
684 			scontext->ext_status[idx] = KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE;
685 	}
686 }
687 
688 void kvm_riscv_vcpu_sbi_deinit(struct kvm_vcpu *vcpu)
689 {
690 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
691 	const struct kvm_riscv_sbi_extension_entry *entry;
692 	const struct kvm_vcpu_sbi_extension *ext;
693 	int idx, i;
694 
695 	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
696 		entry = &sbi_ext[i];
697 		ext = entry->ext_ptr;
698 		idx = entry->ext_idx;
699 
700 		if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status))
701 			continue;
702 
703 		if (scontext->ext_status[idx] == KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE ||
704 		    !ext->deinit)
705 			continue;
706 
707 		ext->deinit(vcpu);
708 	}
709 }
710 
711 void kvm_riscv_vcpu_sbi_reset(struct kvm_vcpu *vcpu)
712 {
713 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
714 	const struct kvm_riscv_sbi_extension_entry *entry;
715 	const struct kvm_vcpu_sbi_extension *ext;
716 	int idx, i;
717 
718 	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
719 		entry = &sbi_ext[i];
720 		ext = entry->ext_ptr;
721 		idx = entry->ext_idx;
722 
723 		if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status))
724 			continue;
725 
726 		if (scontext->ext_status[idx] != KVM_RISCV_SBI_EXT_STATUS_ENABLED ||
727 		    !ext->reset)
728 			continue;
729 
730 		ext->reset(vcpu);
731 	}
732 }
733 
734 void kvm_riscv_vcpu_sbi_validate(struct kvm_vcpu *vcpu)
735 {
736 	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
737 	const struct kvm_riscv_sbi_extension_entry *entry;
738 	const struct kvm_vcpu_sbi_extension *ext;
739 	int idx, i;
740 
741 	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
742 		entry = &sbi_ext[i];
743 		ext = entry->ext_ptr;
744 		idx = entry->ext_idx;
745 
746 		if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status))
747 			continue;
748 
749 		if (scontext->ext_status[idx] != KVM_RISCV_SBI_EXT_STATUS_ENABLED ||
750 		    !ext->validate)
751 			continue;
752 
753 		ext->validate(vcpu);
754 	}
755 }
756