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.


virtual console works with stream-serial implementation
[palacios.git] / palacios / src / palacios / vmm_io.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm_io.h>
21 #include <palacios/vmm_string.h>
22 #include <palacios/vmm.h>
23 #include <palacios/vm_guest.h>
24
25
26
27 #ifndef CONFIG_DEBUG_IO
28 #undef PrintDebug
29 #define PrintDebug(fmt, args...)
30 #endif
31
32
33 static int default_write(struct guest_info * core, uint16_t port, void *src, uint_t length, void * priv_data);
34 static int default_read(struct guest_info * core, uint16_t port, void * dst, uint_t length, void * priv_data);
35
36
37 void v3_init_io_map(struct v3_vm_info * vm) {
38
39   vm->io_map.map.rb_node = NULL;
40   vm->io_map.arch_data = NULL;
41   vm->io_map.update_map = NULL;
42
43 }
44
45
46
47
48 static inline struct v3_io_hook * __insert_io_hook(struct v3_vm_info * vm, struct v3_io_hook * hook) {
49   struct rb_node ** p = &(vm->io_map.map.rb_node);
50   struct rb_node * parent = NULL;
51   struct v3_io_hook * tmp_hook = NULL;
52
53   while (*p) {
54     parent = *p;
55     tmp_hook = rb_entry(parent, struct v3_io_hook, tree_node);
56
57     if (hook->port < tmp_hook->port) {
58       p = &(*p)->rb_left;
59     } else if (hook->port > tmp_hook->port) {
60       p = &(*p)->rb_right;
61     } else {
62       return tmp_hook;
63     }
64   }
65   rb_link_node(&(hook->tree_node), parent, p);
66
67   return NULL;
68 }
69
70
71 static inline struct v3_io_hook * insert_io_hook(struct v3_vm_info * vm, struct v3_io_hook * hook) {
72   struct v3_io_hook * ret;
73
74   if ((ret = __insert_io_hook(vm, hook))) {
75     return ret;
76   }
77
78   v3_rb_insert_color(&(hook->tree_node), &(vm->io_map.map));
79
80   return NULL;
81 }
82
83
84 struct v3_io_hook * v3_get_io_hook(struct v3_vm_info * vm, uint16_t port) {
85   struct rb_node * n = vm->io_map.map.rb_node;
86   struct v3_io_hook * hook = NULL;
87
88   while (n) {
89     hook = rb_entry(n, struct v3_io_hook, tree_node);
90     
91     if (port < hook->port) {
92       n = n->rb_left;
93     } else if (port > hook->port) {
94       n = n->rb_right;
95     } else {
96       return hook;
97     }
98   }
99
100   return NULL;
101 }
102
103
104
105
106
107 int v3_hook_io_port(struct v3_vm_info * vm, uint16_t port, 
108                     int (*read)(struct guest_info * core, uint16_t port, void * dst, uint_t length, void * priv_data),
109                     int (*write)(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data), 
110                     void * priv_data) {
111   struct v3_io_hook * io_hook = (struct v3_io_hook *)V3_Malloc(sizeof(struct v3_io_hook));
112
113   io_hook->port = port;
114
115   if (!read) {
116     io_hook->read = &default_read;
117   } else {
118     io_hook->read = read;
119   }
120
121   if (!write) {
122     io_hook->write = &default_write;
123   } else {
124     io_hook->write = write;
125   }
126
127   io_hook->priv_data = priv_data;
128
129   if (insert_io_hook(vm, io_hook)) {
130       PrintError("Could not insert IO hook for port %u (0x%x)\n", port, port);
131       V3_Free(io_hook);
132       return -1;
133   }
134
135   if (vm->io_map.update_map) {
136       if (vm->io_map.update_map(vm, port, 
137                                   ((read == NULL) ? 0 : 1), 
138                                   ((write == NULL) ? 0 : 1)) == -1) {
139           PrintError("Could not update IO map for port %u (0x%x)\n", port, port);
140           V3_Free(io_hook);
141           return -1;
142       }
143   }
144
145   return 0;
146 }
147
148 int v3_unhook_io_port(struct v3_vm_info * vm, uint16_t port) {
149     struct v3_io_hook * hook = v3_get_io_hook(vm, port);
150
151     if (hook == NULL) {
152         PrintError("Could not find port to unhook %u (0x%x)\n", port, port);
153         return -1;
154     }
155
156     v3_rb_erase(&(hook->tree_node), &(vm->io_map.map));
157
158     if (vm->io_map.update_map) {
159         // set the arch map to default (this should be 1, 1)
160         vm->io_map.update_map(vm, port, 0, 0);
161     }
162
163     V3_Free(hook);
164
165     return 0;
166 }
167
168
169
170
171
172
173
174 void v3_refresh_io_map(struct v3_vm_info * vm) {
175     struct v3_io_map * io_map = &(vm->io_map);
176     struct v3_io_hook * tmp = NULL;
177     
178     if (io_map->update_map == NULL) {
179         PrintError("Trying to refresh an io map with no backend\n");
180         return;
181     }
182
183     v3_rb_for_each_entry(tmp, &(io_map->map), tree_node) {
184         io_map->update_map(vm, tmp->port, 
185                            ((tmp->read == NULL) ? 0 : 1), 
186                            ((tmp->write == NULL) ? 0 : 1));
187     }
188
189 }
190
191
192
193 void v3_print_io_map(struct v3_vm_info * vm) {
194     struct v3_io_map * io_map = &(vm->io_map);
195     struct v3_io_hook * tmp_hook = NULL;
196
197     V3_Print("VMM IO Map\n");
198
199     v3_rb_for_each_entry(tmp_hook, &(io_map->map), tree_node) {
200         V3_Print("IO Port: %hu (Read=%p) (Write=%p)\n", 
201                  tmp_hook->port, 
202                  (void *)(tmp_hook->read), (void *)(tmp_hook->write));
203     }
204 }
205
206
207
208 /*
209  * Write a byte to an I/O port.
210  */
211 void v3_outb(uint16_t port, uint8_t value) {
212     __asm__ __volatile__ (
213         "outb %b0, %w1"
214         :
215         : "a" (value), "Nd" (port)
216     );
217 }
218
219 /*
220  * Read a byte from an I/O port.
221  */
222 uint8_t v3_inb(uint16_t port) {
223     uint8_t value;
224
225     __asm__ __volatile__ (
226         "inb %w1, %b0"
227         : "=a" (value)
228         : "Nd" (port)
229     );
230
231     return value;
232 }
233
234 /*
235  * Write a word to an I/O port.
236  */
237 void v3_outw(uint16_t port, uint16_t value) {
238     __asm__ __volatile__ (
239         "outw %w0, %w1"
240         :
241         : "a" (value), "Nd" (port)
242     );
243 }
244
245 /*
246  * Read a word from an I/O port.
247  */
248 uint16_t v3_inw(uint16_t port) {
249     uint16_t value;
250
251     __asm__ __volatile__ (
252         "inw %w1, %w0"
253         : "=a" (value)
254         : "Nd" (port)
255     );
256
257     return value;
258 }
259
260 /*
261  * Write a double word to an I/O port.
262  */
263 void v3_outdw(uint16_t port, uint_t value) {
264     __asm__ __volatile__ (
265         "outl %0, %1"
266         :
267         : "a" (value), "Nd" (port)
268     );
269 }
270
271 /*
272  * Read a double word from an I/O port.
273  */
274 uint_t v3_indw(uint16_t port) {
275     uint_t value;
276
277     __asm__ __volatile__ (
278         "inl %1, %0"
279         : "=a" (value)
280         : "Nd" (port)
281     );
282
283     return value;
284 }
285
286
287
288
289 /* FIX ME */
290 static int default_write(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data) {
291     if (length == 1) {
292         v3_outb(port, *(uint8_t *)src);
293     } else if (length == 2) {
294         v3_outw(port, *(uint16_t *)src);
295     } else if (length == 4) {
296         v3_outdw(port, *(uint32_t *)src);
297     } else {
298         return -1;
299     }
300     
301     return length;
302 }
303
304 static int default_read(struct guest_info * core, uint16_t port, void * dst, uint_t length, void * priv_data) {
305     if (length == 1) {
306         *(uint8_t *)dst = v3_inb(port);
307     } else if (length == 2) {
308         *(uint16_t *)dst = v3_inw(port);
309     } else if (length == 4) {
310         *(uint32_t *)dst = v3_indw(port);
311     } else {
312         return -1;
313     }
314
315     return length;
316 }