9ns: Fix devtab function pointer signatures
[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 <ros/memops.h>
11 #include <vfs.h>
12 #include <kmalloc.h>
13 #include <kref.h>
14 #include <kthread.h>
15 #include <string.h>
16 #include <stdio.h>
17 #include <assert.h>
18 #include <err.h>
19 #include <pmap.h>
20 #include <umem.h>
21 #include <smp.h>
22 #include <net/ip.h>
23 #include <time.h>
24 #include <bitops.h>
25 #include <core_set.h>
26 #include <address_range.h>
27 #include <arch/ros/perfmon.h>
28 #include <arch/topology.h>
29 #include <arch/perfmon.h>
30 #include <arch/ros/msr-index.h>
31 #include <arch/msr.h>
32 #include <arch/devarch.h>
33
34 #define REAL_MEM_SIZE (1024 * 1024)
35
36 struct perf_context {
37         struct perfmon_session *ps;
38         qlock_t resp_lock;
39         size_t resp_size;
40         uint8_t *resp;
41 };
42
43 struct io_map {
44         struct io_map *next;
45         int reserved;
46         char tag[13];
47         uint32_t start;
48         uint32_t end;
49 };
50
51 static struct {
52         spinlock_t lock;
53         struct io_map *map;
54         struct io_map *free;
55         struct io_map maps[32];                         // some initial free maps
56         qlock_t ql;                                     // lock for reading map
57 } iomap;
58
59 enum {
60         Qdir = 0,
61         Qioalloc = 1,
62         Qiob,
63         Qiow,
64         Qiol,
65         Qgdb,
66         Qrealmem,
67         Qmsr,
68         Qperf,
69         Qcstate,
70         Qpstate,
71
72         Qmax,
73 };
74
75 enum {
76         Linelen = 31,
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         {"perf", {Qperf, 0}, 0, 0666},
90         {"c-state", {Qcstate, 0}, 0, 0666},
91         {"p-state", {Qpstate, 0}, 0, 0666},
92 };
93
94 /* White list entries must not overlap. */
95 #define MSR_MAX_VAR_COUNTERS 16
96 #define MSR_MAX_FIX_COUNTERS 4
97
98 static struct address_range msr_rd_wlist[] = {
99         ADDRESS_RANGE(0x00000000, 0xffffffff),
100 };
101 static struct address_range msr_wr_wlist[] = {
102         ADDRESS_RANGE(MSR_IA32_PERFCTR0,
103                                   MSR_IA32_PERFCTR0 + MSR_MAX_VAR_COUNTERS - 1),
104         ADDRESS_RANGE(MSR_ARCH_PERFMON_EVENTSEL0,
105                                   MSR_ARCH_PERFMON_EVENTSEL0 + MSR_MAX_VAR_COUNTERS - 1),
106         ADDRESS_RANGE(MSR_IA32_PERF_CTL, MSR_IA32_PERF_CTL),
107         ADDRESS_RANGE(MSR_CORE_PERF_FIXED_CTR0,
108                                   MSR_CORE_PERF_FIXED_CTR0 + MSR_MAX_FIX_COUNTERS - 1),
109         ADDRESS_RANGE(MSR_CORE_PERF_FIXED_CTR_CTRL, MSR_CORE_PERF_GLOBAL_OVF_CTRL),
110         ADDRESS_RANGE(MSR_IA32_MPERF, MSR_IA32_APERF),
111 };
112 int gdbactive = 0;
113
114 //
115 //  alloc some io port space and remember who it was
116 //  alloced to.  if port < 0, find a free region.
117 //
118 int ioalloc(int port, int size, int align, char *tag)
119 {
120         struct io_map *map, **l;
121         int i;
122
123         spin_lock(&(&iomap)->lock);
124         if (port < 0) {
125                 // find a free port above 0x400 and below 0x1000
126                 port = 0x400;
127                 for (l = &iomap.map; *l; l = &(*l)->next) {
128                         map = *l;
129                         if (map->start < 0x400)
130                                 continue;
131                         i = map->start - port;
132                         if (i > size)
133                                 break;
134                         if (align > 0)
135                                 port = ((port + align - 1) / align) * align;
136                         else
137                                 port = map->end;
138                 }
139                 if (*l == NULL) {
140                         spin_unlock(&(&iomap)->lock);
141                         return -1;
142                 }
143         } else {
144                 // Only 64KB I/O space on the x86.
145                 if ((port + size) > 0x10000) {
146                         spin_unlock(&(&iomap)->lock);
147                         return -1;
148                 }
149                 // see if the space clashes with previously allocated ports
150                 for (l = &iomap.map; *l; l = &(*l)->next) {
151                         map = *l;
152                         if (map->end <= port)
153                                 continue;
154                         if (map->reserved && map->start == port && map->end == port + size) {
155                                 map->reserved = 0;
156                                 spin_unlock(&(&iomap)->lock);
157                                 return map->start;
158                         }
159                         if (map->start >= port + size)
160                                 break;
161                         spin_unlock(&(&iomap)->lock);
162                         return -1;
163                 }
164         }
165         map = iomap.free;
166         if (map == NULL) {
167                 printd("ioalloc: out of maps");
168                 spin_unlock(&(&iomap)->lock);
169                 return port;
170         }
171         iomap.free = map->next;
172         map->next = *l;
173         map->start = port;
174         map->end = port + size;
175         strlcpy(map->tag, tag, sizeof(map->tag));
176         *l = map;
177
178         archdir[0].qid.vers++;
179
180         spin_unlock(&(&iomap)->lock);
181         return map->start;
182 }
183
184 void iofree(int port)
185 {
186         struct io_map *map, **l;
187
188         spin_lock(&(&iomap)->lock);
189         for (l = &iomap.map; *l; l = &(*l)->next) {
190                 if ((*l)->start == port) {
191                         map = *l;
192                         *l = map->next;
193                         map->next = iomap.free;
194                         iomap.free = map;
195                         break;
196                 }
197                 if ((*l)->start > port)
198                         break;
199         }
200         archdir[0].qid.vers++;
201         spin_unlock(&(&iomap)->lock);
202 }
203
204 int iounused(int start, int end)
205 {
206         struct io_map *map;
207
208         for (map = iomap.map; map; map = map->next) {
209                 if (((start >= map->start) && (start < map->end)) ||
210                     ((start <= map->start) && (end > map->start)))
211                         return 0;
212         }
213         return 1;
214 }
215
216 void ioinit(void)
217 {
218         int i;
219         char *excluded = "";
220
221         panic("Akaros doesn't do IO port allocation yet.  Don't init.");
222         for (i = 0; i < ARRAY_SIZE(iomap.maps) - 1; i++)
223                 iomap.maps[i].next = &iomap.maps[i + 1];
224         iomap.maps[i].next = NULL;
225         iomap.free = iomap.maps;
226         char *s;
227
228         s = excluded;
229         while (s && *s != '\0' && *s != '\n') {
230                 char *ends;
231                 int io_s, io_e;
232
233                 io_s = (int)strtol(s, &ends, 0);
234                 if (ends == NULL || ends == s || *ends != '-') {
235                         printd("ioinit: cannot parse option string\n");
236                         break;
237                 }
238                 s = ++ends;
239
240                 io_e = (int)strtol(s, &ends, 0);
241                 if (ends && *ends == ',')
242                         *ends++ = '\0';
243                 s = ends;
244
245                 ioalloc(io_s, io_e - io_s + 1, 0, "pre-allocated");
246         }
247 }
248
249 // Reserve a range to be ioalloced later.
250 // This is in particular useful for exchangable cards, such
251 // as pcmcia and cardbus cards.
252 int ioreserve(int unused_int, int size, int align, char *tag)
253 {
254         struct io_map *map, **l;
255         int i, port;
256
257         spin_lock(&(&iomap)->lock);
258         // find a free port above 0x400 and below 0x1000
259         port = 0x400;
260         for (l = &iomap.map; *l; l = &(*l)->next) {
261                 map = *l;
262                 if (map->start < 0x400)
263                         continue;
264                 i = map->start - port;
265                 if (i > size)
266                         break;
267                 if (align > 0)
268                         port = ((port + align - 1) / align) * align;
269                 else
270                         port = map->end;
271         }
272         if (*l == NULL) {
273                 spin_unlock(&(&iomap)->lock);
274                 return -1;
275         }
276         map = iomap.free;
277         if (map == NULL) {
278                 printd("ioalloc: out of maps");
279                 spin_unlock(&(&iomap)->lock);
280                 return port;
281         }
282         iomap.free = map->next;
283         map->next = *l;
284         map->start = port;
285         map->end = port + size;
286         map->reserved = 1;
287         strlcpy(map->tag, tag, sizeof(map->tag));
288         *l = map;
289
290         archdir[0].qid.vers++;
291
292         spin_unlock(&(&iomap)->lock);
293         return map->start;
294 }
295
296 static void checkport(int start, int end)
297 {
298         /* standard vga regs are OK */
299         if (start >= 0x2b0 && end <= 0x2df + 1)
300                 return;
301         if (start >= 0x3c0 && end <= 0x3da + 1)
302                 return;
303
304         if (iounused(start, end))
305                 return;
306         error(EPERM, ERROR_FIXME);
307 }
308
309 static struct chan *archattach(char *spec)
310 {
311         return devattach(archdevtab.name, spec);
312 }
313
314 struct walkqid *archwalk(struct chan *c, struct chan *nc, char **name,
315                                                  unsigned int nname)
316 {
317         return devwalk(c, nc, name, nname, archdir, Qmax, devgen);
318 }
319
320 static size_t archstat(struct chan *c, uint8_t *dp, size_t n)
321 {
322         archdir[Qrealmem].length = REAL_MEM_SIZE;
323
324         return devstat(c, dp, n, archdir, Qmax, devgen);
325 }
326
327 static struct perf_context *arch_create_perf_context(void)
328 {
329         ERRSTACK(1);
330         struct perf_context *pc = kzmalloc(sizeof(struct perf_context),
331                                            MEM_WAIT);
332
333         if (waserror()) {
334                 kfree(pc);
335                 nexterror();
336         }
337         qlock_init(&pc->resp_lock);
338         pc->ps = perfmon_create_session();
339         poperror();
340
341         return pc;
342 }
343
344 /* Called after the last reference (FD / chan) to pc is closed. */
345 static void arch_free_perf_context(struct perf_context *pc)
346 {
347         perfmon_close_session(pc->ps);
348         kfree(pc->resp);
349         kfree(pc);
350 }
351
352 static const uint8_t *arch_read_core_set(struct core_set *cset,
353                                          const uint8_t *kptr,
354                                          const uint8_t *ktop)
355 {
356         int i, nb;
357         uint32_t n;
358
359         error_assert(EBADMSG, (kptr + sizeof(uint32_t)) <= ktop);
360         kptr = get_le_u32(kptr, &n);
361         error_assert(EBADMSG, (kptr + n) <= ktop);
362         core_set_init(cset);
363         nb = MIN((int) n * 8, num_cores);
364         for (i = 0; i < nb; i++) {
365                 if (test_bit(i, (const unsigned long *) kptr))
366                         core_set_setcpu(cset, i);
367         }
368
369         return kptr + n;
370 }
371
372 static long arch_perf_write(struct perf_context *pc, const void *udata,
373                             long usize)
374 {
375         ERRSTACK(1);
376         void *kdata;
377         const uint8_t *kptr, *ktop;
378
379         kdata = user_memdup_errno(current, udata, usize);
380         if (unlikely(!kdata))
381                 return -1;
382         qlock(&pc->resp_lock);
383         if (waserror()) {
384                 qunlock(&pc->resp_lock);
385                 kfree(kdata);
386                 nexterror();
387         }
388         /* Fresh command, reset the response buffer */
389         kfree(pc->resp);
390         pc->resp = NULL;
391         pc->resp_size = 0;
392
393         kptr = kdata;
394         ktop = kptr + usize;
395         error_assert(EBADMSG, (kptr + 1) <= ktop);
396         switch (*kptr++) {
397                 case PERFMON_CMD_COUNTER_OPEN: {
398                         int ped;
399                         struct perfmon_event pev;
400                         struct core_set cset;
401
402                         error_assert(EBADMSG, (kptr + 3 * sizeof(uint64_t)) <= ktop);
403                         perfmon_init_event(&pev);
404                         kptr = get_le_u64(kptr, &pev.event);
405                         kptr = get_le_u64(kptr, &pev.flags);
406                         kptr = get_le_u64(kptr, &pev.trigger_count);
407                         kptr = get_le_u64(kptr, &pev.user_data);
408                         kptr = arch_read_core_set(&cset, kptr, ktop);
409
410                         ped = perfmon_open_event(&cset, pc->ps, &pev);
411
412                         pc->resp_size = sizeof(uint32_t);
413                         pc->resp = kmalloc(pc->resp_size, MEM_WAIT);
414                         put_le_u32(pc->resp, (uint32_t) ped);
415                         break;
416                 }
417                 case PERFMON_CMD_COUNTER_STATUS: {
418                         uint32_t ped;
419                         uint8_t *rptr;
420                         struct perfmon_status *pef;
421
422                         error_assert(EBADMSG, (kptr + sizeof(uint32_t)) <= ktop);
423                         kptr = get_le_u32(kptr, &ped);
424
425                         pef = perfmon_get_event_status(pc->ps, (int) ped);
426
427                         pc->resp_size = sizeof(uint32_t) + num_cores * sizeof(uint64_t);
428                         pc->resp = kmalloc(pc->resp_size, MEM_WAIT);
429                         rptr = put_le_u32(pc->resp, num_cores);
430                         for (int i = 0; i < num_cores; i++)
431                                 rptr = put_le_u64(rptr, pef->cores_values[i]);
432
433                         perfmon_free_event_status(pef);
434                         break;
435                 }
436                 case PERFMON_CMD_COUNTER_CLOSE: {
437                         uint32_t ped;
438
439                         error_assert(EBADMSG, (kptr + sizeof(uint32_t)) <= ktop);
440                         kptr = get_le_u32(kptr, &ped);
441
442                         perfmon_close_event(pc->ps, (int) ped);
443                         break;
444                 }
445                 case PERFMON_CMD_CPU_CAPS: {
446                         uint8_t *rptr;
447                         struct perfmon_cpu_caps pcc;
448
449                         perfmon_get_cpu_caps(&pcc);
450
451                         pc->resp_size = 6 * sizeof(uint32_t);
452                         pc->resp = kmalloc(pc->resp_size, MEM_WAIT);
453
454                         rptr = put_le_u32(pc->resp, pcc.perfmon_version);
455                         rptr = put_le_u32(rptr, pcc.proc_arch_events);
456                         rptr = put_le_u32(rptr, pcc.bits_x_counter);
457                         rptr = put_le_u32(rptr, pcc.counters_x_proc);
458                         rptr = put_le_u32(rptr, pcc.bits_x_fix_counter);
459                         rptr = put_le_u32(rptr, pcc.fix_counters_x_proc);
460                         break;
461                 }
462                 default:
463                         error(EINVAL, "Invalid perfmon command: 0x%x", kptr[-1]);
464         }
465         poperror();
466         qunlock(&pc->resp_lock);
467         kfree(kdata);
468
469         return (long) (kptr - (const uint8_t *) kdata);
470 }
471
472 static struct chan *archopen(struct chan *c, int omode)
473 {
474         c = devopen(c, omode, archdir, Qmax, devgen);
475         switch ((uint32_t) c->qid.path) {
476                 case Qperf:
477                         if (!perfmon_supported())
478                                 error(ENODEV, "perf is not supported");
479                         assert(!c->aux);
480                         c->aux = arch_create_perf_context();
481                         break;
482         }
483
484         return c;
485 }
486
487 static void archclose(struct chan *c)
488 {
489         switch ((uint32_t) c->qid.path) {
490                 case Qperf:
491                         if (c->aux) {
492                                 arch_free_perf_context((struct perf_context *) c->aux);
493                                 c->aux = NULL;
494                         }
495                         break;
496         }
497 }
498
499 static size_t archread(struct chan *c, void *a, size_t n, off64_t offset)
500 {
501         char *buf, *p;
502         int err, port;
503         uint64_t *values;
504         uint16_t *sp;
505         uint32_t *lp;
506         struct io_map *map;
507         struct core_set cset;
508         struct msr_address msra;
509         struct msr_value msrv;
510
511         switch ((uint32_t) c->qid.path) {
512                 case Qdir:
513                         return devdirread(c, a, n, archdir, Qmax, devgen);
514                 case Qgdb:
515                         p = gdbactive ? "1" : "0";
516                         return readstr(offset, a, n, p);
517                 case Qiob:
518                         port = offset;
519                         checkport(offset, offset + n);
520                         for (p = a; port < offset + n; port++)
521                                 *p++ = inb(port);
522                         return n;
523                 case Qiow:
524                         if (n & 1)
525                                 error(EINVAL, ERROR_FIXME);
526                         checkport(offset, offset + n);
527                         sp = a;
528                         for (port = offset; port < offset + n; port += 2)
529                                 *sp++ = inw(port);
530                         return n;
531                 case Qiol:
532                         if (n & 3)
533                                 error(EINVAL, ERROR_FIXME);
534                         checkport(offset, offset + n);
535                         lp = a;
536                         for (port = offset; port < offset + n; port += 4)
537                                 *lp++ = inl(port);
538                         return n;
539                 case Qioalloc:
540                         break;
541                 case Qrealmem:
542                         return readmem(offset, a, n, KADDR(0), REAL_MEM_SIZE);
543                 case Qmsr:
544                         if (!address_range_find(msr_rd_wlist, ARRAY_SIZE(msr_rd_wlist),
545                                                 (uintptr_t) offset))
546                                 error(EPERM, "MSR 0x%x not in read whitelist", offset);
547                         core_set_init(&cset);
548                         core_set_fill_available(&cset);
549                         msr_set_address(&msra, (uint32_t) offset);
550                         values = kzmalloc(num_cores * sizeof(uint64_t),
551                                           MEM_WAIT);
552                         if (!values)
553                                 error(ENOMEM, ERROR_FIXME);
554                         msr_set_values(&msrv, values, num_cores);
555
556                         err = msr_cores_read(&cset, &msra, &msrv);
557
558                         if (likely(!err)) {
559                                 if (n >= num_cores * sizeof(uint64_t)) {
560                                         if (!memcpy_to_user_errno(current, a, values,
561                                                                   num_cores * sizeof(uint64_t)))
562                                                 n = num_cores * sizeof(uint64_t);
563                                         else
564                                                 n = -1;
565                                 } else {
566                                         kfree(values);
567                                         error(ERANGE, "Not enough space for MSR read");
568                                 }
569                         } else {
570                                 switch (-err) {
571                                 case (EFAULT):
572                                         error(-err, "read_msr() faulted on MSR 0x%x", offset);
573                                 case (ERANGE):
574                                         error(-err, "Not enough space for MSR read");
575                                 };
576                                 error(-err, "MSR read failed");
577                         }
578                         kfree(values);
579                         return n;
580                 case Qperf: {
581                         struct perf_context *pc = (struct perf_context *) c->aux;
582
583                         assert(pc);
584                         qlock(&pc->resp_lock);
585                         if (pc->resp && ((size_t) offset < pc->resp_size)) {
586                                 n = MIN(n, (long) pc->resp_size - (long) offset);
587                                 if (memcpy_to_user_errno(current, a, pc->resp + offset, n))
588                                         n = -1;
589                         } else {
590                                 n = 0;
591                         }
592                         qunlock(&pc->resp_lock);
593
594                         return n;
595                 case Qcstate:
596                         return readnum_hex(offset, a, n, get_cstate(), NUMSIZE32);
597                 case Qpstate:
598                         return readnum_hex(offset, a, n, get_pstate(), NUMSIZE32);
599                 }
600                 default:
601                         error(EINVAL, ERROR_FIXME);
602         }
603
604         if ((buf = kzmalloc(n, 0)) == NULL)
605                 error(ENOMEM, ERROR_FIXME);
606         p = buf;
607         n = n / Linelen;
608         offset = offset / Linelen;
609
610         switch ((uint32_t) c->qid.path) {
611                 case Qioalloc:
612                         spin_lock(&(&iomap)->lock);
613                         for (map = iomap.map; n > 0 && map != NULL; map = map->next) {
614                                 if (offset-- > 0)
615                                         continue;
616                                 snprintf(p, n * Linelen, "%#8p %#8p %-12.12s\n", map->start,
617                                          map->end - 1, map->tag);
618                                 p += Linelen;
619                                 n--;
620                         }
621                         spin_unlock(&(&iomap)->lock);
622                         break;
623         }
624
625         n = p - buf;
626         memmove(a, buf, n);
627         kfree(buf);
628
629         return n;
630 }
631
632 static ssize_t cstate_write(void *ubuf, size_t len, off64_t off)
633 {
634         set_cstate(strtoul_from_ubuf(ubuf, len, off));
635         /* Poke the other cores so they use the new C-state. */
636         send_broadcast_ipi(I_POKE_CORE);
637         return len;
638 }
639
640 static void __smp_set_pstate(void *arg)
641 {
642         unsigned int val = (unsigned int)(unsigned long)arg;
643
644         set_pstate(val);
645 }
646
647 static ssize_t pstate_write(void *ubuf, size_t len, off64_t off)
648 {
649         struct core_set all_cores;
650
651         core_set_init(&all_cores);
652         core_set_fill_available(&all_cores);
653         smp_do_in_cores(&all_cores, __smp_set_pstate,
654                         (void*)strtoul_from_ubuf(ubuf, len, off));
655         return len;
656 }
657
658 static size_t archwrite(struct chan *c, void *a, size_t n, off64_t offset)
659 {
660         char *p;
661         int port, err;
662         uint64_t value;
663         uint16_t *sp;
664         uint32_t *lp;
665         struct core_set cset;
666         struct msr_address msra;
667         struct msr_value msrv;
668
669         switch ((uint32_t) c->qid.path) {
670                 case Qgdb:
671                         p = a;
672                         if (n != 1)
673                                 error(EINVAL, "Gdb: Write one byte, '1' or '0'");
674                         if (*p == '1')
675                                 gdbactive = 1;
676                         else if (*p == '0')
677                                 gdbactive = 0;
678                         else
679                                 error(EINVAL, "Gdb: must be 1 or 0");
680                         return 1;
681                 case Qiob:
682                         p = a;
683                         checkport(offset, offset + n);
684                         for (port = offset; port < offset + n; port++)
685                                 outb(port, *p++);
686                         return n;
687                 case Qiow:
688                         if (n & 1)
689                                 error(EINVAL, ERROR_FIXME);
690                         checkport(offset, offset + n);
691                         sp = a;
692                         for (port = offset; port < offset + n; port += 2)
693                                 outw(port, *sp++);
694                         return n;
695                 case Qiol:
696                         if (n & 3)
697                                 error(EINVAL, ERROR_FIXME);
698                         checkport(offset, offset + n);
699                         lp = a;
700                         for (port = offset; port < offset + n; port += 4)
701                                 outl(port, *lp++);
702                         return n;
703                 case Qmsr:
704                         if (!address_range_find(msr_wr_wlist, ARRAY_SIZE(msr_wr_wlist),
705                                                 (uintptr_t) offset))
706                                 error(EPERM, "MSR 0x%x not in write whitelist", offset);
707                         if (n != sizeof(uint64_t))
708                                 error(EINVAL, "Tried to write more than a u64 (%p)", n);
709                         if (memcpy_from_user_errno(current, &value, a, sizeof(value)))
710                                 return -1;
711
712                         core_set_init(&cset);
713                         core_set_fill_available(&cset);
714                         msr_set_address(&msra, (uint32_t) offset);
715                         msr_set_value(&msrv, value);
716
717                         err = msr_cores_write(&cset, &msra, &msrv);
718                         if (unlikely(err)) {
719                                 switch (-err) {
720                                 case (EFAULT):
721                                         error(-err, "write_msr() faulted on MSR 0x%x", offset);
722                                 case (ERANGE):
723                                         error(-err, "Not enough space for MSR write");
724                                 };
725                                 error(-err, "MSR write failed");
726                         }
727                         return sizeof(uint64_t);
728                 case Qperf: {
729                         struct perf_context *pc = (struct perf_context *) c->aux;
730
731                         assert(pc);
732
733                         return arch_perf_write(pc, a, n);
734                 }
735                 case Qcstate:
736                         return cstate_write(a, n, 0);
737                 case Qpstate:
738                         return pstate_write(a, n, 0);
739                 default:
740                         error(EINVAL, ERROR_FIXME);
741         }
742         return 0;
743 }
744
745 static void archinit(void)
746 {
747         int ret;
748
749         ret = address_range_init(msr_rd_wlist, ARRAY_SIZE(msr_rd_wlist));
750         assert(!ret);
751         ret = address_range_init(msr_wr_wlist, ARRAY_SIZE(msr_wr_wlist));
752         assert(!ret);
753 }
754
755 struct dev archdevtab __devtab = {
756         .name = "arch",
757
758         .reset = devreset,
759         .init = archinit,
760         .shutdown = devshutdown,
761         .attach = archattach,
762         .walk = archwalk,
763         .stat = archstat,
764         .open = archopen,
765         .create = devcreate,
766         .close = archclose,
767         .read = archread,
768         .bread = devbread,
769         .write = archwrite,
770         .bwrite = devbwrite,
771         .remove = devremove,
772         .wstat = devwstat,
773 };
774
775 void archreset(void)
776 {
777         int i;
778
779         /*
780          * And sometimes there is no keyboard...
781          *
782          * The reset register (0xcf9) is usually in one of the bridge
783          * chips. The actual location and sequence could be extracted from
784          * ACPI but why bother, this is the end of the line anyway.
785          print("Takes a licking and keeps on ticking...\n");
786          */
787         i = inb(0xcf9); /* ICHx reset control */
788         i &= 0x06;
789         outb(0xcf9, i | 0x02);  /* SYS_RST */
790         udelay(1000);
791         outb(0xcf9, i | 0x06);  /* RST_CPU transition */
792
793         udelay(100 * 1000);
794
795         /* some broken hardware -- as well as qemu -- might
796          * never reboot anyway with cf9. This is a standard
797          * keyboard reboot sequence known to work on really
798          * broken stuff -- like qemu. If there is no
799          * keyboard it will do no harm.
800          */
801         for (;;) {
802                 (void)inb(0x64);
803                 outb(0x64, 0xFE);
804                 udelay(100 * 1000);
805         }
806 }