d167873c8082f54eaa7b134854497dde9a90bed3
[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 };
60
61 static spinlock_t vmlock;
62 /* array, not linked list. We expect few, might as well be cache friendly. */
63 static struct vm *vms = NULL;
64 static int nvm = 0;
65
66 static spinlock_t vmidlock[1];
67 static struct kref vmid[1] = { {(void *)1, fake_release} };
68
69 static void vm_release(struct kref *kref)
70 {
71         struct vm *v = container_of(kref, struct vm, kref);
72         spin_lock(&vmlock);
73         /* cute trick. Save the last element of the array in place of the
74          * one we're deleting. Reduce nvm. Don't realloc; that way, next
75
76          * do and just return.
77          */
78         if (v != &vms[nvm-1]){
79                 /* free the image ... oops */
80                 /* get rid of the kref. */
81                 *v = vms[nvm-1];
82         }
83         nvm--;
84         spin_unlock(&vmlock);
85 }
86
87 static int newvmid(void)
88 {
89         int id;
90         spin_lock(vmidlock);
91         id = kref_refcnt(vmid);
92         kref_get(vmid, 1);
93         spin_unlock(vmidlock);
94         return id;
95 }
96
97 static int vmgen(struct chan *c, char *entry_name,
98                  struct dirtab *unused, int unused_nr_dirtab,
99                  int s, struct dir *dp)
100 {
101         struct qid q;
102         struct vm *vm_i;
103         printd("GEN s %d\n", s);
104         /* Whether we're in one dir or at the top, .. still takes us to the top. */
105         if (s == DEVDOTDOT) {
106                 mkqid(&q, Qtopdir, 0, QTDIR);
107                 devdir(c, c->qid, "#V", 0, eve, 0555, dp);
108                 return 1;
109         }
110         printd("TYPE %d\n", TYPE(c->qid));
111         switch (TYPE(c->qid)) {
112         case Qtopdir:
113                 printd("Qtopdir s %d nvm %d\n", s, nvm);
114                 /* Generate elements for the top level dir.  We support clone, stat,
115                  * vm dirs at the top level */
116                 if (s == 0) {
117                         mkqid(&q, Qclone, 0, QTFILE);
118                         devdir(c, q, "clone", 0, eve, 0666, dp);
119                         return 1;
120                 }
121                 s--;
122                 if (s == 0) {
123                         mkqid(&q, Qstat, 0, QTFILE);
124                         devdir(c, q, "stat", 0, eve, 0666, dp);
125                         return 1;
126                 }
127                 s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
128                 spin_lock(&vmlock);
129                 if (s >= nvm){
130                         printd("DONE qtopdir\n");
131                         spin_unlock(&vmlock);
132                         return -1;
133                 }
134                 vm_i = &vms[s];
135                 snprintf(get_cur_genbuf(), GENBUF_SZ, "vm%d", vm_i->id);
136                 spin_unlock(&vmlock);
137                 mkqid(&q, QID(vm_i, Qvmdir), 0, QTDIR);
138                 devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
139                 return 1;
140         case Qvmdir:
141                 /* Gen the contents of the vm dirs */
142                 s += Qctl;      /* first time through, start on Qctl */
143                 switch (s) {
144                 case Qctl:
145                         mkqid(&q, QID(QID2VM(c->qid), Qctl), 0, QTFILE);
146                         devdir(c, q, "ctl", 0, eve, 0666, dp);
147                         return 1;
148                 case Qimage:
149                         mkqid(&q, QID(QID2VM(c->qid), Qimage), 0, QTFILE);
150                         devdir(c, q, "image", 0, eve, 0666, dp);
151                         return 1;
152                 }
153                 return -1;
154                 /* Need to also provide a direct hit for Qclone and all other files (at
155                  * all levels of the hierarchy).  Every file is both
156                  * generated (via the s increments in their respective directories) and
157                  * directly gen-able.  devstat() will call gen with a specific path in
158                  * the qid.  In these cases, we make a dir for whatever they are asking
159                  * for.  Note the qid stays the same.  I think this is what the old
160                  * plan9 comments above devgen were talking about for (ii).
161                  *
162                  * We don't need to do this for the directories - devstat will look for
163                  * the a directory by path and fail.  Then it will manually build the
164                  * stat output (check the -1 case in devstat). */
165         case Qclone:
166                 devdir(c, c->qid, "clone", 0, eve, 0666, dp);
167                 return 1;
168         case Qstat:
169                 devdir(c, c->qid, "stat", 0, eve, 0444, dp);
170                 return 1;
171         case Qctl:
172                 devdir(c, c->qid, "ctl", 0, eve, 0666, dp);
173                 return 1;
174         case Qimage:
175                 devdir(c, c->qid, "image", 0, eve, 0666, dp);
176                 return 1;
177         }
178         return -1;
179 }
180
181 static void vminit(void)
182 {
183         spinlock_init(&vmlock);
184         spinlock_init(vmidlock);
185 }
186
187 static struct chan *vmattach(char *spec)
188 {
189         int i;
190         int litevm_init(void);
191         struct chan *c = devattach('V', spec);
192         mkqid(&c->qid, Qtopdir, 0, QTDIR);
193         i = litevm_init();
194         printk("vminit: litevm_init returns %d\n", i);
195         return c;
196 }
197
198 static struct walkqid *vmwalk(struct chan *c, struct chan *nc, char **name,
199                               int nname)
200 {
201         return devwalk(c, nc, name, nname, 0, 0, vmgen);
202 }
203
204 static int vmstat(struct chan *c, uint8_t *db, int n)
205 {
206         return devstat(c, db, n, 0, 0, vmgen);
207 }
208
209 /* It shouldn't matter if p = current is DYING.  We'll eventually fail to insert
210  * the open chan into p's fd table, then decref the chan. */
211 static struct chan *vmopen(struct chan *c, int omode)
212 {
213         struct vm *v = c->aux;
214         switch (TYPE(c->qid)) {
215         case Qtopdir:
216         case Qvmdir:
217                 if (omode & ORCLOSE)
218                         error(Eperm);
219                 if (omode != OREAD)
220                         error(Eisdir);
221                 break;
222         case Qclone:
223                 spin_lock(&vmlock);
224                 vms = krealloc(vms, sizeof(vms[0])*(nvm+1),0);
225                 v = &vms[nvm];
226                 nvm++;
227                 spin_unlock(&vmlock);
228                 kref_init(&v->kref, vm_release, 1);
229                 v->id = newvmid();
230                 mkqid(&c->qid, QID(v, Qctl), 0, QTFILE);
231                 c->aux = v;
232                 printd("New VM id %d\n", v->id);
233                 break;
234         case Qstat:
235                 break;
236         case Qctl:
237         case Qimage:
238                 /* the purpose of opening is to hold a kref on the proc_vm */
239                 v = c->aux;
240                 /* this isn't a valid pointer yet, since our chan doesn't have a
241                  * ref.  since the time that walk gave our chan the qid, the chan
242                  * could have been closed, and the vm decref'd and freed.  the
243                  * qid is essentially an uncounted reference, and we need to go to
244                  * the source to attempt to get a real ref.  Unfortunately, this is
245                  * another scan of the list, same as devsrv.  We could speed it up
246                  * by storing an "on_list" bool in the vm_is. */
247                 //if (!vm_i)
248                 //      error("Unable to open vm, concurrent closing");
249                 break;
250         }
251         c->mode = openmode(omode);
252         /* Assumes c is unique (can't be closed concurrently */
253         c->flag |= COPEN;
254         c->offset = 0;
255         return c;
256 }
257
258 static void vmcreate(struct chan *c, char *name, int omode, uint32_t perm)
259 {
260         error(Eperm);
261 }
262
263 static void vmremove(struct chan *c)
264 {
265         error(Eperm);
266 }
267
268 static int vmwstat(struct chan *c, uint8_t *dp, int n)
269 {
270         error("No vmwstat");
271         return 0;
272 }
273
274 static void vmclose(struct chan *c)
275 {
276         struct vm *v = c->aux;
277         if (!v)
278                 return;
279         /* There are more closes than opens.  For instance, sysstat doesn't open,
280          * but it will close the chan it got from namec.  We only want to clean
281          * up/decref chans that were actually open. */
282         if (!(c->flag & COPEN))
283                 return;
284         switch (TYPE(c->qid)) {
285                 /* for now, leave the VM active even when we close ctl */
286         case Qctl:
287                 break;
288         case Qimage:
289                 kref_put(&v->kref);
290                 break;
291         }
292 }
293
294 static long vmread(struct chan *c, void *ubuf, long n, int64_t offset)
295 {
296         struct vm *v = c->aux;
297         printd("VMREAD\n");
298         switch (TYPE(c->qid)) {
299         case Qtopdir:
300         case Qvmdir:
301                 return devdirread(c, ubuf, n, 0, 0, vmgen);
302         case Qstat:
303                 return readnum(offset, ubuf, n, nvm, NUMSIZE32);
304         case Qctl:
305                 assert(v);
306                 return readnum(offset, ubuf, n, v->id, NUMSIZE32);
307         case Qimage:
308                 assert(v);
309                 return readmem(offset, ubuf, n,
310                                v->image, v->imagesize);
311         default:
312                 panic("Bad QID %p in devvm", c->qid.path);
313         }
314         return 0;
315 }
316
317 static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
318 {
319         ERRSTACK(1);
320         char buf[32];
321         struct cmdbuf *cb;
322         struct vm *vm;
323         uint64_t hexval;
324
325         switch (TYPE(c->qid)) {
326         case Qtopdir:
327         case Qvmdir:
328         case Qstat:
329                 error(Eperm);
330         case Qctl:
331                 vm = c->aux;
332                 cb = parsecmd(ubuf, n);
333                 if (waserror()) {
334                         kfree(cb);
335                         nexterror();
336                 }
337                 if (!strcmp(cb->f[0], "start")) {
338                         error("can't run a vm yet");
339                 } else if (!strcmp(cb->f[0], "stop")) {
340                         error("can't stop a vm yet");
341                 } else {
342                         error("%s: not implemented", cb->f[0]);
343                 }
344                 kfree(cb);
345                 poperror();
346                 break;
347         case Qimage:
348                 error("can't write an image yet");
349                 break;
350         default:
351                 panic("Bad QID %p in devvm", c->qid.path);
352         }
353         return n;
354 }
355
356 struct dev vmdevtab = {
357         'V',
358         "vm",
359
360         devreset,
361         vminit,
362         devshutdown,
363         vmattach,
364         vmwalk,
365         vmstat,
366         vmopen,
367         vmcreate,
368         vmclose,
369         vmread,
370         devbread,
371         vmwrite,
372         devbwrite,
373         vmremove,
374         vmwstat,
375         devpower,
376 //      devconfig,
377 //      devchaninfo,
378 };