Copying out the image sort of works
authorRonald G. Minnich <rminnich@google.com>
Fri, 10 Jan 2014 23:57:36 +0000 (15:57 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Fri, 17 Jan 2014 22:57:12 +0000 (14:57 -0800)
I know I can copy out one page, anyway.

Signed-off-by: Ronald G. Minnich <rminnich@google.com>
kern/arch/x86/vmx.c
kern/drivers/dev/vm.c

index c7814a6..8192e4d 100644 (file)
@@ -513,7 +513,7 @@ struct litevm *vmx_open(void)
        if (!litevm)
                return 0;
 
-       spinlock_init(&litevm->lock);
+       spinlock_init_irqsave(&litevm->lock);
        LIST_INIT(&litevm->link);
        for (i = 0; i < LITEVM_MAX_VCPUS; ++i) {
                struct litevm_vcpu *vcpu = &litevm->vcpus[i];
@@ -522,6 +522,8 @@ struct litevm *vmx_open(void)
                vcpu->mmu.root_hpa = INVALID_PAGE;
                LIST_INIT(&vcpu->link);
        }
+       printk("vmx_open: busy %d\n", litevm->busy);
+       printk("return %p\n", litevm);
        return litevm;
 }
 
@@ -847,7 +849,7 @@ static int pdptrs_have_reserved_bits_set(struct litevm_vcpu *vcpu,
        uint64_t *pdpt;
        struct litevm_memory_slot *memslot;
 
-       spin_lock(&vcpu->litevm->lock);
+       spin_lock_irqsave(&vcpu->litevm->lock);
        memslot = gfn_to_memslot(vcpu->litevm, pdpt_gfn);
        /* FIXME: !memslot - emulate? 0xff? */
        pdpt = page2kva(gfn_to_page(memslot, pdpt_gfn));
@@ -969,7 +971,7 @@ static void set_cr4(struct litevm_vcpu *vcpu, unsigned long cr4)
                return;
        }
        __set_cr4(vcpu, cr4);
-       spin_lock(&vcpu->litevm->lock);
+       spin_lock_irqsave(&vcpu->litevm->lock);
        litevm_mmu_reset_context(vcpu);
        spin_unlock(&vcpu->litevm->lock);
 }
@@ -998,7 +1000,7 @@ static void set_cr3(struct litevm_vcpu *vcpu, unsigned long cr3)
        }
 
        vcpu->cr3 = cr3;
-       spin_lock(&vcpu->litevm->lock);
+       spin_lock_irqsave(&vcpu->litevm->lock);
        vcpu->mmu.new_cr3(vcpu);
        spin_unlock(&vcpu->litevm->lock);
 }
