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