VMX: change msr emulation to pass in the vm trapframe
[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 <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 /* White list entries needs to be ordered by start address, and never overlap.
94  */
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 };
111 int gdbactive = 0;
112
113 //
114 //  alloc some io port space and remember who it was
115 //  alloced to.  if port < 0, find a free region.
116 //
117 int ioalloc(int port, int size, int align, char *tag)
118 {
119         struct io_map *map, **l;
120         int i;
121
122         spin_lock(&(&iomap)->lock);
123         if (port < 0) {
124                 // find a free port above 0x400 and below 0x1000
125                 port = 0x400;
126                 for (l = &iomap.map; *l; l = &(*l)->next) {
127                         map = *l;
128                         if (map->start < 0x400)
129                                 continue;
130                         i = map->start - port;
131                         if (i > size)
132                                 break;
133                         if (align > 0)
134                                 port = ((port + align - 1) / align) * align;
135                         else
136                                 port = map->end;
137                 }
138                 if (*l == NULL) {
139                         spin_unlock(&(&iomap)->lock);
140                         return -1;
141                 }
142         } else {
143                 // Only 64KB I/O space on the x86.
144                 if ((port + size) > 0x10000) {
145                         spin_unlock(&(&iomap)->lock);
146                         return -1;
147                 }
148                 // see if the space clashes with previously allocated ports
149                 for (l = &iomap.map; *l; l = &(*l)->next) {
150                         map = *l;
151                         if (map->end <= port)
152                                 continue;
153                         if (map->reserved && map->start == port && map->end == port + size) {
154                                 map->reserved = 0;
155                                 spin_unlock(&(&iomap)->lock);
156                                 return map->start;
157                         }
158                         if (map->start >= port + size)
159                                 break;
160                         spin_unlock(&(&iomap)->lock);
161                         return -1;
162                 }
163         }
164         map = iomap.free;
165         if (map == NULL) {
166                 printd("ioalloc: out of maps");
167                 spin_unlock(&(&iomap)->lock);
168                 return port;
169         }
170         iomap.free = map->next;
171         map->next = *l;
172         map->start = port;
173         map->end = port + size;
174         strlcpy(map->tag, tag, sizeof(map->tag));
175         *l = map;
176
177         archdir[0].qid.vers++;
178
179         spin_unlock(&(&iomap)->lock);
180         return map->start;
181 }
182
183 void iofree(int port)
184 {
185         struct io_map *map, **l;
186
187         spin_lock(&(&iomap)->lock);
188         for (l = &iomap.map; *l; l = &(*l)->next) {
189                 if ((*l)->start == port) {
190                         map = *l;
191                         *l = map->next;
192                         map->next = iomap.free;
193                         iomap.free = map;
194                         break;
195                 }
196                 if ((*l)->start > port)
197                         break;
198         }
199         archdir[0].qid.vers++;
200         spin_unlock(&(&iomap)->lock);
201 }
202
203 int iounused(int start, int end)
204 {
205         struct io_map *map;
206
207         for (map = iomap.map; map; map = map->next) {
208                 if (((start >= map->start) && (start < map->end)) ||
209                     ((start <= map->start) && (end > map->start)))
210                         return 0;
211         }
212         return 1;
213 }
214
215 void ioinit(void)
216 {
217         int i;
218         char *excluded = "";
219
220         panic("Akaros doesn't do IO port allocation yet.  Don't init.");
221         for (i = 0; i < ARRAY_SIZE(iomap.maps) - 1; i++)
222                 iomap.maps[i].next = &iomap.maps[i + 1];
223         iomap.maps[i].next = NULL;
224         iomap.free = iomap.maps;
225         char *s;
226
227         s = excluded;
228         while (s && *s != '\0' && *s != '\n') {
229                 char *ends;
230                 int io_s, io_e;
231
232                 io_s = (int)strtol(s, &ends, 0);
233                 if (ends == NULL || ends == s || *ends != '-') {
234                         printd("ioinit: cannot parse option string\n");
235                         break;
236                 }
237                 s = ++ends;
238
239                 io_e = (int)strtol(s, &ends, 0);
240                 if (ends && *ends == ',')
241                         *ends++ = '\0';
242                 s = ends;
243
244                 ioalloc(io_s, io_e - io_s + 1, 0, "pre-allocated");
245         }
246 }
247
248 // Reserve a range to be ioalloced later.
249 // This is in particular useful for exchangable cards, such
250 // as pcmcia and cardbus cards.
251 int ioreserve(int unused_int, int size, int align, char *tag)
252 {
253         struct io_map *map, **l;
254         int i, port;
255
256         spin_lock(&(&iomap)->lock);
257         // find a free port above 0x400 and below 0x1000
258         port = 0x400;
259         for (l = &iomap.map; *l; l = &(*l)->next) {
260                 map = *l;
261                 if (map->start < 0x400)
262                         continue;
263                 i = map->start - port;
264                 if (i > size)
265                         break;
266                 if (align > 0)
267                         port = ((port + align - 1) / align) * align;
268                 else
269                         port = map->end;
270         }
271         if (*l == NULL) {
272                 spin_unlock(&(&iomap)->lock);
273                 return -1;
274         }
275         map = iomap.free;
276         if (map == NULL) {
277                 printd("ioalloc: out of maps");
278                 spin_unlock(&(&iomap)->lock);
279                 return port;
280         }
281         iomap.free = map->next;
282         map->next = *l;
283         map->start = port;
284         map->end = port + size;
285         map->reserved = 1;
286         strlcpy(map->tag, tag, sizeof(map->tag));
287         *l = map;
288
289         archdir[0].qid.vers++;
290
291         spin_unlock(&(&iomap)->lock);
292         return map->start;
293 }
294
295 static void checkport(int start, int end)
296 {
297         /* standard vga regs are OK */
298         if (start >= 0x2b0 && end <= 0x2df + 1)
299                 return;
300         if (start >= 0x3c0 && end <= 0x3da + 1)
301                 return;
302
303         if (iounused(start, end))
304                 return;
305         error(EPERM, ERROR_FIXME);
306 }
307
308 static struct chan *archattach(char *spec)
309 {
310         return devattach(archdevtab.name, spec);
311 }
312
313 struct walkqid *archwalk(struct chan *c, struct chan *nc, char **name,
314                                                  int nname)
315 {
316         return devwalk(c, nc, name, nname, archdir, Qmax, devgen);
317 }
318
319 static int archstat(struct chan *c, uint8_t * dp, int n)
320 {
321         archdir[Qrealmem].length = REAL_MEM_SIZE;
322
323         return devstat(c, dp, n, archdir, Qmax, devgen);
324 }
325
326 static struct perf_context *arch_create_perf_context(void)
327 {
328         ERRSTACK(1);
329         struct perf_context *pc = kzmalloc(sizeof(struct perf_context),
330                                            MEM_WAIT);
331
332         if (waserror()) {
333                 kfree(pc);
334                 nexterror();
335         }
336         qlock_init(&pc->resp_lock);
337         pc->ps = perfmon_create_session();
338         poperror();
339
340         return pc;
341 }
342
343 /* Called after the last reference (FD / chan) to pc is closed. */
344 static void arch_free_perf_context(struct perf_context *pc)
345 {
346         perfmon_close_session(pc->ps);
347         kfree(pc->resp);
348         kfree(pc);
349 }
350
351 static const uint8_t *arch_read_core_set(struct core_set *cset,
352                                          const uint8_t *kptr,
353                                          const uint8_t *ktop)
354 {
355         int i, nb;
356         uint32_t n;
357
358         error_assert(EBADMSG, (kptr + sizeof(uint32_t)) <= ktop);
359         kptr = get_le_u32(kptr, &n);
360         error_assert(EBADMSG, (kptr + n) <= ktop);
361         core_set_init(cset);
362         nb = MIN((int) n * 8, num_cores);
363         for (i = 0; i < nb; i++) {
364                 if (test_bit(i, (const unsigned long *) kptr))
365                         core_set_setcpu(cset, i);
366         }
367
368         return kptr + n;
369 }
370
371 static long arch_perf_write(struct perf_context *pc, const void *udata,
372                             long usize)
373 {
374         ERRSTACK(1);
375         void *kdata;
376         const uint8_t *kptr, *ktop;
377
378         kdata = user_memdup_errno(current, udata, usize);
379         if (unlikely(!kdata))
380                 return -1;
381         qlock(&pc->resp_lock);
382         if (waserror()) {
383                 qunlock(&pc->resp_lock);
384                 kfree(kdata);
385                 nexterror();
386         }
387         /* Fresh command, reset the response buffer */
388         kfree(pc->resp);
389         pc->resp = NULL;
390         pc->resp_size = 0;
391
392         kptr = kdata;
393         ktop = kptr + usize;
394         error_assert(EBADMSG, (kptr + 1) <= ktop);
395         switch (*kptr++) {
396                 case PERFMON_CMD_COUNTER_OPEN: {
397                         int ped;
398                         struct perfmon_event pev;
399                         struct core_set cset;
400
401                         error_assert(EBADMSG, (kptr + 3 * sizeof(uint64_t)) <= ktop);
402                         perfmon_init_event(&pev);
403                         kptr = get_le_u64(kptr, &pev.event);
404                         kptr = get_le_u64(kptr, &pev.flags);
405                         kptr = get_le_u64(kptr, &pev.trigger_count);
406                         kptr = get_le_u64(kptr, &pev.user_data);
407                         kptr = arch_read_core_set(&cset, kptr, ktop);
408
409                         ped = perfmon_open_event(&cset, pc->ps, &pev);
410
411                         pc->resp_size = sizeof(uint32_t);
412                         pc->resp = kmalloc(pc->resp_size, MEM_WAIT);
413                         put_le_u32(pc->resp, (uint32_t) ped);
414                         break;
415                 }
416                 case PERFMON_CMD_COUNTER_STATUS: {
417                         uint32_t ped;
418                         uint8_t *rptr;
419                         struct perfmon_status *pef;
420
421                         error_assert(EBADMSG, (kptr + sizeof(uint32_t)) <= ktop);
422                         kptr = get_le_u32(kptr, &ped);
423
424                         pef = perfmon_get_event_status(pc->ps, (int) ped);
425
426                         pc->resp_size = sizeof(uint32_t) + num_cores * sizeof(uint64_t);
427                         pc->resp = kmalloc(pc->resp_size, MEM_WAIT);
428                         rptr = put_le_u32(pc->resp, num_cores);
429                         for (int i = 0; i < num_cores; i++)
430                                 rptr = put_le_u64(rptr, pef->cores_values[i]);
431
432                         perfmon_free_event_status(pef);
433                         break;
434                 }
435                 case PERFMON_CMD_COUNTER_CLOSE: {
436                         uint32_t ped;
437
438                         error_assert(EBADMSG, (kptr + sizeof(uint32_t)) <= ktop);
439                         kptr = get_le_u32(kptr, &ped);
440
441                         perfmon_close_event(pc->ps, (int) ped);
442                         break;
443                 }
444                 case PERFMON_CMD_CPU_CAPS: {
445                         uint8_t *rptr;
446                         struct perfmon_cpu_caps pcc;
447
448                         kptr++;
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 long archread(struct chan *c, void *a, long n, int64_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 long archwrite(struct chan *c, void *a, long n, int64_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 }