More debugging for VMs.
authorRonald G. Minnich <rminnich@google.com>
Sat, 8 Feb 2014 01:47:04 +0000 (17:47 -0800)
committerRonald G. Minnich <rminnich@google.com>
Sat, 8 Feb 2014 01:47:04 +0000 (17:47 -0800)
Remove some of the chattier bits.

Add a new file, kern/kfs/bin/POR, which is a representation of
the F (bios) segment with one instruction, HLT.

Fix an incorrect test in root which would not allow the kernel to
read files (the check for user addresses should be in the system call).

Still not quite there.

Signed-off-by: Ronald G. Minnich <rminnich@google.com>
kern/arch/x86/vmx.c
kern/arch/x86/vmx_mmu.c
kern/drivers/dev/root.c
kern/drivers/dev/vm.c
kern/kfs/bin/POR [new file with mode: 0644]
kern/kfs/runvm

index 9715e7f..5e2568c 100644 (file)
 #define GDT_ENTRY_TSS 0x24
 
 #define currentcpu (&per_cpu_info[core_id()])
-#define QLOCK_init(x) {printk("qlock_init %p\n", x); qlock_init(x); printk("%p lock_inited\n", x);}
-#define QLOCK(x) {printk("qlock %p\n", x); qlock(x); printk("%p locked\n", x);}
-#define QUNLOCK(x) {printk("qunlock %p\n", x); qunlock(x); printk("%p unlocked\n", x);}
-#define SPLI_irqsave(x){printk("spin_lock_init %p:", x); spinlock_init(x); printk("inited\n");}
-#define SPLL(x){printk("spin_lock %p\n", x); spin_lock_irqsave(x); printk("%p locked\n", x);}
-#define SPLU(x){printk("spin_unlock %p\n", x); spin_unlock(x); printk("%p unlocked\n", x);}
+#define QLOCK_init(x) {printd("qlock_init %p\n", x); qlock_init(x); printd("%p lock_inited\n", x);}
+#define QLOCK(x) {printd("qlock %p\n", x); qlock(x); printd("%p locked\n", x);}
+#define QUNLOCK(x) {printd("qunlock %p\n", x); qunlock(x); printd("%p unlocked\n", x);}
+#define SPLI_irqsave(x){printd("spin_lock_init %p:", x); spinlock_init(x); printd("inited\n");}
+#define SPLL(x){printd("spin_lock %p\n", x); spin_lock_irqsave(x); printd("%p locked\n", x);}
+#define SPLU(x){printd("spin_unlock %p\n", x); spin_unlock(x); printd("%p unlocked\n", x);}
 struct litevm_stat litevm_stat;
 
 static struct litevm_stats_debugfs_item {
@@ -755,17 +755,14 @@ static int litevm_dev_release(struct litevm *litevm)
 
 unsigned long vmcs_readl(unsigned long field)
 {
-       print_func_entry();
        unsigned long value;
 
        asm volatile ("vmread %1, %0":"=g" (value):"r"(field):"cc");
-       print_func_exit();
        return value;
 }
 
 void vmcs_writel(unsigned long field, unsigned long value)
 {
-       print_func_entry();
        uint8_t error;
 
        asm volatile ("vmwrite %1, %2; setna %0":"=g" (error):"r"(value),
@@ -773,14 +770,11 @@ void vmcs_writel(unsigned long field, unsigned long value)
        if (error)
                printk("vmwrite error: reg %lx value %lx (err %d)\n",
                           field, value, vmcs_read32(VM_INSTRUCTION_ERROR));
-       print_func_exit();
 }
 
 static void vmcs_write16(unsigned long field, uint16_t value)
 {
-       print_func_entry();
        vmcs_writel(field, value);
-       print_func_exit();
 }
 
 static void vmcs_write64(unsigned long field, uint64_t value)
@@ -1259,7 +1253,6 @@ static void fx_init(struct litevm_vcpu *vcpu)
 static void vmcs_write32_fixedbits(uint32_t msr, uint32_t vmcs_field,
                                                                   uint32_t val)
 {
-       print_func_entry();
        uint32_t msr_high, msr_low;
        uint64_t msrval;
 
@@ -1270,7 +1263,6 @@ static void vmcs_write32_fixedbits(uint32_t msr, uint32_t vmcs_field,
        val &= msr_high;
        val |= msr_low;
        vmcs_write32(vmcs_field, val);
-       print_func_exit();
 }
 
 /*
@@ -1637,8 +1629,10 @@ int vm_set_memory_region(struct litevm *litevm,
        int memory_config_version;
        void *init_data = mem->init_data;
        int pass = 1;
-
-       printk("litevm %p\n", litevm);
+       printk("%s: slot %d base %08x npages %d\n", 
+               __func__, 
+              mem->slot, mem->guest_phys_addr, 
+              mem->memory_size);
        /* should not happen but ... */
        if (!litevm)
                error("NULL litevm in %s", __func__);
@@ -1677,6 +1671,7 @@ int vm_set_memory_region(struct litevm *litevm,
 raced:
        printk("raced: pass %d\n", pass);
        printk("LOCK %p, locked %d\n", &litevm->lock, spin_locked(&litevm->lock));
+       void monitor(void *);
        monitor(NULL);
        SPLL(&litevm->lock);
        printk("locked\n");
@@ -1705,7 +1700,7 @@ raced:
        r = -EEXIST;
        for (i = 0; i < LITEVM_MEMORY_SLOTS; ++i) {
                struct litevm_memory_slot *s = &litevm->memslots[i];
-
+printk("Region %d: base gfn 0x%x npages %d\n", s->base_gfn, s->npages);
                if (s == memslot)
                        continue;
                if (!((base_gfn + npages <= s->base_gfn) ||
@@ -2285,6 +2280,8 @@ static int handle_exception(struct litevm_vcpu *vcpu,
 
        vect_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
        intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+printk("vect_info %x intro_info %x\n", vect_info, intr_info);
+printk("page fault? %d\n", is_page_fault(intr_info));
 
        if ((vect_info & VECTORING_INFO_VALID_MASK) && !is_page_fault(intr_info)) {
                printk("%s: unexpected, vectoring info 0x%x "
@@ -2292,6 +2289,7 @@ static int handle_exception(struct litevm_vcpu *vcpu,
        }
 
        if (is_external_interrupt(vect_info)) {
+printk("extern interrupt\n");
                int irq = vect_info & VECTORING_INFO_VECTOR_MASK;
                SET_BITMASK_BIT_ATOMIC(((uint8_t *) & vcpu->irq_pending), irq);
                SET_BITMASK_BIT_ATOMIC(((uint8_t *) & vcpu->irq_summary),
@@ -2299,15 +2297,18 @@ static int handle_exception(struct litevm_vcpu *vcpu,
        }
 
        if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) {  /* nmi */
+printk("nmi\n");
                asm("int $2");
                print_func_exit();
                return 1;
        }
        error_code = 0;
        rip = vmcs_readl(GUEST_RIP);
+printk("GUEST_RIP %x\n", rip);
        if (intr_info & INTR_INFO_DELIEVER_CODE_MASK)
                error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
        if (is_page_fault(intr_info)) {
+printk("PAGE FAULT!\n");
                cr2 = vmcs_readl(EXIT_QUALIFICATION);
 
                SPLL(&vcpu->litevm->lock);
@@ -2340,6 +2341,7 @@ static int handle_exception(struct litevm_vcpu *vcpu,
        if (vcpu->rmode.active &&
                handle_rmode_exception(vcpu, intr_info & INTR_INFO_VECTOR_MASK,
                                                           error_code)) {
+           printk("RMODE EXCEPTION might have been handled\n");
                print_func_exit();
                return 1;
        }
index e131b86..651d4cc 100644 (file)
@@ -764,13 +764,9 @@ static int alloc_mmu_pages(struct litevm_vcpu *vcpu)
 
                if (kpage_alloc(&page) != ESUCCESS)
                        goto error_1;
-               printk("page_header %p, page %p\n", page_header, page);
                page->pg_private = page_header;
-               printk("page2ppn(page) is %lx\n", page2ppn(page));
                page_header->page_hpa = (hpa_t) page2pa(page);
-               printk("page_hpa is %lx\n", page_header->page_hpa);
                memset(KADDR(page_header->page_hpa), 0, PAGE_SIZE);
-               printk("INSERT\n");
                LIST_INSERT_HEAD(&vcpu->link, page_header, link);
        }
        print_func_exit();
index 68eefd8..5edd579 100644 (file)
@@ -365,13 +365,11 @@ static long rootread(struct chan *c, void *buf, long n, int64_t offset)
        if (offset + n > len)
                n = len - offset;
        data = rootdata[p].ptr;
-       /* we might call read from the kernel (load_elf()) */
-       if (current) {
-               if (memcpy_to_user_errno(current, buf, data + offset, n) < 0)
-                       error("%s: bad user addr %p", __FUNCTION__, buf);
-       } else {
-               memcpy(buf, data + offset, n);
-       }
+       /* we can't really claim it has to be a user address. Lots of
+        * kernel things read directly, e.g. /dev/reboot, #V, etc.
+        * Address validation should be done in the syscall layer.
+        */
+       memcpy(buf, data + offset, n);
        return n;
 }
 
index 0554b45..f331b84 100644 (file)
@@ -81,7 +81,7 @@ static inline int QID(int index, int type)
 /* we'll need this somewhere more generic. */
 static void readn(struct chan *c, void *vp, long n)
 {
-       print_func_entry();
+       //print_func_entry();
        char *p;
        long nn;
        int total = 0, want = n;
@@ -97,13 +97,13 @@ static void readn(struct chan *c, void *vp, long n)
                n -= nn;
                total += nn;
        }
-       print_func_exit();
+       //print_func_exit();
 }
 
 /* not called yet.  -- we have to unlink the vm */
 static void vm_release(struct kref *kref)
 {
-       print_func_entry();
+       //print_func_entry();
        struct vm *v = container_of(kref, struct vm, kref);
        spin_lock_irqsave(&vmlock);
        /* cute trick. Save the last element of the array in place of the
@@ -121,7 +121,7 @@ static void vm_release(struct kref *kref)
        }
        nvm--;
        spin_unlock(&vmlock);
-       print_func_exit();
+       //print_func_exit();
 }
 
 /* VM ids run in the range 1..infinity. But vmx.c wants them
@@ -129,13 +129,13 @@ static void vm_release(struct kref *kref)
  */
 static int newvmid(void)
 {
-       print_func_entry();
+       //print_func_entry();
        int id;
        spin_lock_irqsave(vmidlock);
        id = kref_refcnt(vmid);
        kref_get(vmid, 1);
        spin_unlock(vmidlock);
-       print_func_exit();
+       //print_func_exit();
        return id - 1;
 }
 
@@ -143,7 +143,7 @@ static int vmgen(struct chan *c, char *entry_name,
                                 struct dirtab *unused, int unused_nr_dirtab,
                                 int s, struct dir *dp)
 {
-       print_func_entry();
+       //print_func_entry();
        struct qid q;
        struct vm *vm_i;
        printd("GEN s %d\n", s);
@@ -151,7 +151,7 @@ static int vmgen(struct chan *c, char *entry_name,
        if (s == DEVDOTDOT) {
                mkqid(&q, Qtopdir, 0, QTDIR);
                devdir(c, c->qid, "#V", 0, eve, 0555, dp);
-               print_func_exit();
+               //print_func_exit();
                return 1;
        }
        printd("TYPE %d\n", TYPE(c->qid));
@@ -163,14 +163,14 @@ static int vmgen(struct chan *c, char *entry_name,
                        if (s == 0) {
                                mkqid(&q, Qclone, 0, QTFILE);
                                devdir(c, q, "clone", 0, eve, 0666, dp);
-                               print_func_exit();
+                               //print_func_exit();
                                return 1;
                        }
                        s--;
                        if (s == 0) {
                                mkqid(&q, Qstat, 0, QTFILE);
                                devdir(c, q, "stat", 0, eve, 0666, dp);
-                               print_func_exit();
+                               //print_func_exit();
                                return 1;
                        }
                        s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
@@ -178,16 +178,15 @@ static int vmgen(struct chan *c, char *entry_name,
                        if (s >= nvm) {
                                printd("DONE qtopdir\n");
                                spin_unlock(&vmlock);
-                               print_func_exit();
+                               //print_func_exit();
                                return -1;
                        }
                        vm_i = &vms[s];
                        snprintf(get_cur_genbuf(), GENBUF_SZ, "vm%d", vm_i->id);
                        spin_unlock(&vmlock);
-                       printk("clone vm_i is %p\n", vm_i);
                        mkqid(&q, QID(s, Qvmdir), 0, QTDIR);
                        devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
-                       print_func_exit();
+                       //print_func_exit();
                        return 1;
                case Qvmdir:
                        /* Gen the contents of the vm dirs */
@@ -196,15 +195,15 @@ static int vmgen(struct chan *c, char *entry_name,
                                case Qctl:
                                        mkqid(&q, QID(s-Qctl, Qctl), 0, QTFILE);
                                        devdir(c, q, "ctl", 0, eve, 0666, dp);
-                                       print_func_exit();
+                                       //print_func_exit();
                                        return 1;
                                case Qimage:
                                        mkqid(&q, QID(s-Qctl, Qimage), 0, QTFILE);
                                        devdir(c, q, "image", 0, eve, 0666, dp);
-                                       print_func_exit();
+                                       //print_func_exit();
                                        return 1;
                        }
-                       print_func_exit();
+                       //print_func_exit();
                        return -1;
                        /* Need to also provide a direct hit for Qclone and all other files (at
                         * all levels of the hierarchy).  Every file is both
@@ -219,28 +218,28 @@ static int vmgen(struct chan *c, char *entry_name,
                         * stat output (check the -1 case in devstat). */
                case Qclone:
                        devdir(c, c->qid, "clone", 0, eve, 0666, dp);
-                       print_func_exit();
+                       //print_func_exit();
                        return 1;
                case Qstat:
                        devdir(c, c->qid, "stat", 0, eve, 0444, dp);
-                       print_func_exit();
+                       //print_func_exit();
                        return 1;
                case Qctl:
                        devdir(c, c->qid, "ctl", 0, eve, 0666, dp);
-                       print_func_exit();
+                       //print_func_exit();
                        return 1;
                case Qimage:
                        devdir(c, c->qid, "image", 0, eve, 0666, dp);
-                       print_func_exit();
+                       //print_func_exit();
                        return 1;
        }
-       print_func_exit();
+       //print_func_exit();
        return -1;
 }
 
 static void vminit(void)
 {
-       print_func_entry();
+       //print_func_entry();
        int i;
        spinlock_init_irqsave(&vmlock);
        spinlock_init_irqsave(vmidlock);
@@ -249,32 +248,32 @@ static void vminit(void)
                vmok = 1;
        printk("vminit: litevm_init returns %d\n", i);
 
-       print_func_exit();
+       //print_func_exit();
 }
 
 static struct chan *vmattach(char *spec)
 {
-       print_func_entry();
+       //print_func_entry();
        if (!vmok)
                error("No VMs available");
        struct chan *c = devattach('V', spec);
        mkqid(&c->qid, Qtopdir, 0, QTDIR);
-       print_func_exit();
+       //print_func_exit();
        return c;
 }
 
 static struct walkqid *vmwalk(struct chan *c, struct chan *nc, char **name,
                                                          int nname)
 {
-       print_func_entry();
-       print_func_exit();
+       //print_func_entry();
+       //print_func_exit();
        return devwalk(c, nc, name, nname, 0, 0, vmgen);
 }
 
 static int vmstat(struct chan *c, uint8_t * db, int n)
 {
-       print_func_entry();
-       print_func_exit();
+       //print_func_entry();
+       //print_func_exit();
        return devstat(c, db, n, 0, 0, vmgen);
 }
 
@@ -282,7 +281,7 @@ static int vmstat(struct chan *c, uint8_t * db, int n)
  * the open chan into p's fd table, then decref the chan. */
 static struct chan *vmopen(struct chan *c, int omode)
 {
-       print_func_entry();
+       //print_func_entry();
        ERRSTACK(1);
        struct vm *v = QID2VM(c->qid);
        printk("vmopen: v is %p\n", v);
@@ -334,45 +333,45 @@ static struct chan *vmopen(struct chan *c, int omode)
        c->flag |= COPEN;
        c->offset = 0;
        poperror();
-       print_func_exit();
+       //print_func_exit();
        return c;
 }
 
 static void vmcreate(struct chan *c, char *name, int omode, uint32_t perm)
 {
-       print_func_entry();
+       //print_func_entry();
        error(Eperm);
-       print_func_exit();
+       //print_func_exit();
 }
 
 static void vmremove(struct chan *c)
 {
-       print_func_entry();
+       //print_func_entry();
        error(Eperm);
-       print_func_exit();
+       //print_func_exit();
 }
 
 static int vmwstat(struct chan *c, uint8_t * dp, int n)
 {
-       print_func_entry();
+       //print_func_entry();
        error("No vmwstat");
-       print_func_exit();
+       //print_func_exit();
        return 0;
 }
 
 static void vmclose(struct chan *c)
 {
-       print_func_entry();
+       //print_func_entry();
        struct vm *v = c->aux;
        if (!v) {
-               print_func_exit();
+               //print_func_exit();
                return;
        }
        /* There are more closes than opens.  For instance, sysstat doesn't open,
         * but it will close the chan it got from namec.  We only want to clean
         * up/decref chans that were actually open. */
        if (!(c->flag & COPEN)) {
-               print_func_exit();
+               //print_func_exit();
                return;
        }
        switch (TYPE(c->qid)) {
@@ -383,40 +382,40 @@ static void vmclose(struct chan *c)
                        kref_put(&v->kref);
                        break;
        }
-       print_func_exit();
+       //print_func_exit();
 }
 
 static long vmread(struct chan *c, void *ubuf, long n, int64_t offset)
 {
-       print_func_entry();
+       //print_func_entry();
        struct vm *v = c->aux;
        printd("VMREAD\n");
        switch (TYPE(c->qid)) {
                case Qtopdir:
                case Qvmdir:
-                       print_func_exit();
+                       //print_func_exit();
                        return devdirread(c, ubuf, n, 0, 0, vmgen);
                case Qstat:
-                       print_func_exit();
+                       //print_func_exit();
                        return readnum(offset, ubuf, n, nvm, NUMSIZE32);
                case Qctl:
                        assert(v);
-                       print_func_exit();
+                       //print_func_exit();
                        return readnum(offset, ubuf, n, v->id, NUMSIZE32);
                case Qimage:
                        assert(v);
-                       print_func_exit();
+                       //print_func_exit();
                        return readmem(offset, ubuf, n, v->image, v->imagesize);
                default:
                        panic("Bad QID %p in devvm", c->qid.path);
        }
-       print_func_exit();
+       //print_func_exit();
        return 0;
 }
 
 static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
 {
-       print_func_entry();
+       //print_func_entry();
        ERRSTACK(3);
        char buf[32];
        struct cmdbuf *cb;
@@ -448,7 +447,7 @@ static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
                                vmr.mmio_completed = strtoul(cb->f[3], NULL, 0);
                                ret = vm_run(litevm, &vmr);
                                printk("vm_run returns %d\n", ret);
-                               print_func_exit();
+                               //print_func_exit();
                                return ret;
                        } else if (!strcmp(cb->f[0], "stop")) {
                                error("can't stop a vm yet");
@@ -471,6 +470,7 @@ static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
                                file = namec(cb->f[1], Aopen, OREAD, 0);
                                printk("after namec file is %p\n", file);
                                if (waserror()) {
+                                       printk("File open, alloc bad\n");
                                        cclose(file);
                                        nexterror();
                                }
@@ -480,6 +480,8 @@ static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
                                 */
                                v = kmalloc(vmr.memory_size, KMALLOC_WAIT);
                                if (waserror()) {
+                                       printk("memory allocated, read bad %s\n", 
+                                               current_errstr());
                                        kfree(v);
                                        nexterror();
                                }
@@ -489,6 +491,8 @@ static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
 
                                if (vm_set_memory_region(litevm, &vmr))
                                        error("vm_set_memory_region failed");
+                               void monitor(void *);
+                               monitor(NULL);
                                poperror();
                                poperror();
                                kfree(v);
@@ -517,7 +521,7 @@ static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
                default:
                        panic("Bad QID %p in devvm", c->qid.path);
        }
-       print_func_exit();
+       //print_func_exit();
        return n;
 }
 
diff --git a/kern/kfs/bin/POR b/kern/kfs/bin/POR
new file mode 100644 (file)
index 0000000..edc5586
Binary files /dev/null and b/kern/kfs/bin/POR differ
index 8c1b8ac..74eedad 100644 (file)
@@ -4,6 +4,9 @@ ls '#V'
 cp /bin/hlt '#r'
 # our kernel.
 echo mapmem '#r/hlt' 1 0 0 0x2001 > '#V/vm0/ctl'
+# also drop it on top of the reset vector.
+
+echo mapmem '#r/hlt' 1 0 0xffff0 0x2001 > '#V/vm0/ctl'
 echo 'run 0 0 0' > '#V/vm0/ctl'