fixed for new swap map setup
[unix-history] / usr / src / old / analyze / analyze.c
CommitLineData
f6d84e07
SL
1#ifndef lint
2static char *sccsid = "@(#)analyze.c 4.7 (Berkeley) %G%";
3#endif
4
5/*
6 * Analyze - analyze a core (and optional paging area) saved from
7 * a virtual Unix system crash.
8 */
c4589a32
BJ
9#include <stdio.h>
10#include <sys/param.h>
11#include <sys/dir.h>
0bc29a7d 12#include <machine/pte.h>
c4589a32
BJ
13#include <nlist.h>
14#include <sys/map.h>
15#include <sys/user.h>
16#include <sys/proc.h>
17#include <sys/text.h>
18#include <sys/cmap.h>
19#include <sys/vm.h>
20
c4589a32
BJ
21int Dflg;
22int dflg;
23int vflg;
24int mflg;
25int fflg;
26int sflg;
abf78ad6 27int uflg;
c4589a32
BJ
28
29/* use vprintf with care; it plays havoc with ``else's'' */
30#define vprintf if (vflg) printf
31
db770cb2 32#ifdef vax
c4589a32 33#define clear(x) ((int)x & 0x7fffffff)
db770cb2
SL
34#else
35#define clear(x) ((int)x)
36#endif
c4589a32 37
a4412164 38struct proc *proc, *aproc;
8fc75516 39int nproc;
a4412164 40struct text *text, *atext;
8fc75516
BJ
41int ntext;
42struct mapent *swapmap;
43int nswapmap;
f6d84e07 44int dmmin, dmmax, dmtext;
c4589a32 45struct cmap *cmap;
abf78ad6 46int ecmx;
c4589a32
BJ
47struct pte *usrpt;
48struct pte *Usrptma;
49int firstfree;
50int maxfree;
51int freemem;
52struct pte p0br[ctopt(MAXTSIZ+MAXDSIZ+MAXSSIZ)][NPTEPG];
53int pid;
54
55struct paginfo {
56 char z_type;
57 char z_count;
58 short z_pid;
59 struct pte z_pte;
60} *paginfo;
61#define ZLOST 0
62#define ZDATA 1
63#define ZSTACK 2
64#define ZUDOT 3
65#define ZPAGET 4
66#define ZTEXT 5
67#define ZFREE 6
68#define ZINTRAN 7
69
c4589a32
BJ
70struct dblks {
71 short d_first;
72 short d_size;
73 char d_type;
74 char d_index;
8fc75516 75} *dblks;
c4589a32
BJ
76int ndblks;
77
78#define DFREE 0
79#define DDATA 1
80#define DSTACK 2
81#define DTEXT 3
82#define DUDOT 4
83#define DPAGET 5
84
85union {
db770cb2 86 char buf[UPAGES][NBPG];
c4589a32
BJ
87 struct user U;
88} u_area;
89#define u u_area.U
90
91int fcore = -1;
92int fswap = -1;
93
94struct nlist nl[] = {
95#define X_PROC 0
96 { "_proc" },
97#define X_USRPT 1
98 { "_usrpt" },
99#define X_PTMA 2
abf78ad6 100 { "_Usrptmap" },
c4589a32 101#define X_FIRSTFREE 3
abf78ad6 102 { "_firstfree" },
c4589a32
BJ
103#define X_MAXFREE 4
104 { "_maxfree" },
105#define X_TEXT 5
106 { "_text" },
107#define X_FREEMEM 6
108 { "_freemem" },
109#define X_CMAP 7
110 { "_cmap" },
111#define X_ECMAP 8
112 { "_ecmap" },
113#define X_SWAPMAP 9
114 { "_swapmap" },
8fc75516
BJ
115#define X_NPROC 10
116 { "_nproc" },
117#define X_NTEXT 11
118 { "_ntext" },
119#define X_NSWAPMAP 12
120 { "_nswapmap" },
f6d84e07
SL
121#define X_DMMIN 13
122 { "_dmmin" },
123#define X_DMMAX 14
124 { "_dmmax" },
125#define X_DMTEXT 15
126 { "_dmtext" },
127 { "" }
c4589a32
BJ
128};
129
130main(argc, argv)
131 int argc;
132 char **argv;
133{
134 register struct nlist *np;
135 register struct proc *p;
136 register struct text *xp;
137 register struct pte *pte;
138 register int i;
139 int w, a;
140
db770cb2
SL
141#ifdef DEBUG
142 setbuf(stdout, NULL);
143#endif
c4589a32
BJ
144 argc--, argv++;
145 while (argc > 0 && argv[0][0] == '-') {
146 register char *cp = *argv++;
147 argc--;
148 while (*++cp) switch (*cp) {
149
150 case 'm':
151 mflg++;
152 break;
153
154 case 'v':
155 vflg++;
156 break;
157
158 case 's':
159 if (argc < 2)
160 goto usage;
161 if ((fswap = open(argv[0], 0)) < 0) {
162 perror(argv[0]);
163 exit(1);
164 }
165 argc--,argv++;
166 sflg++;
167 break;
168
169 case 'f':
170 fflg++;
171 break;
172
173 case 'D':
174 Dflg++;
175 break;
176
177 case 'd':
178 dflg++;
179 break;
180
abf78ad6
BJ
181 case 'u':
182 uflg++;
183 break;
184
c4589a32
BJ
185 default:
186 goto usage;
187 }
188 }
189 if (argc < 1) {
190usage:
191 fprintf(stderr, "usage: analyze [ -vmfd ] [ -s swapfile ] corefile [ system ]\n");
192 exit(1);
193 }
194 close(0);
195 if ((fcore = open(argv[0], 0)) < 0) {
196 perror(argv[0]);
197 exit(1);
198 }
199 nlist(argc > 1 ? argv[1] : "/vmunix", nl);
200 if (nl[0].n_value == 0) {
201 fprintf(stderr, "%s: bad namelist\n",
202 argc > 1 ? argv[1] : "/vmunix");
203 exit(1);
204 }
f6d84e07 205 for (np = nl; np->n_name && *np->n_name; np++)
c4589a32
BJ
206 vprintf("%8.8s %x\n", np->n_name ,np->n_value );
207 usrpt = (struct pte *)clear(nl[X_USRPT].n_value);
208 Usrptma = (struct pte *)clear(nl[X_PTMA].n_value);
209 firstfree = get(nl[X_FIRSTFREE].n_value);
210 maxfree = get(nl[X_MAXFREE].n_value);
211 freemem = get(nl[X_FREEMEM].n_value);
f6d84e07
SL
212 dmmin = get(nl[X_DMMIN]);
213 dmmax = get(nl[X_DMMAX]);
214 dmtext = get(nl[X_DMTEXT]);
c4589a32
BJ
215 paginfo = (struct paginfo *)calloc(maxfree, sizeof (struct paginfo));
216 if (paginfo == NULL) {
217 fprintf(stderr, "maxfree %x?... out of mem!\n", maxfree);
218 exit(1);
219 }
220 vprintf("usrpt %x\nUsrptma %x\nfirstfree %x\nmaxfree %x\nfreemem %x\n",
221 usrpt, Usrptma, firstfree, maxfree, freemem);
a4412164 222 {
8fc75516
BJ
223 lseek(fcore, (long)clear(nl[X_PROC].n_value), 0);
224 read(fcore, (char *)&aproc, sizeof aproc);
225 lseek(fcore, (long)clear(nl[X_NPROC].n_value), 0);
226 read(fcore, (char *)&nproc, sizeof nproc);
227 printf("%d procs\n", nproc);
228 proc = (struct proc *)calloc(nproc, sizeof (struct proc));
229 lseek(fcore, (long)clear(aproc), 0);
230 if (read(fcore, (char *)proc, nproc * sizeof (struct proc))
231 != nproc * sizeof (struct proc)) {
c4589a32
BJ
232 perror("proc read");
233 exit(1);
8fc75516 234 }
c4589a32 235 }
a4412164 236 {
8fc75516
BJ
237 lseek(fcore, (long)clear(nl[X_TEXT].n_value), 0);
238 read(fcore, (char *)&atext, sizeof atext);
239 lseek(fcore, (long)clear(nl[X_NTEXT].n_value), 0);
240 read(fcore, (char *)&ntext, sizeof ntext);
241 printf("%d texts\n", ntext);
242 text = (struct text *)calloc(ntext, sizeof (struct text));
243 lseek(fcore, (long)clear(atext), 0);
244 if (read(fcore, (char *)text, ntext * sizeof (struct text))
245 != ntext * sizeof (struct text)) {
c4589a32
BJ
246 perror("text read");
247 exit(1);
8fc75516 248 }
c4589a32
BJ
249 }
250 i = (get(nl[X_ECMAP].n_value) - get(nl[X_CMAP].n_value));
abf78ad6 251 ecmx = i / sizeof (struct cmap);
c4589a32
BJ
252 cmap = (struct cmap *)calloc(i, 1);
253 if (cmap == NULL) {
254 fprintf(stderr, "not enough mem for %x bytes of cmap\n", i);
255 exit(1);
256 }
257 lseek(fcore, (long)clear(get(nl[X_CMAP].n_value)), 0);
258 if (read(fcore, (char *)cmap, i) != i) {
259 perror("cmap read");
260 exit(1);
261 }
8fc75516
BJ
262 { struct mapent *aswapmap;
263 lseek(fcore, (long)clear(nl[X_SWAPMAP].n_value), 0);
264 read(fcore, (char *)&aswapmap, sizeof aswapmap);
265 lseek(fcore, (long)clear(nl[X_NSWAPMAP].n_value), 0);
266 read(fcore, (char *)&nswapmap, sizeof nswapmap);
267 nswapmap--;
268 printf("%d swapmap entries\n", nswapmap);
269 swapmap = (struct mapent *)calloc(nswapmap, sizeof (struct mapent));
270 dblks = (struct dblks *)calloc(2 * nswapmap, sizeof (struct dblks));
271 lseek(fcore, (long)clear(aswapmap+1), 0);
272 if (read(fcore, (char *)swapmap, nswapmap * sizeof (struct mapent))
273 != nswapmap * sizeof (struct mapent)) {
c4589a32
BJ
274 perror("swapmap read");
275 exit(1);
8fc75516 276 }
c4589a32 277 }
8fc75516 278 for (p = &proc[1]; p < proc+nproc; p++) {
c4589a32
BJ
279 p->p_p0br = (struct pte *)clear(p->p_p0br);
280 p->p_addr = (struct pte *)clear(p->p_addr);
281 if (p->p_stat == 0)
282 continue;
283 printf("proc %d ", p->p_pid);
284 if (p->p_stat == SZOMB) {
285 printf("zombie\n");
286 continue;
287 }
288 if (p->p_flag & SLOAD) {
289 printf("loaded, p0br %x, ", p->p_p0br);
290 printf("%d pages of page tables:", p->p_szpt);
291 a = btokmx(p->p_p0br);
292 for (i = 0; i < p->p_szpt; i++) {
293 w = get(&Usrptma[a + i]);
294 printf(" %x", w & PG_PFNUM);
295 }
296 printf("\n");
297 for(i = 0; i < p->p_szpt; i++) {
298 w = get(&Usrptma[a + i]);
299 if (getpt(w, i))
300 count(p, (struct pte *)&w, ZPAGET);
301 }
302 } else {
303 /* i = ctopt(btoc(u.u_exdata.ux_dsize)); */
304 i = clrnd(ctopt(p->p_tsize + p->p_dsize + p->p_ssize));
305 printf("swapped, swaddr %x\n", p->p_swaddr);
db770cb2 306 duse(p->p_swaddr, ctod(clrnd(UPAGES)), DUDOT, p - proc);
c4589a32 307 duse(p->p_swaddr + ctod(UPAGES),
db770cb2
SL
308 ctod(clrnd(i - p->p_tsize / NPTEPG)),
309 DPAGET, p - proc);
c4589a32
BJ
310 /* i, DPAGET, p - proc); */
311 }
312 p->p_p0br = (struct pte *)p0br;
313 p->p_addr = uaddr(p);
db770cb2
SL
314 if (p->p_textp)
315 p->p_textp = &text[p->p_textp - atext];
c4589a32
BJ
316 if (p->p_pid == 2)
317 continue;
318 if (getu(p))
319 continue;
320 u.u_procp = p;
321 pdmap();
322 if ((p->p_flag & SLOAD) == 0)
323 continue;
324 pid = p->p_pid;
325 for (i = 0; i < p->p_tsize; i++) {
326 pte = tptopte(p, i);
327 if (pte->pg_fod || pte->pg_pfnum == 0)
328 continue;
329 if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans)
330 count(p, pte, ZINTRAN);
331 else
332 count(p, pte, ZTEXT);
333 }
334 vprintf("\n");
335 for (i = 0; i < p->p_dsize; i++) {
336 pte = dptopte(p, i);
337 if (pte->pg_fod || pte->pg_pfnum == 0)
338 continue;
339 if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans)
340 count(p, pte, ZINTRAN);
341 else
342 count(p, pte, ZDATA);
343 }
344 vprintf("\n");
345 for (i = 0; i < p->p_ssize; i++) {
346 pte = sptopte(p, i);
347 if (pte->pg_fod || pte->pg_pfnum == 0)
348 continue;
349 if (pte->pg_pfnum >= firstfree && pte->pg_pfnum < maxfree && cmap[pgtocm(pte->pg_pfnum)].c_intrans)
350 count(p, pte, ZINTRAN);
351 else
352 count(p, pte, ZSTACK);
353 }
354 vprintf("\n");
355 for (i = 0; i < UPAGES; i++)
356 count(p, &p->p_addr[i], ZUDOT);
357 vprintf("\n");
358 vprintf("\n");
359 }
8fc75516 360 for (xp = &text[0]; xp < text+ntext; xp++)
c4589a32 361 if (xp->x_iptr) {
db770cb2
SL
362 int size = ctod(xp->x_size);
363
f6d84e07 364 for (i = 0; i < size; i += dmtext)
c4589a32 365 duse(xp->x_daddr[i],
f6d84e07
SL
366 (size - i) > dmtext
367 ? dmtext : size - i,
c4589a32
BJ
368 DTEXT, xp - text);
369 if (xp->x_flag & XPAGI)
db770cb2
SL
370 duse(xp->x_ptdaddr,
371 ctod(clrnd(ctopt(xp->x_size))),
c4589a32
BJ
372 DTEXT, xp - text);
373 }
374 dmcheck();
375 fixfree();
376 summary();
377 exit(0);
378}
379
380pdmap()
381{
382 register struct text *xp;
383
384 if (fswap == -1 && (u.u_procp->p_flag & SLOAD) == 0)
385 return;
386 if (Dflg)
387 printf("disk for pid %d", u.u_procp->p_pid);
388 if ((xp = u.u_procp->p_textp) && Dflg)
389 ptdmap(xp->x_daddr, xp->x_size);
390 pdmseg("data", &u.u_dmap, DDATA);
391 pdmseg("stack", &u.u_smap, DSTACK);
392 if (Dflg)
393 printf("\n");
394}
395
396ptdmap(dp, size)
397 register daddr_t *dp;
398 int size;
399{
400 register int i;
401 int rem;
402
403 if (Dflg)
404 printf(" text:");
405 for (i = 0, rem = size; rem > 0; i++) {
406 if (Dflg)
f6d84e07
SL
407 printf(" %x<%x>", dp[i], rem < dmtext ? rem : dmtext);
408 rem -= rem < dmtext ? rem : dmtext;
c4589a32
BJ
409 }
410}
411
412pdmseg(cp, dmp, type)
413 char *cp;
414 struct dmap *dmp;
415{
416 register int i;
417 int b, rem;
418
419 if (Dflg)
420 printf(", %s:", cp);
f6d84e07 421 b = dmmin;
c4589a32
BJ
422 for (i = 0, rem = dmp->dm_size; rem > 0; i++) {
423 if (Dflg)
424 printf(" %x<%x>", dmp->dm_map[i], rem < b ? rem : b);
425 duse(dmp->dm_map[i], b, type, u.u_procp - proc);
426 rem -= b;
f6d84e07 427 if (b < dmmax)
c4589a32
BJ
428 b *= 2;
429 }
430}
431
432duse(first, size, type, index)
433{
434 register struct dblks *dp;
435
436 if (fswap == -1)
437 return;
438 dp = &dblks[ndblks];
8fc75516
BJ
439 if (++ndblks > 2*nswapmap) {
440 fprintf(stderr, "too many disk blocks\n");
c4589a32
BJ
441 exit(1);
442 }
443 dp->d_first = first;
444 dp->d_size = size;
445 dp->d_type = type;
446 dp->d_index = index;
447}
448
449dsort(d, e)
450 register struct dblks *d, *e;
451{
452
453 return (e->d_first - d->d_first);
454}
455
456dmcheck()
457{
8fc75516 458 register struct mapent *smp;
c4589a32
BJ
459 register struct dblks *d, *e;
460
461 for (smp = swapmap; smp->m_size; smp++)
462 duse(smp->m_addr, smp->m_size, DFREE, 0);
f6d84e07 463 duse(ctod(CLSIZE), dmtext - ctod(CLSIZE), DFREE, 0);
c4589a32
BJ
464 qsort(dblks, ndblks, sizeof (struct dblks), dsort);
465 d = &dblks[ndblks - 1];
466 if (d->d_first > 1)
467 printf("lost swap map: start %x size %x\n", 1, d->d_first);
468 for (; d > dblks; d--) {
469 if (dflg)
470 dprint(d);
471 e = d - 1;
472 if (d->d_first + d->d_size > e->d_first) {
473 printf("overlap in swap mappings:\n");
474 dprint(d);
475 dprint(e);
476 } else if (d->d_first + d->d_size < e->d_first) {
477 printf("lost swap map: start %x size %x\n",
478 d->d_first + d->d_size,
479 e->d_first - (d->d_first + d->d_size));
480 }
481 }
482 if (dflg)
483 dprint(dblks);
484 if (sflg)
485 printf("swap space ends at %x\n", d->d_first + d->d_size);
486}
487
488char *dnames[] = {
489 "DFREE",
490 "DDATA",
491 "DSTACK",
492 "DTEXT",
493 "DUDOT",
494 "DPAGET",
495};
496
497dprint(d)
498 register struct dblks *d;
499{
500
501 printf("at %4x size %4x type %s", d->d_first, d->d_size,
502 dnames[d->d_type]);
503 switch (d->d_type) {
504
505 case DSTACK:
506 case DDATA:
507 printf(" pid %d", proc[d->d_index].p_pid);
508 break;
509 }
510 printf("\n");
511}
512
513getpt(x, i)
514 int x, i;
515{
516
517 lseek(fcore, (long)ctob((x & PG_PFNUM)), 0);
518 if (read(fcore, (char *)(p0br[i]), NBPG) != NBPG) {
519 perror("read");
520 fprintf(stderr, "getpt error reading frame %x\n", clear(x));
521 return (0);
522 }
523 return (1);
524}
525
526checkpg(p, pte, type)
527 register struct pte *pte;
528 register struct proc *p;
529 int type;
530{
531 char corepg[NBPG], swapg[NBPG];
532 register int i, count, dblock;
533 register int pfnum = pte->pg_pfnum;
534
535 if (type == ZPAGET || type == ZUDOT)
536 return (0);
537 lseek(fcore, (long)(NBPG * pfnum), 0);
538 if (read(fcore, corepg, NBPG) != NBPG){
539 perror("read");
540 fprintf(stderr, "Error reading core page %x\n", pfnum);
541 return (0);
542 }
543 switch (type) {
544
545 case ZDATA:
546 if (ptetodp(p, pte) >= u.u_dmap.dm_size)
547 return (0);
548 break;
549
550 case ZTEXT:
551 break;
552
553 case ZSTACK:
554 if (ptetosp(p, pte) >= u.u_smap.dm_size)
555 return (0);
556 break;
557
558 default:
559 return(0);
560 break;
561 }
562 dblock = vtod(p, ptetov(p, pte), &u.u_dmap, &u.u_smap);
563 vprintf(" %x", dblock);
564 if (pte->pg_fod || pte->pg_pfnum == 0)
565 return (0);
566 if (cmap[pgtocm(pte->pg_pfnum)].c_intrans || pte->pg_m || pte->pg_swapm)
567 return (0);
db770cb2 568 lseek(fswap, (long)(DEV_BSIZE * dblock), 0);
c4589a32
BJ
569 if (read(fswap, swapg, NBPG) != NBPG) {
570 fprintf(stderr,"swap page %x: ", dblock);
571 perror("read");
572 }
573 count = 0;
574 for (i = 0; i < NBPG; i++)
575 if (corepg[i] != swapg[i])
576 count++;
577 if (count == 0)
578 vprintf("\tsame");
579 return (count);
580}
581
582getu(p)
583 register struct proc *p;
584{
585 int i, w, cc, errs = 0;
586
abf78ad6
BJ
587 if (uflg && (p->p_flag & SLOAD))
588 printf("pid %d u. pages:", p->p_pid);
c4589a32
BJ
589 for (i = 0; i < UPAGES; i++) {
590 if (p->p_flag & SLOAD) {
abf78ad6
BJ
591 if (uflg)
592 printf(" %x", p->p_addr[i].pg_pfnum);
c4589a32
BJ
593 lseek(fcore, ctob(p->p_addr[i].pg_pfnum), 0);
594 if (read(fcore, u_area.buf[i], NBPG) != NBPG)
595 perror("core u. read"), errs++;
596 } else if (fswap >= 0) {
597 lseek(fswap, (long)(NBPG * (p->p_swaddr+i)), 0);
598 if (read(fswap, u_area.buf[i], NBPG) != NBPG)
599 perror("swap u. read"), errs++;
600 }
601 }
abf78ad6
BJ
602 if (uflg && (p->p_flag & SLOAD))
603 printf("\n");
c4589a32
BJ
604 return (errs);
605}
606
607char *typepg[] = {
608 "lost",
609 "data",
610 "stack",
611 "udot",
612 "paget",
613 "text",
614 "free",
615 "intransit",
616};
617
618count(p, pte, type)
619 struct proc *p;
620 register struct pte *pte;
621 int type;
622{
623 register int pfnum = pte->pg_pfnum;
624 register struct paginfo *zp = &paginfo[pfnum];
625 int ndif;
626#define zprintf if (type==ZINTRAN || vflg) printf
627
628 if (type == ZINTRAN && pfnum == 0)
629 return;
630 zprintf("page %x %s", pfnum, typepg[type]);
631 if (sflg == 0 || (ndif = checkpg(p, pte, type)) == 0) {
632 zprintf("\n");
633 } else {
634 if (vflg == 0 && type != ZINTRAN)
635 printf("page %x %s,", pfnum, typepg[type]);
636 printf(" %d bytes differ\n",ndif);
637 }
638 if (pfnum < firstfree || pfnum > maxfree) {
639 printf("page number out of range:\n");
640 printf("\tpage %x type %s pid %d\n", pfnum, typepg[type], pid);
641 return;
642 }
643 if (bad(zp, type)) {
644 printf("dup page pte %x", *(int *)pte);
645 dumpcm("", pte->pg_pfnum);
646 dump(zp);
647 printf("pte %x and as %s in pid %d\n", zp->z_pte, typepg[type], pid);
648 return;
649 }
650 zp->z_type = type;
651 zp->z_count++;
652 zp->z_pid = pid;
653 zp->z_pte = *pte;
654}
655
656bad(zp, type)
657 struct paginfo *zp;
658{
659 if (type == ZTEXT) {
660 if (zp->z_type != 0 && zp->z_type != ZTEXT)
661 return (1);
662 return (0);
663 }
664 return (zp->z_count);
665}
666
667dump(zp)
668 struct paginfo *zp;
669{
670
671 printf("page %x type %s pid %d ", zp - paginfo, typepg[zp->z_type], zp->z_pid);
672}
673
674summary()
675{
676 register int i;
677 register struct paginfo *zp;
678 register int pfnum;
679
abf78ad6 680 for (i = firstfree + UPAGES; i < maxfree; i+= CLSIZE) {
c4589a32
BJ
681 zp = &paginfo[i];
682 if (zp->z_type == ZLOST)
683 dumpcm("lost", i);
684 pfnum = pgtocm(i);
685 if (cmap[pfnum].c_lock && cmap[pfnum].c_type != CSYS)
686 dumpcm("locked", i);
687 if (mflg)
688 dumpcm("mem", i);
689 }
690}
691
692char *tynames[] = {
693 "sys",
694 "text",
695 "data",
696 "stack"
697};
698dumpcm(cp, pg)
699 char *cp;
700 int pg;
701{
702 int pslot;
703 int cm;
704 register struct cmap *c;
705
c4589a32 706 cm = pgtocm(pg);
abf78ad6 707 printf("cm %x %s page %x ", cm, cp, pg);
c4589a32
BJ
708 c = &cmap[cm];
709 printf("\t[%x, %x", c->c_page, c->c_ndx);
a4412164
BJ
710 if (c->c_type == CSYS)
711 goto skip;
712 if (c->c_type != CTEXT) {
713 if (c->c_ndx >= nproc) {
714 printf(" [text c->c_ndx %d?]", c->c_ndx);
715 goto skip;
716 }
c4589a32 717 printf(" (=pid %d)", proc[c->c_ndx].p_pid);
a4412164
BJ
718 } else {
719 if (c->c_ndx >= ntext) {
720 printf(" [text c->c_ndx %d?]", c->c_ndx);
721 goto skip;
722 }
723 pslot= (text[c->c_ndx].x_caddr - aproc);
c4589a32
BJ
724 printf(" (=pid");
725 for(;;) {
726 printf(" %d", proc[pslot].p_pid);
727 if (proc[pslot].p_xlink == 0)
728 break;
a4412164 729 pslot= (proc[pslot].p_xlink - aproc);
c4589a32
BJ
730 }
731 printf(")");
732 }
a4412164 733skip:
c4589a32
BJ
734 printf("] ");
735 printf(tynames[c->c_type]);
736 if (c->c_free)
737 printf(" free");
738 if (c->c_gone)
739 printf(" gone");
740 if (c->c_lock)
741 printf(" lock");
742 if (c->c_want)
743 printf(" want");
744 if (c->c_intrans)
745 printf(" intrans");
746 if (c->c_blkno)
747 printf(" blkno %x mdev %d", c->c_blkno, c->c_mdev);
abf78ad6
BJ
748 if (c->c_hlink) {
749 printf(" hlink %x page %x", c->c_hlink, cmtopg(c->c_hlink));
750 if (c->c_hlink > ecmx)
751 printf(" <<<");
752 }
c4589a32
BJ
753 printf("\n");
754}
755
756fixfree()
757{
758 register int i, next, prev;
759
760 next = CMHEAD;
761 for (i=freemem/CLSIZE; --i >=0; ) {
762 prev = next;
763 next = cmap[next].c_next;
764 if (cmap[next].c_free == 0) {
765 printf("link to non free block: in %x to %x\n", cmtopg(prev), cmtopg(next));
766 dumpcm("bad free link in", cmtopg(prev));
767 dumpcm("to non free block", cmtopg(next));
768 }
769 if (cmtopg(next) > maxfree) {
770 printf("free list link out of range: in %x to %x\n", cmtopg(prev), cmtopg(next));
771 dumpcm("bad link in", cmtopg(prev));
772 }
773 paginfo[cmtopg(next)].z_type = ZFREE;
774 if (fflg)
775 dumpcm("free", cmtopg(next));
776 paginfo[cmtopg(next)+1].z_type = ZFREE;
777 if (fflg)
778 dumpcm("free", cmtopg(next)+1);
779 }
780}
781
782get(loc)
783unsigned loc;
784{
785 int x;
786
787 lseek(fcore, (long)clear(loc), 0);
788 if (read(fcore, (char *)&x, sizeof (int)) != sizeof (int)) {
789 perror("read");
790 fprintf(stderr, "get failed on %x\n", clear(loc));
791 return (0);
792 }
793 return (x);
794}
795/*
796 * Convert a virtual page number
797 * to its corresponding disk block number.
798 * Used in pagein/pageout to initiate single page transfers.
799 */
800vtod(p, v, dmap, smap)
801 register struct proc *p;
802 register struct dmap *dmap, *smap;
803{
804 struct dblock db;
805
db770cb2
SL
806 if (isatsv(p, v)) {
807 v = ctod(vtotp(p, v));
f6d84e07 808 return(p->p_textp->x_daddr[v / dmtext] + v % dmtext);
db770cb2 809 }
c4589a32 810 if (isassv(p, v))
db770cb2 811 vstodb(ctod(vtosp(p, v)), ctod(1), smap, &db, 1);
c4589a32 812 else
db770cb2 813 vstodb(ctod(vtodp(p, v)), ctod(1), dmap, &db, 0);
c4589a32
BJ
814 return (db.db_base);
815}
816
817/*
818 * Convert a pte pointer to
819 * a virtual page number.
820 */
821ptetov(p, pte)
822 register struct proc *p;
823 register struct pte *pte;
824{
825
826 if (isatpte(p, pte))
827 return (tptov(p, ptetotp(p, pte)));
828 else if (isadpte(p, pte))
829 return (dptov(p, ptetodp(p, pte)));
830 else
831 return (sptov(p, ptetosp(p, pte)));
832}
833
834/*
835 * Given a base/size pair in virtual swap area,
836 * return a physical base/size pair which is the
837 * (largest) initial, physically contiguous block.
838 */
839vstodb(vsbase, vssize, dmp, dbp, rev)
840 register int vsbase;
841 int vssize;
842 register struct dmap *dmp;
843 register struct dblock *dbp;
844{
f6d84e07 845 register int blk = dmmin;
c4589a32
BJ
846 register swblk_t *ip = dmp->dm_map;
847
848 if (vsbase < 0 || vsbase + vssize > dmp->dm_size)
849 panic("vstodb");
850 while (vsbase >= blk) {
851 vsbase -= blk;
f6d84e07 852 if (blk < dmmax)
c4589a32
BJ
853 blk *= 2;
854 ip++;
855 }
856 dbp->db_size = min(vssize, blk - vsbase);
857 dbp->db_base = *ip + (rev ? blk - (vsbase + vssize) : vsbase);
858}
859
860panic(cp)
861 char *cp;
862{
863 printf("panic!: %s\n", cp);
864}
865
866min(a, b)
867{
868 return (a < b ? a : b);
869}