016b87e384b2cb8a9b79c7561bbd1fdb0ba812dc
[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 <kdebug.h>
77 #include <bitmap.h>
78
79 struct dev nixdevtab;
80
81 static char *devname(void)
82 {
83         return nixdevtab.name;
84 }
85
86 /* qid path types */
87 enum {
88         Qtopdir = 1,
89         Qclone,
90         Qstat,
91         Qnixdir,
92         Qctl,
93         Qimage,
94 };
95
96 /* The QID is the TYPE and the index into the nix array.
97  * We reserve the right to make it an id later. */
98 #define INDEX_SHIFT 5
99 /* nix's have an image.
100  * Note that the image can be read even as it is running. */
101 struct nix {
102         struct kref kref;
103         /* should this be an array of pages? Hmm. */
104         void *image;
105         unsigned long imagesize;
106         int id;
107         /* we could dynamically alloc one of these with num_cores */
108         DECLARE_BITMAP(cpus, MAX_NUM_CORES);
109 };
110
111 static spinlock_t nixlock = SPINLOCK_INITIALIZER_IRQSAVE;
112 /* array, not linked list. We expect few, might as well be cache friendly. */
113 static struct nix *nixs = NULL;
114 static int nnix = 0;
115 static int nixok = 0;
116 /* TODO: make this per-nix, somehow. */
117 static physaddr_t img_paddr = CONFIG_NIX_IMG_PADDR;
118 static size_t img_size = CONFIG_NIX_IMG_SIZE;
119
120 static atomic_t nixid = 0;
121
122 /* initial guest program. */
123 /*
124 .code64
125         pushq   %rax
126         pushq   %rdx
127         movb    $0x30, %al
128         movw    $0x3f8, %dx
129         outb    %al, %dx
130         popq    %rdx
131         popq    %rax
132         ret
133 */
134 unsigned char it[] = {
135   0x50, 0x52, 0xb0, 0x30, 0x66, 0xba, 0xf8, 0x03, 0xee, 0x5a, 0x58, 0xc3
136 };
137 unsigned int it_len = 12;
138
139
140 /* The index is not the id, for now.  The index is the spot in nixs[].  The id
141  * is an increasing integer, regardless of struct nix* reuse. */
142 static inline struct nix *QID2NIX(struct qid q)
143 {
144         return &nixs[q.path >> INDEX_SHIFT];
145 }
146
147 static inline int TYPE(struct qid q)
148 {
149         return ((q).path & ((1 << INDEX_SHIFT) - 1));
150 }
151
152 static inline int QID(int index, int type)
153 {
154         return ((index << INDEX_SHIFT) | type);
155 }
156
157 static inline int QID2ID(struct qid q)
158 {
159         return q.path >> INDEX_SHIFT;
160 }
161
162 /* TODO: (MGMT) not called yet.  -- we have to unlink the nix */
163 static void nix_release(struct kref *kref)
164 {
165         struct nix *v = container_of(kref, struct nix, kref);
166         spin_lock_irqsave(&nixlock);
167         /* cute trick. Save the last element of the array in place of the
168          * one we're deleting. Reduce nnix. Don't realloc; that way, next
169          * time we add a nix the allocator will just return.
170          * Well, this is stupid, because when we do this, we break
171          * the QIDs, which have pointers embedded in them.
172          * darn it, may have to use a linked list. Nope, will probably
173          * just walk the array until we find a matching id. Still ... yuck.
174          *
175          * If we have lots, we can track the lowest free, similar to FDs and low_fd.
176          * honestly, we need an integer allocator (vmem and magazine paper) */
177         if (v != &nixs[nnix - 1]) {
178                 /* free the image ... oops */
179                 /* get rid of the kref. */
180                 *v = nixs[nnix - 1];
181         }
182         nnix--;
183         spin_unlock(&nixlock);
184 }
185
186 /* NIX ids run in the range 0..infinity.  */
187 static int newnixid(void)
188 {
189         return atomic_fetch_and_add(&nixid, 1);
190 }
191
192 static int nixgen(struct chan *c, char *entry_name,
193                    struct dirtab *unused, int unused_nr_dirtab,
194                    int s, struct dir *dp)
195 {
196         struct qid q;
197         struct nix *nix_i;
198         /* Whether we're in one dir or at the top, .. still takes us to the top. */
199         if (s == DEVDOTDOT) {
200                 mkqid(&q, Qtopdir, 0, QTDIR);
201                 devdir(c, c->qid, devname(), 0, eve, 0555, dp);
202                 return 1;
203         }
204         switch (TYPE(c->qid)) {
205         case Qtopdir:
206                 /* Generate elements for the top level dir.  We support clone, stat,
207                  * nix dirs at the top level */
208                 if (s == 0) {
209                         mkqid(&q, Qclone, 0, QTFILE);
210                         devdir(c, q, "clone", 0, eve, 0666, dp);
211                         return 1;
212                 }
213                 s--;
214                 if (s == 0) {
215                         mkqid(&q, Qstat, 0, QTFILE);
216                         devdir(c, q, "stat", 0, eve, 0666, dp);
217                         return 1;
218                 }
219                 s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
220                 spin_lock_irqsave(&nixlock);
221                 if (s >= nnix) {
222                         spin_unlock(&nixlock);
223                         return -1;
224                 }
225                 nix_i = &nixs[s];
226                 /* TODO (MGMT): if no nix_i, advance (in case of holes) */
227                 snprintf(get_cur_genbuf(), GENBUF_SZ, "nix%d", nix_i->id);
228                 spin_unlock(&nixlock);
229                 mkqid(&q, QID(s, Qnixdir), 0, QTDIR);
230                 devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
231                 return 1;
232         case Qnixdir:
233                 /* Gen the contents of the nix dirs */
234                 s += Qctl;      /* first time through, start on Qctl */
235                 switch (s) {
236                 case Qctl:
237                         mkqid(&q, QID(QID2ID(c->qid), Qctl), 0, QTFILE);
238                         devdir(c, q, "ctl", 0, eve, 0666, dp);
239                         return 1;
240                 case Qimage:
241                         mkqid(&q, QID(QID2ID(c->qid), Qimage), 0, QTFILE);
242                         devdir(c, q, "image", 0, eve, 0666, dp);
243                         return 1;
244                 }
245                 return -1;
246                 /* Need to also provide a direct hit for Qclone and all other files (at
247                  * all levels of the hierarchy).  Every file is both
248                  * generated (via the s increments in their respective directories) and
249                  * directly gen-able.  devstat() will call gen with a specific path in
250                  * the qid.  In these cases, we make a dir for whatever they are asking
251                  * for.  Note the qid stays the same.  I think this is what the old
252                  * plan9 comments above devgen were talking about for (ii).
253                  *
254                  * We don't need to do this for the directories - devstat will look for
255                  * the a directory by path and fail.  Then it will manually build the
256                  * stat output (check the -1 case in devstat). */
257         case Qclone:
258                 devdir(c, c->qid, "clone", 0, eve, 0666, dp);
259                 return 1;
260         case Qstat:
261                 devdir(c, c->qid, "stat", 0, eve, 0444, dp);
262                 return 1;
263         case Qctl:
264                 devdir(c, c->qid, "ctl", 0, eve, 0666, dp);
265                 return 1;
266         case Qimage:
267                 devdir(c, c->qid, "image", 0, eve, 0666, dp);
268                 return 1;
269         }
270         return -1;
271 }
272
273 void nixtest(void)
274 {
275         printk("nixtest ran on core %d\n", core_id());
276 }
277
278 static void nixinit(void)
279 {
280         size_t img_order = LOG2_UP(nr_pages(img_size));
281         void *img_kaddr;
282
283         if (img_size != 1ULL << img_order << PGSHIFT) {
284                 printk("nixinit rounding up image size to a power of 2 pgs (was %p)\n",
285                        img_size);
286                 img_size = 1ULL << img_order << PGSHIFT;
287         }
288         img_kaddr = get_cont_phys_pages_at(img_order, img_paddr, 0);
289         if (!img_kaddr) {
290                 printk("nixinit failed to get an image!\n");
291                 return;
292         }
293         nixok = 1;
294         printk("nixinit image at KVA %p of size %p\n", img_kaddr, img_size);
295 }
296
297 static struct chan *nixattach(char *spec)
298 {
299         if (!nixok)
300                 error(EFAIL, "No NIXs available");
301         struct chan *c = devattach(devname(), spec);
302         mkqid(&c->qid, Qtopdir, 0, QTDIR);
303         return c;
304 }
305
306 static struct walkqid *nixwalk(struct chan *c, struct chan *nc, char **name,
307                                 int nname)
308 {
309         return devwalk(c, nc, name, nname, 0, 0, nixgen);
310 }
311
312 static int nixstat(struct chan *c, uint8_t * db, int n)
313 {
314         return devstat(c, db, n, 0, 0, nixgen);
315 }
316
317 /* It shouldn't matter if p = current is DYING.  We'll eventually fail to insert
318  * the open chan into p's fd table, then decref the chan. */
319 static struct chan *nixopen(struct chan *c, int omode)
320 {
321         ERRSTACK(1);
322         struct nix *v = QID2NIX(c->qid);
323         if (waserror()) {
324                 nexterror();
325         }
326         switch (TYPE(c->qid)) {
327         case Qtopdir:
328         case Qnixdir:
329                 if (omode & O_REMCLO)
330                         error(EPERM, ERROR_FIXME);
331                 if (omode & O_WRITE)
332                         error(EISDIR, ERROR_FIXME);
333                 break;
334         case Qclone:
335                 spin_lock_irqsave(&nixlock);
336                 if (nnix >= 1) {
337                         spin_unlock_irqsave(&nixlock);
338                         set_errno(EBUSY);
339                         error(EFAIL, "Already have 1 nix, we don't support more");
340                 }
341                 nixs = krealloc(nixs, sizeof(nixs[0]) * (nnix + 1), 0);
342                 v = &nixs[nnix];
343                 mkqid(&c->qid, QID(nnix, Qctl), 0, QTFILE);
344                 nnix++;
345                 spin_unlock(&nixlock);
346                 kref_init(&v->kref, nix_release, 1);
347                 v->id = newnixid();
348                 v->image = KADDR(img_paddr);
349                 v->imagesize = img_size;
350                 printk("nix image is %p with %d bytes\n", v->image, v->imagesize);
351                 c->aux = v;
352                 bitmap_zero(v->cpus, MAX_NUM_CORES);
353                 memcpy(v->image, it, sizeof(it));
354                 break;
355         case Qstat:
356                 break;
357         case Qctl:
358         case Qimage:
359                 /* TODO: (MGMT) refcnting */
360                 //kref_get(&v->kref, 1);
361                 c->aux = QID2NIX(c->qid);
362                 break;
363         }
364         c->mode = openmode(omode);
365         /* Assumes c is unique (can't be closed concurrently */
366         c->flag |= COPEN;
367         c->offset = 0;
368         poperror();
369         return c;
370 }
371
372 static void nixcreate(struct chan *c, char *name, int omode, uint32_t perm)
373 {
374         error(EPERM, ERROR_FIXME);
375 }
376
377 static void nixremove(struct chan *c)
378 {
379         error(EPERM, ERROR_FIXME);
380 }
381
382 static int nixwstat(struct chan *c, uint8_t * dp, int n)
383 {
384         error(EFAIL, "No nixwstat");
385         return 0;
386 }
387
388 static void nixclose(struct chan *c)
389 {
390         struct nix *v = c->aux;
391         if (!v)
392                 return;
393         /* There are more closes than opens.  For instance, sysstat doesn't open,
394          * but it will close the chan it got from namec.  We only want to clean
395          * up/decref chans that were actually open. */
396         if (!(c->flag & COPEN))
397                 return;
398         switch (TYPE(c->qid)) {
399                 /* TODO: (MGMT) the idea of 'stopping' a nix is tricky.
400                  * for now, leave the NIX active even when we close ctl */
401         case Qctl:
402                 break;
403         case Qimage:
404                 //kref_put(&v->kref);
405                 break;
406         }
407 }
408
409 static long nixread(struct chan *c, void *ubuf, long n, int64_t offset)
410 {
411         struct nix *v = c->aux;
412         switch (TYPE(c->qid)) {
413         case Qtopdir:
414         case Qnixdir:
415                 return devdirread(c, ubuf, n, 0, 0, nixgen);
416         case Qstat:
417                 return readnum(offset, ubuf, n, nnix, NUMSIZE32);
418         case Qctl:
419                 assert(v);
420                 return readnum(offset, ubuf, n, v->id, NUMSIZE32);
421         case Qimage:
422                 assert(v);
423                 return readmem(offset, ubuf, n, v->image, v->imagesize);
424         default:
425                 panic("Bad QID %p in devnix", c->qid.path);
426         }
427         return 0;
428 }
429
430 static void nixwrapper(uint32_t srcid, long a0, long a1, long a2)
431 {
432         void (*f)(void) = (void (*)(void))a0;
433         f();
434         /* TODO: could do some tracking to say this message has been completed */
435 }
436
437 static long nixwrite(struct chan *c, void *ubuf, long n, int64_t off)
438 {
439         struct nix *v = c->aux;
440         ERRSTACK(1);
441         char buf[32];
442         struct cmdbuf *cb;
443         struct nix *nix;
444         uint64_t hexval;
445
446         switch (TYPE(c->qid)) {
447         case Qtopdir:
448         case Qnixdir:
449         case Qstat:
450                 error(EPERM, ERROR_FIXME);
451         case Qctl:
452                 nix = c->aux;
453                 cb = parsecmd(ubuf, n);
454                 /* TODO: lock the nix here, unlock in waserror and before popping */
455                 if (waserror()) {
456                         kfree(cb);
457                         nexterror();
458                 }
459                 if (cb->nf < 1)
460                         error(EFAIL, "short control request");
461                 if (!strcmp(cb->f[0], "run")) {
462                         int core;
463                         uintptr_t ip;
464                         if (cb->nf != 3)
465                                 error(EFAIL, "usage: run core entry");
466                         core = strtoul(cb->f[1], 0, 0);
467                         ip = strtoul(cb->f[2], 0, 0);
468                         if (!test_bit(core, nix->cpus))
469                                 error(EFAIL, "Bad core %d", core);
470                         send_kernel_message(core, nixwrapper, (long)ip, 0, 0, KMSG_ROUTINE);
471                 } else if (!strcmp(cb->f[0], "test")) {
472                         int core;
473                         if (cb->nf != 2)
474                                 error(EFAIL, "usage: test core");
475                         core = strtoul(cb->f[1], 0, 0);
476                         if (!test_bit(core, nix->cpus))
477                                 error(EFAIL, "Bad core %d", core);
478                         send_kernel_message(core, nixwrapper, (long)nixtest, 0, 0,
479                                             KMSG_ROUTINE);
480                 } else if (!strcmp(cb->f[0], "reserve")) {
481                         int core;
482                         if (cb->nf != 2)
483                                 error(EFAIL, "Usage: reserve core (-1 for any)");
484                         core = strtol(cb->f[1], 0, 0);
485                         if (core == -1) {
486                                 core = get_any_idle_core();
487                                 if (core < 0)
488                                         error(EFAIL, "No free idle cores!");
489                         } else {
490                                 if (get_specific_idle_core(core) < 0)
491                                         error(EFAIL, "Failed to reserve core %d\n", core);
492                         }
493                         set_bit(core, nix->cpus);
494                 } else if (!strcmp(cb->f[0], "check")) {
495                         int i;
496                         for(i = 0; i < MAX_NUM_CORES; i++) {
497                                 if (!test_bit(i, nix->cpus))
498                                         continue;
499                                 printk("Core %d is available to nix%d\n", i, nix->id);
500                         }
501                 } else if (!strcmp(cb->f[0], "stop")) {
502                         error(EFAIL, "can't stop a nix yet");
503                 } else {
504                         error(EFAIL, "%s: not implemented", cb->f[0]);
505                 }
506                 kfree(cb);
507                 poperror();
508                 break;
509         case Qimage:
510                 if (off < 0)
511                         error(EFAIL, "offset < 0!");
512
513                 if (off + n > v->imagesize) {
514                         n = v->imagesize - off;
515                 }
516
517                 if (memcpy_from_user_errno(current, v->image + off, ubuf, n) < 0)
518                         error(EFAIL, "%s: bad user addr %p", __FUNCTION__, ubuf);
519                 break;
520
521         default:
522                 panic("Bad QID %p in devnix", c->qid.path);
523         }
524         return n;
525 }
526
527 struct dev nixdevtab __devtab = {
528         .name = "nix",
529
530         .reset = devreset,
531         .init = nixinit,
532         .shutdown = devshutdown,
533         .attach = nixattach,
534         .walk = nixwalk,
535         .stat = nixstat,
536         .open = nixopen,
537         .create = nixcreate,
538         .close = nixclose,
539         .read = nixread,
540         .bread = devbread,
541         .write = nixwrite,
542         .bwrite = devbwrite,
543         .remove = nixremove,
544         .wstat = nixwstat,
545         .power = devpower,
546         .chaninfo = devchaninfo,
547 };