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