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
16static 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
24static 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
31struct 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
36static 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_STA,
75		.ext_ptr = &vcpu_sbi_ext_sta,
76	},
77	{
78		.ext_idx = KVM_RISCV_SBI_EXT_EXPERIMENTAL,
79		.ext_ptr = &vcpu_sbi_ext_experimental,
80	},
81	{
82		.ext_idx = KVM_RISCV_SBI_EXT_VENDOR,
83		.ext_ptr = &vcpu_sbi_ext_vendor,
84	},
85};
86
87static const struct kvm_riscv_sbi_extension_entry *
88riscv_vcpu_get_sbi_ext(struct kvm_vcpu *vcpu, unsigned long idx)
89{
90	const struct kvm_riscv_sbi_extension_entry *sext = NULL;
91
92	if (idx >= KVM_RISCV_SBI_EXT_MAX)
93		return NULL;
94
95	for (int i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
96		if (sbi_ext[i].ext_idx == idx) {
97			sext = &sbi_ext[i];
98			break;
99		}
100	}
101
102	return sext;
103}
104
105bool riscv_vcpu_supports_sbi_ext(struct kvm_vcpu *vcpu, int idx)
106{
107	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
108	const struct kvm_riscv_sbi_extension_entry *sext;
109
110	sext = riscv_vcpu_get_sbi_ext(vcpu, idx);
111
112	return sext && scontext->ext_status[sext->ext_idx] != KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE;
113}
114
115void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run)
116{
117	struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
118
119	vcpu->arch.sbi_context.return_handled = 0;
120	vcpu->stat.ecall_exit_stat++;
121	run->exit_reason = KVM_EXIT_RISCV_SBI;
122	run->riscv_sbi.extension_id = cp->a7;
123	run->riscv_sbi.function_id = cp->a6;
124	run->riscv_sbi.args[0] = cp->a0;
125	run->riscv_sbi.args[1] = cp->a1;
126	run->riscv_sbi.args[2] = cp->a2;
127	run->riscv_sbi.args[3] = cp->a3;
128	run->riscv_sbi.args[4] = cp->a4;
129	run->riscv_sbi.args[5] = cp->a5;
130	run->riscv_sbi.ret[0] = cp->a0;
131	run->riscv_sbi.ret[1] = cp->a1;
132}
133
134void kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu *vcpu,
135				     struct kvm_run *run,
136				     u32 type, u64 reason)
137{
138	unsigned long i;
139	struct kvm_vcpu *tmp;
140
141	kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
142		spin_lock(&vcpu->arch.mp_state_lock);
143		WRITE_ONCE(tmp->arch.mp_state.mp_state, KVM_MP_STATE_STOPPED);
144		spin_unlock(&vcpu->arch.mp_state_lock);
145	}
146	kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
147
148	memset(&run->system_event, 0, sizeof(run->system_event));
149	run->system_event.type = type;
150	run->system_event.ndata = 1;
151	run->system_event.data[0] = reason;
152	run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
153}
154
155int kvm_riscv_vcpu_sbi_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
156{
157	struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
158
159	/* Handle SBI return only once */
160	if (vcpu->arch.sbi_context.return_handled)
161		return 0;
162	vcpu->arch.sbi_context.return_handled = 1;
163
164	/* Update return values */
165	cp->a0 = run->riscv_sbi.ret[0];
166	cp->a1 = run->riscv_sbi.ret[1];
167
168	/* Move to next instruction */
169	vcpu->arch.guest_context.sepc += 4;
170
171	return 0;
172}
173
174static int riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu *vcpu,
175					 unsigned long reg_num,
176					 unsigned long reg_val)
177{
178	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
179	const struct kvm_riscv_sbi_extension_entry *sext;
180
181	if (reg_val != 1 && reg_val != 0)
182		return -EINVAL;
183
184	sext = riscv_vcpu_get_sbi_ext(vcpu, reg_num);
185	if (!sext || scontext->ext_status[sext->ext_idx] == KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE)
186		return -ENOENT;
187
188	scontext->ext_status[sext->ext_idx] = (reg_val) ?
189			KVM_RISCV_SBI_EXT_STATUS_ENABLED :
190			KVM_RISCV_SBI_EXT_STATUS_DISABLED;
191
192	return 0;
193}
194
195static int riscv_vcpu_get_sbi_ext_single(struct kvm_vcpu *vcpu,
196					 unsigned long reg_num,
197					 unsigned long *reg_val)
198{
199	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
200	const struct kvm_riscv_sbi_extension_entry *sext;
201
202	sext = riscv_vcpu_get_sbi_ext(vcpu, reg_num);
203	if (!sext || scontext->ext_status[sext->ext_idx] == KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE)
204		return -ENOENT;
205
206	*reg_val = scontext->ext_status[sext->ext_idx] ==
207				KVM_RISCV_SBI_EXT_STATUS_ENABLED;
208
209	return 0;
210}
211
212static int riscv_vcpu_set_sbi_ext_multi(struct kvm_vcpu *vcpu,
213					unsigned long reg_num,
214					unsigned long reg_val, bool enable)
215{
216	unsigned long i, ext_id;
217
218	if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST)
219		return -ENOENT;
220
221	for_each_set_bit(i, &reg_val, BITS_PER_LONG) {
222		ext_id = i + reg_num * BITS_PER_LONG;
223		if (ext_id >= KVM_RISCV_SBI_EXT_MAX)
224			break;
225
226		riscv_vcpu_set_sbi_ext_single(vcpu, ext_id, enable);
227	}
228
229	return 0;
230}
231
232static int riscv_vcpu_get_sbi_ext_multi(struct kvm_vcpu *vcpu,
233					unsigned long reg_num,
234					unsigned long *reg_val)
235{
236	unsigned long i, ext_id, ext_val;
237
238	if (reg_num > KVM_REG_RISCV_SBI_MULTI_REG_LAST)
239		return -ENOENT;
240
241	for (i = 0; i < BITS_PER_LONG; i++) {
242		ext_id = i + reg_num * BITS_PER_LONG;
243		if (ext_id >= KVM_RISCV_SBI_EXT_MAX)
244			break;
245
246		ext_val = 0;
247		riscv_vcpu_get_sbi_ext_single(vcpu, ext_id, &ext_val);
248		if (ext_val)
249			*reg_val |= KVM_REG_RISCV_SBI_MULTI_MASK(ext_id);
250	}
251
252	return 0;
253}
254
255int kvm_riscv_vcpu_set_reg_sbi_ext(struct kvm_vcpu *vcpu,
256				   const struct kvm_one_reg *reg)
257{
258	unsigned long __user *uaddr =
259			(unsigned long __user *)(unsigned long)reg->addr;
260	unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
261					    KVM_REG_SIZE_MASK |
262					    KVM_REG_RISCV_SBI_EXT);
263	unsigned long reg_val, reg_subtype;
264
265	if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
266		return -EINVAL;
267
268	if (vcpu->arch.ran_atleast_once)
269		return -EBUSY;
270
271	reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
272	reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
273
274	if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id)))
275		return -EFAULT;
276
277	switch (reg_subtype) {
278	case KVM_REG_RISCV_SBI_SINGLE:
279		return riscv_vcpu_set_sbi_ext_single(vcpu, reg_num, reg_val);
280	case KVM_REG_RISCV_SBI_MULTI_EN:
281		return riscv_vcpu_set_sbi_ext_multi(vcpu, reg_num, reg_val, true);
282	case KVM_REG_RISCV_SBI_MULTI_DIS:
283		return riscv_vcpu_set_sbi_ext_multi(vcpu, reg_num, reg_val, false);
284	default:
285		return -ENOENT;
286	}
287
288	return 0;
289}
290
291int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu,
292				   const struct kvm_one_reg *reg)
293{
294	int rc;
295	unsigned long __user *uaddr =
296			(unsigned long __user *)(unsigned long)reg->addr;
297	unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
298					    KVM_REG_SIZE_MASK |
299					    KVM_REG_RISCV_SBI_EXT);
300	unsigned long reg_val, reg_subtype;
301
302	if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
303		return -EINVAL;
304
305	reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
306	reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
307
308	reg_val = 0;
309	switch (reg_subtype) {
310	case KVM_REG_RISCV_SBI_SINGLE:
311		rc = riscv_vcpu_get_sbi_ext_single(vcpu, reg_num, &reg_val);
312		break;
313	case KVM_REG_RISCV_SBI_MULTI_EN:
314	case KVM_REG_RISCV_SBI_MULTI_DIS:
315		rc = riscv_vcpu_get_sbi_ext_multi(vcpu, reg_num, &reg_val);
316		if (!rc && reg_subtype == KVM_REG_RISCV_SBI_MULTI_DIS)
317			reg_val = ~reg_val;
318		break;
319	default:
320		rc = -ENOENT;
321	}
322	if (rc)
323		return rc;
324
325	if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
326		return -EFAULT;
327
328	return 0;
329}
330
331int kvm_riscv_vcpu_set_reg_sbi(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_STATE);
339	unsigned long reg_subtype, reg_val;
340
341	if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
342		return -EINVAL;
343
344	if (copy_from_user(&reg_val, uaddr, KVM_REG_SIZE(reg->id)))
345		return -EFAULT;
346
347	reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
348	reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
349
350	switch (reg_subtype) {
351	case KVM_REG_RISCV_SBI_STA:
352		return kvm_riscv_vcpu_set_reg_sbi_sta(vcpu, reg_num, reg_val);
353	default:
354		return -EINVAL;
355	}
356
357	return 0;
358}
359
360int kvm_riscv_vcpu_get_reg_sbi(struct kvm_vcpu *vcpu,
361			       const struct kvm_one_reg *reg)
362{
363	unsigned long __user *uaddr =
364			(unsigned long __user *)(unsigned long)reg->addr;
365	unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
366					    KVM_REG_SIZE_MASK |
367					    KVM_REG_RISCV_SBI_STATE);
368	unsigned long reg_subtype, reg_val;
369	int ret;
370
371	if (KVM_REG_SIZE(reg->id) != sizeof(unsigned long))
372		return -EINVAL;
373
374	reg_subtype = reg_num & KVM_REG_RISCV_SUBTYPE_MASK;
375	reg_num &= ~KVM_REG_RISCV_SUBTYPE_MASK;
376
377	switch (reg_subtype) {
378	case KVM_REG_RISCV_SBI_STA:
379		ret = kvm_riscv_vcpu_get_reg_sbi_sta(vcpu, reg_num, &reg_val);
380		break;
381	default:
382		return -EINVAL;
383	}
384
385	if (ret)
386		return ret;
387
388	if (copy_to_user(uaddr, &reg_val, KVM_REG_SIZE(reg->id)))
389		return -EFAULT;
390
391	return 0;
392}
393
394const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
395				struct kvm_vcpu *vcpu, unsigned long extid)
396{
397	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
398	const struct kvm_riscv_sbi_extension_entry *entry;
399	const struct kvm_vcpu_sbi_extension *ext;
400	int i;
401
402	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
403		entry = &sbi_ext[i];
404		ext = entry->ext_ptr;
405
406		if (ext->extid_start <= extid && ext->extid_end >= extid) {
407			if (entry->ext_idx >= KVM_RISCV_SBI_EXT_MAX ||
408			    scontext->ext_status[entry->ext_idx] ==
409						KVM_RISCV_SBI_EXT_STATUS_ENABLED)
410				return ext;
411
412			return NULL;
413		}
414	}
415
416	return NULL;
417}
418
419int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run)
420{
421	int ret = 1;
422	bool next_sepc = true;
423	struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
424	const struct kvm_vcpu_sbi_extension *sbi_ext;
425	struct kvm_cpu_trap utrap = {0};
426	struct kvm_vcpu_sbi_return sbi_ret = {
427		.out_val = 0,
428		.err_val = 0,
429		.utrap = &utrap,
430	};
431	bool ext_is_v01 = false;
432
433	sbi_ext = kvm_vcpu_sbi_find_ext(vcpu, cp->a7);
434	if (sbi_ext && sbi_ext->handler) {
435#ifdef CONFIG_RISCV_SBI_V01
436		if (cp->a7 >= SBI_EXT_0_1_SET_TIMER &&
437		    cp->a7 <= SBI_EXT_0_1_SHUTDOWN)
438			ext_is_v01 = true;
439#endif
440		ret = sbi_ext->handler(vcpu, run, &sbi_ret);
441	} else {
442		/* Return error for unsupported SBI calls */
443		cp->a0 = SBI_ERR_NOT_SUPPORTED;
444		goto ecall_done;
445	}
446
447	/*
448	 * When the SBI extension returns a Linux error code, it exits the ioctl
449	 * loop and forwards the error to userspace.
450	 */
451	if (ret < 0) {
452		next_sepc = false;
453		goto ecall_done;
454	}
455
456	/* Handle special error cases i.e trap, exit or userspace forward */
457	if (sbi_ret.utrap->scause) {
458		/* No need to increment sepc or exit ioctl loop */
459		ret = 1;
460		sbi_ret.utrap->sepc = cp->sepc;
461		kvm_riscv_vcpu_trap_redirect(vcpu, sbi_ret.utrap);
462		next_sepc = false;
463		goto ecall_done;
464	}
465
466	/* Exit ioctl loop or Propagate the error code the guest */
467	if (sbi_ret.uexit) {
468		next_sepc = false;
469		ret = 0;
470	} else {
471		cp->a0 = sbi_ret.err_val;
472		ret = 1;
473	}
474ecall_done:
475	if (next_sepc)
476		cp->sepc += 4;
477	/* a1 should only be updated when we continue the ioctl loop */
478	if (!ext_is_v01 && ret == 1)
479		cp->a1 = sbi_ret.out_val;
480
481	return ret;
482}
483
484void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu)
485{
486	struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
487	const struct kvm_riscv_sbi_extension_entry *entry;
488	const struct kvm_vcpu_sbi_extension *ext;
489	int i;
490
491	for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
492		entry = &sbi_ext[i];
493		ext = entry->ext_ptr;
494
495		if (ext->probe && !ext->probe(vcpu)) {
496			scontext->ext_status[entry->ext_idx] =
497				KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE;
498			continue;
499		}
500
501		scontext->ext_status[entry->ext_idx] = ext->default_disabled ?
502					KVM_RISCV_SBI_EXT_STATUS_DISABLED :
503					KVM_RISCV_SBI_EXT_STATUS_ENABLED;
504	}
505}
506