Removes debugging code
[akaros.git] / kern / drivers / dev / vm.c
index bcabc45..3067594 100644 (file)
@@ -37,63 +37,82 @@ enum {
        Qimage,
 };
 
-/* This paddr/kaddr is a bit dangerous.  it'll work so long as we don't need all
- * 64 bits for a physical address (48 is the current norm on x86_64).
- * We're probably going to move to a model where we put the VM index or something
- * into the qid, but this works for now.
+/* The QID is the TYPE and the index into the vms array.
+ * We reserve the right to make it an id later.
  */
-#define ADDR_SHIFT 5
-#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)
-
+#define ID_SHIFT 5
 /* vm's have an image.
  * Note that the image can be read even as it is running. */
 struct vm {
-       struct vm *next;
-       struct kref                                     kref;
+       struct kref kref;
        /* should this be an array of pages? Hmm. */
-       void                                           *image;
-       unsigned long                                   imagesize;
-       int                                             id;
-       struct litevm                                  *archvm;
+       void *image;
+       unsigned long imagesize;
+       int id; // not used yet. 
+       struct litevm *archvm;
 };
 
 static spinlock_t vmlock;
 /* array, not linked list. We expect few, might as well be cache friendly. */
 static struct vm *vms = NULL;
 static int nvm = 0;
+static int vmok = 0;
 
 static spinlock_t vmidlock[1];
 static struct kref vmid[1] = { {(void *)1, fake_release} };
 
+/* not clear what .h to put these in. Put them here. */
+
+struct litevm *vmx_open(void);
+int vmx_create_vcpu(struct litevm *litevm, int n);
+int vmx_init(void);
+int vm_set_memory_region(struct litevm *litevm,
+                                                struct litevm_memory_region *mem);
+int vm_run(struct litevm *litevm, struct litevm_run *litevm_run);
+
+static inline struct vm *
+QID2VM(struct qid q)
+{
+       return &vms[((q).path >> ID_SHIFT)];
+}
+
+static inline int 
+TYPE(struct qid q)
+{
+       return ((q).path & ((1 << ID_SHIFT) - 1));
+}
+
+static inline int QID(int index, int type)
+{
+       return ((index << ID_SHIFT) | type);
+}
+
 /* we'll need this somewhere more generic. */
-static void
-readn(struct chan *c, void *vp, long n)
+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;
 
        p = vp;
