VMM: handle EPT page faults
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 2 Apr 2015 14:37:26 +0000 (10:37 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 7 Apr 2015 19:07:00 +0000 (15:07 -0400)
Pretty damn simple - just use the real page fault handler, and the EPT
is filled in under the hood by all the epte_ ops.

kern/arch/x86/vmm/intel/vmx.c
tests/vmmcp.c

index ef0bb45..61d37c9 100644 (file)
@@ -1140,27 +1140,17 @@ static int vmx_handle_ept_violation(struct vmx_vcpu *vcpu)
        exit_qual = vmcs_read32(EXIT_QUALIFICATION);
        gva = vmcs_readl(GUEST_LINEAR_ADDRESS);
        gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
-       printk("ept: gva %016lx, gpa %016lx\n", gva, gpa);
 
        vmx_put_cpu(vcpu);
 
-       // this is a total hack, for testing things.
-       // note that we only care about the gpa, and the
-       // gpa is our process virtual address. 
-       // Confused yet?
-       page = page_lookup(current->env_pgdir, (void *)gpa, NULL);
-       printk("Lookup %p returns %p\n", gpa, page);
-       if (page) {
-               uint64_t hpa = page2pa(page);
-               printk("hpa for %p is %p\n", gpa, hpa);
-               ret = -1;
-               printk("vmx_do_ept_fault returns %d\n", ret);
-       }
+       int prot = 0;
+       prot |= exit_qual & VMX_EPT_FAULT_READ ? PROT_READ : 0;
+       prot |= exit_qual & VMX_EPT_FAULT_WRITE ? PROT_WRITE : 0;
+       prot |= exit_qual & VMX_EPT_FAULT_INS ? PROT_EXEC : 0;
+       ret = handle_page_fault(current, gpa, prot);
 
        if (ret) {
-               printk("page fault failure "
-                      "GPA: 0x%lx, GVA: 0x%lx\n",
-                      gpa, gva);
+               printk("EPT page fault failure GPA: %p, GVA: %p\n", gpa, gva);
                vmx_dump_cpu(vcpu);
        }
 
@@ -1294,7 +1284,7 @@ int vmx_launch(uint64_t rip, uint64_t rsp, uint64_t cr3)
                } else if (ret == EXIT_REASON_EXTERNAL_INTERRUPT) {
                        printk("External interrupt\n");
                } else {
-                       printk("unhandled exit: reason %x, exit qualification %x\n",
+                       printk("unhandled exit: reason 0x%x, exit qualification 0x%x\n",
                               ret, vmcs_read32(EXIT_QUALIFICATION));
                        vmx_dump_cpu(vcpu);
                        vcpu->shutdown = SHUTDOWN_UNHANDLED_EXIT_REASON;
index 886c06a..753a60d 100644 (file)
@@ -10,7 +10,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ros/syscall.h>
+#include <sys/mman.h>
 
+int *mmap_blob;
 unsigned long long stack[1024];
 volatile int shared = 0;
 int mcp = 1;
@@ -19,6 +21,7 @@ int mcp = 1;
 static void *fail(void*arg)
 {
 
+       *mmap_blob = 1337;
        if (mcp)
        while (V(&shared, int) < 31) {
                if (! (V(&shared, int) & 1))
@@ -43,7 +46,7 @@ void *talk_thread(void *arg)
                }
                cpu_relax();
        }
-       printf("All done\n");
+       printf("All done, read %d\n", *mmap_blob);
        return NULL;
 }
 
@@ -65,6 +68,15 @@ int main(int argc, char **argv)
                perror("Guest pcore setup failed");
                exit(1);
        }
+       /* blob that is faulted in from the EPT first.  we need this to be in low
+        * memory (not above the normal mmap_break), so the EPT can look it up.
+        * Note that we won't get 4096.  The min is 1MB now, and ld is there. */
+       mmap_blob = mmap((int*)4096, PGSIZE, PROT_READ | PROT_WRITE,
+                        MAP_ANONYMOUS, -1, 0);
+       if (mmap_blob == MAP_FAILED) {
+               perror("Unable to mmap");
+               exit(1);
+       }
 
        mcp = 1; //argc - 1;
        if (mcp) {
@@ -127,7 +139,7 @@ int main(int argc, char **argv)
        if (ret != strlen(cmd)) {
                perror(cmd);
        }
-       printf("shared is %d\n", shared);
+       printf("shared is %d, blob is %d\n", shared, *mmap_blob);
 
        return 0;
 }