parlib: have 2LS libraries #include parlib/stdio.h
[akaros.git] / user / vmm / vmx.c
index 80a8d19..7be527d 100644 (file)
@@ -1,5 +1,4 @@
-#include <stdio.h> 
-#include <pthread.h>
+#include <parlib/stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <vmm/virtio_mmio.h>
 #include <vmm/virtio_ids.h>
 #include <ros/arch/vmx.h>
-
-/* nowhere on my linux system. */
-#define ARRAY_SIZE(x) (sizeof((x))/sizeof((x)[0]))
+#include <vmm/sched.h>
+#include <vmm/util.h>
+#include <ros/arch/mmu.h>
+#include <ros/arch/trapframe.h>
 
 char *vmxexit[] = {
        VMX_EXIT_REASONS
 };
 
-void showstatus(FILE *f, struct vmctl *v)
+void showstatus(FILE *f, struct guest_thread *vm_thread)
 {
-       int shutdown = v->ret_code;
-       char *when = shutdown & VMX_EXIT_REASONS_FAILED_VMENTRY ? "entry" : "exit";
-       shutdown &= ~VMX_EXIT_REASONS_FAILED_VMENTRY;
+       struct vm_trapframe *vm_tf = gth_to_vmtf(vm_thread);
+       int shutdown = vm_tf->tf_exit_reason;
+       char *when = shutdown & VMX_EXIT_REASONS_FAILED_VMENTRY ? "entry"
+                                                               : "exit";
        char *reason = "UNKNOWN";
-       if (shutdown < ARRAY_SIZE(vmxexit) && vmxexit[shutdown])
+
+       shutdown &= ~VMX_EXIT_REASONS_FAILED_VMENTRY;
+       if (shutdown < COUNT_OF(vmxexit) && vmxexit[shutdown])
                reason = vmxexit[shutdown];
-       fprintf(f, "Shutdown: core %d, %s due to %s(0x%x); ret code 0x%x\n", v->core, when, reason, shutdown, v->ret_code);
-       fprintf(f, "  gva %p gpa %p cr3 %p\n", (void *)v->gva, (void *)v->gpa, (void *)v->cr3);
-
-       fprintf(f, "  rax  0x%016lx\n",           v->regs.tf_rax);
-       fprintf(f, "  rbx  0x%016lx\n",           v->regs.tf_rbx);
-       fprintf(f, "  rcx  0x%016lx\n",           v->regs.tf_rcx);
-       fprintf(f, "  rdx  0x%016lx\n",           v->regs.tf_rdx);
-       fprintf(f, "  rbp  0x%016lx\n",           v->regs.tf_rbp);
-       fprintf(f, "  rsi  0x%016lx\n",           v->regs.tf_rsi);
-       fprintf(f, "  rdi  0x%016lx\n",           v->regs.tf_rdi);
-       fprintf(f, "  r8   0x%016lx\n",           v->regs.tf_r8);
-       fprintf(f, "  r9   0x%016lx\n",           v->regs.tf_r9);
-       fprintf(f, "  r10  0x%016lx\n",           v->regs.tf_r10);
-       fprintf(f, "  r11  0x%016lx\n",           v->regs.tf_r11);
-       fprintf(f, "  r12  0x%016lx\n",           v->regs.tf_r12);
-       fprintf(f, "  r13  0x%016lx\n",           v->regs.tf_r13);
-       fprintf(f, "  r14  0x%016lx\n",           v->regs.tf_r14);
-       fprintf(f, "  r15  0x%016lx\n",           v->regs.tf_r15);
+       fprintf(f, "Shutdown: core %d, %s due to %s(0x%x); ret code 0x%x\n",
+               vm_tf->tf_guest_pcoreid, when, reason, shutdown,
+                       vm_tf->tf_exit_reason);
+       fprintf_vm_tf(f, vm_tf);
+       backtrace_guest_thread(f, vm_thread);
+}
+
+/* Convert a guest virtual address to physical address. */
+int gva2gpa(struct guest_thread *vm_thread, uint64_t va, uint64_t *pa)
+{
+       assert(vm_thread != NULL);
+       struct vm_trapframe *vm_tf = gth_to_vmtf(vm_thread);
+       uint64_t *ptptr = (uint64_t *)vm_tf->tf_cr3;
+       uint64_t entry;
+
+       for (int shift = PML4_SHIFT;
+            shift >= PML1_SHIFT;
+            shift -= BITS_PER_PML) {
+               entry = ptptr[PMLx(va, shift)];
+               /* bit 63 can be NX.  Bits 62:52 are ignored (for PML4) */
+               entry &= 0x000fffffffffffff;
+
+               if (!PAGE_PRESENT(entry))
+                       return -1;
+               if ((entry & PTE_PS) != 0) {
+                       uint64_t bitmask = ((1 << shift) - 1);
+
+                       *pa = (((uint64_t)va & bitmask) | (entry & ~bitmask));
+                       return 0;
+               }
+               ptptr = (uint64_t *)PG_ADDR(entry);
+       }
+       *pa = ((uint64_t)va & 0xfff) | (uint64_t)ptptr;
+       return 0;
+}
+
+/* Get the RIP as a physical address. */
+int rippa(struct guest_thread *vm_thread, uint64_t *pa)
+{
+       assert(vm_thread != NULL);
+       return gva2gpa(vm_thread, gth_to_vmtf(vm_thread)->tf_rip, pa);
 }