Add the skeleton for vm support
[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/litevm.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         struct chan *c = devattach('V', spec);
190         mkqid(&c->qid, Qtopdir, 0, QTDIR);
191         return c;
192 }
193
194 static struct walkqid *vmwalk(struct chan *c, struct chan *nc, char **name,
195                               int nname)
196 {
197         return devwalk(c, nc, name, nname, 0, 0, vmgen);
198 }
199
200 static int vmstat(struct chan *c, uint8_t *db, int n)
201 {
202         return devstat(c, db, n, 0, 0, vmgen);
203 }
204
205 /* It shouldn't matter if p = current is DYING.  We'll eventually fail to insert
206  * the open chan into p's fd table, then decref the chan. */
207 static struct chan *vmopen(struct chan *c, int omode)
208 {
209         struct vm *v = c->aux;
210         switch (TYPE(c->qid)) {
211         case Qtopdir:
212         case Qvmdir:
213                 if (omode & ORCLOSE)
214                         error(Eperm);
215                 if (omode != OREAD)
216                         error(Eisdir);
217                 break;
218         case Qclone:
219                 spin_lock(&vmlock);
220                 vms = krealloc(vms, sizeof(vms[0])*(nvm+1),0);
221                 v = &vms[nvm];
222                 nvm++;
223                 spin_unlock(&vmlock);
224                 kref_init(&v->kref, vm_release, 1);
225                 v->id = newvmid();
226                 mkqid(&c->qid, QID(v, Qctl), 0, QTFILE);
227                 c->aux = v;
228                 printd("New VM id %d\n", v->id);
229                 break;
230         case Qstat:
231                 break;
232         case Qctl:
233         case Qimage:
234                 /* the purpose of opening is to hold a kref on the proc_vm */
235                 v = c->aux;
236                 /* this isn't a valid pointer yet, since our chan doesn't have a
237                  * ref.  since the time that walk gave our chan the qid, the chan
238                  * could have been closed, and the vm decref'd and freed.  the
239                  * qid is essentially an uncounted reference, and we need to go to
240                  * the source to attempt to get a real ref.  Unfortunately, this is
241                  * another scan of the list, same as devsrv.  We could speed it up
242                  * by storing an "on_list" bool in the vm_is. */
243                 //if (!vm_i)
244                 //      error("Unable to open vm, concurrent closing");
245                 break;
246         }
247         c->mode = openmode(omode);
248         /* Assumes c is unique (can't be closed concurrently */
249         c->flag |= COPEN;
250         c->offset = 0;
251         return c;
252 }
253
254 static void vmcreate(struct chan *c, char *name, int omode, uint32_t perm)
255 {
256         error(Eperm);
257 }
258
259 static void vmremove(struct chan *c)
260 {
261         error(Eperm);
262 }
263
264 static int vmwstat(struct chan *c, uint8_t *dp, int n)
265 {
266         error("No vmwstat");
267         return 0;
268 }
269
270 static void vmclose(struct chan *c)
271 {
272         struct vm *v = c->aux;
273         if (!v)
274                 return;
275         /* There are more closes than opens.  For instance, sysstat doesn't open,
276          * but it will close the chan it got from namec.  We only want to clean
277          * up/decref chans that were actually open. */
278         if (!(c->flag & COPEN))
279                 return;
280         switch (TYPE(c->qid)) {
281                 /* for now, leave the VM active even when we close ctl */
282         case Qctl:
283                 break;
284         case Qimage:
285                 kref_put(&v->kref);
286                 break;
287         }
288 }
289
290 static long vmread(struct chan *c, void *ubuf, long n, int64_t offset)
291 {
292         struct vm *v = c->aux;
293         printd("VMREAD\n");
294         switch (TYPE(c->qid)) {
295         case Qtopdir:
296         case Qvmdir:
297                 return devdirread(c, ubuf, n, 0, 0, vmgen);
298         case Qstat:
299                 return readnum(offset, ubuf, n, nvm, NUMSIZE32);
300         case Qctl:
301                 assert(v);
302                 return readnum(offset, ubuf, n, v->id, NUMSIZE32);
303         case Qimage:
304                 assert(v);
305                 return readmem(offset, ubuf, n,
306                                v->image, v->imagesize);
307         default:
308                 panic("Bad QID %p in devvm", c->qid.path);
309         }
310         return 0;
311 }
312
313 static long vmwrite(struct chan *c, void *ubuf, long n, int64_t unused)
314 {
315         ERRSTACK(1);
316         char buf[32];
317         struct cmdbuf *cb;
318         struct vm *vm;
319         uint64_t hexval;
320
321         switch (TYPE(c->qid)) {
322         case Qtopdir:
323         case Qvmdir:
324         case Qstat:
325                 error(Eperm);
326         case Qctl:
327                 vm = c->aux;
328                 cb = parsecmd(ubuf, n);
329                 if (waserror()) {
330                         kfree(cb);
331                         nexterror();
332                 }
333                 if (!strcmp(cb->f[0], "start")) {
334                         error("can't run a vm yet");
335                 } else if (!strcmp(cb->f[0], "stop")) {
336                         error("can't stop a vm yet");
337                 } else {
338                         error("%s: not implemented", cb->f[0]);
339                 }
340                 kfree(cb);
341                 poperror();
342                 break;
343         case Qimage:
344                 error("can't write an image yet");
345                 break;
346         default:
347                 panic("Bad QID %p in devvm", c->qid.path);
348         }
349         return n;
350 }
351
352 struct dev vmdevtab = {
353         'V',
354         "vm",
355
356         devreset,
357         vminit,
358         devshutdown,
359         vmattach,
360         vmwalk,
361         vmstat,
362         vmopen,
363         vmcreate,
364         vmclose,
365         vmread,
366         devbread,
367         vmwrite,
368         devbwrite,
369         vmremove,
370         vmwstat,
371         devpower,
372 //      devconfig,
373 //      devchaninfo,
374 };