-       while(n > 0) {
+       while (n > 0) {
                nn = devtab[c->type].read(c, p, n, c->offset);
                printk("readn: Got %d@%lld\n", nn, c->offset);
-               if(nn == 0)
-                       error("%s: wanted %d, got %d", Eshort, total, want);
+               if (nn == 0)
+                       error("%s: wanted %d, got %d", Eshort, want, total);
                c->offset += nn;
                p += nn;
                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
@@ -104,14 +123,14 @@ static void vm_release(struct kref *kref)
         * 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]){
+       if (v != &vms[nvm - 1]) {
                /* free the image ... oops */
                /* get rid of the kref. */
-               *v = vms[nvm-1];
+               *v = vms[nvm - 1];
        }
        nvm--;
        spin_unlock(&vmlock);
-       print_func_exit();
+       //print_func_exit();
 }
 
 /* VM ids run in the range 1..infinity. But vmx.c wants them
@@ -119,21 +138,21 @@ 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();
-       return id-1;
+       //print_func_exit();
+       return id - 1;
 }
 
 static int vmgen(struct chan *c, char *entry_name,
-                struct dirtab *unused, int unused_nr_dirtab,
-                int s, struct dir *dp)
+                                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);
@@ -141,126 +160,129 @@ 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));
        switch (TYPE(c->qid)) {
-       case Qtopdir:
-               printd("Qtopdir s %d nvm %d\n", s, nvm);
-               /* Generate elements for the top level dir.  We support clone, stat,
-                * vm dirs at the top level */
-               if (s == 0) {
-                       mkqid(&q, Qclone, 0, QTFILE);
-                       devdir(c, q, "clone", 0, eve, 0666, dp);
-                       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();
-                       return 1;
-               }
-               s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
-               spin_lock_irqsave(&vmlock);
-               if (s >= nvm){
-                       printd("DONE qtopdir\n");
+               case Qtopdir:
+                       printd("Qtopdir s %d nvm %d\n", s, nvm);
+                       /* Generate elements for the top level dir.  We support clone, stat,
+                        * vm dirs at the top level */
+                       if (s == 0) {
+                               mkqid(&q, Qclone, 0, QTFILE);
+                               devdir(c, q, "clone", 0, eve, 0666, dp);
+                               //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();
+                               return 1;
+                       }
+                       s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
+                       spin_lock_irqsave(&vmlock);
+                       if (s >= nvm) {
+                               printd("DONE qtopdir\n");
+                               spin_unlock(&vmlock);
+                               //print_func_exit();
+                               return -1;
+                       }
+                       vm_i = &vms[s];
+                       snprintf(get_cur_genbuf(), GENBUF_SZ, "vm%d", vm_i->id);
                        spin_unlock(&vmlock);
-                       print_func_exit();
+                       mkqid(&q, QID(s, Qvmdir), 0, QTDIR);
+                       devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
+                       //print_func_exit();
+                       return 1;
+               case Qvmdir:
+                       /* Gen the contents of the vm dirs */
+                       s += Qctl;      /* first time through, start on Qctl */
+                       switch (s) {
+                               case Qctl:
+                                       mkqid(&q, QID(s-Qctl, Qctl), 0, QTFILE);
+                                       devdir(c, q, "ctl", 0, eve, 0666, dp);
+                                       //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();
+                                       return 1;
+                       }
+                       //print_func_exit();
                        return -1;
-               }
-               vm_i = &vms[s];
-               snprintf(get_cur_genbuf(), GENBUF_SZ, "vm%d", vm_i->id);
-               spin_unlock(&vmlock);
-               mkqid(&q, QID(vm_i, Qvmdir), 0, QTDIR);
-               devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
-               print_func_exit();
-               return 1;
-       case Qvmdir:
-               /* Gen the contents of the vm dirs */
-               s += Qctl;      /* first time through, start on Qctl */
-               switch (s) {
+                       /* Need to also provide a direct hit for Qclone and all other files (at
+                        * all levels of the hierarchy).  Every file is both
+                        * generated (via the s increments in their respective directories) and
+                        * directly gen-able.  devstat() will call gen with a specific path in
+                        * the qid.  In these cases, we make a dir for whatever they are asking
+                        * for.  Note the qid stays the same.  I think this is what the old
+                        * plan9 comments above devgen were talking about for (ii).
+                        *
+                        * We don't need to do this for the directories - devstat will look for
+                        * the a directory by path and fail.  Then it will manually build the
+                        * stat output (check the -1 case in devstat). */
+               case Qclone:
+                       devdir(c, c->qid, "clone", 0, eve, 0666, dp);
+                       //print_func_exit();
+                       return 1;
+               case Qstat:
+                       devdir(c, c->qid, "stat", 0, eve, 0444, dp);
+                       //print_func_exit();
+                       return 1;
                case Qctl:
-                       mkqid(&q, QID(QID2VM(c->qid), Qctl), 0, QTFILE);
-                       devdir(c, q, "ctl", 0, eve, 0666, dp);
-                       print_func_exit();
+                       devdir(c, c->qid, "ctl", 0, eve, 0666, dp);
+                       //print_func_exit();
                        return 1;
                case Qimage:
-                       mkqid(&q, QID(QID2VM(c->qid), Qimage), 0, QTFILE);
-                       devdir(c, q, "image", 0, eve, 0666, dp);
-                       print_func_exit();
+                       devdir(c, c->qid, "image", 0, eve, 0666, dp);
+                       //print_func_exit();
                        return 1;
-               }
-               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
-                * generated (via the s increments in their respective directories) and
-                * directly gen-able.  devstat() will call gen with a specific path in
-                * the qid.  In these cases, we make a dir for whatever they are asking
-                * for.  Note the qid stays the same.  I think this is what the old
-                * plan9 comments above devgen were talking about for (ii).
-                *
-                * We don't need to do this for the directories - devstat will look for
-                * the a directory by path and fail.  Then it will manually build the
-                * stat output (check the -1 case in devstat). */
-       case Qclone:
-               devdir(c, c->qid, "clone", 0, eve, 0666, dp);
-               print_func_exit();
-               return 1;
-       case Qstat:
-               devdir(c, c->qid, "stat", 0, eve, 0444, dp);
-               print_func_exit();
-               return 1;
-       case Qctl:
-               devdir(c, c->qid, "ctl", 0, eve, 0666, dp);
-               print_func_exit();
-               return 1;
-       case Qimage:
-               devdir(c, c->qid, "image", 0, eve, 0666, dp);
-               print_func_exit();
-               return 1;
        }
