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