Change map_memory and setup_paging to use virtual_machine struct
authorRonald G. Minnich <rminnich@gmail.com>
Thu, 17 Aug 2017 23:13:40 +0000 (16:13 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Tue, 22 Aug 2017 20:04:41 +0000 (16:04 -0400)
The virtual machine struct now contains guest minphys and maxphys addresses.
Map_memory can be called multiple times.

Setup_page is called with a pointer to the virtual_machine, which sets up
the early 1:1 mapping for the entire range of minphys to maxphys.

This is essentially what we already did, but now we can call map_memory
more than once.

While it may seem odd to to map the whole range from minphys to maxphys,
it's basically ok:
- you rarely call map_memory more than once
- the real check is done in the EPT, not the GPT
- GPT is replaced by most kernels
- in the vthreads case, we will typically start the thread
  memory at 4G, and there will be no holes in that space

So it's probably fine.

Change-Id: I48311bea6f7ae102959247ccad3234a85665b187
Signed-off-by: Ronald G. Minnich <rminnich@gmail.com>
[ 80 char line fix ]
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tests/dune/dune.c
tests/vmm/vmrunkernel.c
user/vmm/include/vmm/vmm.h
user/vmm/memory.c
user/vmm/pagetables.c

index 808c90f..78ee960 100644 (file)
@@ -436,7 +436,7 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       mmap_memory(memstart, memsize);
+       mmap_memory(&vm, memstart, memsize);
 
        if (debug)
                fprintf(stderr, "mmap guest physical memory at %p for 0x%lx bytes\n",
index 9680793..ceaa200 100644 (file)
@@ -545,7 +545,7 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       mmap_memory(memstart, memsize);
+       mmap_memory(vm, memstart, memsize);
 
        entry = load_elf(argv[0], 0);
        if (entry == 0) {
@@ -641,7 +641,7 @@ int main(int argc, char **argv)
        ret = vmm_init(vm, vmmflags);
        assert(!ret);
 
-       cr3 = setup_paging(memstart, memsize, debug);
+       cr3 = setup_paging(vm, debug);
        init_timer_alarms();
 
        vm_tf = gth_to_vmtf(vm->gths[0]);
index 388c2e5..13c673e 100644 (file)
@@ -62,6 +62,13 @@ struct virtual_machine {
        uint8_t                                         *low4k;
        struct virtio_mmio_dev          *virtio_mmio_devices[VIRTIO_MMIO_MAX_NUM_DEV];
 
+       /* minimum and maximum physical memory addresses. When we set up the initial
+        * default page tables we use this range. Note that even if the "physical"
+        * memory has holes, we'll create PTEs for it. This seems enough for now but
+        * we shall see. */
+       uintptr_t                   minphys;
+       uintptr_t                   maxphys;
+
        /* Default root pointer to use if one is not set in a
         * guest thread. We expect this to be the common case,
         * where all guests share a page table. It's not required
@@ -118,9 +125,9 @@ static struct virtual_machine *get_my_vm(void)
 void *init_e820map(struct boot_params *bp,
                    unsigned long long memstart,
                    unsigned long long memsize);
-void checkmemaligned(unsigned long long memstart, unsigned long long memsize);
-void mmap_memory(unsigned long long memstart, unsigned long long memsize);
-void *setup_paging(unsigned long long memstart, unsigned long long memsize,
-                   bool debug);
+void checkmemaligned(uintptr_t memstart, size_t memsize);
+void mmap_memory(struct virtual_machine *vm, uintptr_t memstart,
+                 size_t memsize);
+void *setup_paging(struct virtual_machine *vm, bool debug);
 void *setup_biostables(struct virtual_machine *vm,
                        void *a, void *smbiostable);
index 7469c98..b8593e5 100644 (file)
@@ -88,7 +88,7 @@ void *init_e820map(struct boot_params *bp,
 /* checkmemaligned verifies alignment attributes of your memory space.
  * It terminates your process with extreme prejudice if they are
  * incorrect in some way. */
-void checkmemaligned(unsigned long long memstart, unsigned long long memsize)
+void checkmemaligned(uintptr_t memstart, size_t memsize)
 {
        if (!ALIGNED(memstart, PML1_REACH))
                errx(1, "memstart (%#x) wrong: must be aligned to %#x",
@@ -103,8 +103,9 @@ void checkmemaligned(unsigned long long memstart, unsigned long long memsize)
 // RESERVED to _4GiB for that.  The memory is either split, all low, or all
 // high. This code is designed for a kernel. Dune-style code does not need it
 // as it does not have the RESERVED restrictions. Dune-style code can use this,
-// however, by setting memstart to 4 GiB.
-void mmap_memory(unsigned long long memstart, unsigned long long memsize)
+// however, by setting memstart to 4 GiB. This code can be called multiple
+// times with more ranges. It does not check for overlaps.
+void mmap_memory(struct virtual_machine *vm, uintptr_t memstart, size_t memsize)
 {
        void *r1, *r2;
        unsigned long r1size = memsize;
@@ -135,7 +136,7 @@ void mmap_memory(unsigned long long memstart, unsigned long long memsize)
                        exit(1);
                }
                if (memstart >= _4GiB)
-                       return;
+                       goto done;
        }
 
        r1 = mmap((void *)memstart, r1size,
@@ -146,4 +147,11 @@ void mmap_memory(unsigned long long memstart, unsigned long long memsize)
                        memsize, memstart);
                exit(1);
        }
+
+done:
+       if ((vm->minphys == 0) || (vm->minphys > memstart))
+               vm->minphys = memstart;
+
+       if (vm->maxphys < memstart + memsize - 1)
+               vm->maxphys = memstart + memsize - 1;
 }
index f7da0c5..6a69f89 100644 (file)
@@ -1,7 +1,7 @@
 /* Copyright (c) 2017 Google Inc.
  * See LICENSE for details.
  *
- * Memory, paging, e820, bootparams and other helpers */
+ * Set up paging, using the minphys and maxphys in the vm struct. */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -13,11 +13,12 @@ typedef struct {
        uint64_t pte[512];
 } ptp;
 
-void *setup_paging(unsigned long long memstart, unsigned long long memsize,
-                                  bool debug)
+void *setup_paging(struct virtual_machine *vm, bool debug)
 {
        ptp *p512, *p1, *p2m;
        int nptp, npml4, npml3, npml2;
+       uintptr_t memstart = vm->minphys;
+       size_t memsize = vm->maxphys - vm->minphys + 1;
 
        /* This test is redundant when booting kernels, as it is also
         * performed in memory(), but not all users call that function,