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