vmm: Moves gpci into guest_thread
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 11 Sep 2017 19:41:08 +0000 (15:41 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 14 Sep 2017 20:38:25 +0000 (16:38 -0400)
It's a minor pain.  GPCI's are coupled 1:1 with guest threads.  However,
the info for their contents comes from vmrunkernel, not from libvmm (yet).
So for now, the GPCIs are passed to libvmm, which will make copies.

Overall, I want to cut down on the amount of lookups for structures based
on guest_pcoreid, since we'll soon have dynamically growing GPC lists.
That will require delicate synchronization, and I only want that in a few
places.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
tests/vmm/vmrunkernel.c
user/vmm/include/vmm/sched.h
user/vmm/include/vmm/vmm.h
user/vmm/sched.c
user/vmm/vmm.c
user/vmm/vthread.c

index 144f0e4..dd32e26 100644 (file)
@@ -273,7 +273,8 @@ void alloc_intr_pages(void)
         * for the PIRs. Each VAPIC and PIR gets its own 4k page. */
        pir = pages + (vm->nr_gpcs * PGSIZE);
 
-       /* Set the addresses in the gpcis. */
+       /* Set the addresses in the gpcis.  These gpcis get copied into the
+        * guest_threads during their construction. */
        for (int i = 0; i < vm->nr_gpcs; i++) {
                gpcis[i].posted_irq_desc = pir + (PGSIZE * i);
                gpcis[i].vapic_addr = pages + (PGSIZE * i);
@@ -299,7 +300,7 @@ void *inject_timer_spurious(void *args)
        uint8_t vector;
 
        for (int i = 0; i < vm->nr_gpcs; i++) {
-               curgpci = &gpcis[i];
+               curgpci = gth_to_gpci(gpcid_to_gth(vm, i));
                vector = ((uint32_t *)curgpci->vapic_addr)[0x32] & 0xff;
                initial_count = ((uint32_t *)curgpci->vapic_addr)[0x38];
                if (initial_count && vector)
@@ -543,10 +544,10 @@ int main(int argc, char **argv)
        // Set vm->nr_gpcs before it's referenced in the struct setups below.
        vm->nr_gpcs = num_pcs;
        fprintf(stderr, "NUM PCS: %d\n", num_pcs);
+       /* These are only used to be passed to vmm_init, which makes copies
+        * internally */
        gpcis = (struct vmm_gpcore_init *)
                        malloc(num_pcs * sizeof(struct vmm_gpcore_init));
-       vm->gpcis = gpcis;
-
        alloc_intr_pages();
 
        memend = memstart + memsize - 1;
@@ -685,8 +686,9 @@ int main(int argc, char **argv)
        cmdlinesz -= len;
        cmdlinep += len;
 
-       ret = vmm_init(vm, vmmflags);
+       ret = vmm_init(vm, gpcis, vmmflags);
        assert(!ret);
+       free(gpcis);
 
        init_timer_alarms();
 
index ae76a9d..1adad6b 100644 (file)
@@ -7,6 +7,7 @@
 #pragma once
 
 #include <parlib/uthread.h>
+#include <ros/arch/vmm.h>
 #include <sys/queue.h>
 
 __BEGIN_DECLS
@@ -34,6 +35,7 @@ struct guest_thread {
        uth_mutex_t                                     *halt_mtx;
        uth_cond_var_t                          *halt_cv;
        unsigned long                           nr_vmexits;
+       struct vmm_gpcore_init          gpci;
        void                                            *user_data;
        // TODO: work out a real ops strategy.
        bool (*vmcall)(struct guest_thread *gth, struct vm_trapframe *);
@@ -82,7 +84,8 @@ extern int vmm_sched_period_usec;
  * this initializer.
  *
  * Returns 0 on success, -1 o/w. */
-int vmm_init(struct virtual_machine *vm, int flags);
+int vmm_init(struct virtual_machine *vm, struct vmm_gpcore_init *gpcis,
+             int flags);
 /* Starts a guest thread/core. */
 void start_guest_thread(struct guest_thread *gth);
 /* Start and run a task thread. */
index 9e39337..4c558d2 100644 (file)
@@ -54,7 +54,6 @@ struct virtual_machine {
         * up_gpcs refers to the number of guest pcores that have
         * been started so far. */
        unsigned int                            up_gpcs;
-       struct vmm_gpcore_init          *gpcis;
        bool                                            vminit;
 
        /* TODO: put these in appropriate structures.  e.g., virtio things in
@@ -121,9 +120,7 @@ static struct vm_trapframe *gth_to_vmtf(struct guest_thread *gth)
 
 static struct vmm_gpcore_init *gth_to_gpci(struct guest_thread *gth)
 {
-       struct virtual_machine *vm = gth_to_vm(gth);
-
-       return &vm->gpcis[gth->gpc_id];
+       return &gth->gpci;
 }
 
 static struct guest_thread *gpcid_to_gth(struct virtual_machine *vm,
index ac51a5f..e9d8ab8 100644 (file)
@@ -493,7 +493,8 @@ static void destroy_guest_thread(struct guest_thread *gth)
 }
 
 static struct guest_thread *create_guest_thread(struct virtual_machine *vm,
-                                                unsigned int gpcoreid)
+                                                unsigned int gpcoreid,
+                                                struct vmm_gpcore_init *gpci)
 {
        struct guest_thread *gth;
        struct ctlr_thread *cth;
@@ -512,6 +513,7 @@ static struct guest_thread *create_guest_thread(struct virtual_machine *vm,
        gth->buddy = cth;
        cth->buddy = gth;
        gth->gpc_id = gpcoreid;
+       gth->gpci = *gpci;
        cth->stacksize = VMM_THR_STACKSIZE;
        cth->stacktop = __alloc_stack(cth->stacksize);
        if (!cth->stacktop) {
@@ -560,7 +562,8 @@ static void ev_handle_diag(struct event_msg *ev_msg, unsigned int ev_type,
                atomic_read(&nr_unblk_guests), atomic_read(&nr_unblk_tasks));
 }
 
-int vmm_init(struct virtual_machine *vm, int flags)
+int vmm_init(struct virtual_machine *vm, struct vmm_gpcore_init *gpcis,
+             int flags)
 {
        struct guest_thread **gths;
 
@@ -574,9 +577,9 @@ int vmm_init(struct virtual_machine *vm, int flags)
         * CPUID[0x1] will not have to total number of cores.  If we move that
         * handler to userspace, we can create the SMP-booted GPCs on the fly.
         *
-        * We'd also have to deal with gths[] and gpcis[] growing dynamically, which
-        * would require synchronization. */
-       if (syscall(SYS_vmm_add_gpcs, vm->nr_gpcs, vm->gpcis) != vm->nr_gpcs)
+        * We'd also have to deal with gths[] growing dynamically, which would
+        * require synchronization. */
+       if (syscall(SYS_vmm_add_gpcs, vm->nr_gpcs, gpcis) != vm->nr_gpcs)
                return -1;
        if (flags) {
                if (syscall(SYS_vmm_ctl, VMM_CTL_SET_FLAGS, flags))
@@ -586,7 +589,7 @@ int vmm_init(struct virtual_machine *vm, int flags)
        if (!gths)
                return -1;
        for (int i = 0; i < vm->nr_gpcs; i++) {
-               gths[i] = create_guest_thread(vm, i);
+               gths[i] = create_guest_thread(vm, i, &gpcis[i]);
                if (!gths[i]) {
                        for (int j = 0; j < i; j++)
                                destroy_guest_thread(gths[j]);
index ac83066..7db2856 100644 (file)
@@ -24,7 +24,7 @@ int vmm_interrupt_guest(struct virtual_machine *vm, unsigned int gpcoreid,
                return -1;
        }
        gth = vm->gths[gpcoreid];
-       gpci = &vm->gpcis[gpcoreid];
+       gpci = gth_to_gpci(gth);
        /* The OUTSTANDING_NOTIF bit (256) is one greater than the last valid
         * descriptor */
        if (vector >= VMX_POSTED_OUTSTANDING_NOTIF) {
index fff963e..98982b8 100644 (file)
@@ -29,6 +29,7 @@ static int vmsetup(struct virtual_machine *vm, int flags)
        struct vm_trapframe *vm_tf;
        int i, ret;
        uint8_t *p;
+       struct vmm_gpcore_init *gpcis;
 
        if (vm->vminit)
                return -EBUSY;
@@ -36,7 +37,7 @@ static int vmsetup(struct virtual_machine *vm, int flags)
        if (vm->nr_gpcs == 0)
                vm->nr_gpcs = 1;
 
-       vm->gpcis = calloc(vm->nr_gpcs, sizeof(*vm->gpcis));
+       gpcis = calloc(vm->nr_gpcs, sizeof(struct vmm_gpcore_init));
 
        /* technically, we don't need these pages for the
         * all guests. Currently, the kernel requires them. */
@@ -46,21 +47,22 @@ static int vmsetup(struct virtual_machine *vm, int flags)
                        werrstr("Can't allocate 3 pages for guest %d: %r", i);
                        return -1;
                }
-               vm->gpcis[i].posted_irq_desc = &p[0];
-               vm->gpcis[i].vapic_addr = &p[4096];
-               vm->gpcis[i].apic_addr = &p[8192];
+               gpcis[i].posted_irq_desc = &p[0];
+               gpcis[i].vapic_addr = &p[4096];
+               gpcis[i].apic_addr = &p[8192];
                /* TODO: once we are making these GPCs at the same time as vthreads, we
                 * should set fsbase == the TLS desc of the vthread (if any). */
-               vm->gpcis[i].fsbase = 0;
-               vm->gpcis[i].gsbase = 0;
+               gpcis[i].fsbase = 0;
+               gpcis[i].gsbase = 0;
        }
 
        /* Set up default page mappings. */
        setup_paging(vm);
 
-       ret = vmm_init(vm, flags);
+       ret = vmm_init(vm, gpcis, flags);
        if (ret)
                return ret;
+       free(gpcis);
 
        for (i = 0; i < vm->nr_gpcs; i++) {
                vm->gths[i]->halt_exit = vm->halt_exit;