Run a NIX guest.
[akaros.git] / kern / drivers / dev / nix.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  * devnix/#t: a device for NIX mode
8  *
9  * A struct nix is a "visitor" chunk of code.  It has a memory image, and can be
10  * told to run an arbitrary address (in that image or otherwise) in kernel mode
11  * on various pcores, to which it has exclusive access.
12  *
13  * TODO:
14  *
15  * - FOR THE MOMENT, this is only intended to run one NIX at a time.  Too many
16  * sharp edges for any other mode.
17  *
18  * - memory images: we have one now for all nixs.  that'll be a mess.
19  *
20  * - what do we want to do for refcnting?  decref on chan close?  or remove?
21  * how do we manage the struct nix memory? (MGMT)
22  *              - right now, we aren't decreffing at all.  it's easier to work with from
23  *              the shell, but it's definitely a debugging thing.  the proper way to do
24  *              these devices is to release on close (i think).  the use case for the
25  *              NIX is a "turn it on once and reboot if you don't like it", so this is
26  *              fine for now.
27  *              - we're using c->aux, which needs to be an uncounted ref, in my opinion.
28  *              i messed around with this for a long time with devsrv, and all the
29  *              different ways 9ns interacts with a device make it very tricky.
30  *              - once we start freeing, we'll need to manage the memory better.  if we
31  *              have holes in the nixs[], we'll need to handle that in nixgen
32  *
33  * - how are we going to stop a nix?
34  *              - graceful vs immediate?  with some sort of immediate power-cord style
35  *              halting, the entire nix is garbage once we pull the plug.  a more
36  *              graceful style would require the nix to poll or something - probably
37  *              overkill.
38  *              - could send an immediate kmsg (IPI), but we'd need to do some
39  *              bookkeeping to know we're interrupting a NIX and whatnot
40  *              - if we were sure it's a nix core, we might be able to send an immediate
41  *              message telling the core to just smp_idle.  doing that from hard IRQ
42  *              would break a little, so we'd need to be careful (adjust various
43  *              flags, etc).
44  *              - another option would be to hack the halted context and have it call
45  *              a cleanup function (which ultimately smp_idles)
46  *              - if we had a process running the core, and "running the NIX" was a
47  *              syscall or something, we'd want to abort the syscall.  but since the
48  *              syscall isn't trying to rendez or sleep, we couldn't use the existing
49  *              facilities.  so it's the same problem: know it is a nix, somehow
50  *              kill/cleanup.  then just smp_idle.
51  *              - we'll also need to unreserve a core first, so we don't have any
52  *              concurrent startups.  careful of various races with cores coming and
53  *              going.  we can lock the nix before sending the message, but stale RKMs
54  *              could exist for a while.
55  *              - maybe we use a ktask, named nixID or something, to help detect if a
56  *              nix is running.  might also need to track the number of messages sent
57  *              and completed (track completed via the wrapper)
58  */
59
60 #include <kmalloc.h>
61 #include <string.h>
62 #include <stdio.h>
63 #include <assert.h>
64 #include <error.h>
65 #include <pmap.h>
66 #include <sys/queue.h>
67 #include <smp.h>
68 #include <kref.h>
69 #include <atomic.h>
70 #include <alarm.h>
71 #include <event.h>
72 #include <umem.h>
73 #include <devalarm.h>
74 #include <arch/types.h>
75 #include <arch/emulate.h>
76 #include <arch/vmdebug.h>
77 #include <kdebug.h>
78 #include <bitmap.h>
79
80 /* qid path types */
81 enum {
82         Qtopdir = 1,
83         Qclone,
84         Qstat,
85         Qnixdir,
86         Qctl,
87         Qimage,
88 };
89
90 /* The QID is the TYPE and the index into the nix array.
91  * We reserve the right to make it an id later. */
92 #define INDEX_SHIFT 5
93 /* nix's have an image.
94  * Note that the image can be read even as it is running. */
95 struct nix {
96         struct kref kref;
97         /* should this be an array of pages? Hmm. */
98         void *image;
99         unsigned long imagesize;
100         int id;
101         /* we could dynamically alloc one of these with num_cpus */
102         DECLARE_BITMAP(cpus, MAX_NUM_CPUS);
103 };
104
105 static spinlock_t nixlock = SPINLOCK_INITIALIZER_IRQSAVE;
106 /* array, not linked list. We expect few, might as well be cache friendly. */
107 static struct nix *nixs = NULL;
108 static int nnix = 0;
109 static int nixok = 0;
110 /* TODO: make this per-nix, somehow. */
111 static physaddr_t img_paddr = CONFIG_NIX_IMG_PADDR;
112 static size_t img_size = CONFIG_NIX_IMG_SIZE;
113
114 static atomic_t nixid = 0;
115
116 /* initial guest program. */
117 /*
118 .code64
119         pushq   %rax
120         pushq   %rdx
121         movb    $0x30, %al
122         movw    $0x3f8, %dx
123         outb    %al, %dx
124         popq    %rdx
125         popq    %rax
126         ret
127 */
128 unsigned char it[] = {
129   0x50, 0x52, 0xb0, 0x30, 0x66, 0xba, 0xf8, 0x03, 0xee, 0x5a, 0x58, 0xc3
130 };
131 unsigned int it_len = 12;
132
133
134 /* The index is not the id, for now.  The index is the spot in nixs[].  The id
135  * is an increasing integer, regardless of struct nix* reuse. */
136 static inline struct nix *QID2NIX(struct qid q)
137 {
138         return &nixs[q.path >> INDEX_SHIFT];
139 }
140
141 static inline int TYPE(struct qid q)
142 {
143         return ((q).path & ((1 << INDEX_SHIFT) - 1));
144 }
145
146 static inline int QID(int index, int type)
147 {
148         return ((index << INDEX_SHIFT) | type);
149 }
150
151 static inline int QID2ID(struct qid q)
152 {
153         return q.path >> INDEX_SHIFT;
154 }
155
156 /* TODO: (MGMT) not called yet.  -- we have to unlink the nix */
157 static void nix_release(struct kref *kref)
158 {
159         struct nix *v = container_of(kref, struct nix, kref);
160         spin_lock_irqsave(&nixlock);
161         /* cute trick. Save the last element of the array in place of the
162          * one we're deleting. Reduce nnix. Don't realloc; that way, next
163          * time we add a nix the allocator will just return.
164          * Well, this is stupid, because when we do this, we break
165          * the QIDs, which have pointers embedded in them.
166          * darn it, may have to use a linked list. Nope, will probably
167          * just walk the array until we find a matching id. Still ... yuck.
168          *
169          * If we have lots, we can track the lowest free, similar to FDs and low_fd.
170          * honestly, we need an integer allocator (vmem and magazine paper) */
171         if (v != &nixs[nnix - 1]) {
172                 /* free the image ... oops */
173                 /* get rid of the kref. */
174                 *v = nixs[nnix - 1];
175         }
176         nnix--;
177         spin_unlock(&nixlock);
178 }
179
180 /* NIX ids run in the range 0..infinity.  */
181 static int newnixid(void)
182 {
183         return atomic_fetch_and_add(&nixid, 1);
184 }
185
186 static int nixgen(struct chan *c, char *entry_name,
187                    struct dirtab *unused, int unused_nr_dirtab,
188                    int s, struct dir *dp)
189 {
190         struct qid q;
191         struct nix *nix_i;
192         /* Whether we're in one dir or at the top, .. still takes us to the top. */
193         if (s == DEVDOTDOT) {
194                 mkqid(&q, Qtopdir, 0, QTDIR);
195                 devdir(c, c->qid, "#V", 0, eve, 0555, dp);
196                 return 1;
197         }
198         switch (TYPE(c->qid)) {
199         case Qtopdir:
200                 /* Generate elements for the top level dir.  We support clone, stat,
201                  * nix dirs at the top level */
202                 if (s == 0) {
203                         mkqid(&q, Qclone, 0, QTFILE);
204                         devdir(c, q, "clone", 0, eve, 0666, dp);
205                         return 1;
206                 }
207                 s--;
208                 if (s == 0) {
209                         mkqid(&q, Qstat, 0, QTFILE);
210                         devdir(c, q, "stat", 0, eve, 0666, dp);
211                         return 1;
212                 }
213                 s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
214                 spin_lock_irqsave(&nixlock);
215                 if (s >= nnix) {
216                         spin_unlock(&nixlock);
217                         return -1;
218                 }
219                 nix_i = &nixs[s];
220                 /* TODO (MGMT): if no nix_i, advance (in case of holes) */
221                 snprintf(get_cur_genbuf(), GENBUF_SZ, "nix%d", nix_i->id);
222                 spin_unlock(&nixlock);
223                 mkqid(&q, QID(s, Qnixdir), 0, QTDIR);
224                 devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
225                 return 1;
226         case Qnixdir:
227                 /* Gen the contents of the nix dirs */
228                 s += Qctl;      /* first time through, start on Qctl */
229                 switch (s) {
230                 case Qctl:
231                         mkqid(&q, QID(QID2ID(c->qid), Qctl), 0, QTFILE);
232                         devdir(c, q, "ctl", 0, eve, 0666, dp);
233                         return 1;
234                 case Qimage:
235                         mkqid(&q, QID(QID2ID(c->qid), Qimage), 0, QTFILE);
236                         devdir(c, q, "image", 0, eve, 0666, dp);
237                         return 1;
238                 }
239                 return -1;
240                 /* Need to also provide a direct hit for Qclone and all other files (at
241                  * all levels of the hierarchy).  Every file is both
242                  * generated (via the s increments in their respective directories) and
243                  * directly gen-able.  devstat() will call gen with a specific path in
244                  * the qid.  In these cases, we make a dir for whatever they are asking
245                  * for.  Note the qid stays the same.  I think this is what the old
246                  * plan9 comments above devgen were talking about for (ii).
247                  *
248                  * We don't need to do this for the directories - devstat will look for
249                  * the a directory by path and fail.  Then it will manually build the
250                  * stat output (check the -1 case in devstat). */
251         case Qclone:
252                 devdir(c, c->qid, "clone", 0, eve, 0666, dp);
253                 return 1;
254         case Qstat:
255                 devdir(c, c->qid, "stat", 0, eve, 0444, dp);
256                 return 1;
257         case Qctl:
258                 devdir(c, c->qid, "ctl", 0, eve, 0666, dp);
259                 return 1;
260         case Qimage:
261                 devdir(c, c->qid, "image", 0, eve, 0666, dp);
262                 return 1;
263         }
264         return -1;
265 }
266
267 void nixtest(void)
268 {
269         printk("nixtest ran on core %d\n", core_id());
270 }
271
272 static void nixinit(void)
273 {
274         size_t img_order = LOG2_UP(nr_pages(img_size));
275         void *img_kaddr;
276
277         if (img_size != 1ULL << img_order << PGSHIFT) {
278                 printk("nixinit rounding up image size to a power of 2 pgs (was %p)\n",
279                        img_size);
280                 img_size = 1ULL << img_order << PGSHIFT;
281         }
282         img_kaddr = get_cont_phys_pages_at(img_order, img_paddr, 0);
283         if (!img_kaddr) {
284                 printk("nixinit failed to get an image!\n");
285                 return;
286         }
287         nixok = 1;
288         printk("nixinit image at KVA %p of size %p\n", img_kaddr, img_size);
289 }
290
291 static struct chan *nixattach(char *spec)
292 {
293         if (!nixok)
294                 error("No NIXs available");
295         struct chan *c = devattach('t', spec);
296         mkqid(&c->qid, Qtopdir, 0, QTDIR);
297         return c;
298 }
299
300 static struct walkqid *nixwalk(struct chan *c, struct chan *nc, char **name,
301                                 int nname)
302 {
303         return devwalk(c, nc, name, nname, 0, 0, nixgen);
304 }
305
306 static int nixstat(struct chan *c, uint8_t * db, int n)
307 {
308         return devstat(c, db, n, 0, 0, nixgen);
309 }
310
311 /* It shouldn't matter if p = current is DYING.  We'll eventually fail to insert
312  * the open chan into p's fd table, then decref the chan. */
313 static struct chan *nixopen(struct chan *c, int omode)
314 {
315         ERRSTACK(1);
316         struct nix *v = QID2NIX(c->qid);
317         if (waserror()) {
318                 nexterror();
319         }
320         switch (TYPE(c->qid)) {
321         case Qtopdir:
322         case Qnixdir:
323                 if (omode & ORCLOSE)
324                         error(Eperm);
325                 if (!IS_RDONLY(omode))
326                         error(Eisdir);
327                 break;
328         case Qclone:
329                 spin_lock_irqsave(&nixlock);
330                 if (nnix >= 1) {
331                         spin_unlock_irqsave(&nixlock);
332                         set_errno(EBUSY);
333                         error("Already have 1 nix, we don't support more");
334                 }
335                 nixs = krealloc(nixs, sizeof(nixs[0]) * (nnix + 1), 0);
336                 v = &nixs[nnix];
337                 mkqid(&c->qid, QID(nnix, Qctl), 0, QTFILE);
338                 nnix++;
339                 spin_unlock(&nixlock);
340                 kref_init(&v->kref, nix_release, 1);
341                 v->id = newnixid();
342                 v->image = KADDR(img_paddr);
343                 v->imagesize = img_size;
344                 printk("nix image is %p with %d bytes\n", v->image, v->imagesize);
345                 c->aux = v;
346                 bitmap_zero(v->cpus, MAX_NUM_CPUS);
347                 memcpy(v->image, it, sizeof(it));
348                 break;
349         case Qstat:
350                 break;
351         case Qctl:
352         case Qimage:
353                 /* TODO: (MGMT) refcnting */
354                 //kref_get(&v->kref, 1);
355                 c->aux = QID2NIX(c->qid);
356                 break;
357         }
358         c->mode = openmode(omode);
359         /* Assumes c is unique (can't be closed concurrently */
360         c->flag |= COPEN;
361         c->offset = 0;
362         poperror();
363         return c;
364 }
365
366 static void nixcreate(struct chan *c, char *name, int omode, uint32_t perm)
367 {
368         error(Eperm);
369 }
370
371 static void nixremove(struct chan *c)
372 {
373         error(Eperm);
374 }
375
376 static int nixwstat(struct chan *c, uint8_t * dp, int n)
377 {
378         error("No nixwstat");
379         return 0;
380 }
381
382 static void nixclose(struct chan *c)
383 {
384         struct nix *v = c->aux;
385         if (!v)
386                 return;
387         /* There are more closes than opens.  For instance, sysstat doesn't open,
388          * but it will close the chan it got from namec.  We only want to clean
389          * up/decref chans that were actually open. */
390         if (!(c->flag & COPEN))
391                 return;
392         switch (TYPE(c->qid)) {
393                 /* TODO: (MGMT) the idea of 'stopping' a nix is tricky.
394                  * for now, leave the NIX active even when we close ctl */
395         case Qctl:
396                 break;
397         case Qimage:
398                 //kref_put(&v->kref);
399                 break;
400         }
401 }
402
403 static long nixread(struct chan *c, void *ubuf, long n, int64_t offset)
404 {
405         struct nix *v = c->aux;
406         switch (TYPE(c->qid)) {
407         case Qtopdir:
408         case Qnixdir:
409                 return devdirread(c, ubuf, n, 0, 0, nixgen);
410         case Qstat:
411                 return readnum(offset, ubuf, n, nnix, NUMSIZE32);
412         case Qctl:
413                 assert(v);
414                 return readnum(offset, ubuf, n, v->id, NUMSIZE32);
415         case Qimage:
416                 assert(v);
417                 return readmem(offset, ubuf, n, v->image, v->imagesize);
418         default:
419                 panic("Bad QID %p in devnix", c->qid.path);
420         }
421         return 0;
422 }
423
424 static void nixwrapper(uint32_t srcid, long a0, long a1, long a2)
425 {
426         void (*f)(void) = (void (*)(void))a0;
427         f();
428         /* TODO: could do some tracking to say this message has been completed */
429 }
430
431 static long nixwrite(struct chan *c, void *ubuf, long n, int64_t off)
432 {
433         struct nix *v = c->aux;
434         ERRSTACK(1);
435         char buf[32];
436         struct cmdbuf *cb;
437         struct nix *nix;
438         uint64_t hexval;
439
440         switch (TYPE(c->qid)) {
441         case Qtopdir:
442         case Qnixdir:
443         case Qstat:
444                 error(Eperm);
445         case Qctl:
446                 nix = c->aux;
447                 cb = parsecmd(ubuf, n);
448                 /* TODO: lock the nix here, unlock in waserror and before popping */
449                 if (waserror()) {
450                         kfree(cb);
451                         nexterror();
452                 }
453                 if (cb->nf < 1)
454                         error("short control request");
455                 if (!strcmp(cb->f[0], "run")) {
456                         int core;
457                         uintptr_t ip;
458                         if (cb->nf != 3)
459                                 error("usage: run core entry");
460                         core = strtoul(cb->f[1], 0, 0);
461                         ip = strtoul(cb->f[2], 0, 0);
462                         if (!test_bit(core, nix->cpus))
463                                 error("Bad core %d", core);
464                         send_kernel_message(core, nixwrapper, (long)ip, 0, 0, KMSG_ROUTINE);
465                 } else if (!strcmp(cb->f[0], "test")) {
466                         int core;
467                         if (cb->nf != 2)
468                                 error("usage: test core");
469                         core = strtoul(cb->f[1], 0, 0);
470                         if (!test_bit(core, nix->cpus))
471                                 error("Bad core %d", core);
472                         send_kernel_message(core, nixwrapper, (long)nixtest, 0, 0,
473                                             KMSG_ROUTINE);
474                 } else if (!strcmp(cb->f[0], "reserve")) {
475                         int core;
476                         if (cb->nf != 2)
477                                 error("Usage: reserve core (-1 for any)");
478                         core = strtol(cb->f[1], 0, 0);
479                         if (core == -1) {
480                                 core = get_any_idle_core();
481                                 if (core < 0)
482                                         error("No free idle cores!");
483                         } else {
484                                 if (get_this_idle_core(core) < 0)
485                                         error("Failed to reserve core %d\n", core);
486                         }
487                         set_bit(core, nix->cpus);
488                 } else if (!strcmp(cb->f[0], "check")) {
489                         int i;
490                         for(i = 0; i < MAX_NUM_CPUS; i++) {
491                                 if (!test_bit(i, nix->cpus))
492                                         continue;
493                                 printk("Core %d is available to nix%d\n", i, nix->id);
494                         }
495                 } else if (!strcmp(cb->f[0], "stop")) {
496                         error("can't stop a nix yet");
497                 } else {
498                         error("%s: not implemented", cb->f[0]);
499                 }
500                 kfree(cb);
501                 poperror();
502                 break;
503         case Qimage:
504                 if (off < 0)
505                         error("offset < 0!");
506
507                 if (off + n > v->imagesize) {
508                         n = v->imagesize - off;
509                 }
510
511                 if (memcpy_from_user_errno(current, v->image + off, ubuf, n) < 0)
512                         error("%s: bad user addr %p", __FUNCTION__, ubuf);
513                 break;
514
515         default:
516                 panic("Bad QID %p in devnix", c->qid.path);
517         }
518         return n;
519 }
520
521 struct dev nixdevtab __devtab = {
522         't',
523         "nix",
524
525         devreset,
526         nixinit,
527         devshutdown,
528         nixattach,
529         nixwalk,
530         nixstat,
531         nixopen,
532         nixcreate,
533         nixclose,
534         nixread,
535         devbread,
536         nixwrite,
537         devbwrite,
538         nixremove,
539         nixwstat,
540         devpower,
541 //  devconfig,
542         devchaninfo,
543 };