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