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;
}