-       print_func_exit();
+       //print_func_exit();
        return -1;
 }
 
 static void vminit(void)
 {
-       return;
-       print_func_entry();
+       //print_func_entry();
        int i;
        spinlock_init_irqsave(&vmlock);
        spinlock_init_irqsave(vmidlock);
        i = vmx_init();
+       if (i == 0)
+               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)
+                                                         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)
+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);
 }
 
@@ -268,139 +290,141 @@ 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);
-       if (waserror()){
+       if (waserror()) {
                nexterror();
        }
        switch (TYPE(c->qid)) {
-       case Qtopdir:
-       case Qvmdir:
-               if (omode & ORCLOSE)
-                       error(Eperm);
-               if (!IS_RDONLY(omode))
-                       error(Eisdir);
-               break;
-       case Qclone:
-               spin_lock_irqsave(&vmlock);
-               vms = krealloc(vms, sizeof(vms[0])*(nvm+1),0);
-               v = &vms[nvm];
-               nvm++;
-               spin_unlock(&vmlock);
-               kref_init(&v->kref, vm_release, 1);
-               v->id = newvmid();
-               mkqid(&c->qid, QID(v, Qctl), 0, QTFILE);
-               c->aux = v;
-               printd("New VM id %d\n", v->id);
-               v->archvm = vmx_open();
-               if (!v->archvm){
-                       printk("vm_open failed\n");
-                       error("vm_open failed");
-               }
-               if (vmx_create_vcpu(v->archvm, v->id) < 0){
-                       printk("vm_create failed");
-                       error("vm_create failed");
-               }
-               break;
-       case Qstat:
-               break;
-       case Qctl:
-       case Qimage:
-               c->aux = QID2VM(c->qid);
-               printk("open qctl: aux is %p\n", c->aux);
-               break;
+               case Qtopdir:
+               case Qvmdir:
+                       if (omode & ORCLOSE)
+                               error(Eperm);
+                       if (!IS_RDONLY(omode))
+                               error(Eisdir);
+                       break;
+               case Qclone:
+                       spin_lock_irqsave(&vmlock);
+                       vms = krealloc(vms, sizeof(vms[0]) * (nvm + 1), 0);
+                       v = &vms[nvm];
+                       nvm++;
+                       spin_unlock(&vmlock);
+                       kref_init(&v->kref, vm_release, 1);
+                       v->id = newvmid();
+                       mkqid(&c->qid, QID(nvm, Qctl), 0, QTFILE);
+                       c->aux = v;
+                       printd("New VM id %d\n", v->id);
+                       v->archvm = vmx_open();
+                       if (!v->archvm) {
+                               printk("vm_open failed\n");
+                               error("vm_open failed");
+                       }
+                       if (vmx_create_vcpu(v->archvm, v->id) < 0) {
+                               printk("vm_create failed");
+                               error("vm_create failed");
+                       }
+                       printk("Qclone open: id %d, v is %p, v->archvm is %p\n", 
+                                       nvm-1,
+                                       v, v->archvm);
+                       break;
+               case Qstat:
+                       break;
+               case Qctl:
+               case Qimage:
+                       c->aux = QID2VM(c->qid);
+                       printk("open qctl: aux (vm) is %p\n", c->aux);
+                       break;
        }
        c->mode = openmode(omode);
        /* Assumes c is unique (can't be closed concurrently */
        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)
