xref: /plan9/sys/src/9/rb/devarch.c (revision f43f8ee646e2cb29aea7fd7bb5fc7318a3f4921f)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7 #include "io.h"
8 
9 #include "../ip/ip.h"
10 
11 enum {
12 	Qdir = 0,
13 	Qbase,
14 
15 	Qmax = 16,
16 };
17 
18 typedef long Rdwrfn(Chan*, void*, long, vlong);
19 
20 static Rdwrfn *readfn[Qmax];
21 static Rdwrfn *writefn[Qmax];
22 
23 static Dirtab archdir[Qmax] = {
24 	".",		{ Qdir, 0, QTDIR },	0,	0555,
25 };
26 
27 Lock archwlock;	/* the lock is only for changing archdir */
28 int narchdir = Qbase;
29 
30 /*
31  * Add a file to the #P listing.  Once added, you can't delete it.
32  * You can't add a file with the same name as one already there,
33  * and you get a pointer to the Dirtab entry so you can do things
34  * like change the Qid version.  Changing the Qid path is disallowed.
35  */
36 Dirtab*
addarchfile(char * name,int perm,Rdwrfn * rdfn,Rdwrfn * wrfn)37 addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
38 {
39 	int i;
40 	Dirtab d;
41 	Dirtab *dp;
42 
43 	memset(&d, 0, sizeof d);
44 	strcpy(d.name, name);
45 	d.perm = perm;
46 
47 	lock(&archwlock);
48 	if(narchdir >= Qmax){
49 		unlock(&archwlock);
50 		return nil;
51 	}
52 
53 	for(i=0; i<narchdir; i++)
54 		if(strcmp(archdir[i].name, name) == 0){
55 			unlock(&archwlock);
56 			return nil;
57 		}
58 
59 	d.qid.path = narchdir;
60 	archdir[narchdir] = d;
61 	readfn[narchdir] = rdfn;
62 	writefn[narchdir] = wrfn;
63 	dp = &archdir[narchdir++];
64 	unlock(&archwlock);
65 
66 	return dp;
67 }
68 
69 static Chan*
archattach(char * spec)70 archattach(char* spec)
71 {
72 	return devattach('P', spec);
73 }
74 
75 Walkqid*
archwalk(Chan * c,Chan * nc,char ** name,int nname)76 archwalk(Chan* c, Chan *nc, char** name, int nname)
77 {
78 	return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
79 }
80 
81 static int
archstat(Chan * c,uchar * dp,int n)82 archstat(Chan* c, uchar* dp, int n)
83 {
84 	return devstat(c, dp, n, archdir, narchdir, devgen);
85 }
86 
87 static Chan*
archopen(Chan * c,int omode)88 archopen(Chan* c, int omode)
89 {
90 	return devopen(c, omode, archdir, narchdir, devgen);
91 }
92 
93 static void
archclose(Chan *)94 archclose(Chan*)
95 {
96 }
97 
98 static long
archread(Chan * c,void * a,long n,vlong offset)99 archread(Chan *c, void *a, long n, vlong offset)
100 {
101 	Rdwrfn *fn;
102 
103 	switch((ulong)c->qid.path){
104 	case Qdir:
105 		return devdirread(c, a, n, archdir, narchdir, devgen);
106 
107 	default:
108 		if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
109 			return fn(c, a, n, offset);
110 		error(Eperm);
111 		break;
112 	}
113 
114 	return 0;
115 }
116 
117 static long
archwrite(Chan * c,void * a,long n,vlong offset)118 archwrite(Chan *c, void *a, long n, vlong offset)
119 {
120 	Rdwrfn *fn;
121 
122 	if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
123 		return fn(c, a, n, offset);
124 	error(Eperm);
125 
126 	return 0;
127 }
128 
129 void archinit(void);
130 
131 Dev archdevtab = {
132 	'P',
133 	"arch",
134 
135 	devreset,
136 	archinit,
137 	devshutdown,
138 	archattach,
139 	archwalk,
140 	archstat,
141 	archopen,
142 	devcreate,
143 	archclose,
144 	archread,
145 	devbread,
146 	archwrite,
147 	devbwrite,
148 	devremove,
149 	devwstat,
150 };
151 
152 static long
cputyperead(Chan *,void * a,long n,vlong offset)153 cputyperead(Chan*, void *a, long n, vlong offset)
154 {
155 	char str[128];
156 
157 	snprint(str, sizeof str, "MIPS 24k %lud\n", m->hz / Mhz);
158 	return readstr(offset, a, n, str);
159 }
160 
161 static long
tbread(Chan *,void * a,long n,vlong offset)162 tbread(Chan*, void *a, long n, vlong offset)
163 {
164 	char str[16];
165 	uvlong tb;
166 
167 	cycles(&tb);
168 
169 	snprint(str, sizeof(str), "%16.16llux", tb);
170 	return readstr(offset, a, n, str);
171 }
172 
173 static long
nsread(Chan *,void * a,long n,vlong offset)174 nsread(Chan*, void *a, long n, vlong offset)
175 {
176 	char str[16];
177 	uvlong tb;
178 
179 	cycles(&tb);
180 
181 	snprint(str, sizeof(str), "%16.16llux", (tb/700)* 1000);
182 	return readstr(offset, a, n, str);
183 }
184 
185 char *cputype = "mips";
186 
187 char	*faultsprint(char *, char *);
188 char	*fpemuprint(char *, char *);
189 
190 static long
archctlread(Chan *,void * a,long nn,vlong offset)191 archctlread(Chan*, void *a, long nn, vlong offset)
192 {
193 	int n;
194 	char *buf, *p, *ep;
195 
196 	p = buf = malloc(READSTR);
197 	if(p == nil)
198 		error(Enomem);
199 	ep = p + READSTR;
200 	p = seprint(p, ep, "cpu %s %lud\n", cputype,
201 		(ulong)(m->hz+999999)/1000000);
202 	p = seprint(p, ep, "stlb hash collisions");
203 	for (n = 0; n < conf.nmach; n++)
204 		p = seprint(p, ep, " %d", MACHP(n)->hashcoll);
205 	p = seprint(p, ep, "\n");
206 	p = seprint(p, ep, "NKTLB %d ktlb misses %ld utlb misses %ld\n",
207 		NKTLB, m->ktlbfault, m->utlbfault);
208 	p = fpemuprint(p, ep);
209 	faultsprint(p, ep);
210 	n = readstr(offset, a, nn, buf);
211 	free(buf);
212 	return n;
213 }
214 
215 enum
216 {
217 	CMfpemudebug,
218 };
219 
220 static Cmdtab archctlmsg[] =
221 {
222 #ifdef FPEMUDEBUG
223 	CMfpemudebug,	"fpemudebug",	2,
224 #else
225 	CMfpemudebug,	"dummy",	1,
226 #endif
227 };
228 
229 static long
archctlwrite(Chan *,void * a,long n,vlong)230 archctlwrite(Chan*, void *a, long n, vlong)
231 {
232 	Cmdbuf *cb;
233 	Cmdtab *ct;
234 
235 	cb = parsecmd(a, n);
236 	if(waserror()){
237 		free(cb);
238 		nexterror();
239 	}
240 	ct = lookupcmd(cb, archctlmsg, nelem(archctlmsg));
241 	switch(ct->index){
242 	case CMfpemudebug:
243 		fpemudebug = atoi(cb->f[1]);
244 		break;
245 	}
246 	free(cb);
247 	poperror();
248 	return n;
249 }
250 
251 void
archinit(void)252 archinit(void)
253 {
254 	addarchfile("cputype", 0444, cputyperead, nil);
255 	addarchfile("timebase",0444, tbread, nil);
256 	addarchfile("archctl", 0664, archctlread, archctlwrite);
257 //	addarchfile("nsec", 0444, nsread, nil);
258 }
259