x86.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. /*
  2. * tools/testing/selftests/kvm/lib/x86.c
  3. *
  4. * Copyright (C) 2018, Google LLC.
  5. *
  6. * This work is licensed under the terms of the GNU GPL, version 2.
  7. */
  8. #define _GNU_SOURCE /* for program_invocation_name */
  9. #include "test_util.h"
  10. #include "kvm_util.h"
  11. #include "kvm_util_internal.h"
  12. #include "x86.h"
  13. /* Minimum physical address used for virtual translation tables. */
  14. #define KVM_GUEST_PAGE_TABLE_MIN_PADDR 0x180000
  15. /* Virtual translation table structure declarations */
  16. struct pageMapL4Entry {
  17. uint64_t present:1;
  18. uint64_t writable:1;
  19. uint64_t user:1;
  20. uint64_t write_through:1;
  21. uint64_t cache_disable:1;
  22. uint64_t accessed:1;
  23. uint64_t ignored_06:1;
  24. uint64_t page_size:1;
  25. uint64_t ignored_11_08:4;
  26. uint64_t address:40;
  27. uint64_t ignored_62_52:11;
  28. uint64_t execute_disable:1;
  29. };
  30. struct pageDirectoryPointerEntry {
  31. uint64_t present:1;
  32. uint64_t writable:1;
  33. uint64_t user:1;
  34. uint64_t write_through:1;
  35. uint64_t cache_disable:1;
  36. uint64_t accessed:1;
  37. uint64_t ignored_06:1;
  38. uint64_t page_size:1;
  39. uint64_t ignored_11_08:4;
  40. uint64_t address:40;
  41. uint64_t ignored_62_52:11;
  42. uint64_t execute_disable:1;
  43. };
  44. struct pageDirectoryEntry {
  45. uint64_t present:1;
  46. uint64_t writable:1;
  47. uint64_t user:1;
  48. uint64_t write_through:1;
  49. uint64_t cache_disable:1;
  50. uint64_t accessed:1;
  51. uint64_t ignored_06:1;
  52. uint64_t page_size:1;
  53. uint64_t ignored_11_08:4;
  54. uint64_t address:40;
  55. uint64_t ignored_62_52:11;
  56. uint64_t execute_disable:1;
  57. };
  58. struct pageTableEntry {
  59. uint64_t present:1;
  60. uint64_t writable:1;
  61. uint64_t user:1;
  62. uint64_t write_through:1;
  63. uint64_t cache_disable:1;
  64. uint64_t accessed:1;
  65. uint64_t dirty:1;
  66. uint64_t reserved_07:1;
  67. uint64_t global:1;
  68. uint64_t ignored_11_09:3;
  69. uint64_t address:40;
  70. uint64_t ignored_62_52:11;
  71. uint64_t execute_disable:1;
  72. };
  73. /* Register Dump
  74. *
  75. * Input Args:
  76. * indent - Left margin indent amount
  77. * regs - register
  78. *
  79. * Output Args:
  80. * stream - Output FILE stream
  81. *
  82. * Return: None
  83. *
  84. * Dumps the state of the registers given by regs, to the FILE stream
  85. * given by steam.
  86. */
  87. void regs_dump(FILE *stream, struct kvm_regs *regs,
  88. uint8_t indent)
  89. {
  90. fprintf(stream, "%*srax: 0x%.16llx rbx: 0x%.16llx "
  91. "rcx: 0x%.16llx rdx: 0x%.16llx\n",
  92. indent, "",
  93. regs->rax, regs->rbx, regs->rcx, regs->rdx);
  94. fprintf(stream, "%*srsi: 0x%.16llx rdi: 0x%.16llx "
  95. "rsp: 0x%.16llx rbp: 0x%.16llx\n",
  96. indent, "",
  97. regs->rsi, regs->rdi, regs->rsp, regs->rbp);
  98. fprintf(stream, "%*sr8: 0x%.16llx r9: 0x%.16llx "
  99. "r10: 0x%.16llx r11: 0x%.16llx\n",
  100. indent, "",
  101. regs->r8, regs->r9, regs->r10, regs->r11);
  102. fprintf(stream, "%*sr12: 0x%.16llx r13: 0x%.16llx "
  103. "r14: 0x%.16llx r15: 0x%.16llx\n",
  104. indent, "",
  105. regs->r12, regs->r13, regs->r14, regs->r15);
  106. fprintf(stream, "%*srip: 0x%.16llx rfl: 0x%.16llx\n",
  107. indent, "",
  108. regs->rip, regs->rflags);
  109. }
  110. /* Segment Dump
  111. *
  112. * Input Args:
  113. * indent - Left margin indent amount
  114. * segment - KVM segment
  115. *
  116. * Output Args:
  117. * stream - Output FILE stream
  118. *
  119. * Return: None
  120. *
  121. * Dumps the state of the KVM segment given by segment, to the FILE stream
  122. * given by steam.
  123. */
  124. static void segment_dump(FILE *stream, struct kvm_segment *segment,
  125. uint8_t indent)
  126. {
  127. fprintf(stream, "%*sbase: 0x%.16llx limit: 0x%.8x "
  128. "selector: 0x%.4x type: 0x%.2x\n",
  129. indent, "", segment->base, segment->limit,
  130. segment->selector, segment->type);
  131. fprintf(stream, "%*spresent: 0x%.2x dpl: 0x%.2x "
  132. "db: 0x%.2x s: 0x%.2x l: 0x%.2x\n",
  133. indent, "", segment->present, segment->dpl,
  134. segment->db, segment->s, segment->l);
  135. fprintf(stream, "%*sg: 0x%.2x avl: 0x%.2x "
  136. "unusable: 0x%.2x padding: 0x%.2x\n",
  137. indent, "", segment->g, segment->avl,
  138. segment->unusable, segment->padding);
  139. }
  140. /* dtable Dump
  141. *
  142. * Input Args:
  143. * indent - Left margin indent amount
  144. * dtable - KVM dtable
  145. *
  146. * Output Args:
  147. * stream - Output FILE stream
  148. *
  149. * Return: None
  150. *
  151. * Dumps the state of the KVM dtable given by dtable, to the FILE stream
  152. * given by steam.
  153. */
  154. static void dtable_dump(FILE *stream, struct kvm_dtable *dtable,
  155. uint8_t indent)
  156. {
  157. fprintf(stream, "%*sbase: 0x%.16llx limit: 0x%.4x "
  158. "padding: 0x%.4x 0x%.4x 0x%.4x\n",
  159. indent, "", dtable->base, dtable->limit,
  160. dtable->padding[0], dtable->padding[1], dtable->padding[2]);
  161. }
  162. /* System Register Dump
  163. *
  164. * Input Args:
  165. * indent - Left margin indent amount
  166. * sregs - System registers
  167. *
  168. * Output Args:
  169. * stream - Output FILE stream
  170. *
  171. * Return: None
  172. *
  173. * Dumps the state of the system registers given by sregs, to the FILE stream
  174. * given by steam.
  175. */
  176. void sregs_dump(FILE *stream, struct kvm_sregs *sregs,
  177. uint8_t indent)
  178. {
  179. unsigned int i;
  180. fprintf(stream, "%*scs:\n", indent, "");
  181. segment_dump(stream, &sregs->cs, indent + 2);
  182. fprintf(stream, "%*sds:\n", indent, "");
  183. segment_dump(stream, &sregs->ds, indent + 2);
  184. fprintf(stream, "%*ses:\n", indent, "");
  185. segment_dump(stream, &sregs->es, indent + 2);
  186. fprintf(stream, "%*sfs:\n", indent, "");
  187. segment_dump(stream, &sregs->fs, indent + 2);
  188. fprintf(stream, "%*sgs:\n", indent, "");
  189. segment_dump(stream, &sregs->gs, indent + 2);
  190. fprintf(stream, "%*sss:\n", indent, "");
  191. segment_dump(stream, &sregs->ss, indent + 2);
  192. fprintf(stream, "%*str:\n", indent, "");
  193. segment_dump(stream, &sregs->tr, indent + 2);
  194. fprintf(stream, "%*sldt:\n", indent, "");
  195. segment_dump(stream, &sregs->ldt, indent + 2);
  196. fprintf(stream, "%*sgdt:\n", indent, "");
  197. dtable_dump(stream, &sregs->gdt, indent + 2);
  198. fprintf(stream, "%*sidt:\n", indent, "");
  199. dtable_dump(stream, &sregs->idt, indent + 2);
  200. fprintf(stream, "%*scr0: 0x%.16llx cr2: 0x%.16llx "
  201. "cr3: 0x%.16llx cr4: 0x%.16llx\n",
  202. indent, "",
  203. sregs->cr0, sregs->cr2, sregs->cr3, sregs->cr4);
  204. fprintf(stream, "%*scr8: 0x%.16llx efer: 0x%.16llx "
  205. "apic_base: 0x%.16llx\n",
  206. indent, "",
  207. sregs->cr8, sregs->efer, sregs->apic_base);
  208. fprintf(stream, "%*sinterrupt_bitmap:\n", indent, "");
  209. for (i = 0; i < (KVM_NR_INTERRUPTS + 63) / 64; i++) {
  210. fprintf(stream, "%*s%.16llx\n", indent + 2, "",
  211. sregs->interrupt_bitmap[i]);
  212. }
  213. }
  214. void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot)
  215. {
  216. int rc;
  217. TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
  218. "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
  219. /* If needed, create page map l4 table. */
  220. if (!vm->pgd_created) {
  221. vm_paddr_t paddr = vm_phy_page_alloc(vm,
  222. KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot);
  223. vm->pgd = paddr;
  224. vm->pgd_created = true;
  225. }
  226. }
  227. /* VM Virtual Page Map
  228. *
  229. * Input Args:
  230. * vm - Virtual Machine
  231. * vaddr - VM Virtual Address
  232. * paddr - VM Physical Address
  233. * pgd_memslot - Memory region slot for new virtual translation tables
  234. *
  235. * Output Args: None
  236. *
  237. * Return: None
  238. *
  239. * Within the VM given by vm, creates a virtual translation for the page
  240. * starting at vaddr to the page starting at paddr.
  241. */
  242. void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
  243. uint32_t pgd_memslot)
  244. {
  245. uint16_t index[4];
  246. struct pageMapL4Entry *pml4e;
  247. TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
  248. "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
  249. TEST_ASSERT((vaddr % vm->page_size) == 0,
  250. "Virtual address not on page boundary,\n"
  251. " vaddr: 0x%lx vm->page_size: 0x%x",
  252. vaddr, vm->page_size);
  253. TEST_ASSERT(sparsebit_is_set(vm->vpages_valid,
  254. (vaddr >> vm->page_shift)),
  255. "Invalid virtual address, vaddr: 0x%lx",
  256. vaddr);
  257. TEST_ASSERT((paddr % vm->page_size) == 0,
  258. "Physical address not on page boundary,\n"
  259. " paddr: 0x%lx vm->page_size: 0x%x",
  260. paddr, vm->page_size);
  261. TEST_ASSERT((paddr >> vm->page_shift) <= vm->max_gfn,
  262. "Physical address beyond beyond maximum supported,\n"
  263. " paddr: 0x%lx vm->max_gfn: 0x%lx vm->page_size: 0x%x",
  264. paddr, vm->max_gfn, vm->page_size);
  265. index[0] = (vaddr >> 12) & 0x1ffu;
  266. index[1] = (vaddr >> 21) & 0x1ffu;
  267. index[2] = (vaddr >> 30) & 0x1ffu;
  268. index[3] = (vaddr >> 39) & 0x1ffu;
  269. /* Allocate page directory pointer table if not present. */
  270. pml4e = addr_gpa2hva(vm, vm->pgd);
  271. if (!pml4e[index[3]].present) {
  272. pml4e[index[3]].address = vm_phy_page_alloc(vm,
  273. KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot)
  274. >> vm->page_shift;
  275. pml4e[index[3]].writable = true;
  276. pml4e[index[3]].present = true;
  277. }
  278. /* Allocate page directory table if not present. */
  279. struct pageDirectoryPointerEntry *pdpe;
  280. pdpe = addr_gpa2hva(vm, pml4e[index[3]].address * vm->page_size);
  281. if (!pdpe[index[2]].present) {
  282. pdpe[index[2]].address = vm_phy_page_alloc(vm,
  283. KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot)
  284. >> vm->page_shift;
  285. pdpe[index[2]].writable = true;
  286. pdpe[index[2]].present = true;
  287. }
  288. /* Allocate page table if not present. */
  289. struct pageDirectoryEntry *pde;
  290. pde = addr_gpa2hva(vm, pdpe[index[2]].address * vm->page_size);
  291. if (!pde[index[1]].present) {
  292. pde[index[1]].address = vm_phy_page_alloc(vm,
  293. KVM_GUEST_PAGE_TABLE_MIN_PADDR, pgd_memslot)
  294. >> vm->page_shift;
  295. pde[index[1]].writable = true;
  296. pde[index[1]].present = true;
  297. }
  298. /* Fill in page table entry. */
  299. struct pageTableEntry *pte;
  300. pte = addr_gpa2hva(vm, pde[index[1]].address * vm->page_size);
  301. pte[index[0]].address = paddr >> vm->page_shift;
  302. pte[index[0]].writable = true;
  303. pte[index[0]].present = 1;
  304. }
  305. /* Virtual Translation Tables Dump
  306. *
  307. * Input Args:
  308. * vm - Virtual Machine
  309. * indent - Left margin indent amount
  310. *
  311. * Output Args:
  312. * stream - Output FILE stream
  313. *
  314. * Return: None
  315. *
  316. * Dumps to the FILE stream given by stream, the contents of all the
  317. * virtual translation tables for the VM given by vm.
  318. */
  319. void virt_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
  320. {
  321. struct pageMapL4Entry *pml4e, *pml4e_start;
  322. struct pageDirectoryPointerEntry *pdpe, *pdpe_start;
  323. struct pageDirectoryEntry *pde, *pde_start;
  324. struct pageTableEntry *pte, *pte_start;
  325. if (!vm->pgd_created)
  326. return;
  327. fprintf(stream, "%*s "
  328. " no\n", indent, "");
  329. fprintf(stream, "%*s index hvaddr gpaddr "
  330. "addr w exec dirty\n",
  331. indent, "");
  332. pml4e_start = (struct pageMapL4Entry *) addr_gpa2hva(vm,
  333. vm->pgd);
  334. for (uint16_t n1 = 0; n1 <= 0x1ffu; n1++) {
  335. pml4e = &pml4e_start[n1];
  336. if (!pml4e->present)
  337. continue;
  338. fprintf(stream, "%*spml4e 0x%-3zx %p 0x%-12lx 0x%-10lx %u "
  339. " %u\n",
  340. indent, "",
  341. pml4e - pml4e_start, pml4e,
  342. addr_hva2gpa(vm, pml4e), (uint64_t) pml4e->address,
  343. pml4e->writable, pml4e->execute_disable);
  344. pdpe_start = addr_gpa2hva(vm, pml4e->address
  345. * vm->page_size);
  346. for (uint16_t n2 = 0; n2 <= 0x1ffu; n2++) {
  347. pdpe = &pdpe_start[n2];
  348. if (!pdpe->present)
  349. continue;
  350. fprintf(stream, "%*spdpe 0x%-3zx %p 0x%-12lx 0x%-10lx "
  351. "%u %u\n",
  352. indent, "",
  353. pdpe - pdpe_start, pdpe,
  354. addr_hva2gpa(vm, pdpe),
  355. (uint64_t) pdpe->address, pdpe->writable,
  356. pdpe->execute_disable);
  357. pde_start = addr_gpa2hva(vm,
  358. pdpe->address * vm->page_size);
  359. for (uint16_t n3 = 0; n3 <= 0x1ffu; n3++) {
  360. pde = &pde_start[n3];
  361. if (!pde->present)
  362. continue;
  363. fprintf(stream, "%*spde 0x%-3zx %p "
  364. "0x%-12lx 0x%-10lx %u %u\n",
  365. indent, "", pde - pde_start, pde,
  366. addr_hva2gpa(vm, pde),
  367. (uint64_t) pde->address, pde->writable,
  368. pde->execute_disable);
  369. pte_start = addr_gpa2hva(vm,
  370. pde->address * vm->page_size);
  371. for (uint16_t n4 = 0; n4 <= 0x1ffu; n4++) {
  372. pte = &pte_start[n4];
  373. if (!pte->present)
  374. continue;
  375. fprintf(stream, "%*spte 0x%-3zx %p "
  376. "0x%-12lx 0x%-10lx %u %u "
  377. " %u 0x%-10lx\n",
  378. indent, "",
  379. pte - pte_start, pte,
  380. addr_hva2gpa(vm, pte),
  381. (uint64_t) pte->address,
  382. pte->writable,
  383. pte->execute_disable,
  384. pte->dirty,
  385. ((uint64_t) n1 << 27)
  386. | ((uint64_t) n2 << 18)
  387. | ((uint64_t) n3 << 9)
  388. | ((uint64_t) n4));
  389. }
  390. }
  391. }
  392. }
  393. }
  394. /* Set Unusable Segment
  395. *
  396. * Input Args: None
  397. *
  398. * Output Args:
  399. * segp - Pointer to segment register
  400. *
  401. * Return: None
  402. *
  403. * Sets the segment register pointed to by segp to an unusable state.
  404. */
  405. static void kvm_seg_set_unusable(struct kvm_segment *segp)
  406. {
  407. memset(segp, 0, sizeof(*segp));
  408. segp->unusable = true;
  409. }
  410. static void kvm_seg_fill_gdt_64bit(struct kvm_vm *vm, struct kvm_segment *segp)
  411. {
  412. void *gdt = addr_gva2hva(vm, vm->gdt);
  413. struct desc64 *desc = gdt + (segp->selector >> 3) * 8;
  414. desc->limit0 = segp->limit & 0xFFFF;
  415. desc->base0 = segp->base & 0xFFFF;
  416. desc->base1 = segp->base >> 16;
  417. desc->type = segp->type;
  418. desc->s = segp->s;
  419. desc->dpl = segp->dpl;
  420. desc->p = segp->present;
  421. desc->limit1 = segp->limit >> 16;
  422. desc->avl = segp->avl;
  423. desc->l = segp->l;
  424. desc->db = segp->db;
  425. desc->g = segp->g;
  426. desc->base2 = segp->base >> 24;
  427. if (!segp->s)
  428. desc->base3 = segp->base >> 32;
  429. }
  430. /* Set Long Mode Flat Kernel Code Segment
  431. *
  432. * Input Args:
  433. * vm - VM whose GDT is being filled, or NULL to only write segp
  434. * selector - selector value
  435. *
  436. * Output Args:
  437. * segp - Pointer to KVM segment
  438. *
  439. * Return: None
  440. *
  441. * Sets up the KVM segment pointed to by segp, to be a code segment
  442. * with the selector value given by selector.
  443. */
  444. static void kvm_seg_set_kernel_code_64bit(struct kvm_vm *vm, uint16_t selector,
  445. struct kvm_segment *segp)
  446. {
  447. memset(segp, 0, sizeof(*segp));
  448. segp->selector = selector;
  449. segp->limit = 0xFFFFFFFFu;
  450. segp->s = 0x1; /* kTypeCodeData */
  451. segp->type = 0x08 | 0x01 | 0x02; /* kFlagCode | kFlagCodeAccessed
  452. * | kFlagCodeReadable
  453. */
  454. segp->g = true;
  455. segp->l = true;
  456. segp->present = 1;
  457. if (vm)
  458. kvm_seg_fill_gdt_64bit(vm, segp);
  459. }
  460. /* Set Long Mode Flat Kernel Data Segment
  461. *
  462. * Input Args:
  463. * vm - VM whose GDT is being filled, or NULL to only write segp
  464. * selector - selector value
  465. *
  466. * Output Args:
  467. * segp - Pointer to KVM segment
  468. *
  469. * Return: None
  470. *
  471. * Sets up the KVM segment pointed to by segp, to be a data segment
  472. * with the selector value given by selector.
  473. */
  474. static void kvm_seg_set_kernel_data_64bit(struct kvm_vm *vm, uint16_t selector,
  475. struct kvm_segment *segp)
  476. {
  477. memset(segp, 0, sizeof(*segp));
  478. segp->selector = selector;
  479. segp->limit = 0xFFFFFFFFu;
  480. segp->s = 0x1; /* kTypeCodeData */
  481. segp->type = 0x00 | 0x01 | 0x02; /* kFlagData | kFlagDataAccessed
  482. * | kFlagDataWritable
  483. */
  484. segp->g = true;
  485. segp->present = true;
  486. if (vm)
  487. kvm_seg_fill_gdt_64bit(vm, segp);
  488. }
  489. /* Address Guest Virtual to Guest Physical
  490. *
  491. * Input Args:
  492. * vm - Virtual Machine
  493. * gpa - VM virtual address
  494. *
  495. * Output Args: None
  496. *
  497. * Return:
  498. * Equivalent VM physical address
  499. *
  500. * Translates the VM virtual address given by gva to a VM physical
  501. * address and then locates the memory region containing the VM
  502. * physical address, within the VM given by vm. When found, the host
  503. * virtual address providing the memory to the vm physical address is returned.
  504. * A TEST_ASSERT failure occurs if no region containing translated
  505. * VM virtual address exists.
  506. */
  507. vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
  508. {
  509. uint16_t index[4];
  510. struct pageMapL4Entry *pml4e;
  511. struct pageDirectoryPointerEntry *pdpe;
  512. struct pageDirectoryEntry *pde;
  513. struct pageTableEntry *pte;
  514. void *hva;
  515. TEST_ASSERT(vm->mode == VM_MODE_FLAT48PG, "Attempt to use "
  516. "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
  517. index[0] = (gva >> 12) & 0x1ffu;
  518. index[1] = (gva >> 21) & 0x1ffu;
  519. index[2] = (gva >> 30) & 0x1ffu;
  520. index[3] = (gva >> 39) & 0x1ffu;
  521. if (!vm->pgd_created)
  522. goto unmapped_gva;
  523. pml4e = addr_gpa2hva(vm, vm->pgd);
  524. if (!pml4e[index[3]].present)
  525. goto unmapped_gva;
  526. pdpe = addr_gpa2hva(vm, pml4e[index[3]].address * vm->page_size);
  527. if (!pdpe[index[2]].present)
  528. goto unmapped_gva;
  529. pde = addr_gpa2hva(vm, pdpe[index[2]].address * vm->page_size);
  530. if (!pde[index[1]].present)
  531. goto unmapped_gva;
  532. pte = addr_gpa2hva(vm, pde[index[1]].address * vm->page_size);
  533. if (!pte[index[0]].present)
  534. goto unmapped_gva;
  535. return (pte[index[0]].address * vm->page_size) + (gva & 0xfffu);
  536. unmapped_gva:
  537. TEST_ASSERT(false, "No mapping for vm virtual address, "
  538. "gva: 0x%lx", gva);
  539. }
  540. static void kvm_setup_gdt(struct kvm_vm *vm, struct kvm_dtable *dt, int gdt_memslot,
  541. int pgd_memslot)
  542. {
  543. if (!vm->gdt)
  544. vm->gdt = vm_vaddr_alloc(vm, getpagesize(),
  545. KVM_UTIL_MIN_VADDR, gdt_memslot, pgd_memslot);
  546. dt->base = vm->gdt;
  547. dt->limit = getpagesize();
  548. }
  549. static void kvm_setup_tss_64bit(struct kvm_vm *vm, struct kvm_segment *segp,
  550. int selector, int gdt_memslot,
  551. int pgd_memslot)
  552. {
  553. if (!vm->tss)
  554. vm->tss = vm_vaddr_alloc(vm, getpagesize(),
  555. KVM_UTIL_MIN_VADDR, gdt_memslot, pgd_memslot);
  556. memset(segp, 0, sizeof(*segp));
  557. segp->base = vm->tss;
  558. segp->limit = 0x67;
  559. segp->selector = selector;
  560. segp->type = 0xb;
  561. segp->present = 1;
  562. kvm_seg_fill_gdt_64bit(vm, segp);
  563. }
  564. void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot, int gdt_memslot)
  565. {
  566. struct kvm_sregs sregs;
  567. /* Set mode specific system register values. */
  568. vcpu_sregs_get(vm, vcpuid, &sregs);
  569. sregs.idt.limit = 0;
  570. kvm_setup_gdt(vm, &sregs.gdt, gdt_memslot, pgd_memslot);
  571. switch (vm->mode) {
  572. case VM_MODE_FLAT48PG:
  573. sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG;
  574. sregs.cr4 |= X86_CR4_PAE;
  575. sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
  576. kvm_seg_set_unusable(&sregs.ldt);
  577. kvm_seg_set_kernel_code_64bit(vm, 0x8, &sregs.cs);
  578. kvm_seg_set_kernel_data_64bit(vm, 0x10, &sregs.ds);
  579. kvm_seg_set_kernel_data_64bit(vm, 0x10, &sregs.es);
  580. kvm_setup_tss_64bit(vm, &sregs.tr, 0x18, gdt_memslot, pgd_memslot);
  581. break;
  582. default:
  583. TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", vm->mode);
  584. }
  585. sregs.cr3 = vm->pgd;
  586. vcpu_sregs_set(vm, vcpuid, &sregs);
  587. }
  588. /* Adds a vCPU with reasonable defaults (i.e., a stack)
  589. *
  590. * Input Args:
  591. * vcpuid - The id of the VCPU to add to the VM.
  592. * guest_code - The vCPU's entry point
  593. */
  594. void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code)
  595. {
  596. struct kvm_mp_state mp_state;
  597. struct kvm_regs regs;
  598. vm_vaddr_t stack_vaddr;
  599. stack_vaddr = vm_vaddr_alloc(vm, DEFAULT_STACK_PGS * getpagesize(),
  600. DEFAULT_GUEST_STACK_VADDR_MIN, 0, 0);
  601. /* Create VCPU */
  602. vm_vcpu_add(vm, vcpuid, 0, 0);
  603. /* Setup guest general purpose registers */
  604. vcpu_regs_get(vm, vcpuid, &regs);
  605. regs.rflags = regs.rflags | 0x2;
  606. regs.rsp = stack_vaddr + (DEFAULT_STACK_PGS * getpagesize());
  607. regs.rip = (unsigned long) guest_code;
  608. vcpu_regs_set(vm, vcpuid, &regs);
  609. /* Setup the MP state */
  610. mp_state.mp_state = 0;
  611. vcpu_set_mp_state(vm, vcpuid, &mp_state);
  612. }
  613. /* VM VCPU CPUID Set
  614. *
  615. * Input Args:
  616. * vm - Virtual Machine
  617. * vcpuid - VCPU id
  618. * cpuid - The CPUID values to set.
  619. *
  620. * Output Args: None
  621. *
  622. * Return: void
  623. *
  624. * Set the VCPU's CPUID.
  625. */
  626. void vcpu_set_cpuid(struct kvm_vm *vm,
  627. uint32_t vcpuid, struct kvm_cpuid2 *cpuid)
  628. {
  629. struct vcpu *vcpu = vcpu_find(vm, vcpuid);
  630. int rc;
  631. TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
  632. rc = ioctl(vcpu->fd, KVM_SET_CPUID2, cpuid);
  633. TEST_ASSERT(rc == 0, "KVM_SET_CPUID2 failed, rc: %i errno: %i",
  634. rc, errno);
  635. }
  636. /* Create a VM with reasonable defaults
  637. *
  638. * Input Args:
  639. * vcpuid - The id of the single VCPU to add to the VM.
  640. * extra_mem_pages - The size of extra memories to add (this will
  641. * decide how much extra space we will need to
  642. * setup the page tables using mem slot 0)
  643. * guest_code - The vCPU's entry point
  644. *
  645. * Output Args: None
  646. *
  647. * Return:
  648. * Pointer to opaque structure that describes the created VM.
  649. */
  650. struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_pages,
  651. void *guest_code)
  652. {
  653. struct kvm_vm *vm;
  654. /*
  655. * For x86 the maximum page table size for a memory region
  656. * will be when only 4K pages are used. In that case the
  657. * total extra size for page tables (for extra N pages) will
  658. * be: N/512+N/512^2+N/512^3+... which is definitely smaller
  659. * than N/512*2.
  660. */
  661. uint64_t extra_pg_pages = extra_mem_pages / 512 * 2;
  662. /* Create VM */
  663. vm = vm_create(VM_MODE_FLAT48PG,
  664. DEFAULT_GUEST_PHY_PAGES + extra_pg_pages,
  665. O_RDWR);
  666. /* Setup guest code */
  667. kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
  668. /* Setup IRQ Chip */
  669. vm_create_irqchip(vm);
  670. /* Add the first vCPU. */
  671. vm_vcpu_add_default(vm, vcpuid, guest_code);
  672. return vm;
  673. }
  674. struct kvm_x86_state {
  675. struct kvm_vcpu_events events;
  676. struct kvm_mp_state mp_state;
  677. struct kvm_regs regs;
  678. struct kvm_xsave xsave;
  679. struct kvm_xcrs xcrs;
  680. struct kvm_sregs sregs;
  681. struct kvm_debugregs debugregs;
  682. union {
  683. struct kvm_nested_state nested;
  684. char nested_[16384];
  685. };
  686. struct kvm_msrs msrs;
  687. };
  688. static int kvm_get_num_msrs(struct kvm_vm *vm)
  689. {
  690. struct kvm_msr_list nmsrs;
  691. int r;
  692. nmsrs.nmsrs = 0;
  693. r = ioctl(vm->kvm_fd, KVM_GET_MSR_INDEX_LIST, &nmsrs);
  694. TEST_ASSERT(r == -1 && errno == E2BIG, "Unexpected result from KVM_GET_MSR_INDEX_LIST probe, r: %i",
  695. r);
  696. return nmsrs.nmsrs;
  697. }
  698. struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
  699. {
  700. struct vcpu *vcpu = vcpu_find(vm, vcpuid);
  701. struct kvm_msr_list *list;
  702. struct kvm_x86_state *state;
  703. int nmsrs, r, i;
  704. static int nested_size = -1;
  705. if (nested_size == -1) {
  706. nested_size = kvm_check_cap(KVM_CAP_NESTED_STATE);
  707. TEST_ASSERT(nested_size <= sizeof(state->nested_),
  708. "Nested state size too big, %i > %zi",
  709. nested_size, sizeof(state->nested_));
  710. }
  711. nmsrs = kvm_get_num_msrs(vm);
  712. list = malloc(sizeof(*list) + nmsrs * sizeof(list->indices[0]));
  713. list->nmsrs = nmsrs;
  714. r = ioctl(vm->kvm_fd, KVM_GET_MSR_INDEX_LIST, list);
  715. TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_MSR_INDEX_LIST, r: %i",
  716. r);
  717. state = malloc(sizeof(*state) + nmsrs * sizeof(state->msrs.entries[0]));
  718. r = ioctl(vcpu->fd, KVM_GET_VCPU_EVENTS, &state->events);
  719. TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_VCPU_EVENTS, r: %i",
  720. r);
  721. r = ioctl(vcpu->fd, KVM_GET_MP_STATE, &state->mp_state);
  722. TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_MP_STATE, r: %i",
  723. r);
  724. r = ioctl(vcpu->fd, KVM_GET_REGS, &state->regs);
  725. TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_REGS, r: %i",
  726. r);
  727. r = ioctl(vcpu->fd, KVM_GET_XSAVE, &state->xsave);
  728. TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XSAVE, r: %i",
  729. r);
  730. if (kvm_check_cap(KVM_CAP_XCRS)) {
  731. r = ioctl(vcpu->fd, KVM_GET_XCRS, &state->xcrs);
  732. TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XCRS, r: %i",
  733. r);
  734. }
  735. r = ioctl(vcpu->fd, KVM_GET_SREGS, &state->sregs);
  736. TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_SREGS, r: %i",
  737. r);
  738. if (nested_size) {
  739. state->nested.size = sizeof(state->nested_);
  740. r = ioctl(vcpu->fd, KVM_GET_NESTED_STATE, &state->nested);
  741. TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_NESTED_STATE, r: %i",
  742. r);
  743. TEST_ASSERT(state->nested.size <= nested_size,
  744. "Nested state size too big, %i (KVM_CHECK_CAP gave %i)",
  745. state->nested.size, nested_size);
  746. } else
  747. state->nested.size = 0;
  748. state->msrs.nmsrs = nmsrs;
  749. for (i = 0; i < nmsrs; i++)
  750. state->msrs.entries[i].index = list->indices[i];
  751. r = ioctl(vcpu->fd, KVM_GET_MSRS, &state->msrs);
  752. TEST_ASSERT(r == nmsrs, "Unexpected result from KVM_GET_MSRS, r: %i (failed at %x)",
  753. r, r == nmsrs ? -1 : list->indices[r]);
  754. r = ioctl(vcpu->fd, KVM_GET_DEBUGREGS, &state->debugregs);
  755. TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_DEBUGREGS, r: %i",
  756. r);
  757. free(list);
  758. return state;
  759. }
  760. void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *state)
  761. {
  762. struct vcpu *vcpu = vcpu_find(vm, vcpuid);
  763. int r;
  764. if (state->nested.size) {
  765. r = ioctl(vcpu->fd, KVM_SET_NESTED_STATE, &state->nested);
  766. TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_NESTED_STATE, r: %i",
  767. r);
  768. }
  769. r = ioctl(vcpu->fd, KVM_SET_XSAVE, &state->xsave);
  770. TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XSAVE, r: %i",
  771. r);
  772. if (kvm_check_cap(KVM_CAP_XCRS)) {
  773. r = ioctl(vcpu->fd, KVM_SET_XCRS, &state->xcrs);
  774. TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XCRS, r: %i",
  775. r);
  776. }
  777. r = ioctl(vcpu->fd, KVM_SET_SREGS, &state->sregs);
  778. TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_SREGS, r: %i",
  779. r);
  780. r = ioctl(vcpu->fd, KVM_SET_MSRS, &state->msrs);
  781. TEST_ASSERT(r == state->msrs.nmsrs, "Unexpected result from KVM_SET_MSRS, r: %i (failed at %x)",
  782. r, r == state->msrs.nmsrs ? -1 : state->msrs.entries[r].index);
  783. r = ioctl(vcpu->fd, KVM_SET_VCPU_EVENTS, &state->events);
  784. TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_VCPU_EVENTS, r: %i",
  785. r);
  786. r = ioctl(vcpu->fd, KVM_SET_MP_STATE, &state->mp_state);
  787. TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_MP_STATE, r: %i",
  788. r);
  789. r = ioctl(vcpu->fd, KVM_SET_DEBUGREGS, &state->debugregs);
  790. TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_DEBUGREGS, r: %i",
  791. r);
  792. r = ioctl(vcpu->fd, KVM_SET_REGS, &state->regs);
  793. TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_REGS, r: %i",
  794. r);
  795. }