+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)) {
-               /* for now, leave the VM active even when we close ctl */
-       case Qctl:
-               break;
-       case Qimage:
-               kref_put(&v->kref);
-               break;
+                       /* for now, leave the VM active even when we close ctl */
+               case Qctl:
+                       break;
+               case Qimage:
+                       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();
-               return devdirread(c, ubuf, n, 0, 0, vmgen);
-       case Qstat:
-               print_func_exit();
-               return readnum(offset, ubuf, n, nvm, NUMSIZE32);
-       case Qctl:
-               assert(v);
-               print_func_exit();
-               return readnum(offset, ubuf, n, v->id, NUMSIZE32);
-       case Qimage:
-               assert(v);
-               print_func_exit();
-               return readmem(offset, ubuf, n,
-                              v->image, v->imagesize);
-       default:
-               panic("Bad QID %p in devvm", c->qid.path);
+               case Qtopdir:
+               case Qvmdir:
+                       //print_func_exit();
+                       return devdirread(c, ubuf, n, 0, 0, vmgen);
+               case Qstat:
+                       //print_func_exit();
+                       return readnum(offset, ubuf, n, nvm, NUMSIZE32);
+               case Qctl:
+                       assert(v);
+                       //print_func_exit();
+                       return readnum(offset, ubuf, n, v->id, NUMSIZE32);
+               case Qimage:
+                       assert(v);
+                       //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;
@@ -409,100 +433,107 @@ static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
        uint64_t hexval;
        printd("vmwrite(%p, %p, %d)\n", c, ubuf, n);
        switch (TYPE(c->qid)) {
-       case Qtopdir:
-       case Qvmdir:
-       case Qstat:
-               error(Eperm);
-       case Qctl:
-               vm = c->aux;
-               cb = parsecmd(ubuf, n);
-               if (waserror()) {
-                       kfree(cb);
-                       nexterror();
-               }
-               if (!strcmp(cb->f[0], "run")) {
-                       int ret;
-                       if (cb->nf != 4)
-                               error("usage: run vcpu emulated mmio_completed");
-                       litevm = vm->archvm;
-                       struct litevm_run vmr;
-                       vmr.vcpu = strtoul(cb->f[1], NULL, 0);
-                       vmr.emulated = strtoul(cb->f[2], NULL, 0);
-                       vmr.mmio_completed = strtoul(cb->f[3], NULL, 0);
-                       ret = vm_run(litevm, &vmr);
-                       printk("vm_run returns %d\n", ret);
-                       print_func_exit();
-                       return ret;
-               } else if (!strcmp(cb->f[0], "stop")) {
-                       error("can't stop a vm yet");
-               } else if (!strcmp(cb->f[0], "fillmem")) {
-                       struct chan *file;
-                       void *v;
+               case Qtopdir:
+               case Qvmdir:
+               case Qstat:
+                       error(Eperm);
+               case Qctl:
                        vm = c->aux;
                        litevm = vm->archvm;
-                       uint64_t filesize;
-                       struct litevm_memory_region vmr;
-                       int got;
-
-                       if (cb->nf != 6)
-                               error("usage: mapmem file 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);
-                       filesize = strtoul(cb->f[5], NULL, 0);
-                       vmr.memory_size = (filesize + 4095) & ~4095ULL;
-
-                       file = namec(cb->f[1], Aopen, OREAD, 0);
-                       printk("after namec file is %p\n", file);
-                       if (waserror()){
-                               cclose(file);
-                               nexterror();
-                       }
-                       /* at some point we want to mmap from the kernel
-                        * but we don't have that yet. This all needs
-                        * rethinking but the abstractions of kvm do too.
-                        */
-                       v = kmalloc(vmr.memory_size, KMALLOC_WAIT);
-                       if (waserror()){
-                               kfree(v);
+                       printk("qctl: vm is %p, litevm is %p\n", vm, litevm);
+                       cb = parsecmd(ubuf, n);
+                       if (waserror()) {
+                               kfree(cb);
                                nexterror();
                        }
+                       if (!strcmp(cb->f[0], "run")) {
+                               int ret;
+                               if (cb->nf != 4)
+                                       error("usage: run vcpu emulated mmio_completed");
+                               struct litevm_run vmr;
+                               vmr.vcpu = strtoul(cb->f[1], NULL, 0);
+                               vmr.emulated = strtoul(cb->f[2], NULL, 0);
+                               vmr.mmio_completed = strtoul(cb->f[3], NULL, 0);
+                               disable_irq();
+                               ret = vm_run(litevm, &vmr);
+                               enable_irq();
+                               printk("vm_run returns %d\n", ret);
+                               //print_func_exit();
+                               return ret;
+                       } else if (!strcmp(cb->f[0], "stop")) {
+                               error("can't stop a vm yet");
+                       } else if (!strcmp(cb->f[0], "mapmem")) {
+                               struct chan *file;
+                               void *v;
+                               vm = c->aux;
+                               uint64_t filesize;
+                               struct litevm_memory_region vmr;
+                               int got;
 
-                       readn(file, v, filesize);
-                       vmr.init_data = v;
+                               if (cb->nf != 6)
+                                       error("usage: mapmem file 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);
+                               filesize = strtoul(cb->f[5], NULL, 0);
+                               vmr.memory_size = (filesize + 4095) & ~4095ULL;
 
-                       if (vm_set_memory_region(litevm, &vmr))
-                               error("vm_set_memory_region failed");
-                       poperror();
-                       poperror();
-                       kfree(v);
-                       cclose(file);
+                               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();
+                               }
+                               /* at some point we want to mmap from the kernel
+                                * but we don't have that yet. This all needs
+                                * rethinking but the abstractions of kvm do too.
+                                */
+                               v = kmalloc(vmr.memory_size, KMALLOC_WAIT);
+                               if (waserror()) {
+                                       printk("memory allocated, read bad %s\n", 
+                                               current_errstr());
+                                       kfree(v);
+                                       nexterror();
+                               }
 
-               } 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(litevm, &vmr))
-                               error("vm_set_memory_region failed");
-               } else {
-                       error("%s: not implemented", cb->f[0]);
-               }
-               kfree(cb);
-               poperror();
-               break;
-       case Qimage:
-               error("can't write an image yet");
-               break;
-       default:
-               panic("Bad QID %p in devvm", c->qid.path);
+                               readn(file, v, filesize);
+                               vmr.init_data = v;
+
+                               if (vm_set_memory_region(litevm, &vmr))
+                                       error("vm_set_memory_region failed");
+                               void monitor(void *);
+                               monitor(NULL);
+                               poperror();
+                               poperror();
+                               kfree(v);
+                               cclose(file);
+
+                       } else if (!strcmp(cb->f[0], "region")) {
+                               void *v;
+                               struct litevm_memory_region vmr;
+                               if (cb->nf != 5)
+                                       error("usage: mapmem slot flags addr size");
+                               vmr.slot = strtoul(cb->f[1], NULL, 0);
+                               vmr.flags = strtoul(cb->f[2], NULL, 0);
+                               vmr.guest_phys_addr = strtoul(cb->f[3], NULL, 0);
+                               vmr.memory_size = strtoul(cb->f[4], NULL, 0);
+                               vmr.init_data = NULL;
+                               if (vm_set_memory_region(litevm, &vmr))
+                                       error("vm_set_memory_region failed");
+                       } else {
+                               error("%s: not implemented", cb->f[0]);
+                       }
+                       kfree(cb);
+                       poperror();
+                       break;
+               case Qimage:
+                       error("can't write an image yet");
+                       break;
+               default:
+                       panic("Bad QID %p in devvm", c->qid.path);
        }
-       print_func_exit();
+       //print_func_exit();
        return n;
 }
 
@@ -526,6 +557,6 @@ struct dev vmdevtab __devtab = {
        vmremove,
        vmwstat,
        devpower,
-//     devconfig,
+//  devconfig,
        devchaninfo,
 };