processor.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * RISC-V code
  4. *
  5. * Copyright (C) 2021 Western Digital Corporation or its affiliates.
  6. */
  7. #include <linux/compiler.h>
  8. #include <assert.h>
  9. #include "guest_modes.h"
  10. #include "kvm_util.h"
  11. #include "processor.h"
  12. #include "ucall_common.h"
  13. #define DEFAULT_RISCV_GUEST_STACK_VADDR_MIN 0xac0000
  14. static vm_vaddr_t exception_handlers;
  15. bool __vcpu_has_ext(struct kvm_vcpu *vcpu, uint64_t ext)
  16. {
  17. unsigned long value = 0;
  18. int ret;
  19. ret = __vcpu_get_reg(vcpu, ext, &value);
  20. return !ret && !!value;
  21. }
  22. static uint64_t pte_addr(struct kvm_vm *vm, uint64_t entry)
  23. {
  24. return ((entry & PGTBL_PTE_ADDR_MASK) >> PGTBL_PTE_ADDR_SHIFT) <<
  25. PGTBL_PAGE_SIZE_SHIFT;
  26. }
  27. static uint64_t ptrs_per_pte(struct kvm_vm *vm)
  28. {
  29. return PGTBL_PAGE_SIZE / sizeof(uint64_t);
  30. }
  31. static uint64_t pte_index_mask[] = {
  32. PGTBL_L0_INDEX_MASK,
  33. PGTBL_L1_INDEX_MASK,
  34. PGTBL_L2_INDEX_MASK,
  35. PGTBL_L3_INDEX_MASK,
  36. };
  37. static uint32_t pte_index_shift[] = {
  38. PGTBL_L0_INDEX_SHIFT,
  39. PGTBL_L1_INDEX_SHIFT,
  40. PGTBL_L2_INDEX_SHIFT,
  41. PGTBL_L3_INDEX_SHIFT,
  42. };
  43. static uint64_t pte_index(struct kvm_vm *vm, vm_vaddr_t gva, int level)
  44. {
  45. TEST_ASSERT(level > -1,
  46. "Negative page table level (%d) not possible", level);
  47. TEST_ASSERT(level < vm->mmu.pgtable_levels,
  48. "Invalid page table level (%d)", level);
  49. return (gva & pte_index_mask[level]) >> pte_index_shift[level];
  50. }
  51. void virt_arch_pgd_alloc(struct kvm_vm *vm)
  52. {
  53. size_t nr_pages = vm_page_align(vm, ptrs_per_pte(vm) * 8) / vm->page_size;
  54. if (vm->mmu.pgd_created)
  55. return;
  56. vm->mmu.pgd = vm_phy_pages_alloc(vm, nr_pages,
  57. KVM_GUEST_PAGE_TABLE_MIN_PADDR,
  58. vm->memslots[MEM_REGION_PT]);
  59. vm->mmu.pgd_created = true;
  60. }
  61. void virt_arch_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr)
  62. {
  63. uint64_t *ptep, next_ppn;
  64. int level = vm->mmu.pgtable_levels - 1;
  65. TEST_ASSERT((vaddr % vm->page_size) == 0,
  66. "Virtual address not on page boundary,\n"
  67. " vaddr: 0x%lx vm->page_size: 0x%x", vaddr, vm->page_size);
  68. TEST_ASSERT(sparsebit_is_set(vm->vpages_valid,
  69. (vaddr >> vm->page_shift)),
  70. "Invalid virtual address, vaddr: 0x%lx", vaddr);
  71. TEST_ASSERT((paddr % vm->page_size) == 0,
  72. "Physical address not on page boundary,\n"
  73. " paddr: 0x%lx vm->page_size: 0x%x", paddr, vm->page_size);
  74. TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
  75. "Physical address beyond maximum supported,\n"
  76. " paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
  77. paddr, vm->max_gfn, vm->page_size);
  78. ptep = addr_gpa2hva(vm, vm->mmu.pgd) + pte_index(vm, vaddr, level) * 8;
  79. if (!*ptep) {
  80. next_ppn = vm_alloc_page_table(vm) >> PGTBL_PAGE_SIZE_SHIFT;
  81. *ptep = (next_ppn << PGTBL_PTE_ADDR_SHIFT) |
  82. PGTBL_PTE_VALID_MASK;
  83. }
  84. level--;
  85. while (level > -1) {
  86. ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) +
  87. pte_index(vm, vaddr, level) * 8;
  88. if (!*ptep && level > 0) {
  89. next_ppn = vm_alloc_page_table(vm) >>
  90. PGTBL_PAGE_SIZE_SHIFT;
  91. *ptep = (next_ppn << PGTBL_PTE_ADDR_SHIFT) |
  92. PGTBL_PTE_VALID_MASK;
  93. }
  94. level--;
  95. }
  96. paddr = paddr >> PGTBL_PAGE_SIZE_SHIFT;
  97. *ptep = (paddr << PGTBL_PTE_ADDR_SHIFT) |
  98. PGTBL_PTE_PERM_MASK | PGTBL_PTE_VALID_MASK;
  99. }
  100. vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
  101. {
  102. uint64_t *ptep;
  103. int level = vm->mmu.pgtable_levels - 1;
  104. if (!vm->mmu.pgd_created)
  105. goto unmapped_gva;
  106. ptep = addr_gpa2hva(vm, vm->mmu.pgd) + pte_index(vm, gva, level) * 8;
  107. if (!ptep)
  108. goto unmapped_gva;
  109. level--;
  110. while (level > -1) {
  111. ptep = addr_gpa2hva(vm, pte_addr(vm, *ptep)) +
  112. pte_index(vm, gva, level) * 8;
  113. if (!ptep)
  114. goto unmapped_gva;
  115. level--;
  116. }
  117. return pte_addr(vm, *ptep) + (gva & (vm->page_size - 1));
  118. unmapped_gva:
  119. TEST_FAIL("No mapping for vm virtual address gva: 0x%lx level: %d",
  120. gva, level);
  121. exit(1);
  122. }
  123. static void pte_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent,
  124. uint64_t page, int level)
  125. {
  126. #ifdef DEBUG
  127. static const char *const type[] = { "pte", "pmd", "pud", "p4d"};
  128. uint64_t pte, *ptep;
  129. if (level < 0)
  130. return;
  131. for (pte = page; pte < page + ptrs_per_pte(vm) * 8; pte += 8) {
  132. ptep = addr_gpa2hva(vm, pte);
  133. if (!*ptep)
  134. continue;
  135. fprintf(stream, "%*s%s: %lx: %lx at %p\n", indent, "",
  136. type[level], pte, *ptep, ptep);
  137. pte_dump(stream, vm, indent + 1,
  138. pte_addr(vm, *ptep), level - 1);
  139. }
  140. #endif
  141. }
  142. void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
  143. {
  144. struct kvm_mmu *mmu = &vm->mmu;
  145. int level = mmu->pgtable_levels - 1;
  146. uint64_t pgd, *ptep;
  147. if (!mmu->pgd_created)
  148. return;
  149. for (pgd = mmu->pgd; pgd < mmu->pgd + ptrs_per_pte(vm) * 8; pgd += 8) {
  150. ptep = addr_gpa2hva(vm, pgd);
  151. if (!*ptep)
  152. continue;
  153. fprintf(stream, "%*spgd: %lx: %lx at %p\n", indent, "",
  154. pgd, *ptep, ptep);
  155. pte_dump(stream, vm, indent + 1,
  156. pte_addr(vm, *ptep), level - 1);
  157. }
  158. }
  159. void riscv_vcpu_mmu_setup(struct kvm_vcpu *vcpu)
  160. {
  161. struct kvm_vm *vm = vcpu->vm;
  162. unsigned long satp;
  163. unsigned long satp_mode;
  164. unsigned long max_satp_mode;
  165. /*
  166. * The RISC-V Sv48 MMU mode supports 56-bit physical address
  167. * for 48-bit virtual address with 4KB last level page size.
  168. */
  169. switch (vm->mode) {
  170. case VM_MODE_P56V57_4K:
  171. case VM_MODE_P50V57_4K:
  172. case VM_MODE_P41V57_4K:
  173. satp_mode = SATP_MODE_57;
  174. break;
  175. case VM_MODE_P56V48_4K:
  176. case VM_MODE_P50V48_4K:
  177. case VM_MODE_P41V48_4K:
  178. satp_mode = SATP_MODE_48;
  179. break;
  180. case VM_MODE_P56V39_4K:
  181. case VM_MODE_P50V39_4K:
  182. case VM_MODE_P41V39_4K:
  183. satp_mode = SATP_MODE_39;
  184. break;
  185. default:
  186. TEST_FAIL("Unknown guest mode, mode: 0x%x", vm->mode);
  187. }
  188. max_satp_mode = vcpu_get_reg(vcpu, RISCV_CONFIG_REG(satp_mode));
  189. if ((satp_mode >> SATP_MODE_SHIFT) > max_satp_mode)
  190. TEST_FAIL("Unable to set satp mode 0x%lx, max mode 0x%lx\n",
  191. satp_mode >> SATP_MODE_SHIFT, max_satp_mode);
  192. satp = (vm->mmu.pgd >> PGTBL_PAGE_SIZE_SHIFT) & SATP_PPN;
  193. satp |= satp_mode;
  194. vcpu_set_reg(vcpu, RISCV_GENERAL_CSR_REG(satp), satp);
  195. }
  196. void vcpu_arch_dump(FILE *stream, struct kvm_vcpu *vcpu, uint8_t indent)
  197. {
  198. struct kvm_riscv_core core;
  199. core.mode = vcpu_get_reg(vcpu, RISCV_CORE_REG(mode));
  200. core.regs.pc = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.pc));
  201. core.regs.ra = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.ra));
  202. core.regs.sp = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.sp));
  203. core.regs.gp = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.gp));
  204. core.regs.tp = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.tp));
  205. core.regs.t0 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.t0));
  206. core.regs.t1 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.t1));
  207. core.regs.t2 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.t2));
  208. core.regs.s0 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.s0));
  209. core.regs.s1 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.s1));
  210. core.regs.a0 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.a0));
  211. core.regs.a1 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.a1));
  212. core.regs.a2 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.a2));
  213. core.regs.a3 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.a3));
  214. core.regs.a4 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.a4));
  215. core.regs.a5 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.a5));
  216. core.regs.a6 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.a6));
  217. core.regs.a7 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.a7));
  218. core.regs.s2 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.s2));
  219. core.regs.s3 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.s3));
  220. core.regs.s4 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.s4));
  221. core.regs.s5 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.s5));
  222. core.regs.s6 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.s6));
  223. core.regs.s7 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.s7));
  224. core.regs.s8 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.s8));
  225. core.regs.s9 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.s9));
  226. core.regs.s10 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.s10));
  227. core.regs.s11 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.s11));
  228. core.regs.t3 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.t3));
  229. core.regs.t4 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.t4));
  230. core.regs.t5 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.t5));
  231. core.regs.t6 = vcpu_get_reg(vcpu, RISCV_CORE_REG(regs.t6));
  232. fprintf(stream,
  233. " MODE: 0x%lx\n", core.mode);
  234. fprintf(stream,
  235. " PC: 0x%016lx RA: 0x%016lx SP: 0x%016lx GP: 0x%016lx\n",
  236. core.regs.pc, core.regs.ra, core.regs.sp, core.regs.gp);
  237. fprintf(stream,
  238. " TP: 0x%016lx T0: 0x%016lx T1: 0x%016lx T2: 0x%016lx\n",
  239. core.regs.tp, core.regs.t0, core.regs.t1, core.regs.t2);
  240. fprintf(stream,
  241. " S0: 0x%016lx S1: 0x%016lx A0: 0x%016lx A1: 0x%016lx\n",
  242. core.regs.s0, core.regs.s1, core.regs.a0, core.regs.a1);
  243. fprintf(stream,
  244. " A2: 0x%016lx A3: 0x%016lx A4: 0x%016lx A5: 0x%016lx\n",
  245. core.regs.a2, core.regs.a3, core.regs.a4, core.regs.a5);
  246. fprintf(stream,
  247. " A6: 0x%016lx A7: 0x%016lx S2: 0x%016lx S3: 0x%016lx\n",
  248. core.regs.a6, core.regs.a7, core.regs.s2, core.regs.s3);
  249. fprintf(stream,
  250. " S4: 0x%016lx S5: 0x%016lx S6: 0x%016lx S7: 0x%016lx\n",
  251. core.regs.s4, core.regs.s5, core.regs.s6, core.regs.s7);
  252. fprintf(stream,
  253. " S8: 0x%016lx S9: 0x%016lx S10: 0x%016lx S11: 0x%016lx\n",
  254. core.regs.s8, core.regs.s9, core.regs.s10, core.regs.s11);
  255. fprintf(stream,
  256. " T3: 0x%016lx T4: 0x%016lx T5: 0x%016lx T6: 0x%016lx\n",
  257. core.regs.t3, core.regs.t4, core.regs.t5, core.regs.t6);
  258. }
  259. static void __aligned(16) guest_unexp_trap(void)
  260. {
  261. sbi_ecall(KVM_RISCV_SELFTESTS_SBI_EXT,
  262. KVM_RISCV_SELFTESTS_SBI_UNEXP,
  263. 0, 0, 0, 0, 0, 0);
  264. }
  265. void vcpu_arch_set_entry_point(struct kvm_vcpu *vcpu, void *guest_code)
  266. {
  267. vcpu_set_reg(vcpu, RISCV_CORE_REG(regs.pc), (unsigned long)guest_code);
  268. }
  269. struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id)
  270. {
  271. int r;
  272. size_t stack_size;
  273. unsigned long stack_vaddr;
  274. unsigned long current_gp = 0;
  275. struct kvm_mp_state mps;
  276. struct kvm_vcpu *vcpu;
  277. stack_size = vm->page_size == 4096 ? DEFAULT_STACK_PGS * vm->page_size :
  278. vm->page_size;
  279. stack_vaddr = __vm_vaddr_alloc(vm, stack_size,
  280. DEFAULT_RISCV_GUEST_STACK_VADDR_MIN,
  281. MEM_REGION_DATA);
  282. vcpu = __vm_vcpu_add(vm, vcpu_id);
  283. riscv_vcpu_mmu_setup(vcpu);
  284. /*
  285. * With SBI HSM support in KVM RISC-V, all secondary VCPUs are
  286. * powered-off by default so we ensure that all secondary VCPUs
  287. * are powered-on using KVM_SET_MP_STATE ioctl().
  288. */
  289. mps.mp_state = KVM_MP_STATE_RUNNABLE;
  290. r = __vcpu_ioctl(vcpu, KVM_SET_MP_STATE, &mps);
  291. TEST_ASSERT(!r, "IOCTL KVM_SET_MP_STATE failed (error %d)", r);
  292. /* Setup global pointer of guest to be same as the host */
  293. asm volatile (
  294. "add %0, gp, zero" : "=r" (current_gp) : : "memory");
  295. vcpu_set_reg(vcpu, RISCV_CORE_REG(regs.gp), current_gp);
  296. /* Setup stack pointer and program counter of guest */
  297. vcpu_set_reg(vcpu, RISCV_CORE_REG(regs.sp), stack_vaddr + stack_size);
  298. /* Setup sscratch for guest_get_vcpuid() */
  299. vcpu_set_reg(vcpu, RISCV_GENERAL_CSR_REG(sscratch), vcpu_id);
  300. /* Setup default exception vector of guest */
  301. vcpu_set_reg(vcpu, RISCV_GENERAL_CSR_REG(stvec), (unsigned long)guest_unexp_trap);
  302. return vcpu;
  303. }
  304. void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...)
  305. {
  306. va_list ap;
  307. uint64_t id = RISCV_CORE_REG(regs.a0);
  308. int i;
  309. TEST_ASSERT(num >= 1 && num <= 8, "Unsupported number of args,\n"
  310. " num: %u", num);
  311. va_start(ap, num);
  312. for (i = 0; i < num; i++) {
  313. switch (i) {
  314. case 0:
  315. id = RISCV_CORE_REG(regs.a0);
  316. break;
  317. case 1:
  318. id = RISCV_CORE_REG(regs.a1);
  319. break;
  320. case 2:
  321. id = RISCV_CORE_REG(regs.a2);
  322. break;
  323. case 3:
  324. id = RISCV_CORE_REG(regs.a3);
  325. break;
  326. case 4:
  327. id = RISCV_CORE_REG(regs.a4);
  328. break;
  329. case 5:
  330. id = RISCV_CORE_REG(regs.a5);
  331. break;
  332. case 6:
  333. id = RISCV_CORE_REG(regs.a6);
  334. break;
  335. case 7:
  336. id = RISCV_CORE_REG(regs.a7);
  337. break;
  338. }
  339. vcpu_set_reg(vcpu, id, va_arg(ap, uint64_t));
  340. }
  341. va_end(ap);
  342. }
  343. void kvm_exit_unexpected_exception(int vector, int ec)
  344. {
  345. ucall(UCALL_UNHANDLED, 2, vector, ec);
  346. }
  347. void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)
  348. {
  349. struct ucall uc;
  350. if (get_ucall(vcpu, &uc) == UCALL_UNHANDLED) {
  351. TEST_FAIL("Unexpected exception (vector:0x%lx, ec:0x%lx)",
  352. uc.args[0], uc.args[1]);
  353. }
  354. }
  355. struct handlers {
  356. exception_handler_fn exception_handlers[NR_VECTORS][NR_EXCEPTIONS];
  357. };
  358. void route_exception(struct pt_regs *regs)
  359. {
  360. struct handlers *handlers = (struct handlers *)exception_handlers;
  361. int vector = 0, ec;
  362. ec = regs->cause & ~CAUSE_IRQ_FLAG;
  363. if (ec >= NR_EXCEPTIONS)
  364. goto unexpected_exception;
  365. /* Use the same handler for all the interrupts */
  366. if (regs->cause & CAUSE_IRQ_FLAG) {
  367. vector = 1;
  368. ec = 0;
  369. }
  370. if (handlers && handlers->exception_handlers[vector][ec])
  371. return handlers->exception_handlers[vector][ec](regs);
  372. unexpected_exception:
  373. return kvm_exit_unexpected_exception(vector, ec);
  374. }
  375. void vcpu_init_vector_tables(struct kvm_vcpu *vcpu)
  376. {
  377. extern char exception_vectors;
  378. vcpu_set_reg(vcpu, RISCV_GENERAL_CSR_REG(stvec), (unsigned long)&exception_vectors);
  379. }
  380. void vm_init_vector_tables(struct kvm_vm *vm)
  381. {
  382. vm->handlers = __vm_vaddr_alloc(vm, sizeof(struct handlers),
  383. vm->page_size, MEM_REGION_DATA);
  384. *(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
  385. }
  386. void vm_install_exception_handler(struct kvm_vm *vm, int vector, exception_handler_fn handler)
  387. {
  388. struct handlers *handlers = addr_gva2hva(vm, vm->handlers);
  389. assert(vector < NR_EXCEPTIONS);
  390. handlers->exception_handlers[0][vector] = handler;
  391. }
  392. void vm_install_interrupt_handler(struct kvm_vm *vm, exception_handler_fn handler)
  393. {
  394. struct handlers *handlers = addr_gva2hva(vm, vm->handlers);
  395. handlers->exception_handlers[1][0] = handler;
  396. }
  397. uint32_t guest_get_vcpuid(void)
  398. {
  399. return csr_read(CSR_SSCRATCH);
  400. }
  401. struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
  402. unsigned long arg1, unsigned long arg2,
  403. unsigned long arg3, unsigned long arg4,
  404. unsigned long arg5)
  405. {
  406. register uintptr_t a0 asm ("a0") = (uintptr_t)(arg0);
  407. register uintptr_t a1 asm ("a1") = (uintptr_t)(arg1);
  408. register uintptr_t a2 asm ("a2") = (uintptr_t)(arg2);
  409. register uintptr_t a3 asm ("a3") = (uintptr_t)(arg3);
  410. register uintptr_t a4 asm ("a4") = (uintptr_t)(arg4);
  411. register uintptr_t a5 asm ("a5") = (uintptr_t)(arg5);
  412. register uintptr_t a6 asm ("a6") = (uintptr_t)(fid);
  413. register uintptr_t a7 asm ("a7") = (uintptr_t)(ext);
  414. struct sbiret ret;
  415. asm volatile (
  416. "ecall"
  417. : "+r" (a0), "+r" (a1)
  418. : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7)
  419. : "memory");
  420. ret.error = a0;
  421. ret.value = a1;
  422. return ret;
  423. }
  424. bool guest_sbi_probe_extension(int extid, long *out_val)
  425. {
  426. struct sbiret ret;
  427. ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, extid,
  428. 0, 0, 0, 0, 0);
  429. __GUEST_ASSERT(!ret.error || ret.error == SBI_ERR_NOT_SUPPORTED,
  430. "ret.error=%ld, ret.value=%ld\n", ret.error, ret.value);
  431. if (ret.error == SBI_ERR_NOT_SUPPORTED)
  432. return false;
  433. if (out_val)
  434. *out_val = ret.value;
  435. return true;
  436. }
  437. unsigned long get_host_sbi_spec_version(void)
  438. {
  439. struct sbiret ret;
  440. ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_GET_SPEC_VERSION, 0,
  441. 0, 0, 0, 0, 0);
  442. GUEST_ASSERT(!ret.error);
  443. return ret.value;
  444. }
  445. void kvm_selftest_arch_init(void)
  446. {
  447. /*
  448. * riscv64 doesn't have a true default mode, so start by detecting the
  449. * supported vm mode.
  450. */
  451. guest_modes_append_default();
  452. }
  453. unsigned long riscv64_get_satp_mode(void)
  454. {
  455. int kvm_fd, vm_fd, vcpu_fd, err;
  456. uint64_t val;
  457. struct kvm_one_reg reg = {
  458. .id = RISCV_CONFIG_REG(satp_mode),
  459. .addr = (uint64_t)&val,
  460. };
  461. kvm_fd = open_kvm_dev_path_or_exit();
  462. vm_fd = __kvm_ioctl(kvm_fd, KVM_CREATE_VM, NULL);
  463. TEST_ASSERT(vm_fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_VM, vm_fd));
  464. vcpu_fd = ioctl(vm_fd, KVM_CREATE_VCPU, 0);
  465. TEST_ASSERT(vcpu_fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_VCPU, vcpu_fd));
  466. err = ioctl(vcpu_fd, KVM_GET_ONE_REG, &reg);
  467. TEST_ASSERT(err == 0, KVM_IOCTL_ERROR(KVM_GET_ONE_REG, vcpu_fd));
  468. close(vcpu_fd);
  469. close(vm_fd);
  470. close(kvm_fd);
  471. return val;
  472. }