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.


793a0f3bae2348d78beb10b1b395826a365ffd43
[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
24
25
26
27 #ifndef DEBUG_IO
28 #undef PrintDebug
29 #define PrintDebug(fmt, args...)
30 #endif
31
32
33 static int default_write(uint16_t port, void *src, uint_t length, void * priv_data);
34 static int default_read(uint16_t port, void * dst, uint_t length, void * priv_data);
35
36
37 void v3_init_io_map(struct guest_info * info) {
38
39   info->io_map.map.rb_node = NULL;
40   info->io_map.arch_data = NULL;
41   info->io_map.update_map = NULL;
42
43 }
44
45
46
47
48 static inline struct v3_io_hook * __insert_io_hook(struct guest_info * info, struct v3_io_hook * hook) {
49   struct rb_node ** p = &(info->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 guest_info * info, struct v3_io_hook * hook) {
72   struct v3_io_hook * ret;
73
74   if ((ret = __insert_io_hook(info, hook))) {
75     return ret;
76   }
77
78   v3_rb_insert_color(&(hook->tree_node), &(info->io_map.map));
79
80   return NULL;
81 }
82
83
84 struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint_t port) {
85   struct rb_node * n = info->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
108 int v3_hook_io_port(struct guest_info * info, uint_t port, 
109                     int (*read)(uint16_t port, void * dst, uint_t length, void * priv_data),
110                     int (*write)(uint16_t port, void * src, uint_t length, void * priv_data), 
111                     void * priv_data) {
112   struct v3_io_hook * io_hook = (struct v3_io_hook *)V3_Malloc(sizeof(struct v3_io_hook));
113
114   io_hook->port = port;
115
116   if (!read) {
117     io_hook->read = &default_read;
118   } else {
119     io_hook->read = read;
120   }
121
122   if (!write) {
123     io_hook->write = &default_write;
124   } else {
125     io_hook->write = write;
126   }
127
128
129   io_hook->priv_data = priv_data;
130
131   if (insert_io_hook(info, io_hook)) {
132       PrintError("Could not insert IO hook for port %d\n", port);
133       V3_Free(io_hook);
134       return -1;
135   }
136
137
138   if (info->io_map.update_map(info, port, 
139                               ((read == NULL) ? 0 : 1), 
140                               ((write == NULL) ? 0 : 1)) == -1) {
141       PrintError("Could not update IO map for port %d\n", port);
142       V3_Free(io_hook);
143       return -1;
144   }
145
146
147   return 0;
148 }
149
150 int v3_unhook_io_port(struct guest_info * info, uint_t port) {
151   struct v3_io_hook * hook = v3_get_io_hook(info, port);
152
153   if (hook == NULL) {
154     return -1;
155   }
156
157   v3_rb_erase(&(hook->tree_node), &(info->io_map.map));
158
159   // set the arch map to default (this should be 1, 1)
160   info->io_map.update_map(info, port, 0, 0);
161
162   V3_Free(hook);
163
164   return 0;
165 }
166
167
168
169
170
171
172 void v3_print_io_map(struct guest_info * info) {
173   struct v3_io_hook * tmp_hook = NULL;
174   struct rb_node * node = v3_rb_first(&(info->io_map.map));
175
176   PrintDebug("VMM IO Map\n");
177
178   do {
179     tmp_hook = rb_entry(node, struct v3_io_hook, tree_node);
180
181     PrintDebug("IO Port: %hu (Read=%p) (Write=%p)\n", 
182                tmp_hook->port, 
183                (void *)(tmp_hook->read), (void *)(tmp_hook->write));
184   } while ((node = v3_rb_next(node)));
185 }
186
187
188
189 /*
190  * Write a byte to an I/O port.
191  */
192 void v3_outb(uint16_t port, uint8_t value) {
193     __asm__ __volatile__ (
194         "outb %b0, %w1"
195         :
196         : "a" (value), "Nd" (port)
197     );
198 }
199
200 /*
201  * Read a byte from an I/O port.
202  */
203 uint8_t v3_inb(uint16_t port) {
204     uint8_t value;
205
206     __asm__ __volatile__ (
207         "inb %w1, %b0"
208         : "=a" (value)
209         : "Nd" (port)
210     );
211
212     return value;
213 }
214
215 /*
216  * Write a word to an I/O port.
217  */
218 void v3_outw(uint16_t port, uint16_t value) {
219     __asm__ __volatile__ (
220         "outw %w0, %w1"
221         :
222         : "a" (value), "Nd" (port)
223     );
224 }
225
226 /*
227  * Read a word from an I/O port.
228  */
229 uint16_t v3_inw(uint16_t port) {
230     uint16_t value;
231
232     __asm__ __volatile__ (
233         "inw %w1, %w0"
234         : "=a" (value)
235         : "Nd" (port)
236     );
237
238     return value;
239 }
240
241 /*
242  * Write a double word to an I/O port.
243  */
244 void v3_outdw(uint16_t port, uint_t value) {
245     __asm__ __volatile__ (
246         "outl %0, %1"
247         :
248         : "a" (value), "Nd" (port)
249     );
250 }
251
252 /*
253  * Read a double word from an I/O port.
254  */
255 uint_t v3_indw(uint16_t port) {
256     uint_t value;
257
258     __asm__ __volatile__ (
259         "inl %1, %0"
260         : "=a" (value)
261         : "Nd" (port)
262     );
263
264     return value;
265 }
266
267
268
269
270 /* FIX ME */
271 static int default_write(uint16_t port, void *src, uint_t length, void * priv_data) {
272   /*
273     
274   if (length == 1) {
275   __asm__ __volatile__ (
276   "outb %b0, %w1"
277   :
278   : "a" (*dst), "Nd" (port)
279   );
280   } else if (length == 2) {
281   __asm__ __volatile__ (
282   "outw %b0, %w1"
283   :
284   : "a" (*dst), "Nd" (port)
285   );
286   } else if (length == 4) {
287   __asm__ __volatile__ (
288   "outw %b0, %w1"
289   :
290   : "a" (*dst), "Nd" (port)
291   );
292   }
293   */
294   return 0;
295 }
296
297 static int default_read(uint16_t port, void * dst, uint_t length, void * priv_data) {
298
299   /*    
300         uint8_t value;
301
302     __asm__ __volatile__ (
303         "inb %w1, %b0"
304         : "=a" (value)
305         : "Nd" (port)
306     );
307
308     return value;
309   */
310
311   return 0;
312 }