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