processor.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <assert.h>
  3. #include <linux/compiler.h>
  4. #include <asm/kvm.h>
  5. #include "kvm_util.h"
  6. #include "processor.h"
  7. #include "ucall_common.h"
  8. #define LOONGARCH_PAGE_TABLE_PHYS_MIN 0x200000
  9. #define LOONGARCH_GUEST_STACK_VADDR_MIN 0x200000
  10. static vm_paddr_t invalid_pgtable[4];
  11. static vm_vaddr_t exception_handlers;
  12. static uint64_t virt_pte_index(struct kvm_vm *vm, vm_vaddr_t gva, int level)
  13. {
  14. unsigned int shift;
  15. uint64_t mask;
  16. shift = level * (vm->page_shift - 3) + vm->page_shift;
  17. mask = (1UL << (vm->page_shift - 3)) - 1;
  18. return (gva >> shift) & mask;
  19. }
  20. static uint64_t pte_addr(struct kvm_vm *vm, uint64_t entry)
  21. {
  22. return entry & ~((0x1UL << vm->page_shift) - 1);
  23. }
  24. static uint64_t ptrs_per_pte(struct kvm_vm *vm)
  25. {
  26. return 1 << (vm->page_shift - 3);
  27. }
  28. static void virt_set_pgtable(struct kvm_vm *vm, vm_paddr_t table, vm_paddr_t child)
  29. {
  30. uint64_t *ptep;
  31. int i, ptrs_per_pte;
  32. ptep = addr_gpa2hva(vm, table);
  33. ptrs_per_pte = 1 << (vm->page_shift - 3);
  34. for (i = 0; i < ptrs_per_pte; i++)
  35. WRITE_ONCE(*(ptep + i), child);
  36. }
  37. void virt_arch_pgd_alloc(struct kvm_vm *vm)
  38. {
  39. int i;
  40. vm_paddr_t child, table;
  41. if (vm->mmu.pgd_created)
  42. return;
  43. child = table = 0;
  44. for (i = 0; i < vm->mmu.pgtable_levels; i++) {
  45. invalid_pgtable[i] = child;
  46. table = vm_phy_page_alloc(vm, LOONGARCH_PAGE_TABLE_PHYS_MIN,
  47. vm->memslots[MEM_REGION_PT]);
  48. TEST_ASSERT(table, "Fail to allocate page tale at level %d\n", i);
  49. virt_set_pgtable(vm, table, child);
  50. child = table;
  51. }
  52. vm->mmu.pgd = table;
  53. vm->mmu.pgd_created = true;
  54. }
  55. static int virt_pte_none(uint64_t *ptep, int level)
  56. {
  57. return *ptep == invalid_pgtable[level];
  58. }
  59. static uint64_t *virt_populate_pte(struct kvm_vm *vm, vm_vaddr_t gva, int alloc)
  60. {
  61. int level;
  62. uint64_t *ptep;
  63. vm_paddr_t child;
  64. if (!vm->mmu.pgd_created)
  65. goto unmapped_gva;
  66. child = vm->mmu.pgd;
  67. level = vm->mmu.pgtable_levels - 1;
  68. while (level > 0) {
  69. ptep = addr_gpa2hva(vm, child) + virt_pte_index(vm, gva, level) * 8;
  70. if (virt_pte_none(ptep, level)) {
  71. if (alloc) {
  72. child = vm_alloc_page_table(vm);
  73. virt_set_pgtable(vm, child, invalid_pgtable[level - 1]);
  74. WRITE_ONCE(*ptep, child);
  75. } else
  76. goto unmapped_gva;
  77. } else
  78. child = pte_addr(vm, *ptep);
  79. level--;
  80. }
  81. ptep = addr_gpa2hva(vm, child) + virt_pte_index(vm, gva, level) * 8;
  82. return ptep;
  83. unmapped_gva:
  84. TEST_FAIL("No mapping for vm virtual address, gva: 0x%lx", gva);
  85. exit(EXIT_FAILURE);
  86. }
  87. vm_paddr_t addr_arch_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
  88. {
  89. uint64_t *ptep;
  90. ptep = virt_populate_pte(vm, gva, 0);
  91. TEST_ASSERT(*ptep != 0, "Virtual address vaddr: 0x%lx not mapped\n", gva);
  92. return pte_addr(vm, *ptep) + (gva & (vm->page_size - 1));
  93. }
  94. void virt_arch_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr)
  95. {
  96. uint32_t prot_bits;
  97. uint64_t *ptep;
  98. TEST_ASSERT((vaddr % vm->page_size) == 0,
  99. "Virtual address not on page boundary,\n"
  100. "vaddr: 0x%lx vm->page_size: 0x%x", vaddr, vm->page_size);
  101. TEST_ASSERT(sparsebit_is_set(vm->vpages_valid,
  102. (vaddr >> vm->page_shift)),
  103. "Invalid virtual address, vaddr: 0x%lx", vaddr);
  104. TEST_ASSERT((paddr % vm->page_size) == 0,
  105. "Physical address not on page boundary,\n"
  106. "paddr: 0x%lx vm->page_size: 0x%x", paddr, vm->page_size);
  107. TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
  108. "Physical address beyond maximum supported,\n"
  109. "paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
  110. paddr, vm->max_gfn, vm->page_size);
  111. ptep = virt_populate_pte(vm, vaddr, 1);
  112. prot_bits = _PAGE_PRESENT | __READABLE | __WRITEABLE | _CACHE_CC | _PAGE_USER;
  113. WRITE_ONCE(*ptep, paddr | prot_bits);
  114. }
  115. static void pte_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent, uint64_t page, int level)
  116. {
  117. uint64_t pte, *ptep;
  118. static const char * const type[] = { "pte", "pmd", "pud", "pgd"};
  119. if (level < 0)
  120. return;
  121. for (pte = page; pte < page + ptrs_per_pte(vm) * 8; pte += 8) {
  122. ptep = addr_gpa2hva(vm, pte);
  123. if (virt_pte_none(ptep, level))
  124. continue;
  125. fprintf(stream, "%*s%s: %lx: %lx at %p\n",
  126. indent, "", type[level], pte, *ptep, ptep);
  127. pte_dump(stream, vm, indent + 1, pte_addr(vm, *ptep), level--);
  128. }
  129. }
  130. void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
  131. {
  132. int level;
  133. if (!vm->mmu.pgd_created)
  134. return;
  135. level = vm->mmu.pgtable_levels - 1;
  136. pte_dump(stream, vm, indent, vm->mmu.pgd, level);
  137. }
  138. void vcpu_arch_dump(FILE *stream, struct kvm_vcpu *vcpu, uint8_t indent)
  139. {
  140. }
  141. void assert_on_unhandled_exception(struct kvm_vcpu *vcpu)
  142. {
  143. struct ucall uc;
  144. if (get_ucall(vcpu, &uc) != UCALL_UNHANDLED)
  145. return;
  146. TEST_FAIL("Unexpected exception (pc:0x%lx, estat:0x%lx, badv:0x%lx)",
  147. uc.args[0], uc.args[1], uc.args[2]);
  148. }
  149. void route_exception(struct ex_regs *regs)
  150. {
  151. int vector;
  152. unsigned long pc, estat, badv;
  153. struct handlers *handlers;
  154. handlers = (struct handlers *)exception_handlers;
  155. vector = (regs->estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT;
  156. if (handlers && handlers->exception_handlers[vector])
  157. return handlers->exception_handlers[vector](regs);
  158. pc = regs->pc;
  159. badv = regs->badv;
  160. estat = regs->estat;
  161. ucall(UCALL_UNHANDLED, 3, pc, estat, badv);
  162. while (1) ;
  163. }
  164. void vm_init_descriptor_tables(struct kvm_vm *vm)
  165. {
  166. void *addr;
  167. vm->handlers = __vm_vaddr_alloc(vm, sizeof(struct handlers),
  168. LOONGARCH_GUEST_STACK_VADDR_MIN, MEM_REGION_DATA);
  169. addr = addr_gva2hva(vm, vm->handlers);
  170. memset(addr, 0, vm->page_size);
  171. exception_handlers = vm->handlers;
  172. sync_global_to_guest(vm, exception_handlers);
  173. }
  174. void vm_install_exception_handler(struct kvm_vm *vm, int vector, handler_fn handler)
  175. {
  176. struct handlers *handlers = addr_gva2hva(vm, vm->handlers);
  177. assert(vector < VECTOR_NUM);
  178. handlers->exception_handlers[vector] = handler;
  179. }
  180. uint32_t guest_get_vcpuid(void)
  181. {
  182. return csr_read(LOONGARCH_CSR_CPUID);
  183. }
  184. void vcpu_args_set(struct kvm_vcpu *vcpu, unsigned int num, ...)
  185. {
  186. int i;
  187. va_list ap;
  188. struct kvm_regs regs;
  189. TEST_ASSERT(num >= 1 && num <= 8, "Unsupported number of args,\n"
  190. "num: %u\n", num);
  191. vcpu_regs_get(vcpu, &regs);
  192. va_start(ap, num);
  193. for (i = 0; i < num; i++)
  194. regs.gpr[i + 4] = va_arg(ap, uint64_t);
  195. va_end(ap);
  196. vcpu_regs_set(vcpu, &regs);
  197. }
  198. static void loongarch_set_reg(struct kvm_vcpu *vcpu, uint64_t id, uint64_t val)
  199. {
  200. __vcpu_set_reg(vcpu, id, val);
  201. }
  202. static void loongarch_get_csr(struct kvm_vcpu *vcpu, uint64_t id, void *addr)
  203. {
  204. uint64_t csrid;
  205. csrid = KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U64 | 8 * id;
  206. __vcpu_get_reg(vcpu, csrid, addr);
  207. }
  208. static void loongarch_set_csr(struct kvm_vcpu *vcpu, uint64_t id, uint64_t val)
  209. {
  210. uint64_t csrid;
  211. csrid = KVM_REG_LOONGARCH_CSR | KVM_REG_SIZE_U64 | 8 * id;
  212. __vcpu_set_reg(vcpu, csrid, val);
  213. }
  214. static void loongarch_vcpu_setup(struct kvm_vcpu *vcpu)
  215. {
  216. int width;
  217. unsigned long val;
  218. struct kvm_vm *vm = vcpu->vm;
  219. switch (vm->mode) {
  220. case VM_MODE_P36V47_16K:
  221. case VM_MODE_P47V47_16K:
  222. break;
  223. default:
  224. TEST_FAIL("Unknown guest mode, mode: 0x%x", vm->mode);
  225. }
  226. /* kernel mode and page enable mode */
  227. val = PLV_KERN | CSR_CRMD_PG;
  228. loongarch_set_csr(vcpu, LOONGARCH_CSR_CRMD, val);
  229. loongarch_set_csr(vcpu, LOONGARCH_CSR_PRMD, val);
  230. loongarch_set_csr(vcpu, LOONGARCH_CSR_EUEN, 1);
  231. loongarch_set_csr(vcpu, LOONGARCH_CSR_ECFG, 0);
  232. loongarch_set_csr(vcpu, LOONGARCH_CSR_TCFG, 0);
  233. loongarch_set_csr(vcpu, LOONGARCH_CSR_ASID, 1);
  234. /* time count start from 0 */
  235. val = 0;
  236. loongarch_set_reg(vcpu, KVM_REG_LOONGARCH_COUNTER, val);
  237. width = vm->page_shift - 3;
  238. switch (vm->mmu.pgtable_levels) {
  239. case 4:
  240. /* pud page shift and width */
  241. val = (vm->page_shift + width * 2) << 20 | (width << 25);
  242. /* fall throuth */
  243. case 3:
  244. /* pmd page shift and width */
  245. val |= (vm->page_shift + width) << 10 | (width << 15);
  246. /* pte page shift and width */
  247. val |= vm->page_shift | width << 5;
  248. break;
  249. default:
  250. TEST_FAIL("Got %u page table levels, expected 3 or 4", vm->mmu.pgtable_levels);
  251. }
  252. loongarch_set_csr(vcpu, LOONGARCH_CSR_PWCTL0, val);
  253. /* PGD page shift and width */
  254. val = (vm->page_shift + width * (vm->mmu.pgtable_levels - 1)) | width << 6;
  255. loongarch_set_csr(vcpu, LOONGARCH_CSR_PWCTL1, val);
  256. loongarch_set_csr(vcpu, LOONGARCH_CSR_PGDL, vm->mmu.pgd);
  257. /*
  258. * Refill exception runs on real mode
  259. * Entry address should be physical address
  260. */
  261. val = addr_gva2gpa(vm, (unsigned long)handle_tlb_refill);
  262. loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBRENTRY, val);
  263. /*
  264. * General exception runs on page-enabled mode
  265. * Entry address should be virtual address
  266. */
  267. val = (unsigned long)handle_exception;
  268. loongarch_set_csr(vcpu, LOONGARCH_CSR_EENTRY, val);
  269. loongarch_get_csr(vcpu, LOONGARCH_CSR_TLBIDX, &val);
  270. val &= ~CSR_TLBIDX_SIZEM;
  271. val |= PS_DEFAULT_SIZE << CSR_TLBIDX_SIZE;
  272. loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBIDX, val);
  273. loongarch_set_csr(vcpu, LOONGARCH_CSR_STLBPGSIZE, PS_DEFAULT_SIZE);
  274. /* LOONGARCH_CSR_KS1 is used for exception stack */
  275. val = __vm_vaddr_alloc(vm, vm->page_size,
  276. LOONGARCH_GUEST_STACK_VADDR_MIN, MEM_REGION_DATA);
  277. TEST_ASSERT(val != 0, "No memory for exception stack");
  278. val = val + vm->page_size;
  279. loongarch_set_csr(vcpu, LOONGARCH_CSR_KS1, val);
  280. loongarch_get_csr(vcpu, LOONGARCH_CSR_TLBREHI, &val);
  281. val &= ~CSR_TLBREHI_PS;
  282. val |= PS_DEFAULT_SIZE << CSR_TLBREHI_PS_SHIFT;
  283. loongarch_set_csr(vcpu, LOONGARCH_CSR_TLBREHI, val);
  284. loongarch_set_csr(vcpu, LOONGARCH_CSR_CPUID, vcpu->id);
  285. loongarch_set_csr(vcpu, LOONGARCH_CSR_TMID, vcpu->id);
  286. }
  287. struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id)
  288. {
  289. size_t stack_size;
  290. uint64_t stack_vaddr;
  291. struct kvm_regs regs;
  292. struct kvm_vcpu *vcpu;
  293. vcpu = __vm_vcpu_add(vm, vcpu_id);
  294. stack_size = vm->page_size;
  295. stack_vaddr = __vm_vaddr_alloc(vm, stack_size,
  296. LOONGARCH_GUEST_STACK_VADDR_MIN, MEM_REGION_DATA);
  297. TEST_ASSERT(stack_vaddr != 0, "No memory for vm stack");
  298. loongarch_vcpu_setup(vcpu);
  299. /* Setup guest general purpose registers */
  300. vcpu_regs_get(vcpu, &regs);
  301. regs.gpr[3] = stack_vaddr + stack_size;
  302. vcpu_regs_set(vcpu, &regs);
  303. return vcpu;
  304. }
  305. void vcpu_arch_set_entry_point(struct kvm_vcpu *vcpu, void *guest_code)
  306. {
  307. struct kvm_regs regs;
  308. /* Setup guest PC register */
  309. vcpu_regs_get(vcpu, &regs);
  310. regs.pc = (uint64_t)guest_code;
  311. vcpu_regs_set(vcpu, &regs);
  312. }