VMM: Add our virtio_mmio_dev struct and specify its interface functions
[akaros.git] / user / vmm / ioapic.c
1 /*
2  * IOAPIC emulation
3  *
4  * Copyright 2015 Google Inc.
5  *
6  * See LICENSE for details.
7  */
8
9 #include <stdio.h>
10 #include <sys/types.h>
11 #include <pthread.h>
12 #include <sys/stat.h>
13 #include <fcntl.h>
14 #include <parlib/arch/arch.h>
15 #include <parlib/ros_debug.h>
16 #include <unistd.h>
17 #include <errno.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/uio.h>
21 #include <stdint.h>
22 #include <err.h>
23 #include <sys/mman.h>
24 #include <vmm/vmm.h>
25 #include <vmm/virtio.h>
26 #include <vmm/virtio_mmio.h>
27 #include <vmm/virtio_ids.h>
28 #include <vmm/virtio_config.h>
29 #include <vmm/sched.h>
30
31 #define IOAPIC_CONFIG 0x100
32 #define IOAPIC_NUM_PINS 24
33
34 int debug_ioapic = 1;
35 int apic_id_mask = 0xf0;
36
37 #define DPRINTF(fmt, ...) \
38         if (debug_ioapic) { fprintf(stderr, "ioapic: " fmt , ## __VA_ARGS__); }
39
40
41 struct ioapic {
42         int id;
43         int reg;
44         uint32_t arbid;
45         uint32_t value[256];
46 };
47
48 static struct ioapic ioapic[1];
49
50 static uint32_t ioapic_read(int ix, uint64_t offset)
51 {
52         uint32_t ret = (uint32_t)-1;
53         uint32_t reg = ioapic[ix].reg;
54
55
56         if (offset == 0) {
57                 DPRINTF("ioapic_read ix %x return 0x%x\n", ix, reg);
58                 return reg;
59         }
60
61         DPRINTF("ioapic_read %x 0x%x\n", ix, (int)reg);
62         switch (reg) {
63         case 0:
64                 return ioapic[ix].id;
65                 break;
66         case 1:
67                 return 0x170011;
68                 break;
69         case 2:
70                 return ioapic[ix].arbid;
71                 break;
72         default:
73                 if (reg >= 0 && reg < (IOAPIC_NUM_PINS*2 + 0x10)) {
74                         //bx_io_redirect_entry_t *entry = ioredtbl + index;
75                         //data = (ioregsel&1) ? entry->get_hi_part() : entry->get_lo_part();
76                         ret = ioapic[ix].value[reg];
77                         DPRINTF("IOAPIC_READ %x: %x return %08x\n", ix, reg, ret);
78                         return ret;
79                 } else {
80                         DPRINTF("IOAPIC READ: %x BAD INDEX 0x%x\n", ix, reg);
81                 }
82                 return ret;
83                 break;
84         }
85         return 0;
86 }
87
88 static void ioapic_write(int ix, uint64_t offset, uint32_t value)
89 {
90         uint32_t ret;
91         uint32_t reg = ioapic[ix].reg;
92
93         if (offset == 0) {
94                 DPRINTF("ioapic_write ix %x set reg 0x%x\n", ix, value);
95                 ioapic[ix].reg = value;
96                 return;
97         }
98
99         switch (reg) {
100         case 0:
101                 DPRINTF("IOAPIC_WRITE: Set %d ID to %d\n", ix, value);
102                 ioapic[ix].id = value;
103                 break;
104         case 1:
105         case 2:
106                 DPRINTF("IOAPIC_WRITE: Can't write %d\n", reg);
107         default:
108                 if (reg >= 0 && reg < (IOAPIC_NUM_PINS*2 + 0x10)) {
109                         ioapic[ix].value[reg] = value;
110                         DPRINTF("IOAPIC %x: set %08x to %016x\n", ix, reg, value);
111                 } else {
112                         DPRINTF("IOAPIC WRITE: %x BAD INDEX 0x%x\n", ix, reg);
113                 }
114                 break;
115         }
116
117 }
118
119 int do_ioapic(struct guest_thread *vm_thread, uint64_t gpa, int destreg,
120               uint64_t *regp, int store)
121 {
122         // TODO: compute an index for the ioapic array. 
123         int ix = 0;
124         uint32_t offset = gpa & 0xfffff;
125         /* basic sanity tests. */
126         DPRINTF("%s: %p 0x%x %p %s\n", __func__, (void *)gpa, destreg, regp, store ? "write" : "read");
127
128         if ((offset != 0) && (offset != 0x10)) {
129                 DPRINTF("Bad register offset: 0x%x and has to be 0x0 or 0x10\n", offset);
130                 return -1;
131         }
132
133         if (store) {
134                 ioapic_write(ix, offset, *regp);
135         } else {
136                 *regp = ioapic_read(ix, offset);
137         }
138
139 }