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