vcpu_sbi.c 17 KB

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