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