Add 'self' to #proc
[akaros.git] / kern / drivers / dev / proc.c
1 /*
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9
10 //#define DEBUG
11 /* proc on plan 9 has lots of capabilities, some of which we might
12  * want for akaros:
13  * debug control
14  * event tracing
15  * process control (no need for signal system call, etc.)
16  * textual status
17  * rather than excise code that won't work, I'm bracketing it with
18  * #if 0 until we know we don't want it
19  */
20 #include <vfs.h>
21 #include <kfs.h>
22 #include <slab.h>
23 #include <kmalloc.h>
24 #include <kref.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <assert.h>
28 #include <error.h>
29 #include <cpio.h>
30 #include <pmap.h>
31 #include <smp.h>
32 #include <arch/vmm/vmm.h>
33 #include <ros/vmm.h>
34
35 struct dev procdevtab;
36
37 static char *devname(void)
38 {
39         return procdevtab.name;
40 }
41
42 enum {
43         Qdir,
44         Qtrace,
45         Qtracepids,
46         Qself,
47         Qns,
48         Qargs,
49         Qctl,
50         Qfd,
51         Qfpregs,
52         Qkregs,
53         Qmem,
54         Qnote,
55         Qnoteid,
56         Qnotepg,
57         Qproc,
58         Qregs,
59         Qsegment,
60         Qstatus,
61         Qstrace,
62         Qvmstatus,
63         Qtext,
64         Qwait,
65         Qprofile,
66         Qsyscall,
67         Qcore,
68 };
69
70 enum {
71         CMclose,
72         CMclosefiles,
73         CMfixedpri,
74         CMhang,
75         CMkill,
76         CMnohang,
77         CMnoswap,
78         CMpri,
79         CMprivate,
80         CMprofile,
81         CMstart,
82         CMstartstop,
83         CMstartsyscall,
84         CMstop,
85         CMwaitstop,
86         CMwired,
87         CMcore,
88         CMvminit,
89         CMvmstart,
90         CMvmkill,
91         CMstraceme,
92         CMstraceall,
93         CMstraceoff,
94 };
95
96 enum {
97         Nevents = 0x4000,
98         Emask = Nevents - 1,
99         Ntracedpids = 1024,
100         STATSIZE = 8 + 1 + 10 + 1 + 6 + 2,
101 };
102
103 /*
104  * Status, fd, and ns are left fully readable (0444) because of their use in debugging,
105  * particularly on shared servers.
106  * Arguably, ns and fd shouldn't be readable; if you'd prefer, change them to 0000
107  */
108 struct dirtab procdir[] = {
109         {"args", {Qargs}, 0, 0660},
110         {"ctl", {Qctl}, 0, 0660},
111         {"fd", {Qfd}, 0, 0444},
112         {"fpregs", {Qfpregs}, 0, 0000},
113         //  {"kregs",   {Qkregs},   sizeof(Ureg),       0600},
114         {"mem", {Qmem}, 0, 0000},
115         {"note", {Qnote}, 0, 0000},
116         {"noteid", {Qnoteid}, 0, 0664},
117         {"notepg", {Qnotepg}, 0, 0000},
118         {"ns", {Qns}, 0, 0444},
119         {"proc", {Qproc}, 0, 0400},
120         //  {"regs",        {Qregs},    sizeof(Ureg),       0000},
121         {"segment", {Qsegment}, 0, 0444},
122         {"status", {Qstatus}, STATSIZE, 0444},
123         {"strace", {Qstrace}, 0, 0666},
124         {"vmstatus", {Qvmstatus}, 0, 0444},
125         {"text", {Qtext}, 0, 0000},
126         {"wait", {Qwait}, 0, 0400},
127         {"profile", {Qprofile}, 0, 0400},
128         {"syscall", {Qsyscall}, 0, 0400},
129         {"core", {Qcore}, 0, 0444},
130 };
131
132 static
133 struct cmdtab proccmd[] = {
134         {CMclose, "close", 2},
135         {CMclosefiles, "closefiles", 1},
136         {CMfixedpri, "fixedpri", 2},
137         {CMhang, "hang", 1},
138         {CMnohang, "nohang", 1},
139         {CMnoswap, "noswap", 1},
140         {CMkill, "kill", 1},
141         {CMpri, "pri", 2},
142         {CMprivate, "private", 1},
143         {CMprofile, "profile", 1},
144         {CMstart, "start", 1},
145         {CMstartstop, "startstop", 1},
146         {CMstartsyscall, "startsyscall", 1},
147         {CMstop, "stop", 1},
148         {CMwaitstop, "waitstop", 1},
149         {CMwired, "wired", 2},
150         {CMcore, "core", 2},
151         {CMcore, "core", 2},
152         {CMcore, "core", 2},
153         {CMvminit, "vminit", 0},
154         {CMvmstart, "vmstart", 0},
155         {CMvmkill, "vmkill", 0},
156         {CMstraceme, "straceme", 0},
157         {CMstraceall, "straceall", 0},
158         {CMstraceoff, "straceoff", 0},
159 };
160
161 /*
162  * struct qids are, in path:
163  *       5 bits of file type (qids above) (old comment said 4 here)
164  *      23 bits of process slot number + 1 (pid + 1 is stored)
165  *           in vers,
166  *      32 bits of pid, for consistency checking
167  * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid.
168  */
169 #define QSHIFT  5       /* location in qid of proc slot # */
170 #define SLOTBITS 23     /* number of bits in the slot */
171 #define QIDMASK ((1<<QSHIFT)-1)
172 #define SLOTMASK        (((1<<SLOTBITS)-1) << QSHIFT)
173
174 #define QID(q)          ((((uint32_t)(q).path)&QIDMASK)>>0)
175 #define SLOT(q)         (((((uint32_t)(q).path)&SLOTMASK)>>QSHIFT)-1)
176 #define PID(q)          ((q).vers)
177 #define NOTEID(q)       ((q).vers)
178
179 static void procctlreq(struct proc *, char *, int);
180 static int procctlmemio(struct proc *, uintptr_t, int, void *, int);
181 //static struct chan*   proctext(struct chan*, struct proc*);
182 //static Segment* txt2data(struct proc*, Segment*);
183 //static int    procstopped(void*);
184 static void mntscan(struct mntwalk *, struct proc *);
185
186 //static Traceevent *tevents;
187 static char *tpids, *tpidsc, *tpidse;
188 static spinlock_t tlock;
189 static int topens;
190 static int tproduced, tconsumed;
191 //static void notrace(struct proc*, int, int64_t);
192
193 //void (*proctrace)(struct proc*, int, int64_t) = notrace;
194
195 #if 0
196 static void profclock(Ureg * ur, Timer *)
197 {
198         Tos *tos;
199
200         if (up == NULL || current->state != Running)
201                 return;
202
203         /* user profiling clock */
204         if (userureg(ur)) {
205                 tos = (Tos *) (USTKTOP - sizeof(Tos));
206                 tos->clock += TK2MS(1);
207                 segclock(userpc(ur));
208         }
209 }
210 #endif
211 static int
212 procgen(struct chan *c, char *name, struct dirtab *tab, int unused, int s,
213                 struct dir *dp)
214 {
215         struct qid qid;
216         struct proc *p;
217         char *ename;
218
219         int pid;
220         uint32_t path, perm, len;
221         if (s == DEVDOTDOT) {
222                 mkqid(&qid, Qdir, 0, QTDIR);
223                 devdir(c, qid, devname(), 0, eve, 0555, dp);
224                 return 1;
225         }
226
227         if (c->qid.path == Qdir) {
228                 if (s == 0) {
229                         strlcpy(get_cur_genbuf(), "trace", GENBUF_SZ);
230                         mkqid(&qid, Qtrace, -1, QTFILE);
231                         devdir(c, qid, get_cur_genbuf(), 0, eve, 0444, dp);
232                         return 1;
233                 }
234                 if (s == 1) {
235                         strlcpy(get_cur_genbuf(), "tracepids", GENBUF_SZ);
236                         mkqid(&qid, Qtracepids, -1, QTFILE);
237                         devdir(c, qid, get_cur_genbuf(), 0, eve, 0444, dp);
238                         return 1;
239                 }
240                 if (s == 2) {
241                         p = current;
242                         strlcpy(get_cur_genbuf(), "self", GENBUF_SZ);
243                         mkqid(&qid, (p->pid + 1) << QSHIFT, p->pid, QTDIR);
244                         devdir(c, qid, get_cur_genbuf(), 0, p->user, DMDIR | 0555, dp);
245                         return 1;
246                 }
247                 s -= 3;
248                 if (name != NULL) {
249                         /* ignore s and use name to find pid */
250                         pid = strtol(name, &ename, 10);
251                         if (pid <= 0 || ename[0] != '\0')
252                                 return -1;
253                         p = pid2proc(pid);
254                         if (!p)
255                                 return -1;
256                         /* Need to update s, so that it's the correct 'index' for our proc
257                          * (aka, the pid).  We use s later when making the qid. */
258                         s = pid;
259                 } else {
260                         /* This is a shitty iterator, and the list isn't guaranteed to give
261                          * you the same ordering twice in a row. (procs come and go). */
262                         p = pid_nth(s);
263                         if (!p)
264                                 return -1;
265                         pid = p->pid;
266                 }
267
268                 snprintf(get_cur_genbuf(), GENBUF_SZ, "%u", pid);
269                 /*
270                  * String comparison is done in devwalk so
271                  * name must match its formatted pid.
272                  */
273                 if (name != NULL && strcmp(name, get_cur_genbuf()) != 0) {
274                         printk("pid-name mismatch, name: %s, pid %d\n", name, pid);
275                         kref_put(&p->p_kref);
276                         return -1;
277                 }
278                 mkqid(&qid, (s + 1) << QSHIFT, pid, QTDIR);
279                 devdir(c, qid, get_cur_genbuf(), 0, p->user, DMDIR | 0555, dp);
280                 kref_put(&p->p_kref);
281                 return 1;
282         }
283         if (c->qid.path == Qtrace) {
284                 strlcpy(get_cur_genbuf(), "trace", GENBUF_SZ);
285                 mkqid(&qid, Qtrace, -1, QTFILE);
286                 devdir(c, qid, get_cur_genbuf(), 0, eve, 0444, dp);
287                 return 1;
288         }
289         if (c->qid.path == Qtracepids) {
290                 strlcpy(get_cur_genbuf(), "tracepids", GENBUF_SZ);
291                 mkqid(&qid, Qtracepids, -1, QTFILE);
292                 devdir(c, qid, get_cur_genbuf(), 0, eve, 0444, dp);
293                 return 1;
294         }
295         if (s >= ARRAY_SIZE(procdir))
296                 return -1;
297         if (tab)
298                 panic("procgen");
299
300         tab = &procdir[s];
301         /* path is everything other than the QID part.  Not sure from the orig code
302          * if they wanted just the pid part (SLOTMASK) or everything above QID */
303         path = c->qid.path & ~QIDMASK;  /* slot component */
304         if ((p = pid2proc(SLOT(c->qid))) == NULL)
305                 return -1;
306         perm = 0444 | tab->perm;
307 #if 0
308         if (perm == 0)
309                 perm = p->procmode;
310         else    /* just copy read bits */
311                 perm |= p->procmode & 0444;
312 #endif
313
314         len = tab->length;
315 #if 0
316         switch (QID(c->qid)) {
317                 case Qwait:
318                         len = p->nwait; /* incorrect size, but >0 means there's something to read */
319                         break;
320                 case Qprofile:
321                         q = p->seg[TSEG];
322                         if (q && q->profile) {
323                                 len = (q->top - q->base) >> LRESPROF;
324                                 len *= sizeof(*q->profile);
325                         }
326                         break;
327         }
328 #endif
329
330         mkqid(&qid, path | tab->qid.path, c->qid.vers, QTFILE);
331         devdir(c, qid, tab->name, len, p->user, perm, dp);
332         kref_put(&p->p_kref);
333         return 1;
334 }
335
336 #if 0
337 static void notrace(struct proc *, Tevent, int64_t)
338 {
339 }
340
341 static spinlock_t tlck = SPINLOCK_INITIALIZER_IRQSAVE;
342
343 static void _proctrace(struct proc *p, Tevent etype, int64_t ts)
344 {
345         Traceevent *te;
346         int tp;
347
348         ilock(&tlck);
349         if (p->trace == 0 || topens == 0 || tproduced - tconsumed >= Nevents) {
350                 iunlock(&tlck);
351                 return;
352         }
353         tp = tproduced++;
354         iunlock(&tlck);
355
356         te = &tevents[tp & Emask];
357         te->pid = p->pid;
358         te->etype = etype;
359         if (ts == 0)
360                 te->time = todget(NULL);
361         else
362                 te->time = ts;
363         te->core = m->machno;
364 }
365
366 void proctracepid(struct proc *p)
367 {
368         if (p->trace == 1 && proctrace != notrace) {
369                 p->trace = 2;
370                 ilock(&tlck);
371                 tpidsc = seprint(tpidsc, tpidse, "%d %s\n", p->pid, p->text);
372                 iunlock(&tlck);
373         }
374 }
375
376 #endif
377 static void procinit(void)
378 {
379 #if 0
380         if (conf.nproc >= (SLOTMASK >> QSHIFT) - 1)
381                 printd("warning: too many procs for devproc\n");
382         addclock0link((void (*)(void))profclock, 113);  /* Relative prime to HZ */
383 #endif
384 }
385
386 static struct chan *procattach(char *spec)
387 {
388         return devattach(devname(), spec);
389 }
390
391 static struct walkqid *procwalk(struct chan *c, struct chan *nc, char **name,
392                                                                 int nname)
393 {
394         return devwalk(c, nc, name, nname, 0, 0, procgen);
395 }
396
397 static int procstat(struct chan *c, uint8_t * db, int n)
398 {
399         return devstat(c, db, n, 0, 0, procgen);
400 }
401
402 /*
403  *  none can't read or write state on other
404  *  processes.  This is to contain access of
405  *  servers running as none should they be
406  *  subverted by, for example, a stack attack.
407  */
408 static void nonone(struct proc *p)
409 {
410         return;
411 #if 0
412         if (p == up)
413                 return;
414         if (strcmp(current->user, "none") != 0)
415                 return;
416         if (iseve())
417                 return;
418         error(EPERM, ERROR_FIXME);
419 #endif
420 }
421
422 static struct chan *procopen(struct chan *c, int omode)
423 {
424         ERRSTACK(2);
425         struct proc *p;
426         struct pgrp *pg;
427         struct chan *tc;
428         int pid;
429
430         if (c->qid.type & QTDIR)
431                 return devopen(c, omode, 0, 0, procgen);
432
433         if (QID(c->qid) == Qtrace) {
434                 error(ENOSYS, ERROR_FIXME);
435 #if 0
436                 if (omode != OREAD)
437                         error(EPERM, ERROR_FIXME);
438                 lock(&tlock);
439                 if (waserror()) {
440                         unlock(&tlock);
441                         nexterror();
442                 }
443                 if (topens > 0)
444                         error(EFAIL, "already open");
445                 topens++;
446                 if (tevents == NULL) {
447                         tevents = (Traceevent *) kzmalloc(sizeof(Traceevent) * Nevents,
448                                                                                           MEM_WAIT);
449                         if (tevents == NULL)
450                                 error(ENOMEM, ERROR_FIXME);
451                         tpids = kzmalloc(Ntracedpids * 20, MEM_WAIT);
452                         if (tpids == NULL) {
453                                 kfree(tpids);
454                                 tpids = NULL;
455                                 error(ENOMEM, ERROR_FIXME);
456                         }
457                         tpidsc = tpids;
458                         tpidse = tpids + Ntracedpids * 20;
459                         *tpidsc = 0;
460                         tproduced = tconsumed = 0;
461                 }
462                 proctrace = _proctrace;
463                 poperror();
464                 unlock(&tlock);
465
466                 c->mode = openmode(omode);
467                 c->flag |= COPEN;
468                 c->offset = 0;
469                 return c;
470 #endif
471         }
472         if (QID(c->qid) == Qtracepids) {
473                 error(ENOSYS, ERROR_FIXME);
474 #if 0
475                 if (omode != OREAD)
476                         error(EPERM, ERROR_FIXME);
477                 c->mode = openmode(omode);
478                 c->flag |= COPEN;
479                 c->offset = 0;
480                 return c;
481 #endif
482         }
483         if ((p = pid2proc(SLOT(c->qid))) == NULL)
484                 error(ESRCH, ERROR_FIXME);
485         //qlock(&p->debug);
486         if (waserror()) {
487                 //qunlock(&p->debug);
488                 kref_put(&p->p_kref);
489                 nexterror();
490         }
491         pid = PID(c->qid);
492         if (p->pid != pid)
493                 error(ESRCH, ERROR_FIXME);
494
495         omode = openmode(omode);
496
497         switch (QID(c->qid)) {
498                 case Qtext:
499                         error(ENOSYS, ERROR_FIXME);
500 /*
501                         if (omode != OREAD)
502                                 error(EPERM, ERROR_FIXME);
503                         tc = proctext(c, p);
504                         tc->offset = 0;
505                         poperror();
506                         qunlock(&p->debug);
507                         kref_put(&p->p_kref);
508                         cclose(c);
509                         return tc;
510 */
511                 case Qproc:
512                 case Qsegment:
513                 case Qprofile:
514                 case Qfd:
515                         if (omode != O_READ)
516                                 error(EPERM, ERROR_FIXME);
517                         break;
518
519                 case Qnote:
520 //          if (p->privatemem)
521                         error(EPERM, ERROR_FIXME);
522                         break;
523
524                 case Qmem:
525 //          if (p->privatemem)
526                         error(EPERM, ERROR_FIXME);
527                         //nonone(p);
528                         break;
529
530                 case Qargs:
531                 case Qnoteid:
532                 case Qwait:
533                 case Qregs:
534                 case Qfpregs:
535                 case Qkregs:
536                 case Qsyscall:
537                 case Qcore:
538                         nonone(p);
539                         break;
540
541                 case Qns:
542                         if (omode != O_READ)
543                                 error(EPERM, ERROR_FIXME);
544                         c->aux = kzmalloc(sizeof(struct mntwalk), MEM_WAIT);
545                         break;
546                 case Qstatus:
547                 case Qvmstatus:
548                 case Qctl:
549                         break;
550
551                 case Qstrace:
552                         if (!p->strace)
553                                 error(ENOENT, "Process does not have tracing enabled");
554                         /* the ref we are upping is the one we put in __proc_free, which is
555                          * the one we got from CMstrace{on,me}.  We have a ref on p, so we
556                          * know we won't free until we decref the proc. */
557                         kref_get(&p->strace->users, 1);
558                         c->aux = p->strace;
559                         break;
560                 case Qnotepg:
561                         error(ENOSYS, ERROR_FIXME);
562 #if 0
563                         nonone(p);
564                         pg = p->pgrp;
565                         if (pg == NULL)
566                                 error(ESRCH, ERROR_FIXME);
567                         if (omode != OWRITE || pg->pgrpid == 1)
568                                 error(EPERM, ERROR_FIXME);
569                         c->pgrpid.path = pg->pgrpid + 1;
570                         c->pgrpid.vers = p->noteid;
571 #endif
572                         break;
573
574                 default:
575                         printk("procopen %#llux\n", c->qid.path);
576                         error(EINVAL, ERROR_FIXME);
577         }
578
579         /* Affix pid to qid */
580 //  if (p->state != Dead)
581         c->qid.vers = p->pid;
582         /* make sure the process slot didn't get reallocated while we were playing */
583         //coherence();
584         /* TODO: think about what we really want here.  In akaros, we wouldn't have
585          * our pid changed like that. */
586         if (p->pid != pid)
587                 error(ESRCH, ERROR_FIXME);
588
589         tc = devopen(c, omode, 0, 0, procgen);
590         poperror();
591         //qunlock(&p->debug);
592         kref_put(&p->p_kref);
593         return tc;
594 }
595
596 static int procwstat(struct chan *c, uint8_t * db, int n)
597 {
598         ERRSTACK(2);
599         error(ENOSYS, ERROR_FIXME);
600 #if 0
601         struct proc *p;
602         struct dir *d;
603
604         if (c->qid.type & QTDIR)
605                 error(EPERM, ERROR_FIXME);
606
607         if (QID(c->qid) == Qtrace)
608                 return devwstat(c, db, n);
609
610         if ((p = pid2proc(SLOT(c->qid))) == NULL)
611                 error(ESRCH, ERROR_FIXME);
612         nonone(p);
613         d = NULL;
614         qlock(&p->debug);
615         if (waserror()) {
616                 qunlock(&p->debug);
617                 kref_put(&p->p_kref);
618                 kfree(d);
619                 nexterror();
620         }
621
622         if (p->pid != PID(c->qid))
623                 error(ESRCH, ERROR_FIXME);
624
625         if (strcmp(current->user, p->user) != 0 && strcmp(current->user, eve) != 0)
626                 error(EPERM, ERROR_FIXME);
627
628         d = kzmalloc(sizeof(struct dir) + n, MEM_WAIT);
629         n = convM2D(db, n, &d[0], (char *)&d[1]);
630         if (n == 0)
631                 error(ENOENT, ERROR_FIXME);
632         if (!emptystr(d->uid) && strcmp(d->uid, p->user) != 0) {
633                 if (strcmp(current->user, eve) != 0)
634                         error(EPERM, ERROR_FIXME);
635                 else
636                         kstrdup(&p->user, d->uid);
637         }
638         if (d->mode != ~0UL)
639                 p->procmode = d->mode & 0777;
640
641         poperror();
642         qunlock(&p->debug);
643         kref_put(&p->p_kref);
644         kfree(d);
645
646         return n;
647 #endif
648 }
649
650 #if 0
651 static long procoffset(long offset, char *va, int *np)
652 {
653         if (offset > 0) {
654                 offset -= *np;
655                 if (offset < 0) {
656                         memmove(va, va + *np + offset, -offset);
657                         *np = -offset;
658                 } else
659                         *np = 0;
660         }
661         return offset;
662 }
663
664 static int procqidwidth(struct chan *c)
665 {
666         char buf[32];
667
668         return sprint(buf, "%lu", c->qid.vers);
669 }
670
671 int procfdprint(struct chan *c, int fd, int w, char *s, int ns)
672 {
673         int n;
674
675         if (w == 0)
676                 w = procqidwidth(c);
677         n = snprint(s, ns,
678                                 "%3d %.2s %C %4ud (%.16llux %*lud %.2ux) %5ld %8lld %s\n", fd,
679                                 &"r w rw"[(c->mode & 3) << 1], c->dev->dc, c->devno,
680                                 c->qid.path, w, c->qid.vers, c->qid.type, c->iounit, c->offset,
681                                 c->name->s);
682         return n;
683 }
684
685 static int procfds(struct proc *p, char *va, int count, long offset)
686 {
687         ERRSTACK(2);
688         struct fgrp *f;
689         struct chan *c;
690         char buf[256];
691         int n, i, w, ww;
692         char *a;
693
694         /* print to buf to avoid holding fgrp lock while writing to user space */
695         if (count > sizeof buf)
696                 count = sizeof buf;
697         a = buf;
698
699         qlock(&p->debug);
700         f = p->fgrp;
701         if (f == NULL) {
702                 qunlock(&p->debug);
703                 return 0;
704         }
705         lock(f);
706         if (waserror()) {
707                 unlock(f);
708                 qunlock(&p->debug);
709                 nexterror();
710         }
711
712         n = readstr(0, a, count, p->dot->name->s);
713         n += snprint(a + n, count - n, "\n");
714         offset = procoffset(offset, a, &n);
715         /* compute width of qid.path */
716         w = 0;
717         for (i = 0; i <= f->maxfd; i++) {
718                 c = f->fd[i];
719                 if (c == NULL)
720                         continue;
721                 ww = procqidwidth(c);
722                 if (ww > w)
723                         w = ww;
724         }
725         for (i = 0; i <= f->maxfd; i++) {
726                 c = f->fd[i];
727                 if (c == NULL)
728                         continue;
729                 n += procfdprint(c, i, w, a + n, count - n);
730                 offset = procoffset(offset, a, &n);
731         }
732         poperror();
733         unlock(f);
734         qunlock(&p->debug);
735
736         /* copy result to user space, now that locks are released */
737         memmove(va, buf, n);
738
739         return n;
740 }
741 #endif
742 static void procclose(struct chan *c)
743 {
744         if (QID(c->qid) == Qtrace) {
745                 spin_lock(&tlock);
746                 if (topens > 0)
747                         topens--;
748                 /* ??
749                    if(topens == 0)
750                    proctrace = notrace;
751                  */
752                 spin_unlock(&tlock);
753         }
754         if (QID(c->qid) == Qsyscall) {
755                 if (c->aux)
756                         qclose(c->aux);
757                 c->aux = NULL;
758         }
759         if (QID(c->qid) == Qns && c->aux != 0)
760                 kfree(c->aux);
761         if (QID(c->qid) == Qstrace && c->aux != 0) {
762                 struct strace *s = c->aux;
763
764                 kref_put(&s->users);
765                 c->aux = NULL;
766         }
767 }
768
769 void int2flag(int flag, char *s)
770 {
771         if (flag == 0) {
772                 *s = '\0';
773                 return;
774         }
775         *s++ = '-';
776         if (flag & MAFTER)
777                 *s++ = 'a';
778         if (flag & MBEFORE)
779                 *s++ = 'b';
780         if (flag & MCREATE)
781                 *s++ = 'c';
782         if (flag & MCACHE)
783                 *s++ = 'C';
784         *s = '\0';
785 }
786
787 #if 0
788 static char *argcpy(char *s, char *p)
789 {
790         char *t, *tp, *te;
791         int n;
792
793         n = p - s;
794         if (n > 128)
795                 n = 128;
796         if (n <= 0) {
797                 t = kzmalloc(1, MEM_WAIT);
798                 *t = 0;
799                 return t;
800         }
801         t = kzmalloc(n, MEM_WAIT);
802         tp = t;
803         te = t + n;
804
805         while (tp + 1 < te) {
806                 for (p--; p > s && p[-1] != 0; p--) ;
807                 tp = seprint(tp, te, "%q ", p);
808                 if (p == s)
809                         break;
810         }
811         if (*tp == ' ')
812                 *tp = 0;
813         return t;
814 }
815
816 static int procargs(struct proc *p, char *buf, int nbuf)
817 {
818         char *s;
819
820         if (p->setargs == 0) {
821                 s = argcpy(p->args, p->args + p->nargs);
822                 kfree(p->args);
823                 p->nargs = strlen(s);
824                 p->args = s;
825                 p->setargs = 1;
826         }
827         return snprint(buf, nbuf, "%s", p->args);
828 }
829
830 static int eventsavailable(void *)
831 {
832         return tproduced > tconsumed;
833 }
834 #endif
835 static long procread(struct chan *c, void *va, long n, int64_t off)
836 {
837         ERRSTACK(1);
838         struct proc *p;
839         long l, r;
840         int i, j, navail, pid, rsize;
841         char flag[10], *sps, *srv;
842         uintptr_t offset, u;
843         int tesz;
844         uint8_t *rptr;
845         struct mntwalk *mw;
846         struct strace *s;
847
848         if (c->qid.type & QTDIR) {
849                 int nn;
850                 printd("procread: dir\n");
851                 nn = devdirread(c, va, n, 0, 0, procgen);
852                 printd("procread: %d\n", nn);
853                 return nn;
854         }
855
856         offset = off;
857         /* Some shit in proc doesn't need to grab the reference.  For strace, we
858          * already have the chan open, and all we want to do is read the queue,
859          * which exists because of our kref on it. */
860         switch (QID(c->qid)) {
861                 case Qstrace:
862                         s = c->aux;
863                         n = qread(s->q, va, n);
864                         return n;
865         }
866
867         if ((p = pid2proc(SLOT(c->qid))) == NULL)
868                 error(ESRCH, "%d: no such process", SLOT(c->qid));
869         if (p->pid != PID(c->qid)) {
870                 kref_put(&p->p_kref);
871                 error(ESRCH, "weird: p->pid is %d, PID(c->qid) is %d: mismatch",
872                       p->pid, PID(c->qid));
873         }
874         switch (QID(c->qid)) {
875                 default:
876                         kref_put(&p->p_kref);
877                         break;
878                 case Qstatus:{
879                                 /* the old code grew the stack and was hideous.
880                                  * status is not a high frequency operation; just malloc. */
881                                 char *buf = kmalloc(4096, MEM_WAIT);
882                                 char *s = buf, *e = buf + 4096;
883                                 int i;
884
885                                 s = seprintf(s, e,
886                                          "%8d %-*s %-10s %6d", p->pid, PROC_PROGNAME_SZ,
887                                          p->progname, procstate2str(p->state),
888                                          p->ppid);
889                                 if (p->strace)
890                                         s = seprintf(s, e, " %d trace users %d traced procs",
891                                                      kref_refcnt(&p->strace->users),
892                                                      kref_refcnt(&p->strace->procs));
893                                 kref_put(&p->p_kref);
894                                 i = readstr(off, va, n, buf);
895                                 kfree(buf);
896                                 return i;
897                         }
898
899                 case Qvmstatus:
900                         {
901                                 size_t buflen = 50 * 65 + 2;
902                                 char *buf = kmalloc(buflen, MEM_WAIT);
903                                 int i, offset;
904                                 offset = 0;
905                                 offset += snprintf(buf + offset, buflen - offset, "{\n");
906                                 for (i = 0; i < 65; i++) {
907                                         if (p->vmm.vmexits[i] != 0) {
908                                                 offset += snprintf(buf + offset, buflen - offset,
909                                                                    "\"%s\":\"%lld\",\n",
910                                                                    VMX_EXIT_REASON_NAMES[i],
911                                                                    p->vmm.vmexits[i]);
912                                         }
913                                 }
914                                 offset += snprintf(buf + offset, buflen - offset, "}\n");
915                                 kref_put(&p->p_kref);
916                                 n = readstr(off, va, n, buf);
917                                 kfree(buf);
918                                 return n;
919                         }
920                 case Qns:
921                         //qlock(&p->debug);
922                         if (waserror()) {
923                                 //qunlock(&p->debug);
924                                 kref_put(&p->p_kref);
925                                 nexterror();
926                         }
927                         if (p->pgrp == NULL || p->pid != PID(c->qid))
928                                 error(ESRCH, ERROR_FIXME);
929                         mw = c->aux;
930                         if (mw->cddone) {
931                                 poperror();
932                                 //qunlock(&p->debug);
933                                 kref_put(&p->p_kref);
934                                 return 0;
935                         }
936                         mntscan(mw, p);
937                         if (mw->mh == 0) {
938                                 mw->cddone = 1;
939                                 i = snprintf(va, n, "cd %s\n", p->dot->name->s);
940                                 poperror();
941                                 //qunlock(&p->debug);
942                                 kref_put(&p->p_kref);
943                                 return i;
944                         }
945                         int2flag(mw->cm->mflag, flag);
946                         if (strcmp(mw->cm->to->name->s, "#M") == 0) {
947                                 srv = srvname(mw->cm->to->mchan);
948                                 i = snprintf(va, n, "mount %s %s %s %s\n", flag,
949                                                          srv == NULL ? mw->cm->to->mchan->name->s : srv,
950                                                          mw->mh->from->name->s,
951                                                          mw->cm->spec ? mw->cm->spec : "");
952                                 kfree(srv);
953                         } else
954                                 i = snprintf(va, n, "bind %s %s %s\n", flag,
955                                                          mw->cm->to->name->s, mw->mh->from->name->s);
956                         poperror();
957                         //qunlock(&p->debug);
958                         kref_put(&p->p_kref);
959                         return i;
960         }
961         error(EINVAL, "QID %d did not match any QIDs for #proc", QID(c->qid));
962         return 0;       /* not reached */
963 }
964
965 static void mntscan(struct mntwalk *mw, struct proc *p)
966 {
967         struct pgrp *pg;
968         struct mount *t;
969         struct mhead *f;
970         int best, i, last, nxt;
971
972         pg = p->pgrp;
973         rlock(&pg->ns);
974
975         nxt = 0;
976         best = (int)(~0U >> 1); /* largest 2's complement int */
977
978         last = 0;
979         if (mw->mh)
980                 last = mw->cm->mountid;
981
982         for (i = 0; i < MNTHASH; i++) {
983                 for (f = pg->mnthash[i]; f; f = f->hash) {
984                         for (t = f->mount; t; t = t->next) {
985                                 if (mw->mh == 0 || (t->mountid > last && t->mountid < best)) {
986                                         mw->cm = t;
987                                         mw->mh = f;
988                                         best = mw->cm->mountid;
989                                         nxt = 1;
990                                 }
991                         }
992                 }
993         }
994         if (nxt == 0)
995                 mw->mh = 0;
996
997         runlock(&pg->ns);
998 }
999
1000 static long procwrite(struct chan *c, void *va, long n, int64_t off)
1001 {
1002         ERRSTACK(2);
1003
1004         struct proc *p, *t;
1005         int i, id, l;
1006         char *args;
1007         uintptr_t offset;
1008
1009         if (c->qid.type & QTDIR)
1010                 error(EISDIR, ERROR_FIXME);
1011
1012         if ((p = pid2proc(SLOT(c->qid))) == NULL)
1013                 error(ESRCH, ERROR_FIXME);
1014
1015         if (waserror()) {
1016                 kref_put(&p->p_kref);
1017                 nexterror();
1018         }
1019         if (p->pid != PID(c->qid))
1020                 error(ESRCH, ERROR_FIXME);
1021
1022         offset = off;
1023
1024         switch (QID(c->qid)) {
1025 #if 0
1026                 case Qargs:
1027                         if (n == 0)
1028                                 error(EINVAL, ERROR_FIXME);
1029                         if (n >= sizeof buf - strlen(p->text) - 1)
1030                                 error(E2BIG, ERROR_FIXME);
1031                         l = snprintf(buf, sizeof buf, "%s [%s]", p->text, (char *)va);
1032                         args = kzmalloc(l + 1, MEM_WAIT);
1033                         if (args == NULL)
1034                                 error(ENOMEM, ERROR_FIXME);
1035                         memmove(args, buf, l);
1036                         args[l] = 0;
1037                         kfree(p->args);
1038                         p->nargs = l;
1039                         p->args = args;
1040                         p->setargs = 1;
1041                         break;
1042
1043                 case Qmem:
1044                         if (p->state != Stopped)
1045                                 error(EINVAL, ERROR_FIXME);
1046
1047                         n = procctlmemio(p, offset, n, va, 0);
1048                         break;
1049
1050                 case Qregs:
1051                         if (offset >= sizeof(Ureg))
1052                                 n = 0;
1053                         else if (offset + n > sizeof(Ureg))
1054                                 n = sizeof(Ureg) - offset;
1055                         if (p->dbgreg == 0)
1056                                 error(ENODATA, ERROR_FIXME);
1057                         setregisters(p->dbgreg, (char *)(p->dbgreg) + offset, va, n);
1058                         break;
1059
1060                 case Qfpregs:
1061                         n = fpudevprocio(p, va, n, offset, 1);
1062                         break;
1063 #endif
1064                 case Qctl:
1065                         procctlreq(p, va, n);
1066                         break;
1067
1068                 /* this lets your write a marker into the data stream,
1069                  * which is a very powerful tool. */
1070                 case Qstrace:
1071                         assert(c->aux);
1072                         /* it is possible that the q hungup and is closed.  that would be
1073                          * the case if all of the procs closed and decref'd.  if the q is
1074                          * closed, qwrite() will throw an error. */
1075                         n = qwrite(((struct strace*)c->aux)->q, va, n);
1076                         break;
1077                 default:
1078                         error(EFAIL, "unknown qid %#llux in procwrite\n", c->qid.path);
1079         }
1080         poperror();
1081         kref_put(&p->p_kref);
1082         return n;
1083 }
1084
1085 struct dev procdevtab __devtab = {
1086         .name = "proc",
1087
1088         .reset = devreset,
1089         .init = procinit,
1090         .shutdown = devshutdown,
1091         .attach = procattach,
1092         .walk = procwalk,
1093         .stat = procstat,
1094         .open = procopen,
1095         .create = devcreate,
1096         .close = procclose,
1097         .read = procread,
1098         .bread = devbread,
1099         .write = procwrite,
1100         .bwrite = devbwrite,
1101         .remove = devremove,
1102         .wstat = procwstat,
1103         .power = devpower,
1104         .chaninfo = devchaninfo,
1105 };
1106
1107 #if 0
1108 static struct chan *proctext(struct chan *c, struct proc *p)
1109 {
1110         ERRSTACK(2);
1111         struct chan *tc;
1112         Image *i;
1113         Segment *s;
1114
1115         s = p->seg[TSEG];
1116         if (s == 0)
1117                 error(ENOENT, ERROR_FIXME);
1118         if (p->state == Dead)
1119                 error(ESRCH, ERROR_FIXME);
1120
1121         lock(s);
1122         i = s->image;
1123         if (i == 0) {
1124                 unlock(s);
1125                 error(ESRCH, ERROR_FIXME);
1126         }
1127         unlock(s);
1128
1129         lock(i);
1130         if (waserror()) {
1131                 unlock(i);
1132                 nexterror();
1133         }
1134
1135         tc = i->c;
1136         if (tc == 0)
1137                 error(ESRCH, ERROR_FIXME);
1138
1139         /* TODO: what do you want here?  you can't get a kref and have the new val
1140          * be 1.  Here is the old code: if (kref_get(&tc->ref, 1) == 1 || ... ) */
1141         if (kref_refcnt(&tc->ref, 1) == 1 || (tc->flag & COPEN) == 0
1142                 || tc->mode != OREAD) {
1143                 cclose(tc);
1144                 error(ESRCH, ERROR_FIXME);
1145         }
1146
1147         if (p->pid != PID(c->qid)) {
1148                 cclose(tc);
1149                 error(ESRCH, ERROR_FIXME);
1150         }
1151
1152         poperror();
1153         unlock(i);
1154
1155         return tc;
1156 }
1157
1158 /* TODO: this will fail at compile time, since we don't have a proc-wide rendez,
1159  * among other things, and we'll need to rewrite this for akaros */
1160 void procstopwait(struct proc *p, int ctl)
1161 {
1162         ERRSTACK(2);
1163         int pid;
1164
1165         if (p->pdbg)
1166                 error(EBUSY, ERROR_FIXME);
1167         if (procstopped(p) || p->state == Broken)
1168                 return;
1169
1170         if (ctl != 0)
1171                 p->procctl = ctl;
1172         p->pdbg = up;
1173         pid = p->pid;
1174         qunlock(&p->debug);
1175         current->psstate = "Stopwait";
1176         if (waserror()) {
1177                 p->pdbg = 0;
1178                 qlock(&p->debug);
1179                 nexterror();
1180         }
1181         rendez_sleep(&current->sleep, procstopped, p);
1182         poperror();
1183         qlock(&p->debug);
1184         if (p->pid != pid)
1185                 error(ESRCH, ERROR_FIXME);
1186 }
1187
1188 #endif
1189 static void procctlcloseone(struct proc *p, int fd)
1190 {
1191 // TODO: resolve this and sys_close
1192         struct file *file = get_file_from_fd(&p->open_files, fd);
1193         int retval = 0;
1194         printd("%s %d\n", __func__, fd);
1195         /* VFS */
1196         if (file) {
1197                 put_file_from_fd(&p->open_files, fd);
1198                 kref_put(&file->f_kref);        /* Drop the ref from get_file */
1199                 return;
1200         }
1201         /* 9ns, should also handle errors (bad FD, etc) */
1202         retval = sysclose(fd);
1203         return;
1204
1205         //sys_close(p, fd);
1206 }
1207
1208 void procctlclosefiles(struct proc *p, int all, int fd)
1209 {
1210         int i;
1211
1212         if (all)
1213                 for (i = 0; i < NR_FILE_DESC_MAX; i++)
1214                         procctlcloseone(p, i);
1215         else
1216                 procctlcloseone(p, fd);
1217 }
1218
1219 static void strace_shutdown(struct kref *a)
1220 {
1221         struct strace *strace = container_of(a, struct strace, procs);
1222         static const char base_msg[] = "Traced ~%lu syscs, Dropped %lu";
1223         size_t msg_len = NUMSIZE64 * 2 + sizeof(base_msg);
1224         char *msg = kmalloc(msg_len, 0);
1225
1226         if (msg)
1227                 snprintf(msg, msg_len, base_msg, strace->appx_nr_sysc,
1228                          atomic_read(&strace->nr_drops));
1229         qhangup(strace->q, msg);
1230         kfree(msg);
1231 }
1232
1233 static void strace_release(struct kref *a)
1234 {
1235         struct strace *strace = container_of(a, struct strace, users);
1236
1237         qfree(strace->q);
1238         kfree(strace);
1239 }
1240
1241 static void procctlreq(struct proc *p, char *va, int n)
1242 {
1243         ERRSTACK(1);
1244         int8_t irq_state = 0;
1245         int npc, pri, core;
1246         struct cmdbuf *cb;
1247         struct cmdtab *ct;
1248         int64_t time;
1249         char *e;
1250         struct strace *strace;
1251
1252         cb = parsecmd(va, n);
1253         if (waserror()) {
1254                 kfree(cb);
1255                 nexterror();
1256         }
1257
1258         ct = lookupcmd(cb, proccmd, ARRAY_SIZE(proccmd));
1259
1260         switch (ct->index) {
1261         case CMstraceall:
1262         case CMstraceme:
1263                 /* common allocation.  if we inherited, we might have one already */
1264                 if (!p->strace) {
1265                         strace = kzmalloc(sizeof(*p->strace), MEM_WAIT);
1266                         strace->q = qopen(65536, Qdropoverflow|Qcoalesce, NULL, NULL);
1267                         /* both of these refs are put when the proc is freed.  procs is for
1268                          * every process that has this p->strace.  users is procs + every
1269                          * user (e.g. from open()).
1270                          *
1271                          * it is possible to kref_put the procs kref in proc_destroy, which
1272                          * would make strace's job easier (no need to do an async wait on
1273                          * the child), and we wouldn't need to decref p in
1274                          * procread(Qstrace).  But the downside is that proc_destroy races
1275                          * with us here with the kref initialization. */
1276                         kref_init(&strace->procs, strace_shutdown, 1);
1277                         kref_init(&strace->users, strace_release, 1);
1278                         if (!atomic_cas_ptr((void**)&p->strace, 0, strace)) {
1279                                 /* someone else won the race and installed strace. */
1280                                 qfree(strace->q);
1281                                 kfree(strace);
1282                                 error(EAGAIN, "Concurrent strace init, try again");
1283                         }
1284                 }
1285                 break;
1286         }
1287
1288         /* actually do the command. */
1289         switch (ct->index) {
1290         case CMvmstart:
1291         case CMvmkill:
1292         default:
1293                 error(EFAIL, "Command not implemented");
1294                 break;
1295         case CMclose:
1296                 procctlclosefiles(p, 0, atoi(cb->f[1]));
1297                 break;
1298         case CMclosefiles:
1299                 procctlclosefiles(p, 1, 0);
1300                 break;
1301 #if 0
1302                 we may want this.Let us pause a proc.case CMhang:p->hang = 1;
1303                 break;
1304 #endif
1305         case CMkill:
1306                 p = pid2proc(strtol(cb->f[1], 0, 0));
1307                 if (!p)
1308                         error(EFAIL, "No such proc\n");
1309
1310                 enable_irqsave(&irq_state);
1311                 proc_destroy(p);
1312                 disable_irqsave(&irq_state);
1313                 proc_decref(p);
1314                 /* this is a little ghetto. it's not fully free yet, but we are also
1315                  * slowing it down by messing with it, esp with the busy waiting on a
1316                  * hyperthreaded core. */
1317                 spin_on(p->env_cr3);
1318                 break;
1319         case CMvminit:
1320                 break;
1321         case CMstraceme:
1322                 p->strace_on = TRUE;
1323                 p->strace_inherit = FALSE;
1324                 break;
1325         case CMstraceall:
1326                 p->strace_on = TRUE;
1327                 p->strace_inherit = TRUE;
1328                 break;
1329         case CMstraceoff:
1330                 p->strace_on = FALSE;
1331                 p->strace_inherit = FALSE;
1332                 break;
1333         }
1334         poperror();
1335         kfree(cb);
1336 }
1337
1338 #if 0
1339 static int procstopped(void *a)
1340 {
1341         struct proc *p = a;
1342         return p->state == Stopped;
1343 }
1344
1345 static int
1346 procctlmemio(struct proc *p, uintptr_t offset, int n, void *va, int read)
1347 {
1348         KMap *k;
1349         Pte *pte;
1350         Page *pg;
1351         Segment *s;
1352         uintptr_t soff, l;                      /* hmmmm */
1353         uint8_t *b;
1354         uintmem pgsz;
1355
1356         for (;;) {
1357                 s = seg(p, offset, 1);
1358                 if (s == 0)
1359                         error(EINVAL, ERROR_FIXME);
1360
1361                 if (offset + n >= s->top)
1362                         n = s->top - offset;
1363
1364                 if (!read && (s->type & SG_TYPE) == SG_TEXT)
1365                         s = txt2data(p, s);
1366
1367                 s->steal++;
1368                 soff = offset - s->base;
1369                 if (waserror()) {
1370                         s->steal--;
1371                         nexterror();
1372                 }
1373                 if (fixfault(s, offset, read, 0, s->color) == 0)
1374                         break;
1375                 poperror();
1376                 s->steal--;
1377         }
1378         poperror();
1379         pte = s->map[soff / PTEMAPMEM];
1380         if (pte == 0)
1381                 panic("procctlmemio");
1382         pgsz = m->pgsz[s->pgszi];
1383         pg = pte->pages[(soff & (PTEMAPMEM - 1)) / pgsz];
1384         if (pagedout(pg))
1385                 panic("procctlmemio1");
1386
1387         l = pgsz - (offset & (pgsz - 1));
1388         if (n > l)
1389                 n = l;
1390
1391         k = kmap(pg);
1392         if (waserror()) {
1393                 s->steal--;
1394                 kunmap(k);
1395                 nexterror();
1396         }
1397         b = (uint8_t *) VA(k);
1398         b += offset & (pgsz - 1);
1399         if (read == 1)
1400                 memmove(va, b, n);      /* This can fault */
1401         else
1402                 memmove(b, va, n);
1403         poperror();
1404         kunmap(k);
1405
1406         /* Ensure the process sees text page changes */
1407         if (s->flushme)
1408                 memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
1409
1410         s->steal--;
1411
1412         if (read == 0)
1413                 p->newtlb = 1;
1414
1415         return n;
1416 }
1417
1418 static Segment *txt2data(struct proc *p, Segment * s)
1419 {
1420         int i;
1421         Segment *ps;
1422
1423         ps = newseg(SG_DATA, s->base, s->size);
1424         ps->image = s->image;
1425         kref_get(&ps->image->ref, 1);
1426         ps->fstart = s->fstart;
1427         ps->flen = s->flen;
1428         ps->flushme = 1;
1429
1430         qlock(&p->seglock);
1431         for (i = 0; i < NSEG; i++)
1432                 if (p->seg[i] == s)
1433                         break;
1434         if (i == NSEG)
1435                 panic("segment gone");
1436
1437         qunlock(&s->lk);
1438         putseg(s);
1439         qlock(&ps->lk);
1440         p->seg[i] = ps;
1441         qunlock(&p->seglock);
1442
1443         return ps;
1444 }
1445
1446 Segment *data2txt(Segment * s)
1447 {
1448         Segment *ps;
1449
1450         ps = newseg(SG_TEXT, s->base, s->size);
1451         ps->image = s->image;
1452         kref_get(&ps->image->ref, 1);
1453         ps->fstart = s->fstart;
1454         ps->flen = s->flen;
1455         ps->flushme = 1;
1456
1457         return ps;
1458 }
1459 #endif