Part-way to writing memory
[akaros.git] / kern / drivers / dev / vm.c
1 //#define DEBUG
2 /* Copyright 2014 Google Inc.
3  * Copyright (c) 2013 The Regents of the University of California
4  * Barret Rhoden <brho@cs.berkeley.edu>
5  * See LICENSE for details.
6  *
7  * devvm/#V: a device for VMs
8  *
9  */
10
11 #include <kmalloc.h>
12 #include <string.h>
13 #include <stdio.h>
14 #include <assert.h>
15 #include <error.h>
16 #include <pmap.h>
17 #include <sys/queue.h>
18 #include <smp.h>
19 #include <kref.h>
20 #include <atomic.h>
21 #include <alarm.h>
22 #include <event.h>
23 #include <umem.h>
24 #include <devalarm.h>
25 #include <arch/types.h>
26 #include <arch/vm.h>
27 #include <arch/emulate.h>
28 #include <arch/vmdebug.h>
29
30 /* qid path types */
31 enum {
32         Qtopdir = 1,
33         Qclone,
34         Qstat,
35         Qvmdir,
36         Qctl,
37         Qimage,
38 };
39
40 /* This paddr/kaddr is a bit dangerous.  it'll work so long as we don't need all
41  * 64 bits for a physical address (48 is the current norm on x86_64).
42  * We're probably going to move to a model where we put the VM index or something
43  * into the qid, but this works for now.
44  */
45 #define ADDR_SHIFT 5
46 #define QID2VM(q) ((struct proc_alarm*)KADDR(((q).path >> ADDR_SHIFT)))
47 #define TYPE(q) ((q).path & ((1 << ADDR_SHIFT) - 1))
48 #define QID(ptr, type) ((PADDR(ptr) << ADDR_SHIFT) | type)
49
50 /* vm's have an image.
51  * Note that the image can be read even as it is running. */
52 struct vm {
53         struct vm *next;
54         struct kref                                     kref;
55         /* should this be an array of pages? Hmm. */
56         void                                           *image;
57         unsigned long                                   imagesize;
58         int                                             id;
59         struct litevm                                  *archvm;
60 };
61
62 static spinlock_t vmlock;
63 /* array, not linked list. We expect few, might as well be cache friendly. */
64 static struct vm *vms = NULL;
65 static int nvm = 0;
66
67 static spinlock_t vmidlock[1];
68 static struct kref vmid[1] = { {(void *)1, fake_release} };
69
70 /* we'll need this somewhere more generic. */
71 static void
72 readn(struct chan *c, void *vp, long n)
73 {
74         char *p;
75         long nn;
76         int total = 0, want = n;
77
78         p = vp;
79         while(n > 0) {
80                 nn = devtab[c->type]->read(c, p, n, c->offset);
81                 printk("readn: Got %d@%lld\n", nn, c->offset);
82                 if(nn == 0)
83                         error("%s: wanted %d, got %d", Eshort, total, want);
84                 c->offset += nn;
85                 p += nn;
86                 n -= nn;
87                 total += nn;
88         }
89 }
90
91
92 static void vm_release(struct kref *kref)
93 {
94         struct vm *v = container_of(kref, struct vm, kref);
95         spin_lock(&vmlock);
96         /* cute trick. Save the last element of the array in place of the
97          * one we're deleting. Reduce nvm. Don't realloc; that way, next
98          * time we add a vm the allocator will just return. */
99         if (v != &vms[nvm-1]){
100                 /* free the image ... oops */
101                 /* get rid of the kref. */
102                 *v = vms[nvm-1];
103         }
104         nvm--;
105         spin_unlock(&vmlock);
106 }
107
108 static int newvmid(void)
109 {
110         int id;
111         spin_lock(vmidlock);
112         id = kref_refcnt(vmid);
113         kref_get(vmid, 1);
114         spin_unlock(vmidlock);
115         return id;
116 }
117
118 static int vmgen(struct chan *c, char *entry_name,
119                  struct dirtab *unused, int unused_nr_dirtab,
120                  int s, struct dir *dp)
121 {
122         struct qid q;
123         struct vm *vm_i;
124         printd("GEN s %d\n", s);
125         /* Whether we're in one dir or at the top, .. still takes us to the top. */
126         if (s == DEVDOTDOT) {
127                 mkqid(&q, Qtopdir, 0, QTDIR);
128                 devdir(c, c->qid, "#V", 0, eve, 0555, dp);
129                 return 1;
130         }
131         printd("TYPE %d\n", TYPE(c->qid));
132         switch (TYPE(c->qid)) {
133         case Qtopdir:
134                 printd("Qtopdir s %d nvm %d\n", s, nvm);
135                 /* Generate elements for the top level dir.  We support clone, stat,
136                  * vm dirs at the top level */
137                 if (s == 0) {
138                         mkqid(&q, Qclone, 0, QTFILE);
139                         devdir(c, q, "clone", 0, eve, 0666, dp);
140                         return 1;
141                 }
142                 s--;
143                 if (s == 0) {
144                         mkqid(&q, Qstat, 0, QTFILE);
145                         devdir(c, q, "stat", 0, eve, 0666, dp);
146                         return 1;
147                 }
148                 s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
149                 spin_lock(&vmlock);
150                 if (s >= nvm){
151                         printd("DONE qtopdir\n");
152                         spin_unlock(&vmlock);
153                         return -1;
154                 }
155                 vm_i = &vms[s];
156                 snprintf(get_cur_genbuf(), GENBUF_SZ, "vm%d", vm_i->id);
157                 spin_unlock(&vmlock);
158                 mkqid(&q, QID(vm_i, Qvmdir), 0, QTDIR);
159                 devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
160                 return 1;
161         case Qvmdir:
162                 /* Gen the contents of the vm dirs */
163                 s += Qctl;      /* first time through, start on Qctl */
164                 switch (s) {
165                 case Qctl:
166                         mkqid(&q, QID(QID2VM(c->qid), Qctl), 0, QTFILE);
167                         devdir(c, q, "ctl", 0, eve, 0666, dp);
168                         return 1;
169                 case Qimage:
170                         mkqid(&q, QID(QID2VM(c->qid), Qimage), 0, QTFILE);
171                         devdir(c, q, "image", 0, eve, 0666, dp);
172                         return 1;
173                 }
174                 return -1;
175                 /* Need to also provide a direct hit for Qclone and all other files (at
176                  * all levels of the hierarchy).  Every file is both
177                  * generated (via the s increments in their respective directories) and
178                  * directly gen-able.  devstat() will call gen with a specific path in
179                  * the qid.  In these cases, we make a dir for whatever they are asking
180                  * for.  Note the qid stays the same.  I think this is what the old
181                  * plan9 comments above devgen were talking about for (ii).
182                  *
183                  * We don't need to do this for the directories - devstat will look for
184                  * the a directory by path and fail.  Then it will manually build the
185                  * stat output (check the -1 case in devstat). */
186         case Qclone:
187                 devdir(c, c->qid, "clone", 0, eve, 0666, dp);
188                 return 1;
189         case Qstat:
190                 devdir(c, c->qid, "stat", 0, eve, 0444, dp);
191                 return 1;
192         case Qctl:
193                 devdir(c, c->qid, "ctl", 0, eve, 0666, dp);
194                 return 1;
195         case Qimage:
196                 devdir(c, c->qid, "image", 0, eve, 0666, dp);
197                 return 1;
198         }
199         return -1;
200 }
201
202 static void vminit(void)
203 {
204         int i;
205         spinlock_init(&vmlock);
206         spinlock_init(vmidlock);
207         i = vmx_init();
208         printk("vminit: litevm_init returns %d\n", i);
209
210 }
211
212 static struct chan *vmattach(char *spec)
213 {
214         struct chan *c = devattach('V', spec);
215         mkqid(&c->qid, Qtopdir, 0, QTDIR);
216         return c;
217 }
218
219 static struct walkqid *vmwalk(struct chan *c, struct chan *nc, char **name,
220                               int nname)
221 {
222         return devwalk(c, nc, name, nname, 0, 0, vmgen);
223 }
224
225 static int vmstat(struct chan *c, uint8_t *db, int n)
226 {
227         return devstat(c, db, n, 0, 0, vmgen);
228 }
229
230 /* It shouldn't matter if p = current is DYING.  We'll eventually fail to insert
231  * the open chan into p's fd table, then decref the chan. */
232 static struct chan *vmopen(struct chan *c, int omode)
233 {
234         ERRSTACK(2);
235         struct vm *v = c->aux;
236         if (waserror()){
237                 nexterror();
238         }
239         switch (TYPE(c->qid)) {
240         case Qtopdir:
241         case Qvmdir:
242                 if (omode & ORCLOSE)
243                         error(Eperm);
244                 if (omode != OREAD)
245                         error(Eisdir);
246                 break;
247         case Qclone:
248                 spin_lock(&vmlock);
249                 vms = krealloc(vms, sizeof(vms[0])*(nvm+1),0);
250                 v = &vms[nvm];
251                 nvm++;
252                 spin_unlock(&vmlock);
253                 kref_init(&v->kref, vm_release, 1);
254                 v->id = newvmid();
255                 mkqid(&c->qid, QID(v, Qctl), 0, QTFILE);
256                 c->aux = v;
257                 printd("New VM id %d\n", v->id);
258                 v->archvm = vmx_open();
259                 if (!v->archvm)
260                         error("vm_open failed");
261                 if (vmx_create_vcpu(v->archvm, 1) < 0)
262                         error("vm_create failed");
263                 break;
264         case Qstat:
265                 break;
266         case Qctl:
267         case Qimage:
268                 /* the purpose of opening is to hold a kref on the proc_vm */
269                 v = c->aux;
270                 break;
271         }
272         c->mode = openmode(omode);
273         /* Assumes c is unique (can't be closed concurrently */
274         c->flag |= COPEN;
275         c->offset = 0;
276         return c;
277 }
278
279 static void vmcreate(struct chan *c, char *name, int omode, uint32_t perm)
280 {
281         error(Eperm);
282 }
283
284 static void vmremove(struct chan *c)
285 {
286         error(Eperm);
287 }
288
289 static int vmwstat(struct chan *c, uint8_t *dp, int n)
290 {
291         error("No vmwstat");
292         return 0;
293 }
294
295 static void vmclose(struct chan *c)
296 {
297         struct vm *v = c->aux;
298         if (!v)
299                 return;
300         /* There are more closes than opens.  For instance, sysstat doesn't open,
301          * but it will close the chan it got from namec.  We only want to clean
302          * up/decref chans that were actually open. */
303         if (!(c->flag & COPEN))
304                 return;
305         switch (TYPE(c->qid)) {
306                 /* for now, leave the VM active even when we close ctl */
307         case Qctl:
308                 break;
309         case Qimage:
310                 kref_put(&v->kref);
311                 break;
312         }
313 }
314
315 static long vmread(struct chan *c, void *ubuf, long n, int64_t offset)
316 {
317         struct vm *v = c->aux;
318         printd("VMREAD\n");
319         switch (TYPE(c->qid)) {
320         case Qtopdir:
321         case Qvmdir:
322                 return devdirread(c, ubuf, n, 0, 0, vmgen);
323         case Qstat:
324                 return readnum(offset, ubuf, n, nvm, NUMSIZE32);
325         case Qctl:
326                 assert(v);
327                 return readnum(offset, ubuf, n, v->id, NUMSIZE32);
328         case Qimage:
329                 assert(v);
330                 return readmem(offset, ubuf, n,
331                                v->image, v->imagesize);
332         default:
333                 panic("Bad QID %p in devvm", c->qid.path);
334         }
335         return 0;
336 }
337
338 static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
339 {
340         ERRSTACK(3);
341         char buf[32];
342         struct cmdbuf *cb;
343         struct litevm *vm;
344         uint64_t hexval;
345         printd("vmwrite(%p, %p, %d)\n", c, ubuf, n);
346         switch (TYPE(c->qid)) {
347         case Qtopdir:
348         case Qvmdir:
349         case Qstat:
350                 error(Eperm);
351         case Qctl:
352                 vm = c->aux;
353                 cb = parsecmd(ubuf, n);
354                 if (waserror()) {
355                         kfree(cb);
356                         nexterror();
357                 }
358                 if (!strcmp(cb->f[0], "start")) {
359                         error("can't run a vm yet");
360                 } else if (!strcmp(cb->f[0], "stop")) {
361                         error("can't stop a vm yet");
362                 } else if (!strcmp(cb->f[0], "fillmem")) {
363                         struct chan *file;
364                         void *v;
365                         vm = c->aux;
366                         uint64_t filesize;
367                         struct litevm_memory_region vmr;
368                         int got;
369
370                         if (cb->nf != 6)
371                                 error("usage: mapmem file slot flags addr size");
372                         vmr.slot = strtoul(cb->f[2], NULL, 0);
373                         vmr.flags = strtoul(cb->f[3], NULL, 0);
374                         vmr.guest_phys_addr = strtoul(cb->f[4], NULL, 0);
375                         filesize = strtoul(cb->f[5], NULL, 0);
376                         vmr.memory_size = (filesize + 4095) & ~4095ULL;
377
378                         file = namec(cb->f[1], Aopen, OREAD, 0);
379                         printk("after namec file is %p\n", file);
380                         if (waserror()){
381                                 cclose(file);
382                                 nexterror();
383                         }
384                         /* at some point we want to mmap from the kernel
385                          * but we don't have that yet. This all needs
386                          * rethinking but the abstractions of kvm do too.
387                          */
388                         v = kmalloc(vmr.memory_size, KMALLOC_WAIT);
389                         if (waserror()){
390                                 kfree(v);
391                                 nexterror();
392                         }
393
394                         readn(file, v, filesize);
395                         vmr.init_data = v;
396
397                         if (vm_set_memory_region(vm, &vmr))
398                                 error("vm_set_memory_region failed");
399                         poperror();
400                         poperror();
401                         kfree(v);
402                         cclose(file);
403
404                 } else if (!strcmp(cb->f[0], "region")) {
405                         void *v;
406                         struct litevm_memory_region vmr;
407                         if (cb->nf != 5)
408                                 error("usage: mapmem slot flags addr size");
409                         vmr.slot = strtoul(cb->f[2], NULL, 0);
410                         vmr.flags = strtoul(cb->f[3], NULL, 0);
411                         vmr.guest_phys_addr = strtoul(cb->f[4], NULL, 0);
412                         vmr.memory_size = strtoul(cb->f[5], NULL, 0);
413                         if (vm_set_memory_region(vm, &vmr))
414                                 error("vm_set_memory_region failed");
415                 } else {
416                         error("%s: not implemented", cb->f[0]);
417                 }
418                 kfree(cb);
419                 poperror();
420                 break;
421         case Qimage:
422                 error("can't write an image yet");
423                 break;
424         default:
425                 panic("Bad QID %p in devvm", c->qid.path);
426         }
427         return n;
428 }
429
430 struct dev vmdevtab = {
431         'V',
432         "vm",
433
434         devreset,
435         vminit,
436         devshutdown,
437         vmattach,
438         vmwalk,
439         vmstat,
440         vmopen,
441         vmcreate,
442         vmclose,
443         vmread,
444         devbread,
445         vmwrite,
446         devbwrite,
447         vmremove,
448         vmwstat,
449         devpower,
450 //      devconfig,
451 //      devchaninfo,
452 };