@@ -1401,7 +1403,18 @@ int vm_set_memory_region(struct litevm *litevm,
        struct litevm_memory_slot old, new;
        int memory_config_version;
        void *init_data = mem->init_data;
+       int pass = 1;
 
+       printk("litevm %p\n", litevm);
+       /* should not happen but ... */
+       if (! litevm)
+               error("NULL litevm in %s", __func__);
+
+       if (!mem)
+               error("NULL mem in %s", __func__);
+
+       if (litevm->busy)
+               error("litevm->busy is set! 0x%x\n", litevm->busy);
        r = -EINVAL;
        /* General sanity checks */
        if (mem->memory_size & (PAGE_SIZE - 1))
@@ -1427,7 +1440,9 @@ int vm_set_memory_region(struct litevm *litevm,
         * allocation of a bunch of pages for us.
         */
 raced:
-       spin_lock(&litevm->lock);
+       printk("raced: pass %d\n", pass);
+       spin_lock_irqsave(&litevm->lock);
+       printk("locked\n");
 
        if (waserror()){
                spin_unlock(&litevm->lock);
@@ -1463,6 +1478,7 @@ raced:
         * detect any races.
         */
        spin_unlock(&litevm->lock);
+       printk("unlocked\n");
        poperror();
 
        /* Deallocate if slot is being removed */
@@ -1488,6 +1504,8 @@ raced:
                        if (ret != ESUCCESS)
                                goto out_free;
                        if (init_data){
+                               printk("init data memcpy(%p,%p,4096);\n",
+                                      page2kva(new.phys_mem[i]), init_data);
                                memcpy(page2kva(new.phys_mem[i]), init_data, PAGE_SIZE);
                                init_data += PAGE_SIZE;
                        }
@@ -1500,21 +1518,26 @@ raced:
                dirty_bytes = (((npages + BITS_PER_LONG-1)/BITS_PER_LONG)*BITS_PER_LONG)/8;
 
                new.dirty_bitmap = kzmalloc(dirty_bytes, KMALLOC_WAIT);
-               if (!new.dirty_bitmap)
+               if (!new.dirty_bitmap){
+                       printk("VM: alloc of %d bytes for map failed\n", dirty_bytes);
                        goto out_free;
+               }
        }
 
-       spin_lock(&litevm->lock);
-
+       spin_lock_irqsave(&litevm->lock);
+       printk("locked\n");
        if (memory_config_version != litevm->memory_config_version) {
                spin_unlock(&litevm->lock);
+               printk("unlocked, try again\n");
                litevm_free_physmem_slot(&new, &old);
                goto raced;
        }
 
        r = -EAGAIN;
-       if (litevm->busy)
+       if (litevm->busy){
+               printk("BUSY!\n");
                goto out_unlock;
+       }
 
        if (mem->slot >= litevm->nmemslots)
                litevm->nmemslots = mem->slot + 1;
@@ -1523,7 +1546,7 @@ raced:
        ++litevm->memory_config_version;
 
        spin_unlock(&litevm->lock);
-
+       printk("unlocked\n");
        for (i = 0; i < LITEVM_MAX_VCPUS; ++i) {
                struct litevm_vcpu *vcpu;
 
@@ -1540,7 +1563,6 @@ raced:
 out_unlock:
        spin_unlock(&litevm->lock);
        printk("out_unlock\n");
-       error("well, something went badly.");
 out_free:
        printk("out_free\n");
        litevm_free_physmem_slot(&new, &old);
@@ -1561,7 +1583,7 @@ static int litevm_dev_ioctl_get_dirty_log(struct litevm *litevm,
        int n;
        unsigned long any = 0;
 
-       spin_lock(&litevm->lock);
+       spin_lock_irqsave(&litevm->lock);
 
        /*
         * Prevent changes to guest memory configuration even while the lock
@@ -1589,7 +1611,7 @@ static int litevm_dev_ioctl_get_dirty_log(struct litevm *litevm,
 
 
        if (any) {
-               spin_lock(&litevm->lock);
+               spin_lock_irqsave(&litevm->lock);
                litevm_mmu_slot_remove_write_access(litevm, log->slot);
                spin_unlock(&litevm->lock);
                memset(memslot->dirty_bitmap, 0, n);
@@ -1606,7 +1628,7 @@ static int litevm_dev_ioctl_get_dirty_log(struct litevm *litevm,
        r = 0;
 
 out:
-       spin_lock(&litevm->lock);
+       spin_lock_irqsave(&litevm->lock);
        --litevm->busy;
        spin_unlock(&litevm->lock);
        return r;
@@ -1982,7 +2004,7 @@ static int handle_exception(struct litevm_vcpu *vcpu, struct litevm_run *litevm_
        if (is_page_fault(intr_info)) {
                cr2 = vmcs_readl(EXIT_QUALIFICATION);
 
-               spin_lock(&vcpu->litevm->lock);
+               spin_lock_irqsave(&vcpu->litevm->lock);
                if (!vcpu->mmu.page_fault(vcpu, cr2, error_code)) {
                        spin_unlock(&vcpu->litevm->lock);
                        return 1;
@@ -2107,7 +2129,7 @@ static int handle_invlpg(struct litevm_vcpu *vcpu, struct litevm_run *litevm_run
 {
        uint64_t address = vmcs_read64(EXIT_QUALIFICATION);
        int instruction_length = vmcs_read32(VM_EXIT_INSTRUCTION_LEN);
-       spin_lock(&vcpu->litevm->lock);
+       spin_lock_irqsave(&vcpu->litevm->lock);
        vcpu->mmu.inval_page(vcpu, address);
        spin_unlock(&vcpu->litevm->lock);
        vmcs_writel(GUEST_RIP, vmcs_readl(GUEST_RIP) + instruction_length);
@@ -3063,7 +3085,7 @@ static int litevm_dev_ioctl_translate(struct litevm *litevm, struct litevm_trans
        vcpu = vcpu_load(litevm, tr->vcpu);
        if (!vcpu)
                return -ENOENT;
-       spin_lock(&litevm->lock);
+       spin_lock_irqsave(&litevm->lock);
        gpa = vcpu->mmu.gva_to_gpa(vcpu, vaddr);
        tr->physical_address = gpa;
        tr->valid = gpa != UNMAPPED_GVA;
index cc3deb8..f7adb98 100644 (file)
@@ -43,7 +43,7 @@ enum {
  * into the qid, but this works for now.
  */
 #define ADDR_SHIFT 5
-#define QID2VM(q) ((struct proc_alarm*)KADDR(((q).path >> ADDR_SHIFT)))
+#define QID2VM(q) ((struct vm*)KADDR(((q).path >> ADDR_SHIFT)))
 #define TYPE(q) ((q).path & ((1 << ADDR_SHIFT) - 1))
 #define QID(ptr, type) ((PADDR(ptr) << ADDR_SHIFT) | type)
 
@@ -92,10 +92,15 @@ readn(struct chan *c, void *vp, long n)
 static void vm_release(struct kref *kref)
 {
        struct vm *v = container_of(kref, struct vm, kref);
-       spin_lock(&vmlock);
+       spin_lock_irqsave(&vmlock);
        /* cute trick. Save the last element of the array in place of the
         * one we're deleting. Reduce nvm. Don't realloc; that way, next
-        * time we add a vm the allocator will just return. */
+        * time we add a vm the allocator will just return.
+        * Well, this is stupid, because when we do this, we break
+        * the QIDs, which have pointers embedded in them.
+        * darn it, may have to use a linked list. Nope, will probably
+        * just walk the array until we find a matching id. Still ... yuck.
+        */
        if (v != &vms[nvm-1]){
                /* free the image ... oops */
                /* get rid of the kref. */
@@ -108,7 +113,7 @@ static void vm_release(struct kref *kref)
 static int newvmid(void)
 {
        int id;
-       spin_lock(vmidlock);
+       spin_lock_irqsave(vmidlock);
        id = kref_refcnt(vmid);
        kref_get(vmid, 1);
        spin_unlock(vmidlock);
@@ -146,7 +151,7 @@ static int vmgen(struct chan *c, char *entry_name,
                        return 1;
                }
                s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
-               spin_lock(&vmlock);
+               spin_lock_irqsave(&vmlock);
                if (s >= nvm){
                        printd("DONE qtopdir\n");
                        spin_unlock(&vmlock);
@@ -202,8 +207,8 @@ static int vmgen(struct chan *c, char *entry_name,
 static void vminit(void)
 {
        int i;
-       spinlock_init(&vmlock);
-       spinlock_init(vmidlock);
+       spinlock_init_irqsave(&vmlock);
+       spinlock_init_irqsave(vmidlock);
        i = vmx_init();
        printk("vminit: litevm_init returns %d\n", i);
 
@@ -232,7 +237,8 @@ static int vmstat(struct chan *c, uint8_t *db, int n)
 static struct chan *vmopen(struct chan *c, int omode)
 {
        ERRSTACK(2);
-       struct vm *v = c->aux;
+       struct vm *v = QID2VM(c->qid);
+       printk("vmopen: v is %p\n", v);
        if (waserror()){
                nexterror();
        }
@@ -245,7 +251,7 @@ static struct chan *vmopen(struct chan *c, int omode)
                        error(Eisdir);
                break;
        case Qclone:
-               spin_lock(&vmlock);
+               spin_lock_irqsave(&vmlock);
                vms = krealloc(vms, sizeof(vms[0])*(nvm+1),0);
                v = &vms[nvm];
                nvm++;
@@ -265,8 +271,8 @@ static struct chan *vmopen(struct chan *c, int omode)
                break;
        case Qctl:
        case Qimage:
-               /* the purpose of opening is to hold a kref on the proc_vm */
-               v = c->aux;
+               c->aux = QID2VM(c->qid);
+               printk("open qctl: aux is %p\n", c->aux);
                break;
        }
        c->mode = openmode(omode);
@@ -340,7 +346,8 @@ static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
        ERRSTACK(3);
        char buf[32];
        struct cmdbuf *cb;
-       struct litevm *vm;
+       struct vm *vm;
+       struct litevm *litevm;
        uint64_t hexval;
        printd("vmwrite(%p, %p, %d)\n", c, ubuf, n);
        switch (TYPE(c->qid)) {
@@ -363,6 +370,7 @@ static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
                        struct chan *file;
                        void *v;
                        vm = c->aux;
+                       litevm = vm->archvm;
                        uint64_t filesize;
                        struct litevm_memory_region vmr;
                        int got;
@@ -394,7 +402,7 @@ static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
                        readn(file, v, filesize);
                        vmr.init_data = v;
 
-                       if (vm_set_memory_region(vm, &vmr))
+                       if (vm_set_memory_region(litevm, &vmr))
                                error("vm_set_memory_region failed");
                        poperror();
                        poperror();
@@ -404,13 +412,14 @@ static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
                } else if (!strcmp(cb->f[0], "region")) {
                        void *v;
                        struct litevm_memory_region vmr;
+                       litevm = vm->archvm;
                        if (cb->nf != 5)
                                error("usage: mapmem slot flags addr size");
                        vmr.slot = strtoul(cb->f[2], NULL, 0);
                        vmr.flags = strtoul(cb->f[3], NULL, 0);
                        vmr.guest_phys_addr = strtoul(cb->f[4], NULL, 0);
                        vmr.memory_size = strtoul(cb->f[5], NULL, 0);
-                       if (vm_set_memory_region(vm, &vmr))
+                       if (vm_set_memory_region(litevm, &vmr))
                                error("vm_set_memory_region failed");
                } else {
                        error("%s: not implemented", cb->f[0]);