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