Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


removed references to GeekOS and added some namespace changes,
[palacios.git] / palacios / src / palacios / vmm_io.c
1 /* (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> */
2 /* (c) 2008, The V3VEE Project <http://www.v3vee.org> */
3
4 #include <palacios/vmm_io.h>
5 #include <palacios/vmm_string.h>
6 #include <palacios/vmm.h>
7
8
9
10
11 #ifndef DEBUG_IO
12 #undef PrintDebug
13 #define PrintDebug(fmt, args...)
14 #endif
15
16
17 static int default_write(ushort_t port, void *src, uint_t length, void * priv_data);
18 static int default_read(ushort_t port, void * dst, uint_t length, void * priv_data);
19
20
21 void init_vmm_io_map(struct guest_info * info) {
22   struct vmm_io_map * io_map = &(info->io_map);
23   io_map->num_ports = 0;
24   io_map->head = NULL;
25 }
26
27
28
29
30
31 static int add_io_hook(struct vmm_io_map * io_map, struct vmm_io_hook * io_hook) {
32
33   if (!(io_map->head)) {
34     io_map->head = io_hook;
35     io_map->num_ports = 1;
36     return 0;
37   } else if (io_map->head->port > io_hook->port) {
38     io_hook->next = io_map->head;
39
40     io_map->head->prev = io_hook;
41     io_map->head = io_hook;
42     io_map->num_ports++;
43
44     return 0;
45   } else {
46     struct vmm_io_hook * tmp_hook = io_map->head;
47     
48     while ((tmp_hook->next)  && 
49            (tmp_hook->next->port <= io_hook->port)) {
50         tmp_hook = tmp_hook->next;
51     }
52     
53     if (tmp_hook->port == io_hook->port) {
54       //tmp_hook->read = io_hook->read;
55       //tmp_hook->write = io_hook->write;
56       //V3_Free(io_hook);
57       return -1;
58     } else {
59       io_hook->prev = tmp_hook;
60       io_hook->next = tmp_hook->next;
61
62       if (tmp_hook->next) {
63         tmp_hook->next->prev = io_hook;
64       }
65
66       tmp_hook->next = io_hook;
67
68       io_map->num_ports++;
69       return 0;
70     }
71   }
72   return -1;
73 }
74
75 static int remove_io_hook(struct vmm_io_map * io_map, struct vmm_io_hook * io_hook) {
76   if (io_map->head == io_hook) {
77     io_map->head = io_hook->next;
78   } else if (io_hook->prev) {
79     io_hook->prev->next = io_hook->next;
80   } else {
81     return -1;
82     // data corruption failure
83   }
84   
85   if (io_hook->next) {
86     io_hook->next->prev = io_hook->prev;
87   }
88
89   io_map->num_ports--;
90
91   return 0;
92 }
93
94
95
96
97
98 int v3_hook_io_port(struct guest_info * info, uint_t port, 
99                     int (*read)(ushort_t port, void * dst, uint_t length, void * priv_data),
100                     int (*write)(ushort_t port, void * src, uint_t length, void * priv_data), 
101                     void * priv_data) {
102   struct vmm_io_map * io_map = &(info->io_map);
103   struct vmm_io_hook * io_hook = (struct vmm_io_hook *)V3_Malloc(sizeof(struct vmm_io_hook));
104
105   io_hook->port = port;
106
107   if (!read) {
108     io_hook->read = &default_read;
109   } else {
110     io_hook->read = read;
111   }
112
113   if (!write) {
114     io_hook->write = &default_write;
115   } else {
116     io_hook->write = write;
117   }
118
119   io_hook->next = NULL;
120   io_hook->prev = NULL;
121
122   io_hook->priv_data = priv_data;
123
124   if (add_io_hook(io_map, io_hook) != 0) {
125     V3_Free(io_hook);
126     return -1;
127   }
128
129   return 0;
130 }
131
132 int v3_unhook_io_port(struct guest_info * info, uint_t port) {
133   struct vmm_io_map * io_map = &(info->io_map);
134   struct vmm_io_hook * hook = v3_get_io_hook(io_map, port);
135
136   if (hook == NULL) {
137     return -1;
138   }
139
140   remove_io_hook(io_map, hook);
141   return 0;
142 }
143
144
145 struct vmm_io_hook * v3_get_io_hook(struct vmm_io_map * io_map, uint_t port) {
146   struct vmm_io_hook * tmp_hook;
147   FOREACH_IO_HOOK(*io_map, tmp_hook) {
148     if (tmp_hook->port == port) {
149       return tmp_hook;
150     }
151   }
152   return NULL;
153 }
154
155
156
157 void PrintDebugIOMap(struct vmm_io_map * io_map) {
158   struct vmm_io_hook * iter = io_map->head;
159
160   PrintDebug("VMM IO Map (Entries=%d)\n", io_map->num_ports);
161
162   while (iter) {
163     PrintDebug("IO Port: %hu (Read=%x) (Write=%x)\n", iter->port, iter->read, iter->write);
164   }
165 }
166
167
168
169 /*
170  * Write a byte to an I/O port.
171  */
172 void v3_outb(ushort_t port, uchar_t value) {
173     __asm__ __volatile__ (
174         "outb %b0, %w1"
175         :
176         : "a" (value), "Nd" (port)
177     );
178 }
179
180 /*
181  * Read a byte from an I/O port.
182  */
183 uchar_t v3_inb(ushort_t port) {
184     uchar_t value;
185
186     __asm__ __volatile__ (
187         "inb %w1, %b0"
188         : "=a" (value)
189         : "Nd" (port)
190     );
191
192     return value;
193 }
194
195 /*
196  * Write a word to an I/O port.
197  */
198 void v3_outw(ushort_t port, ushort_t value) {
199     __asm__ __volatile__ (
200         "outw %w0, %w1"
201         :
202         : "a" (value), "Nd" (port)
203     );
204 }
205
206 /*
207  * Read a word from an I/O port.
208  */
209 ushort_t v3_inw(ushort_t port) {
210     ushort_t value;
211
212     __asm__ __volatile__ (
213         "inw %w1, %w0"
214         : "=a" (value)
215         : "Nd" (port)
216     );
217
218     return value;
219 }
220
221 /*
222  * Write a double word to an I/O port.
223  */
224 void v3_outdw(ushort_t port, uint_t value) {
225     __asm__ __volatile__ (
226         "outl %0, %1"
227         :
228         : "a" (value), "Nd" (port)
229     );
230 }
231
232 /*
233  * Read a double word from an I/O port.
234  */
235 uint_t v3_indw(ushort_t port) {
236     uint_t value;
237
238     __asm__ __volatile__ (
239         "inl %1, %0"
240         : "=a" (value)
241         : "Nd" (port)
242     );
243
244     return value;
245 }
246
247
248
249
250 /* FIX ME */
251 static int default_write(ushort_t port, void *src, uint_t length, void * priv_data) {
252   /*
253     
254   if (length == 1) {
255   __asm__ __volatile__ (
256   "outb %b0, %w1"
257   :
258   : "a" (*dst), "Nd" (port)
259   );
260   } else if (length == 2) {
261   __asm__ __volatile__ (
262   "outw %b0, %w1"
263   :
264   : "a" (*dst), "Nd" (port)
265   );
266   } else if (length == 4) {
267   __asm__ __volatile__ (
268   "outw %b0, %w1"
269   :
270   : "a" (*dst), "Nd" (port)
271   );
272   }
273   */
274   return 0;
275 }
276
277 static int default_read(ushort_t port, void * dst, uint_t length, void * priv_data) {
278
279   /*    
280         uchar_t value;
281
282     __asm__ __volatile__ (
283         "inb %w1, %b0"
284         : "=a" (value)
285         : "Nd" (port)
286     );
287
288     return value;
289   */
290
291   return 0;
292 }