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_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
87 static const struct kvm_riscv_sbi_extension_entry *
riscv_vcpu_get_sbi_ext(struct kvm_vcpu * vcpu,unsigned long idx)88 riscv_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
riscv_vcpu_supports_sbi_ext(struct kvm_vcpu * vcpu,int idx)105 bool 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
kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu * vcpu,struct kvm_run * run)115 void 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] = SBI_ERR_NOT_SUPPORTED;
131 run->riscv_sbi.ret[1] = 0;
132 }
133
kvm_riscv_vcpu_sbi_system_reset(struct kvm_vcpu * vcpu,struct kvm_run * run,u32 type,u64 reason)134 void 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
kvm_riscv_vcpu_sbi_return(struct kvm_vcpu * vcpu,struct kvm_run * run)155 int 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
riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu * vcpu,unsigned long reg_num,unsigned long reg_val)174 static 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
riscv_vcpu_get_sbi_ext_single(struct kvm_vcpu * vcpu,unsigned long reg_num,unsigned long * reg_val)195 static 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
riscv_vcpu_set_sbi_ext_multi(struct kvm_vcpu * vcpu,unsigned long reg_num,unsigned long reg_val,bool enable)212 static 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, ®_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
riscv_vcpu_get_sbi_ext_multi(struct kvm_vcpu * vcpu,unsigned long reg_num,unsigned long * reg_val)232 static 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
kvm_riscv_vcpu_set_reg_sbi_ext(struct kvm_vcpu * vcpu,const struct kvm_one_reg * reg)255 int 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(®_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
kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu * vcpu,const struct kvm_one_reg * reg)291 int 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, ®_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, ®_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, ®_val, KVM_REG_SIZE(reg->id)))
326 return -EFAULT;
327
328 return 0;
329 }
330
kvm_riscv_vcpu_set_reg_sbi(struct kvm_vcpu * vcpu,const struct kvm_one_reg * reg)331 int 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(®_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
kvm_riscv_vcpu_get_reg_sbi(struct kvm_vcpu * vcpu,const struct kvm_one_reg * reg)360 int 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, ®_val);
380 break;
381 default:
382 return -EINVAL;
383 }
384
385 if (ret)
386 return ret;
387
388 if (copy_to_user(uaddr, ®_val, KVM_REG_SIZE(reg->id)))
389 return -EFAULT;
390
391 return 0;
392 }
393
kvm_vcpu_sbi_find_ext(struct kvm_vcpu * vcpu,unsigned long extid)394 const 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
kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu * vcpu,struct kvm_run * run)419 int 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 }
474 ecall_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
kvm_riscv_vcpu_sbi_init(struct kvm_vcpu * vcpu)484 void 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