]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/devkprof.c
pc kernel: fix wrong simd exception mask (fixes go bootstrap)
[plan9front.git] / sys / src / 9 / port / devkprof.c
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
8
9 #define LRES    3               /* log of PC resolution */
10 #define SZ      4               /* sizeof of count cell; well known as 4 */
11
12 struct
13 {
14         uintptr minpc;
15         uintptr maxpc;
16         int     nbuf;
17         int     time;
18         ulong   *buf;
19 }kprof;
20
21 enum{
22         Kprofdirqid,
23         Kprofdataqid,
24         Kprofctlqid,
25 };
26 Dirtab kproftab[]={
27         ".",    {Kprofdirqid, 0, QTDIR},                0,      DMDIR|0550,
28         "kpdata",       {Kprofdataqid},         0,      0600,
29         "kpctl",        {Kprofctlqid},          0,      0600,
30 };
31
32 static void
33 _kproftimer(uintptr pc)
34 {
35         extern void spldone(void);
36
37         if(kprof.time == 0)
38                 return;
39         /*
40          *  if the pc is coming out of spllo or splx,
41          *  use the pc saved when we went splhi.
42          */
43         if(pc>=(uintptr)spllo && pc<=(uintptr)spldone)
44                 pc = m->splpc;
45
46         kprof.buf[0] += TK2MS(1);
47         if(kprof.minpc<=pc && pc<kprof.maxpc){
48                 pc -= kprof.minpc;
49                 pc >>= LRES;
50                 kprof.buf[pc] += TK2MS(1);
51         }else
52                 kprof.buf[1] += TK2MS(1);
53 }
54
55 static void
56 kprofinit(void)
57 {
58         if(SZ != sizeof kprof.buf[0])
59                 panic("kprof size");
60         kproftimer = _kproftimer;
61 }
62
63 static Chan*
64 kprofattach(char *spec)
65 {
66         ulong n;
67
68         /* allocate when first used */
69         kprof.minpc = KTZERO;
70         kprof.maxpc = (uintptr)etext;
71         kprof.nbuf = (kprof.maxpc-kprof.minpc) >> LRES;
72         n = kprof.nbuf*SZ;
73         if(kprof.buf == 0) {
74                 kprof.buf = xalloc(n);
75                 if(kprof.buf == 0)
76                         error(Enomem);
77         }
78         kproftab[1].length = n;
79         return devattach('K', spec);
80 }
81
82 static Walkqid*
83 kprofwalk(Chan *c, Chan *nc, char **name, int nname)
84 {
85         return devwalk(c, nc, name, nname, kproftab, nelem(kproftab), devgen);
86 }
87
88 static int
89 kprofstat(Chan *c, uchar *db, int n)
90 {
91         return devstat(c, db, n, kproftab, nelem(kproftab), devgen);
92 }
93
94 static Chan*
95 kprofopen(Chan *c, int omode)
96 {
97         if(c->qid.type == QTDIR){
98                 if(omode != OREAD)
99                         error(Eperm);
100         }
101         c->mode = openmode(omode);
102         c->flag |= COPEN;
103         c->offset = 0;
104         return c;
105 }
106
107 static void
108 kprofclose(Chan*)
109 {
110 }
111
112 static long
113 kprofread(Chan *c, void *va, long n, vlong off)
114 {
115         ulong end;
116         ulong w, *bp;
117         uchar *a, *ea;
118         ulong offset = off;
119
120         switch((int)c->qid.path){
121         case Kprofdirqid:
122                 return devdirread(c, va, n, kproftab, nelem(kproftab), devgen);
123
124         case Kprofdataqid:
125                 end = kprof.nbuf*SZ;
126                 if(offset & (SZ-1))
127                         error(Ebadarg);
128                 if(offset >= end){
129                         n = 0;
130                         break;
131                 }
132                 if(offset+n > end)
133                         n = end-offset;
134                 n &= ~(SZ-1);
135                 a = va;
136                 ea = a + n;
137                 bp = kprof.buf + offset/SZ;
138                 while(a < ea){
139                         w = *bp++;
140                         *a++ = w>>24;
141                         *a++ = w>>16;
142                         *a++ = w>>8;
143                         *a++ = w>>0;
144                 }
145                 break;
146
147         default:
148                 n = 0;
149                 break;
150         }
151         return n;
152 }
153
154 static long
155 kprofwrite(Chan *c, void *a, long n, vlong)
156 {
157         switch((int)(c->qid.path)){
158         case Kprofctlqid:
159                 if(strncmp(a, "startclr", 8) == 0){
160                         memset((char *)kprof.buf, 0, kprof.nbuf*SZ);
161                         kprof.time = 1;
162                 }else if(strncmp(a, "start", 5) == 0)
163                         kprof.time = 1;
164                 else if(strncmp(a, "stop", 4) == 0)
165                         kprof.time = 0;
166                 break;
167         default:
168                 error(Ebadusefd);
169         }
170         return n;
171 }
172
173 Dev kprofdevtab = {
174         'K',
175         "kprof",
176
177         devreset,
178         kprofinit,
179         devshutdown,
180         kprofattach,
181         kprofwalk,
182         kprofstat,
183         kprofopen,
184         devcreate,
185         kprofclose,
186         kprofread,
187         devbread,
188         kprofwrite,
189         devbwrite,
190         devremove,
191         devwstat,
192 };