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