vmm: fix gva2gpa PCID mask bug
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 16 May 2019 20:50:33 +0000 (16:50 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 16 May 2019 21:02:33 +0000 (17:02 -0400)
gva2gpa() walks the guest's page table.  It gets the page table from the
cr3.  However, it was not masking the PCID / ASID, so we'd end up
walking incorrectly.

This was a nasty one; after rebasing the linux-guest repo from 4.13 to
5.1, we'd crash during boot.

When Linux touched the IOAPIC, it would appear to fault at
0xffff8880003000000.  Checking the asm and registers showed it was
trying to access the fix_map location for the IOAPIC.  After confirming
the page tables were establish and were in use, I eventually realized
that maybe the Linux setup was fine, and we were making that memory
read, and EPT faulting.

At that point, it was a matter of tracing the execution and seeing
gva2gpa() failed.  At some point, our Linux setup starting using PCIDs,
such that the lower byte was 1.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/vmm/vmx.c

index 7be527d..1d450f8 100644 (file)
@@ -50,7 +50,7 @@ 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);
 {
        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 *ptptr = (uint64_t*)PTE_ADDR(vm_tf->tf_cr3);
        uint64_t entry;
 
        for (int shift = PML4_SHIFT;
        uint64_t entry;
 
        for (int shift = PML4_SHIFT;