Rename KMALLOC_* -> MEM_* [2/2]
[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 = arch_read_core_set(&cset, kptr, ktop);
399
400                         ped = perfmon_open_event(&cset, pc->ps, &pev);
401
402                         pc->resp_size = sizeof(uint32_t);
403                         pc->resp = kmalloc(pc->resp_size, MEM_WAIT);
404                         put_le_u32(pc->resp, (uint32_t) ped);
405                         break;
406                 }
407                 case PERFMON_CMD_COUNTER_STATUS: {
408                         int i;
409                         uint32_t ped;
410                         uint8_t *rptr;
411                         uint64_t *mvalues;
412                         struct perfmon_status *pef;
413
414                         error_assert(EBADMSG, (kptr + sizeof(uint32_t)) <= ktop);
415                         kptr = get_le_u32(kptr, &ped);
416
417                         pef = perfmon_get_event_status(pc->ps, (int) ped);
418
419                         mvalues = kzmalloc(num_cores * sizeof(mvalues),
420                                            MEM_WAIT);
421                         for (i = 0; i < num_cores; i++)
422                                 mvalues[i] = pef->cores_values[i];
423
424                         pc->resp_size = 3 * sizeof(uint64_t) + sizeof(uint32_t) +
425                                 num_cores * sizeof(uint64_t);
426                         pc->resp = kmalloc(pc->resp_size, MEM_WAIT);
427
428                         rptr = put_le_u64(pc->resp, pef->ev.event);
429                         rptr = put_le_u64(rptr, pef->ev.flags);
430                         rptr = put_le_u64(rptr, pef->ev.trigger_count);
431                         rptr = put_le_u32(rptr, num_cores);
432                         for (i = 0; i < num_cores; i++)
433                                 rptr = put_le_u64(rptr, mvalues[i]);
434                         kfree(mvalues);
435                         perfmon_free_event_status(pef);
436                         break;
437                 }
438                 case PERFMON_CMD_COUNTER_CLOSE: {
439                         uint32_t ped;
440
441                         error_assert(EBADMSG, (kptr + sizeof(uint32_t)) <= ktop);
442                         kptr = get_le_u32(kptr, &ped);
443
444                         perfmon_close_event(pc->ps, (int) ped);
445                         break;
446                 }
447                 case PERFMON_CMD_CPU_CAPS: {
448                         uint8_t *rptr;
449                         struct perfmon_cpu_caps pcc;
450
451                         kptr++;
452                         perfmon_get_cpu_caps(&pcc);
453
454                         pc->resp_size = 6 * sizeof(uint32_t);
455                         pc->resp = kmalloc(pc->resp_size, MEM_WAIT);
456
457                         rptr = put_le_u32(pc->resp, pcc.perfmon_version);
458                         rptr = put_le_u32(rptr, pcc.proc_arch_events);
459                         rptr = put_le_u32(rptr, pcc.bits_x_counter);
460                         rptr = put_le_u32(rptr, pcc.counters_x_proc);
461                         rptr = put_le_u32(rptr, pcc.bits_x_fix_counter);
462                         rptr = put_le_u32(rptr, pcc.fix_counters_x_proc);
463                         break;
464                 }
465                 default:
466                         error(EINVAL, "Invalid perfmon command: 0x%x", kptr[-1]);
467         }
468         poperror();
469         kfree(kdata);
470
471         return (long) (kptr - (const uint8_t *) kdata);
472 }
473
474 static struct chan *archopen(struct chan *c, int omode)
475 {
476         c = devopen(c, omode, archdir, Qmax, devgen);
477         switch ((uint32_t) c->qid.path) {
478                 case Qperf:
479                         if (!perfmon_supported())
480                                 error(ENODEV, "perf is not supported");
481                         assert(!c->aux);
482                         c->aux = arch_create_perf_context();
483                         break;
484         }
485
486         return c;
487 }
488
489 static void archclose(struct chan *c)
490 {
491         switch ((uint32_t) c->qid.path) {
492                 case Qperf:
493                         if (c->aux) {
494                                 arch_free_perf_context((struct perf_context *) c->aux);
495                                 c->aux = NULL;
496                         }
497                         break;
498         }
499 }
500
501 static long archread(struct chan *c, void *a, long n, int64_t offset)
502 {
503         char *buf, *p;
504         int err, port;
505         uint64_t *values;
506         uint16_t *sp;
507         uint32_t *lp;
508         struct io_map *map;
509         struct core_set cset;
510         struct msr_address msra;
511         struct msr_value msrv;
512
513         switch ((uint32_t) c->qid.path) {
514                 case Qdir:
515                         return devdirread(c, a, n, archdir, Qmax, devgen);
516                 case Qgdb:
517                         p = gdbactive ? "1" : "0";
518                         return readstr(offset, a, n, p);
519                 case Qiob:
520                         port = offset;
521                         checkport(offset, offset + n);
522                         for (p = a; port < offset + n; port++)
523                                 *p++ = inb(port);
524                         return n;
525                 case Qiow:
526                         if (n & 1)
527                                 error(EINVAL, ERROR_FIXME);
528                         checkport(offset, offset + n);
529                         sp = a;
530                         for (port = offset; port < offset + n; port += 2)
531                                 *sp++ = inw(port);
532                         return n;
533                 case Qiol:
534                         if (n & 3)
535                                 error(EINVAL, ERROR_FIXME);
536                         checkport(offset, offset + n);
537                         lp = a;
538                         for (port = offset; port < offset + n; port += 4)
539                                 *lp++ = inl(port);
540                         return n;
541                 case Qioalloc:
542                         break;
543                 case Qrealmem:
544                         return readmem(offset, a, n, KADDR(0), REAL_MEM_SIZE);
545                 case Qmsr:
546                         if (!address_range_find(msr_rd_wlist, ARRAY_SIZE(msr_rd_wlist),
547                                                 (uintptr_t) offset))
548                                 error(EPERM, "MSR 0x%x not in read whitelist", offset);
549                         core_set_init(&cset);
550                         core_set_fill_available(&cset);
551                         msr_set_address(&msra, (uint32_t) offset);
552                         values = kzmalloc(num_cores * sizeof(uint64_t),
553                                           MEM_WAIT);
554                         if (!values)
555                                 error(ENOMEM, ERROR_FIXME);
556                         msr_set_values(&msrv, values, num_cores);
557
558                         err = msr_cores_read(&cset, &msra, &msrv);
559
560                         if (likely(!err)) {
561                                 if (n >= num_cores * sizeof(uint64_t)) {
562                                         if (!memcpy_to_user_errno(current, a, values,
563                                                                   num_cores * sizeof(uint64_t)))
564                                                 n = num_cores * sizeof(uint64_t);
565                                         else
566                                                 n = -1;
567                                 } else {
568                                         kfree(values);
569                                         error(ERANGE, "Not enough space for MSR read");
570                                 }
571                         } else {
572                                 switch (-err) {
573                                 case (EFAULT):
574                                         error(-err, "read_msr() faulted on MSR 0x%x", offset);
575                                 case (ERANGE):
576                                         error(-err, "Not enough space for MSR read");
577                                 };
578                                 error(-err, "MSR read failed");
579                         }
580                         kfree(values);
581                         return n;
582                 case Qperf: {
583                         struct perf_context *pc = (struct perf_context *) c->aux;
584
585                         assert(pc);
586                         if (pc->resp && ((size_t) offset < pc->resp_size)) {
587                                 n = MIN(n, (long) pc->resp_size - (long) offset);
588                                 if (memcpy_to_user_errno(current, a, pc->resp + offset, n))
589                                         n = -1;
590                         } else {
591                                 n = 0;
592                         }
593
594                         return n;
595                 }
596                 default:
597                         error(EINVAL, ERROR_FIXME);
598         }
599
600         if ((buf = kzmalloc(n, 0)) == NULL)
601                 error(ENOMEM, ERROR_FIXME);
602         p = buf;
603         n = n / Linelen;
604         offset = offset / Linelen;
605
606         switch ((uint32_t) c->qid.path) {
607                 case Qioalloc:
608                         spin_lock(&(&iomap)->lock);
609                         for (map = iomap.map; n > 0 && map != NULL; map = map->next) {
610                                 if (offset-- > 0)
611                                         continue;
612                                 snprintf(p, n * Linelen, "%#8p %#8p %-12.12s\n", map->start,
613                                          map->end - 1, map->tag);
614                                 p += Linelen;
615                                 n--;
616                         }
617                         spin_unlock(&(&iomap)->lock);
618                         break;
619         }
620
621         n = p - buf;
622         memmove(a, buf, n);
623         kfree(buf);
624
625         return n;
626 }
627
628 static long archwrite(struct chan *c, void *a, long n, int64_t offset)
629 {
630         char *p;
631         int port, err;
632         uint64_t value;
633         uint16_t *sp;
634         uint32_t *lp;
635         struct core_set cset;
636         struct msr_address msra;
637         struct msr_value msrv;
638
639         switch ((uint32_t) c->qid.path) {
640                 case Qgdb:
641                         p = a;
642                         if (n != 1)
643                                 error(EINVAL, "Gdb: Write one byte, '1' or '0'");
644                         if (*p == '1')
645                                 gdbactive = 1;
646                         else if (*p == '0')
647                                 gdbactive = 0;
648                         else
649                                 error(EINVAL, "Gdb: must be 1 or 0");
650                         return 1;
651                 case Qiob:
652                         p = a;
653                         checkport(offset, offset + n);
654                         for (port = offset; port < offset + n; port++)
655                                 outb(port, *p++);
656                         return n;
657                 case Qiow:
658                         if (n & 1)
659                                 error(EINVAL, ERROR_FIXME);
660                         checkport(offset, offset + n);
661                         sp = a;
662                         for (port = offset; port < offset + n; port += 2)
663                                 outw(port, *sp++);
664                         return n;
665                 case Qiol:
666                         if (n & 3)
667                                 error(EINVAL, ERROR_FIXME);
668                         checkport(offset, offset + n);
669                         lp = a;
670                         for (port = offset; port < offset + n; port += 4)
671                                 outl(port, *lp++);
672                         return n;
673                 case Qmsr:
674                         if (!address_range_find(msr_wr_wlist, ARRAY_SIZE(msr_wr_wlist),
675                                                 (uintptr_t) offset))
676                                 error(EPERM, "MSR 0x%x not in write whitelist", offset);
677                         if (n != sizeof(uint64_t))
678                                 error(EINVAL, "Tried to write more than a u64 (%p)", n);
679                         if (memcpy_from_user_errno(current, &value, a, sizeof(value)))
680                                 return -1;
681
682                         core_set_init(&cset);
683                         core_set_fill_available(&cset);
684                         msr_set_address(&msra, (uint32_t) offset);
685                         msr_set_value(&msrv, value);
686
687                         err = msr_cores_write(&cset, &msra, &msrv);
688                         if (unlikely(err)) {
689                                 switch (-err) {
690                                 case (EFAULT):
691                                         error(-err, "write_msr() faulted on MSR 0x%x", offset);
692                                 case (ERANGE):
693                                         error(-err, "Not enough space for MSR write");
694                                 };
695                                 error(-err, "MSR write failed");
696                         }
697                         return sizeof(uint64_t);
698                 case Qperf: {
699                         struct perf_context *pc = (struct perf_context *) c->aux;
700
701                         assert(pc);
702
703                         return arch_perf_write(pc, a, n);
704                 }
705                 default:
706                         error(EINVAL, ERROR_FIXME);
707         }
708         return 0;
709 }
710
711 static void archinit(void)
712 {
713         int ret;
714
715         ret = address_range_init(msr_rd_wlist, ARRAY_SIZE(msr_rd_wlist));
716         assert(!ret);
717         ret = address_range_init(msr_wr_wlist, ARRAY_SIZE(msr_wr_wlist));
718         assert(!ret);
719 }
720
721 struct dev archdevtab __devtab = {
722         .name = "arch",
723
724         .reset = devreset,
725         .init = archinit,
726         .shutdown = devshutdown,
727         .attach = archattach,
728         .walk = archwalk,
729         .stat = archstat,
730         .open = archopen,
731         .create = devcreate,
732         .close = archclose,
733         .read = archread,
734         .bread = devbread,
735         .write = archwrite,
736         .bwrite = devbwrite,
737         .remove = devremove,
738         .wstat = devwstat,
739 };
740
741 void archreset(void)
742 {
743         int i;
744
745         /*
746          * And sometimes there is no keyboard...
747          *
748          * The reset register (0xcf9) is usually in one of the bridge
749          * chips. The actual location and sequence could be extracted from
750          * ACPI but why bother, this is the end of the line anyway.
751          print("Takes a licking and keeps on ticking...\n");
752          */
753         i = inb(0xcf9); /* ICHx reset control */
754         i &= 0x06;
755         outb(0xcf9, i | 0x02);  /* SYS_RST */
756         udelay(1000);
757         outb(0xcf9, i | 0x06);  /* RST_CPU transition */
758
759         udelay(100 * 1000);
760
761         /* some broken hardware -- as well as qemu -- might
762          * never reboot anyway with cf9. This is a standard
763          * keyboard reboot sequence known to work on really
764          * broken stuff -- like qemu. If there is no
765          * keyboard it will do no harm.
766          */
767         for (;;) {
768                 (void)inb(0x64);
769                 outb(0x64, 0xFE);
770                 udelay(100 * 1000);
771         }
772 }