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