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