nix: Fixes lock and atomic_t initialization
[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 = SPINLOCK_INITIALIZER_IRQSAVE;
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 = 0;
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;
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         while (1) {
255                 if (!page_is_free(ppn)) {
256                         printk("%s: got a non-free page@ppn %p\n", __func__, ppn);
257                         break;
258                 }
259                 kpage_alloc_specific(&nixpages[ppn], ppn);
260                 npages++;
261                 ppn++;
262         }
263         printk("nixinit: nix_init returns %d\n", npages);
264
265         if (npages > 0) {
266                 nixok = 1;
267         }
268
269         print_func_exit();
270 }
271
272 static struct chan *nixattach(char *spec)
273 {
274         print_func_entry();
275         if (!nixok)
276                 error("No NIXs available");
277         struct chan *c = devattach('t', spec);
278         mkqid(&c->qid, Qtopdir, 0, QTDIR);
279         print_func_exit();
280         return c;
281 }
282
283 static struct walkqid *nixwalk(struct chan *c, struct chan *nc, char **name,
284                                 int nname)
285 {
286         print_func_entry();
287         print_func_exit();
288         return devwalk(c, nc, name, nname, 0, 0, nixgen);
289 }
290
291 static int nixstat(struct chan *c, uint8_t * db, int n)
292 {
293         print_func_entry();
294         print_func_exit();
295         return devstat(c, db, n, 0, 0, nixgen);
296 }
297
298 /* It shouldn't matter if p = current is DYING.  We'll eventually fail to insert
299  * the open chan into p's fd table, then decref the chan. */
300 static struct chan *nixopen(struct chan *c, int omode)
301 {
302         print_func_entry();
303         ERRSTACK(1);
304         struct nix *v = QID2NIX(c->qid);
305         printk("nixopen: v is %p\n", v);
306         if (waserror()) {
307                 nexterror();
308         }
309         switch (TYPE(c->qid)) {
310         case Qtopdir:
311         case Qnixdir:
312                 if (omode & ORCLOSE)
313                         error(Eperm);
314                 if (!IS_RDONLY(omode))
315                         error(Eisdir);
316                 break;
317         case Qclone:
318                 spin_lock_irqsave(&nixlock);
319                 nixs = krealloc(nixs, sizeof(nixs[0]) * (nnix + 1), 0);
320                 v = &nixs[nnix];
321                 mkqid(&c->qid, QID(nnix, Qctl), 0, QTFILE);
322                 nnix++;
323                 spin_unlock(&nixlock);
324                 kref_init(&v->kref, nix_release, 1);
325                 v->id = newnixid();
326                 v->image = KADDR(GiB);
327                 v->imagesize = npages * 4096;
328                 c->aux = v;
329                 bitmap_zero(v->cpus, MAX_NUM_CPUS);
330                 printd("New NIX id %d @ %p\n", v->id, v);
331                 printk("image is %p with %d bytes\n", v->image, v->imagesize);
332                 printk("Qclone open: id %d, v is %p\n", nnix-1, v);
333                 break;
334         case Qstat:
335                 break;
336         case Qctl:
337         case Qimage:
338                 //kref_get(&v->kref, 1);
339                 c->aux = QID2NIX(c->qid);
340                 printk("open qctl/image: aux (nix) is %p\n", c->aux);
341                 break;
342         }
343         c->mode = openmode(omode);
344         /* Assumes c is unique (can't be closed concurrently */
345         c->flag |= COPEN;
346         c->offset = 0;
347         poperror();
348         print_func_exit();
349         return c;
350 }
351
352 static void nixcreate(struct chan *c, char *name, int omode, uint32_t perm)
353 {
354         print_func_entry();
355         error(Eperm);
356         print_func_exit();
357 }
358
359 static void nixremove(struct chan *c)
360 {
361         print_func_entry();
362         error(Eperm);
363         print_func_exit();
364 }
365
366 static int nixwstat(struct chan *c, uint8_t * dp, int n)
367 {
368         print_func_entry();
369         error("No nixwstat");
370         print_func_exit();
371         return 0;
372 }
373
374 static void nixclose(struct chan *c)
375 {
376         print_func_entry();
377         struct nix *v = c->aux;
378         if (!v) {
379                 print_func_exit();
380                 return;
381         }
382         /* There are more closes than opens.  For instance, sysstat doesn't open,
383          * but it will close the chan it got from namec.  We only want to clean
384          * up/decref chans that were actually open. */
385         if (!(c->flag & COPEN)) {
386                 print_func_exit();
387                 return;
388         }
389         switch (TYPE(c->qid)) {
390                 /* the idea of 'stopping' a nix is tricky. 
391                  * for now, leave the NIX active even when we close ctl */
392         case Qctl:
393                 break;
394         case Qimage:
395                 //kref_put(&v->kref);
396                 break;
397         }
398         print_func_exit();
399 }
400
401 static long nixread(struct chan *c, void *ubuf, long n, int64_t offset)
402 {
403         print_func_entry();
404         struct nix *v = c->aux;
405         printd("NIXREAD\n");
406         switch (TYPE(c->qid)) {
407         case Qtopdir:
408         case Qnixdir:
409                 print_func_exit();
410                 return devdirread(c, ubuf, n, 0, 0, nixgen);
411         case Qstat:
412                 print_func_exit();
413                 return readnum(offset, ubuf, n, nnix, NUMSIZE32);
414         case Qctl:
415                 assert(v);
416                 print_func_exit();
417                 return readnum(offset, ubuf, n, v->id, NUMSIZE32);
418         case Qimage:
419                 assert(v);
420                 print_func_exit();
421                 return readmem(offset, ubuf, n, v->image, v->imagesize);
422         default:
423                 panic("Bad QID %p in devnix", c->qid.path);
424         }
425         print_func_exit();
426         return 0;
427 }
428
429 static void nixwrapper(uint32_t srcid, long a0, long a1, long a2)
430 {
431         void (*f)(void) = (void (*)(void))a0;
432         f();
433 }
434
435 static long nixwrite(struct chan *c, void *ubuf, long n, int64_t off)
436 {
437         struct nix *v = c->aux;
438         print_func_entry();
439         ERRSTACK(1);
440         char buf[32];
441         struct cmdbuf *cb;
442         struct nix *nix;
443         uint64_t hexval;
444         printd("nixwrite(%p, %p, %d)\n", c, ubuf, n);
445         switch (TYPE(c->qid)) {
446         case Qtopdir:
447         case Qnixdir:
448         case Qstat:
449                 error(Eperm);
450         case Qctl:
451                 nix = c->aux;
452                 printk("qctl: nix is %p, nix is %p\n", nix, nix);
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 (!strcmp(cb->f[0], "run")) {
460                         int core;
461                         uintptr_t ip;
462                         if (cb->nf != 3)
463                                 error("usage: run core entry");
464                         core = strtoul(cb->f[1], 0, 0);
465                         ip = strtoul(cb->f[2], 0, 0);
466                         if (!test_bit(core, nix->cpus))
467                                 error("Bad core %d", core);
468                         send_kernel_message(core, nixwrapper, (long)ip, 0, 0, KMSG_ROUTINE);
469                         printk("nix_run returns \n");
470                         print_func_exit();
471                 } else if (!strcmp(cb->f[0], "test")) {
472                         int core;
473                         if (cb->nf != 2)
474                                 error("usage: test core");
475                         core = strtoul(cb->f[1], 0, 0);
476                         if (!test_bit(core, nix->cpus))
477                                 error("Bad core %d", core);
478                         send_kernel_message(core, nixwrapper, (long)nixtest, 0, 0,
479                                             KMSG_ROUTINE);
480                         printk("nix_run (test) returns \n");
481                         print_func_exit();
482                 } else if (!strcmp(cb->f[0], "reserve")) {
483                         int core;
484                         if (cb->nf != 2)
485                                 error("Usage: reserve core (-1 for any)");
486                         core = strtol(cb->f[1], 0, 0);
487                         if (core == -1) {
488                                 core = get_any_idle_core();
489                                 if (core < 0)
490                                         error("No free idle cores!");
491                         } else {
492                                 if (get_this_idle_core(core) < 0)
493                                         error("Failed to reserve core %d\n", core);
494                         }
495                         set_bit(core, nix->cpus);
496                 } else if (!strcmp(cb->f[0], "check")) {
497                         int i;
498                         for(i = 0; i < MAX_NUM_CPUS; i++) {
499                                 if (!test_bit(i, nix->cpus))
500                                         continue;
501                                 printk("Core %d is available to nix%d\n", i, nix->id);
502                         }
503                 } else if (!strcmp(cb->f[0], "stop")) {
504                         error("can't stop a nix yet");
505                 } else {
506                         error("%s: not implemented", cb->f[0]);
507                 }
508                 kfree(cb);
509                 poperror();
510                 break;
511         case Qimage:
512                 if (off < 0)
513                         error("offset < 0!");
514
515                 if (off + n > v->imagesize) {
516                         n = v->imagesize - off;
517                 }
518                 printd("copy to %p ubuf %p size %d\n", v->image + off, ubuf, n);
519
520                 if (memcpy_from_user_errno(current, v->image + off, ubuf, n) < 0)
521                         error("%s: bad user addr %p", __FUNCTION__, ubuf);
522                 break;
523
524         default:
525                 panic("Bad QID %p in devnix", c->qid.path);
526         }
527         print_func_exit();
528         return n;
529 }
530
531 struct dev nixdevtab __devtab = {
532         't',
533         "nix",
534
535         devreset,
536         nixinit,
537         devshutdown,
538         nixattach,
539         nixwalk,
540         nixstat,
541         nixopen,
542         nixcreate,
543         nixclose,
544         nixread,
545         devbread,
546         nixwrite,
547         devbwrite,
548         nixremove,
549         nixwstat,
550         devpower,
551 //  devconfig,
552         devchaninfo,
553 };