xref: /plan9/sys/lib/acid/kernel (revision b94bb474148e9d24a82a427863d9c9eb4c20f4ae)
1include("/sys/lib/acid/syscall");
2
3// print various /proc files
4defn fd() {
5	rc("cat /proc/"+itoa(pid)+"/fd");
6}
7
8defn segment() {
9	rc("cat /proc/"+itoa(pid)+"/segment");
10}
11
12defn ns() {
13	rc("cat /proc/"+itoa(pid)+"/ns");
14}
15
16defn qid(qid) {
17	complex Qid qid;
18	return itoa(qid.path\X)+"."+itoa(qid.vers\X);
19}
20
21defn path(p) {
22	complex Path p;
23	if p != 0 then {
24		return *(p.s\s);
25	} else
26		return "<null>";
27}
28
29// print Image cache contents
30// requires include("/sys/src/9/xxx/segment.acid")
31IHASHSIZE = 64;
32defn imagecacheline(h) {
33	while h != 0 do {
34		complex Image h;
35		print (h\X, " ", qid(h.qid), " type ", h.type\D, " ref ", h.ref, " next ", h.next\X, " ", path(h.c.path), "\n");
36		h = h.hash;
37	}
38}
39
40defn imagecache() {
41	local i;
42
43	i=0; loop 1,IHASHSIZE do {
44		imagecacheline(imagealloc.free[i]);
45		i = i+1;
46	}
47}
48
49// dump channels
50defn chan(c) {
51	local d, q;
52
53	c = (Chan)c;
54	d=(Dev)(*(devtab+4*c.type));
55	q=c.qid;
56	print("chan(", c\X, "): ref=", c.ref\D, " #", d.dc\r, c.dev\D, " (", q.path, " ", q.vers\D, " ", q.type\X, ")");
57	print(" fid=", c.fid\D, " iounit=", c.iounit\D);
58	if c.ref != 0 then {
59		print(" ", path(c.path), " mchan=", c.mchan\X);
60		if c.mchan != 0 then {
61			print(" ", path(c.mchan.path));
62		}
63	}
64	print("\n");
65}
66
67defn chans() {
68	local c;
69
70	c = (Chan)chanalloc.list;
71	while c != 0 do {
72		if c.ref != 0 then
73			chan(c);
74		c=(Chan)c.link;
75	}
76}
77
78defn nchans() {
79	local c, n;
80
81	n = 0;
82	c = (Chan)chanalloc.list;
83	while c != 0 do {
84		if c.ref != 0 then
85			n++;
86		c = (Chan)c.link;
87	}
88	return n;
89}
90
91defn activechanlist() {
92	local l, n;
93
94	l = {};
95	c = (Chan)chanalloc.list;
96	while c != 0 do {
97		if c.ref != 0 then
98			l = append l,c;
99		c = (Chan)c.link;
100	}
101	return l;
102}
103
104defn difflist(a, b) {
105	local l, x;
106
107	l = {};
108	while a != {} do {
109		x = head a;
110		if match(x, b) == -1 then
111			l = append l, x;
112		a = tail a;
113	}
114	return l;
115}
116
117_active_chan_list = {};
118defn newchans() {
119	local l, new;
120
121	l = activechanlist();
122	if _active_chan_list != {} then
123		newerchans(_active_chan_list);
124	_active_chan_list = l;
125}
126
127defn newerchans(oldlist){
128	local new;
129
130	new = difflist(activechanlist(), oldlist);
131	while new != {} do {
132		chan(head new);
133		new = tail new;
134	}
135}
136
137// look for channels that refer to themselves
138defn badchans() {
139	local bad, c, i, len, mtpt, p;
140
141	c = (Chan)chanalloc.list;
142	while c != 0 do {
143		if c.ref != 0 then {
144			bad = "";
145			p = (Path)c.path;
146			if p != 0 then {
147				path(p);
148				mtpt = p.mtpt;
149				len = p.mlen;
150				i=0; loop 1,len do {
151					if mtpt[i] == c then
152						bad = bad+" mtpt self-ref";
153					i = i+1;
154				}
155			}
156			if bad != "" then
157				print("chan(", c\X, "):", bad, "\n");
158		}
159		c = (Chan)c.link;
160	}
161}
162
163// manipulate processes
164defn proctab(x) {
165	return procalloc.arena+sizeofProc*x;
166}
167
168defn proc(p) {
169	complex Proc p;
170	local s, i;
171
172	if p.state != 0 && p.pid != 0 && p.text != 0 then {	// 0 is Dead
173		s = p.psstate;
174		if s == 0 then {
175			s = "kproc";
176		} else {
177			s = *(s\s);
178		}
179		print(p\X, " ", p.pid, ": ", *(p.text\s), " ", *(p.user\s), " pc ", p.pc\X, " ", s, " (", *(statename[p.state]\s), ") ut ", p.time[0]\D, " st ", p.time[1]\D, " qpc ", p.qpc\X, "\n");
180	}
181}
182
183defn procenv(p) {
184	complex Proc p;
185	local e, v;
186
187	e = p.egrp;
188	complex Egrp e;
189	v = e.ent;
190	while v != 0 do {
191		complex Evalue v;
192		print(*(v.name\s), "=");
193		printstringn(v.value, v.len);
194		print("\n");
195		v = v.link;
196	}
197}
198
199KSTACK=4096;
200
201defn procstksize(p) {
202	complex Proc p;
203	local top, sp;
204
205	if p.state != 0 then {	// 0 is Dead
206		top = p.kstack+KSTACK;
207		sp = *p.sched;
208		print(top-sp\D, "\n");
209	}
210}
211
212defn procstk(p) {
213	complex Proc p;
214	local l;
215
216	if p.state != 0 then {	// 0 is Dead
217		l = p.sched;
218		if objtype=="386" then
219			_stk(gotolabel, *l, linkreg(0), 0);
220		else
221			_stk(*(l+4), *l, linkreg(0), 0);
222	}
223}
224
225defn procs() {
226	local i;
227
228	i=0; loop 1,conf.nproc do {
229		proc(proctab(i));
230		i = i+1;
231	}
232}
233
234defn stacks() {
235	local i, p;
236
237	i=0; loop 1,conf.nproc do {
238		p = (Proc)proctab(i);
239		if p.state != 0 then {
240			print("=========================================================\n");
241			proc(p);
242			procstk(p);
243		}
244		i = i+1;
245	}
246}
247
248defn stacksizes() {
249	local i;
250
251	i=0; loop 1,conf.nproc do {
252		procstksize(proctab(i));
253		i = i+1;
254	}
255}
256
257// segment-related
258defn procsegs(p) {
259	complex Proc p;
260	local i;
261
262	i=0; loop 1,NSEG do {
263		psegment(p.seg[i]);
264		i = i+1;
265	}
266}
267
268segtypes = { "text", "data", "bss", "stack", "shared", "physical", "shdata", "map" };
269defn psegment(s) {
270	complex Segment s;
271
272	if s != 0 then {
273		print(s\X, " ", segtypes[s.type&SG_TYPE], " ", s.base\X, "-", s.top\X, " image ", s.image\X, "\n");
274	}
275}
276
277// find physical address for an address in a given process
278defn procaddr(p, a) {
279	complex Proc p;
280	local i, s, r;
281
282	r = 0;
283	i=0; loop 1,NSEG do {
284		s = p.seg[i];
285		if s != 0 then {
286			complex Segment s;
287			if s.base <= a && a < s.top then {
288				r = segaddr(s, a);
289			}
290		}
291		i = i+1;
292	}
293	return r;
294}
295
296// find an address in a given segment
297defn segaddr(s, a) {
298	complex Segment s;
299	local pte, pg;
300
301	a = a - s.base;
302	if s.map == 0 || s.mapsize < a/PTEMAPMEM then {
303		return 0;
304	}
305
306	pte = s.map[a/PTEMAPMEM];
307	if pte == 0 then {
308		return 0;
309	}
310
311	complex Pte pte;
312	pg = pte.pages[(a%PTEMAPMEM)/BY2PG];
313	if pg == 0 then {
314		return 0;
315	}
316
317	if pg & 1 then {	// swapped out, return disk address
318		return pg&~1;
319	}
320
321	complex Page pg;
322	return (KZERO|(pg.pa+(a%BY2PG)))\X;
323}
324
325defn kzero() {
326	return main - (main & 0x0FFFFFFF);
327}
328
329// PC only
330PTEMAPMEM = (1024*1024);
331BY2PG = 4096;
332PTEPERTAB = (PTEMAPMEM/BY2PG);
333defn up() {
334	local mach;
335
336	MACHADDR = KZERO+0x15000;
337	mach = MACHADDR;
338	complex Mach mach;
339	return mach.externup;
340}
341
342defn intrcount() {
343	local p, pp, t, i, j;
344
345	p = intrtimes;
346	i=0;
347	loop 1,256 do {
348		pp = p[i];
349		i=i+1;
350		if pp != 0 then {
351			j=0;
352			t=0;
353			loop 1,1000 do {
354				t = t+pp[j];
355				j=j+1;
356			}
357			print(itoa(i, "%5d"), " ", itoa(t, "%11d"), "\n");
358		}
359	}
360}
361
362print("/sys/lib/acid/kernel");
363
364defn needacid(s){
365	print("\trc(\"cd /sys/src/9/", kdir, "; mk ", s, ".acid\")\n");
366	print("\tinclude(\"/sys/src/9/", kdir, "/", s, ".acid\")\n");
367}
368
369defn kinit() {
370if (map()[2]) != {} then {	// map has more than two elements -> active proc
371	kdir = "unknown";
372	KZERO = kzero();
373
374	if objtype == "386" then {
375		map({"*data", KZERO, 0xffffffff, KZERO});
376		kdir="pc";
377	}
378	if (objtype == "mips" || objtype == "mips2") then {
379		kdir = "ch";
380	}
381	if objtype == "alpha" then {
382		map({"*data", KZERO, 0xffffffff, KZERO});
383		kdir = "alpha";
384	}
385	needacid("proc");
386}
387}
388