Nix work assignments use RKMs
[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  */
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 #include <arch/types.h>
26 #include <arch/nix.h>
27 #include <arch/emulate.h>
28 #include <arch/vmdebug.h>
29 #include <kdebug.h>
30 #include <bitmap.h>
31
32 /* qid path types */
33 enum {
34         Qtopdir = 1,
35         Qclone,
36         Qstat,
37         Qnixdir,
38         Qctl,
39         Qimage,
40 };
41
42 /* The QID is the TYPE and the index into the nix array.
43  * We reserve the right to make it an id later.
44  */
45 #define ID_SHIFT 5
46 /* nix's have an image.
47  * Note that the image can be read even as it is running. */
48 struct nix {
49         struct kref kref;
50         /* should this be an array of pages? Hmm. */
51         void *image;
52         unsigned long imagesize;
53         int id; // not used yet.
54         /* we could dynamically alloc one of these with num_cpus */
55         DECLARE_BITMAP(cpus, MAX_NUM_CPUS);
56 };
57
58 static spinlock_t nixlock;
59 /* array, not linked list. We expect few, might as well be cache friendly. */
60 static struct nix *nixs = NULL;
61 static int nnix = 0;
62 static int nixok = 0;
63 static int npages;
64 // only 4 gig for now.
65 static page_t *nixpages[1048576];
66
67 static spinlock_t nixidlock[1];
68 static struct kref nixid[1] = { {(void *)1, fake_release} };
69
70 //int nix_run(struct nix *nix, struct nix_run *nix_run);
71
72 static inline struct nix *
73 QID2NIX(struct qid q)
74 {
75         return &nixs[((q).vers)];
76 }
77
78 static inline int
79 TYPE(struct qid q)
80 {
81         return ((q).path & ((1 << ID_SHIFT) - 1));
82 }
83
84 static inline int QID(int index, int type)
85 {
86         return ((index << ID_SHIFT) | type);
87 }
88
89 /* we'll need this somewhere more generic. */
90 static void readn(struct chan *c, void *vp, long n)
91 {
92         print_func_entry();
93         char *p;
94         long nn;
95         int total = 0, want = n;
96
97         p = vp;
98         while (n > 0) {
99                 nn = devtab[c->type].read(c, p, n, c->offset);
100                 printk("readn: Got %d@%lld\n", nn, c->offset);
101                 if (nn == 0)
102                         error("%s: wanted %d, got %d", Eshort, want, total);
103                 c->offset += nn;
104                 p += nn;
105                 n -= nn;
106                 total += nn;
107         }
108         print_func_exit();
109 }
110
111 /* not called yet.  -- we have to unlink the nix */
112 static void nix_release(struct kref *kref)
113 {
114         print_func_entry();
115         struct nix *v = container_of(kref, struct nix, kref);
116         spin_lock_irqsave(&nixlock);
117         /* cute trick. Save the last element of the array in place of the
118          * one we're deleting. Reduce nnix. Don't realloc; that way, next
119          * time we add a nix the allocator will just return.
120          * Well, this is stupid, because when we do this, we break
121          * the QIDs, which have pointers embedded in them.
122          * darn it, may have to use a linked list. Nope, will probably
123          * just walk the array until we find a matching id. Still ... yuck.
124          */
125         if (v != &nixs[nnix - 1]) {
126                 /* free the image ... oops */
127                 /* get rid of the kref. */
128                 *v = nixs[nnix - 1];
129         }
130         nnix--;
131         spin_unlock(&nixlock);
132         print_func_exit();
133 }
134
135 /* NIX ids run in the range 1..infinity.
136  */
137 static int newnixid(void)
138 {
139         print_func_entry();
140         int id;
141         spin_lock_irqsave(nixidlock);
142         id = kref_refcnt(nixid);
143         kref_get(nixid, 1);
144         spin_unlock(nixidlock);
145         print_func_exit();
146         return id - 1;
147 }
148
149 static int nixgen(struct chan *c, char *entry_name,
150                    struct dirtab *unused, int unused_nr_dirtab,
151                    int s, struct dir *dp)
152 {
153         print_func_entry();
154         struct qid q;
155         struct nix *nix_i;
156         printd("GEN s %d\n", s);
157         /* Whether we're in one dir or at the top, .. still takes us to the top. */
158         if (s == DEVDOTDOT) {
159                 mkqid(&q, Qtopdir, 0, QTDIR);
160                 devdir(c, c->qid, "#V", 0, eve, 0555, dp);
161                 print_func_exit();
162                 return 1;
163         }
164         printd("TYPE %d\n", TYPE(c->qid));
165         switch (TYPE(c->qid)) {
166         case Qtopdir:
167                 printd("Qtopdir s %d nnix %d\n", s, nnix);
168                 /* Generate elements for the top level dir.  We support clone, stat,
169                  * nix dirs at the top level */
170                 if (s == 0) {
171                         mkqid(&q, Qclone, 0, QTFILE);
172                         devdir(c, q, "clone", 0, eve, 0666, dp);
173                         print_func_exit();
174                         return 1;
175                 }
176                 s--;
177                 if (s == 0) {
178                         mkqid(&q, Qstat, 0, QTFILE);
179                         devdir(c, q, "stat", 0, eve, 0666, dp);
180                         print_func_exit();
181                         return 1;
182                 }
183                 s--;    /* 1 -> 0th element, 2 -> 1st element, etc */
184                 spin_lock_irqsave(&nixlock);
185                 if (s >= nnix) {
186                         printd("DONE qtopdir\n");
187                         spin_unlock(&nixlock);
188                         print_func_exit();
189                         return -1;
190                 }
191                 nix_i = &nixs[s];
192                 snprintf(get_cur_genbuf(), GENBUF_SZ, "nix%d", nix_i->id);
193                 spin_unlock(&nixlock);
194                 mkqid(&q, QID(s, Qnixdir), 0, QTDIR);
195                 devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
196                 print_func_exit();
197                 return 1;
198         case Qnixdir:
199                 /* Gen the contents of the nix dirs */
200                 s += Qctl;      /* first time through, start on Qctl */
201                 switch (s) {
202                 case Qctl:
203                         mkqid(&q, QID(s-Qctl, Qctl), 0, QTFILE);
204                         devdir(c, q, "ctl", 0, eve, 0666, dp);
205                         print_func_exit();
206                         return 1;
207                 case Qimage:
208                         mkqid(&q, QID(s-Qctl, Qimage), 0, QTFILE);
209                         devdir(c, q, "image", 0, eve, 0666, dp);
210                         print_func_exit();
211                         return 1;
212                 }
213                 print_func_exit();
214                 return -1;
215                 /* Need to also provide a direct hit for Qclone and all other files (at
216                  * all levels of the hierarchy).  Every file is both
217                  * generated (via the s increments in their respective directories) and
218                  * directly gen-able.  devstat() will call gen with a specific path in
219                  * the qid.  In these cases, we make a dir for whatever they are asking
220                  * for.  Note the qid stays the same.  I think this is what the old
221                  * plan9 comments above devgen were talking about for (ii).
222                  *
223                  * We don't need to do this for the directories - devstat will look for
224                  * the a directory by path and fail.  Then it will manually build the
225                  * stat output (check the -1 case in devstat). */
226         case Qclone:
227                 devdir(c, c->qid, "clone", 0, eve, 0666, dp);
228                 print_func_exit();
229                 return 1;
230         case Qstat:
231                 devdir(c, c->qid, "stat", 0, eve, 0444, dp);
232                 print_func_exit();
233                 return 1;
234         case Qctl:
235                 devdir(c, c->qid, "ctl", 0, eve, 0666, dp);
236                 print_func_exit();
237                 return 1;
238         case Qimage:
239                 devdir(c, c->qid, "image", 0, eve, 0666, dp);
240                 print_func_exit();
241                 return 1;
242         }
243         print_func_exit();
244         return -1;
245 }
246
247 void nixtest(void)
248 {
249         printk("nixtest\n");
250 }
251
252 // allocate pages, starting at 1G, and running until we run out.
253 static void nixinit(void)
254 {
255         //error_t kpage_alloc_specific(page_t** page, size_t ppn)
256         print_func_entry();
257         uint64_t ppn = GiB/4096;
258         spinlock_init_irqsave(&nixlock);
259         spinlock_init_irqsave(nixidlock);
260         while (1) {
261                 if (!page_is_free(ppn)) {
262                         printk("%s: got a non-free page@ppn %p\n", __func__, ppn);
263                         break;
264                 }
265                 kpage_alloc_specific(&nixpages[ppn], ppn);
266                 npages++;
267                 ppn++;
268         }
269         printk("nixinit: nix_init returns %d\n", npages);
270
271         if (npages > 0) {
272                 nixok = 1;
273         }
274
275         print_func_exit();
276 }
277
278 static struct chan *nixattach(char *spec)
279 {
280         print_func_entry();
281         if (!nixok)
282                 error("No NIXs available");
283         struct chan *c = devattach('t', spec);
284         mkqid(&c->qid, Qtopdir, 0, QTDIR);
285         print_func_exit();
286         return c;
287 }
288
289 static struct walkqid *nixwalk(struct chan *c, struct chan *nc, char **name,
290                                 int nname)
291 {
292         print_func_entry();
293         print_func_exit();
294         return devwalk(c, nc, name, nname, 0, 0, nixgen);
295 }
296
297 static int nixstat(struct chan *c, uint8_t * db, int n)
298 {
299         print_func_entry();
300         print_func_exit();
301         return devstat(c, db, n, 0, 0, nixgen);
302 }
303
304 /* It shouldn't matter if p = current is DYING.  We'll eventually fail to insert
305  * the open chan into p's fd table, then decref the chan. */
306 static struct chan *nixopen(struct chan *c, int omode)
307 {
308         print_func_entry();
309         ERRSTACK(1);
310         struct nix *v = QID2NIX(c->qid);
311         printk("nixopen: v is %p\n", v);
312         if (waserror()) {
313                 nexterror();
314         }
315         switch (TYPE(c->qid)) {
316         case Qtopdir:
317         case Qnixdir:
318                 if (omode & ORCLOSE)
319                         error(Eperm);
320                 if (!IS_RDONLY(omode))
321                         error(Eisdir);
322                 break;
323         case Qclone:
324                 spin_lock_irqsave(&nixlock);
325                 nixs = krealloc(nixs, sizeof(nixs[0]) * (nnix + 1), 0);
326                 v = &nixs[nnix];
327                 mkqid(&c->qid, QID(nnix, Qctl), 0, QTFILE);
328                 nnix++;
329                 spin_unlock(&nixlock);
330                 kref_init(&v->kref, nix_release, 1);
331                 v->id = newnixid();
332                 v->image = KADDR(GiB);
333                 v->imagesize = npages * 4096;
334                 c->aux = v;
335                 bitmap_zero(v->cpus, MAX_NUM_CPUS);
336                 printd("New NIX id %d @ %p\n", v->id, v);
337                 printk("image is %p with %d bytes\n", v->image, v->imagesize);
338                 printk("Qclone open: id %d, v is %p\n", nnix-1, v);
339                 break;
340         case Qstat:
341                 break;
342         case Qctl:
343         case Qimage:
344                 //kref_get(&v->kref, 1);
345                 c->aux = QID2NIX(c->qid);
346                 printk("open qctl/image: aux (nix) is %p\n", c->aux);
347                 break;
348         }
349         c->mode = openmode(omode);
350         /* Assumes c is unique (can't be closed concurrently */
351         c->flag |= COPEN;
352         c->offset = 0;
353         poperror();
354         print_func_exit();
355         return c;
356 }
357
358 static void nixcreate(struct chan *c, char *name, int omode, uint32_t perm)
359 {
360         print_func_entry();
361         error(Eperm);
362         print_func_exit();
363 }
364
365 static void nixremove(struct chan *c)
366 {
367         print_func_entry();
368         error(Eperm);
369         print_func_exit();
370 }
371
372 static int nixwstat(struct chan *c, uint8_t * dp, int n)
373 {
374         print_func_entry();
375         error("No nixwstat");
376         print_func_exit();
377         return 0;
378 }
379
380 static void nixclose(struct chan *c)
381 {
382         print_func_entry();
383         struct nix *v = c->aux;
384         if (!v) {
385                 print_func_exit();
386                 return;
387         }
388         /* There are more closes than opens.  For instance, sysstat doesn't open,
389          * but it will close the chan it got from namec.  We only want to clean
390          * up/decref chans that were actually open. */
391         if (!(c->flag & COPEN)) {
392                 print_func_exit();
393                 return;
394         }
395         switch (TYPE(c->qid)) {
396                 /* for now, leave the NIX active even when we close ctl */
397         case Qctl:
398                 break;
399         case Qimage:
400                 //kref_put(&v->kref);
401                 break;
402         }
403         print_func_exit();
404 }
405
406 static long nixread(struct chan *c, void *ubuf, long n, int64_t offset)
407 {
408         print_func_entry();
409         struct nix *v = c->aux;
410         printd("NIXREAD\n");
411         switch (TYPE(c->qid)) {
412         case Qtopdir:
413         case Qnixdir:
414                 print_func_exit();
415                 return devdirread(c, ubuf, n, 0, 0, nixgen);
416         case Qstat:
417                 print_func_exit();
418                 return readnum(offset, ubuf, n, nnix, NUMSIZE32);
419         case Qctl:
420                 assert(v);
421                 print_func_exit();
422                 return readnum(offset, ubuf, n, v->id, NUMSIZE32);
423         case Qimage:
424                 assert(v);
425                 print_func_exit();
426                 return readmem(offset, ubuf, n, v->image, v->imagesize);
427         default:
428                 panic("Bad QID %p in devnix", c->qid.path);
429         }
430         print_func_exit();
431         return 0;
432 }
433
434 static void nixwrapper(uint32_t srcid, long a0, long a1, long a2)
435 {
436         void (*f)(void) = (void (*)(void))a0;
437         f();
438 }
439
440 static long nixwrite(struct chan *c, void *ubuf, long n, int64_t off)
441 {
442         struct nix *v = c->aux;
443         print_func_entry();
444         ERRSTACK(3);
445         char buf[32];
446         struct cmdbuf *cb;
447         struct nix *nix;
448         uint64_t hexval;
449         printd("nixwrite(%p, %p, %d)\n", c, ubuf, n);
450         switch (TYPE(c->qid)) {
451         case Qtopdir:
452         case Qnixdir:
453         case Qstat:
454                 error(Eperm);
455         case Qctl:
456                 nix = c->aux;
457                 printk("qctl: nix is %p, nix is %p\n", nix, nix);
458                 cb = parsecmd(ubuf, n);
459                 /* TODO: lock the nix here, unlock in waserror and before popping */
460                 if (waserror()) {
461                         kfree(cb);
462                         nexterror();
463                 }
464                 if (!strcmp(cb->f[0], "run")) {
465                         int core;
466                         uintptr_t ip;
467                         if (cb->nf != 3)
468                                 error("usage: run core entry");
469                         core = strtoul(cb->f[1], 0, 0);
470                         ip = strtoul(cb->f[2], 0, 0);
471                         if (!test_bit(core, nix->cpus))
472                                 error("Bad core %d", core);
473                         send_kernel_message(core, nixwrapper, (long)ip, 0, 0, KMSG_ROUTINE);
474                         printk("nix_run returns \n");
475                         print_func_exit();
476                 } else if (!strcmp(cb->f[0], "test")) {
477                         int core;
478                         if (cb->nf != 2)
479                                 error("usage: test core");
480                         core = strtoul(cb->f[1], 0, 0);
481                         if (!test_bit(core, nix->cpus))
482                                 error("Bad core %d", core);
483                         send_kernel_message(core, nixwrapper, (long)nixtest, 0, 0,
484                                             KMSG_ROUTINE);
485                         printk("nix_run (test) returns \n");
486                         print_func_exit();
487                 } else if (!strcmp(cb->f[0], "reserve")) {
488                         int core;
489                         if (cb->nf != 2)
490                                 error("Usage: reserve core (-1 for any)");
491                         core = strtol(cb->f[1], 0, 0);
492                         if (core == -1) {
493                                 core = get_any_idle_core();
494                                 if (core < 0)
495                                         error("No free idle cores!");
496                         } else {
497                                 if (get_this_idle_core(core) < 0)
498                                         error("Failed to reserve core %d\n", core);
499                         }
500                         set_bit(core, nix->cpus);
501                 } else if (!strcmp(cb->f[0], "check")) {
502                         int i;
503                         for(i = 0; i < MAX_NUM_CPUS; i++) {
504                                 if (!test_bit(i, nix->cpus))
505                                         continue;
506                                 printk("Core %d is available to nix%d\n", i, nix->id);
507                         }
508                 } else if (!strcmp(cb->f[0], "stop")) {
509                         error("can't stop a nix yet");
510                 } else {
511                         error("%s: not implemented", cb->f[0]);
512                 }
513                 kfree(cb);
514                 poperror();
515                 break;
516         case Qimage:
517                 if (off < 0)
518                         error("offset < 0!");
519
520                 if (off + n > v->imagesize) {
521                         n = v->imagesize - off;
522                 }
523                 printd("copy to %p ubuf %p size %d\n", v->image + off, ubuf, n);
524
525                 if (memcpy_from_user_errno(current, v->image + off, ubuf, n) < 0)
526                         error("%s: bad user addr %p", __FUNCTION__, ubuf);
527                 break;
528
529         default:
530                 panic("Bad QID %p in devnix", c->qid.path);
531         }
532         print_func_exit();
533         return n;
534 }
535
536 struct dev nixdevtab __devtab = {
537         't',
538         "nix",
539
540         devreset,
541         nixinit,
542         devshutdown,
543         nixattach,
544         nixwalk,
545         nixstat,
546         nixopen,
547         nixcreate,
548         nixclose,
549         nixread,
550         devbread,
551         nixwrite,
552         devbwrite,
553         nixremove,
554         nixwstat,
555         devpower,
556 //  devconfig,
557         devchaninfo,
558 };