Migrated devarch MSR access to new MSR API
[akaros.git] / kern / arch / x86 / devarch.c
1 /* 
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9
10 #include <vfs.h>
11 #include <kmalloc.h>
12 #include <kref.h>
13 #include <kthread.h>
14 #include <string.h>
15 #include <stdio.h>
16 #include <assert.h>
17 #include <error.h>
18 #include <pmap.h>
19 #include <umem.h>
20 #include <smp.h>
21 #include <ip.h>
22 #include <time.h>
23 #include <core_set.h>
24 #include <address_range.h>
25 #include <arch/ros/msr-index.h>
26 #include <arch/msr.h>
27 #include <arch/devarch.h>
28
29 #define REAL_MEM_SIZE (1024 * 1024)
30
31 struct io_map {
32         struct io_map *next;
33         int reserved;
34         char tag[13];
35         uint32_t start;
36         uint32_t end;
37 };
38
39 static struct {
40         spinlock_t lock;
41         struct io_map *map;
42         struct io_map *free;
43         struct io_map maps[32];                         // some initial free maps
44         qlock_t ql;                                     // lock for reading map
45 } iomap;
46
47 enum {
48         Qdir = 0,
49         Qioalloc = 1,
50         Qiob,
51         Qiow,
52         Qiol,
53         Qgdb,
54         Qrealmem,
55         Qmsr,
56
57         Qmax,
58 };
59
60 enum {
61         Linelen = 31,
62 };
63
64 struct dev archdevtab;
65 static struct dirtab archdir[Qmax] = {
66         {".", {Qdir, 0, QTDIR}, 0, 0555},
67         {"ioalloc", {Qioalloc, 0}, 0, 0444},
68         {"iob", {Qiob, 0}, 0, 0666},
69         {"iow", {Qiow, 0}, 0, 0666},
70         {"iol", {Qiol, 0}, 0, 0666},
71         {"gdb", {Qgdb, 0}, 0, 0660},
72         {"realmem", {Qrealmem, 0}, 0, 0444},
73         {"msr", {Qmsr, 0}, 0, 0666},
74 };
75 /* White list entries needs to be ordered by start address, and never overlap.
76  */
77 #define MAX_COUNTERS 16
78 #define MAX_FIX_COUNTERS 4
79
80 static const struct address_range msr_rd_wlist[] = {
81         ADDRESS_RANGE(0x00000000, 0xffffffff),
82 };
83 static const struct address_range msr_wr_wlist[] = {
84         ADDRESS_RANGE(MSR_IA32_PERFCTR0, MSR_IA32_PERFCTR0 + MAX_COUNTERS - 1),
85         ADDRESS_RANGE(MSR_ARCH_PERFMON_EVENTSEL0,
86                                   MSR_ARCH_PERFMON_EVENTSEL0 + MAX_COUNTERS - 1),
87         ADDRESS_RANGE(MSR_IA32_PERF_CTL, MSR_IA32_PERF_CTL),
88         ADDRESS_RANGE(MSR_CORE_PERF_FIXED_CTR0,
89                                   MSR_CORE_PERF_FIXED_CTR0 + MAX_FIX_COUNTERS - 1),
90         ADDRESS_RANGE(MSR_CORE_PERF_FIXED_CTR_CTRL, MSR_CORE_PERF_GLOBAL_OVF_CTRL),
91 };
92 int gdbactive = 0;
93
94 //
95 //  alloc some io port space and remember who it was
96 //  alloced to.  if port < 0, find a free region.
97 //
98 int ioalloc(int port, int size, int align, char *tag)
99 {
100         struct io_map *map, **l;
101         int i;
102
103         spin_lock(&(&iomap)->lock);
104         if (port < 0) {
105                 // find a free port above 0x400 and below 0x1000
106                 port = 0x400;
107                 for (l = &iomap.map; *l; l = &(*l)->next) {
108                         map = *l;
109                         if (map->start < 0x400)
110                                 continue;
111                         i = map->start - port;
112                         if (i > size)
113                                 break;
114                         if (align > 0)
115                                 port = ((port + align - 1) / align) * align;
116                         else
117                                 port = map->end;
118                 }
119                 if (*l == NULL) {
120                         spin_unlock(&(&iomap)->lock);
121                         return -1;
122                 }
123         } else {
124                 // Only 64KB I/O space on the x86.
125                 if ((port + size) > 0x10000) {
126                         spin_unlock(&(&iomap)->lock);
127                         return -1;
128                 }
129                 // see if the space clashes with previously allocated ports
130                 for (l = &iomap.map; *l; l = &(*l)->next) {
131                         map = *l;
132                         if (map->end <= port)
133                                 continue;
134                         if (map->reserved && map->start == port && map->end == port + size) {
135                                 map->reserved = 0;
136                                 spin_unlock(&(&iomap)->lock);
137                                 return map->start;
138                         }
139                         if (map->start >= port + size)
140                                 break;
141                         spin_unlock(&(&iomap)->lock);
142                         return -1;
143                 }
144         }
145         map = iomap.free;
146         if (map == NULL) {
147                 printd("ioalloc: out of maps");
148                 spin_unlock(&(&iomap)->lock);
149                 return port;
150         }
151         iomap.free = map->next;
152         map->next = *l;
153         map->start = port;
154         map->end = port + size;
155         strlcpy(map->tag, tag, sizeof(map->tag));
156         *l = map;
157
158         archdir[0].qid.vers++;
159
160         spin_unlock(&(&iomap)->lock);
161         return map->start;
162 }
163
164 void iofree(int port)
165 {
166         struct io_map *map, **l;
167
168         spin_lock(&(&iomap)->lock);
169         for (l = &iomap.map; *l; l = &(*l)->next) {
170                 if ((*l)->start == port) {
171                         map = *l;
172                         *l = map->next;
173                         map->next = iomap.free;
174                         iomap.free = map;
175                         break;
176                 }
177                 if ((*l)->start > port)
178                         break;
179         }
180         archdir[0].qid.vers++;
181         spin_unlock(&(&iomap)->lock);
182 }
183
184 int iounused(int start, int end)
185 {
186         struct io_map *map;
187
188         for (map = iomap.map; map; map = map->next) {
189                 if (((start >= map->start) && (start < map->end))
190                         || ((start <= map->start) && (end > map->start)))
191                         return 0;
192         }
193         return 1;
194 }
195
196 void ioinit(void)
197 {
198         int i;
199         char *excluded = "";
200
201         panic("Akaros doesn't do IO port allocation yet.  Don't init.");
202         for (i = 0; i < ARRAY_SIZE(iomap.maps) - 1; i++)
203                 iomap.maps[i].next = &iomap.maps[i + 1];
204         iomap.maps[i].next = NULL;
205         iomap.free = iomap.maps;
206         char *s;
207
208         s = excluded;
209         while (s && *s != '\0' && *s != '\n') {
210                 char *ends;
211                 int io_s, io_e;
212
213                 io_s = (int)strtol(s, &ends, 0);
214                 if (ends == NULL || ends == s || *ends != '-') {
215                         printd("ioinit: cannot parse option string\n");
216                         break;
217                 }
218                 s = ++ends;
219
220                 io_e = (int)strtol(s, &ends, 0);
221                 if (ends && *ends == ',')
222                         *ends++ = '\0';
223                 s = ends;
224
225                 ioalloc(io_s, io_e - io_s + 1, 0, "pre-allocated");
226         }
227 }
228
229 // Reserve a range to be ioalloced later.
230 // This is in particular useful for exchangable cards, such
231 // as pcmcia and cardbus cards.
232 int ioreserve(int unused_int, int size, int align, char *tag)
233 {
234         struct io_map *map, **l;
235         int i, port;
236
237         spin_lock(&(&iomap)->lock);
238         // find a free port above 0x400 and below 0x1000
239         port = 0x400;
240         for (l = &iomap.map; *l; l = &(*l)->next) {
241                 map = *l;
242                 if (map->start < 0x400)
243                         continue;
244                 i = map->start - port;
245                 if (i > size)
246                         break;
247                 if (align > 0)
248                         port = ((port + align - 1) / align) * align;
249                 else
250                         port = map->end;
251         }
252         if (*l == NULL) {
253                 spin_unlock(&(&iomap)->lock);
254                 return -1;
255         }
256         map = iomap.free;
257         if (map == NULL) {
258                 printd("ioalloc: out of maps");
259                 spin_unlock(&(&iomap)->lock);
260                 return port;
261         }
262         iomap.free = map->next;
263         map->next = *l;
264         map->start = port;
265         map->end = port + size;
266         map->reserved = 1;
267         strlcpy(map->tag, tag, sizeof(map->tag));
268         *l = map;
269
270         archdir[0].qid.vers++;
271
272         spin_unlock(&(&iomap)->lock);
273         return map->start;
274 }
275
276 static void checkport(int start, int end)
277 {
278         /* standard vga regs are OK */
279         if (start >= 0x2b0 && end <= 0x2df + 1)
280                 return;
281         if (start >= 0x3c0 && end <= 0x3da + 1)
282                 return;
283
284         if (iounused(start, end))
285                 return;
286         error(EPERM, NULL);
287 }
288
289 static struct chan *archattach(char *spec)
290 {
291         return devattach(archdevtab.name, spec);
292 }
293
294 struct walkqid *archwalk(struct chan *c, struct chan *nc, char **name,
295                                                  int nname)
296 {
297         return devwalk(c, nc, name, nname, archdir, Qmax, devgen);
298 }
299
300 static int archstat(struct chan *c, uint8_t * dp, int n)
301 {
302         archdir[Qrealmem].length = REAL_MEM_SIZE;
303
304         return devstat(c, dp, n, archdir, Qmax, devgen);
305 }
306
307 static struct chan *archopen(struct chan *c, int omode)
308 {
309         return devopen(c, omode, archdir, Qmax, devgen);
310 }
311
312 static void archclose(struct chan *unused)
313 {
314 }
315
316 static long archread(struct chan *c, void *a, long n, int64_t offset)
317 {
318         char *buf, *p;
319         int err, port;
320         uint64_t *values;
321         uint16_t *sp;
322         uint32_t *lp;
323         struct io_map *map;
324         struct core_set cset;
325         struct msr_address msra;
326         struct msr_value msrv;
327
328         switch ((uint32_t) c->qid.path) {
329                 case Qdir:
330                         return devdirread(c, a, n, archdir, Qmax, devgen);
331                 case Qgdb:
332                         p = gdbactive ? "1" : "0";
333                         return readstr(offset, a, n, p);
334                 case Qiob:
335                         port = offset;
336                         checkport(offset, offset + n);
337                         for (p = a; port < offset + n; port++)
338                                 *p++ = inb(port);
339                         return n;
340                 case Qiow:
341                         if (n & 1)
342                                 error(EINVAL, NULL);
343                         checkport(offset, offset + n);
344                         sp = a;
345                         for (port = offset; port < offset + n; port += 2)
346                                 *sp++ = inw(port);
347                         return n;
348                 case Qiol:
349                         if (n & 3)
350                                 error(EINVAL, NULL);
351                         checkport(offset, offset + n);
352                         lp = a;
353                         for (port = offset; port < offset + n; port += 4)
354                                 *lp++ = inl(port);
355                         return n;
356                 case Qioalloc:
357                         break;
358                 case Qrealmem:
359                         return readmem(offset, a, n, KADDR(0), REAL_MEM_SIZE);
360                 case Qmsr:
361                         if (!address_range_find(msr_rd_wlist, ARRAY_SIZE(msr_rd_wlist),
362                                                                         (uintptr_t) offset))
363                                 error(EPERM, NULL);
364                         core_set_init(&cset);
365                         core_set_fill_available(&cset);
366                         msr_init_address(&msra);
367                         msr_set_address(&msra, (uint32_t) offset);
368                         msr_init_value(&msrv);
369                         values = kzmalloc(num_cores * sizeof(uint64_t), KMALLOC_WAIT);
370                         if (!values)
371                                 error(ENOMEM, NULL);
372                         msr_set_values(&msrv, values, num_cores);
373
374                         err = msr_cores_read(&cset, &msra, &msrv);
375
376                         n = -1;
377                         if (likely(!err)) {
378                                 if (n >= num_cores * sizeof(uint64_t)) {
379                                         if (!memcpy_to_user_errno(current, a, values,
380                                                                                           num_cores * sizeof(uint64_t)))
381                                                 n = num_cores * sizeof(uint64_t);
382                                 } else {
383                                         kfree(values);
384                                         error(ERANGE, NULL);
385                                 }
386                         }
387                         kfree(values);
388                         return n;
389                 default:
390                         error(EINVAL, NULL);
391         }
392
393         if ((buf = kzmalloc(n, 0)) == NULL)
394                 error(ENOMEM, NULL);
395         p = buf;
396         n = n / Linelen;
397         offset = offset / Linelen;
398
399         switch ((uint32_t) c->qid.path) {
400                 case Qioalloc:
401                         spin_lock(&(&iomap)->lock);
402                         for (map = iomap.map; n > 0 && map != NULL; map = map->next) {
403                                 if (offset-- > 0)
404                                         continue;
405                                 snprintf(p, n * Linelen, "%#8p %#8p %-12.12s\n", map->start,
406                                                  map->end - 1, map->tag);
407                                 p += Linelen;
408                                 n--;
409                         }
410                         spin_unlock(&(&iomap)->lock);
411                         break;
412         }
413
414         n = p - buf;
415         memmove(a, buf, n);
416         kfree(buf);
417
418         return n;
419 }
420
421 static long archwrite(struct chan *c, void *a, long n, int64_t offset)
422 {
423         char *p;
424         int port, err;
425         uint64_t value;
426         uint16_t *sp;
427         uint32_t *lp;
428         struct core_set cset;
429         struct msr_address msra;
430         struct msr_value msrv;
431
432         switch ((uint32_t) c->qid.path) {
433                 case Qgdb:
434                         p = a;
435                         if (n != 1)
436                                 error(EINVAL, "Gdb: Write one byte, '1' or '0'");
437                         if (*p == '1')
438                                 gdbactive = 1;
439                         else if (*p == '0')
440                                 gdbactive = 0;
441                         else
442                                 error(EINVAL, "Gdb: must be 1 or 0");
443                         return 1;
444                 case Qiob:
445                         p = a;
446                         checkport(offset, offset + n);
447                         for (port = offset; port < offset + n; port++)
448                                 outb(port, *p++);
449                         return n;
450                 case Qiow:
451                         if (n & 1)
452                                 error(EINVAL, NULL);
453                         checkport(offset, offset + n);
454                         sp = a;
455                         for (port = offset; port < offset + n; port += 2)
456                                 outw(port, *sp++);
457                         return n;
458                 case Qiol:
459                         if (n & 3)
460                                 error(EINVAL, NULL);
461                         checkport(offset, offset + n);
462                         lp = a;
463                         for (port = offset; port < offset + n; port += 4)
464                                 outl(port, *lp++);
465                         return n;
466                 case Qmsr:
467                         if (!address_range_find(msr_wr_wlist, ARRAY_SIZE(msr_wr_wlist),
468                                                                         (uintptr_t) offset))
469                                 error(EPERM, NULL);
470                         if (n != sizeof(uint64_t))
471                                 error(EINVAL, NULL);
472                         if (memcpy_from_user_errno(current, &value, a, sizeof(value)))
473                                 return -1;
474
475                         core_set_init(&cset);
476                         core_set_fill_available(&cset);
477                         msr_init_address(&msra);
478                         msr_set_address(&msra, (uint32_t) offset);
479                         msr_init_value(&msrv);
480                         msr_set_value(&msrv, value);
481
482                         err = msr_cores_write(&cset, &msra, &msrv);
483                         if (unlikely(err))
484                                 error(-err, NULL);
485                         return sizeof(uint64_t);
486                 default:
487                         error(EINVAL, NULL);
488         }
489         return 0;
490 }
491
492 struct dev archdevtab __devtab = {
493         .name = "arch",
494
495         .reset = devreset,
496         .init = devinit,
497         .shutdown = devshutdown,
498         .attach = archattach,
499         .walk = archwalk,
500         .stat = archstat,
501         .open = archopen,
502         .create = devcreate,
503         .close = archclose,
504         .read = archread,
505         .bread = devbread,
506         .write = archwrite,
507         .bwrite = devbwrite,
508         .remove = devremove,
509         .wstat = devwstat,
510 };
511
512 void archreset(void)
513 {
514         int i;
515
516         /*
517          * And sometimes there is no keyboard...
518          *
519          * The reset register (0xcf9) is usually in one of the bridge
520          * chips. The actual location and sequence could be extracted from
521          * ACPI but why bother, this is the end of the line anyway.
522          print("Takes a licking and keeps on ticking...\n");
523          */
524         i = inb(0xcf9); /* ICHx reset control */
525         i &= 0x06;
526         outb(0xcf9, i | 0x02);  /* SYS_RST */
527         udelay(1000);
528         outb(0xcf9, i | 0x06);  /* RST_CPU transition */
529
530         udelay(100 * 1000);
531
532         /* some broken hardware -- as well as qemu -- might
533          * never reboot anyway with cf9. This is a standard
534          * keyboard reboot sequence known to work on really
535          * broken stuff -- like qemu. If there is no
536          * keyboard it will do no harm.
537          */
538         for (;;) {
539                 (void)inb(0x64);
540                 outb(0x64, 0xFE);
541                 udelay(100 * 1000);
542         }
543 }