parlib: have 2LS libraries #include parlib/stdio.h
[akaros.git] / user / vmm / vmx.c
1 #include <parlib/stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <parlib/arch/arch.h>
6 #include <parlib/ros_debug.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <dirent.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ros/syscall.h>
13 #include <sys/mman.h>
14 #include <vmm/coreboot_tables.h>
15 #include <ros/common.h>
16 #include <vmm/vmm.h>
17 #include <vmm/virtio.h>
18 #include <vmm/virtio_mmio.h>
19 #include <vmm/virtio_ids.h>
20 #include <ros/arch/vmx.h>
21 #include <vmm/sched.h>
22 #include <vmm/util.h>
23 #include <ros/arch/mmu.h>
24 #include <ros/arch/trapframe.h>
25
26 char *vmxexit[] = {
27         VMX_EXIT_REASONS
28 };
29
30 void showstatus(FILE *f, struct guest_thread *vm_thread)
31 {
32         struct vm_trapframe *vm_tf = gth_to_vmtf(vm_thread);
33         int shutdown = vm_tf->tf_exit_reason;
34         char *when = shutdown & VMX_EXIT_REASONS_FAILED_VMENTRY ? "entry"
35                                                                 : "exit";
36         char *reason = "UNKNOWN";
37
38         shutdown &= ~VMX_EXIT_REASONS_FAILED_VMENTRY;
39         if (shutdown < COUNT_OF(vmxexit) && vmxexit[shutdown])
40                 reason = vmxexit[shutdown];
41         fprintf(f, "Shutdown: core %d, %s due to %s(0x%x); ret code 0x%x\n",
42                 vm_tf->tf_guest_pcoreid, when, reason, shutdown,
43                         vm_tf->tf_exit_reason);
44         fprintf_vm_tf(f, vm_tf);
45         backtrace_guest_thread(f, vm_thread);
46 }
47
48 /* Convert a guest virtual address to physical address. */
49 int gva2gpa(struct guest_thread *vm_thread, uint64_t va, uint64_t *pa)
50 {
51         assert(vm_thread != NULL);
52         struct vm_trapframe *vm_tf = gth_to_vmtf(vm_thread);
53         uint64_t *ptptr = (uint64_t *)vm_tf->tf_cr3;
54         uint64_t entry;
55
56         for (int shift = PML4_SHIFT;
57              shift >= PML1_SHIFT;
58              shift -= BITS_PER_PML) {
59                 entry = ptptr[PMLx(va, shift)];
60                 /* bit 63 can be NX.  Bits 62:52 are ignored (for PML4) */
61                 entry &= 0x000fffffffffffff;
62
63                 if (!PAGE_PRESENT(entry))
64                         return -1;
65                 if ((entry & PTE_PS) != 0) {
66                         uint64_t bitmask = ((1 << shift) - 1);
67
68                         *pa = (((uint64_t)va & bitmask) | (entry & ~bitmask));
69                         return 0;
70                 }
71                 ptptr = (uint64_t *)PG_ADDR(entry);
72         }
73         *pa = ((uint64_t)va & 0xfff) | (uint64_t)ptptr;
74         return 0;
75 }
76
77 /* Get the RIP as a physical address. */
78 int rippa(struct guest_thread *vm_thread, uint64_t *pa)
79 {
80         assert(vm_thread != NULL);
81         return gva2gpa(vm_thread, gth_to_vmtf(vm_thread)->tf_rip, pa);
82 }