VMM: handle EPT page faults Pretty damn simple - just use the real page fault handler, and the EPT is filled in under the hood by all the epte_ ops.
diff --git a/kern/arch/x86/vmm/intel/vmx.c b/kern/arch/x86/vmm/intel/vmx.c index ef0bb45..61d37c9 100644 --- a/kern/arch/x86/vmm/intel/vmx.c +++ b/kern/arch/x86/vmm/intel/vmx.c
@@ -1140,27 +1140,17 @@ 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 @@ } 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;
diff --git a/tests/vmmcp.c b/tests/vmmcp.c index 886c06a..753a60d 100644 --- a/tests/vmmcp.c +++ b/tests/vmmcp.c
@@ -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 @@ static void *fail(void*arg) { + *mmap_blob = 1337; if (mcp) while (V(&shared, int) < 31) { if (! (V(&shared, int) & 1)) @@ -43,7 +46,7 @@ } cpu_relax(); } - printf("All done\n"); + printf("All done, read %d\n", *mmap_blob); return NULL; } @@ -65,6 +68,15 @@ 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 @@ 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; }