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