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.


updated IO and MSRs to allow hooking/unhooking dynamic at runtime
[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     V3_Free(io_hook);
133     return -1;
134   }
135
136
137   if (info->io_map.update_map(info, port, 
138                               ((read == NULL) ? 0 : 1), 
139                               ((write == NULL) ? 0 : 1)) == -1) {
140     V3_Free(io_hook);
141     return -1;
142   }
143
144
145   return 0;
146 }
147
148 int v3_unhook_io_port(struct guest_info * info, uint_t port) {
149   struct v3_io_hook * hook = v3_get_io_hook(info, port);
150
151   if (hook == NULL) {
152     return -1;
153   }
154
155   v3_rb_erase(&(hook->tree_node), &(info->io_map.map));
156
157   // set the arch map to default (this should be 1, 1)
158   info->io_map.update_map(info, port, 0, 0);
159
160   V3_Free(hook);
161
162   return 0;
163 }
164
165
166
167
168
169
170 void v3_print_io_map(struct guest_info * info) {
171   struct v3_io_hook * tmp_hook = NULL;
172   struct rb_node * node = v3_rb_first(&(info->io_map.map));
173
174   PrintDebug("VMM IO Map\n");
175
176   do {
177     tmp_hook = rb_entry(node, struct v3_io_hook, tree_node);
178
179     PrintDebug("IO Port: %hu (Read=%p) (Write=%p)\n", 
180                tmp_hook->port, 
181                (void *)(tmp_hook->read), (void *)(tmp_hook->write));
182   } while ((node = v3_rb_next(node)));
183 }
184
185
186
187 /*
188  * Write a byte to an I/O port.
189  */
190 void v3_outb(uint16_t port, uint8_t value) {
191     __asm__ __volatile__ (
192         "outb %b0, %w1"
193         :
194         : "a" (value), "Nd" (port)
195     );
196 }
197
198 /*
199  * Read a byte from an I/O port.
200  */
201 uint8_t v3_inb(uint16_t port) {
202     uint8_t value;
203
204     __asm__ __volatile__ (
205         "inb %w1, %b0"
206         : "=a" (value)
207         : "Nd" (port)
208     );
209
210     return value;
211 }
212
213 /*
214  * Write a word to an I/O port.
215  */
216 void v3_outw(uint16_t port, uint16_t value) {
217     __asm__ __volatile__ (
218         "outw %w0, %w1"
219         :
220         : "a" (value), "Nd" (port)
221     );
222 }
223
224 /*
225  * Read a word from an I/O port.
226  */
227 uint16_t v3_inw(uint16_t port) {
228     uint16_t value;
229
230     __asm__ __volatile__ (
231         "inw %w1, %w0"
232         : "=a" (value)
233         : "Nd" (port)
234     );
235
236     return value;
237 }
238
239 /*
240  * Write a double word to an I/O port.
241  */
242 void v3_outdw(uint16_t port, uint_t value) {
243     __asm__ __volatile__ (
244         "outl %0, %1"
245         :
246         : "a" (value), "Nd" (port)
247     );
248 }
249
250 /*
251  * Read a double word from an I/O port.
252  */
253 uint_t v3_indw(uint16_t port) {
254     uint_t value;
255
256     __asm__ __volatile__ (
257         "inl %1, %0"
258         : "=a" (value)
259         : "Nd" (port)
260     );
261
262     return value;
263 }
264
265
266
267
268 /* FIX ME */
269 static int default_write(uint16_t port, void *src, uint_t length, void * priv_data) {
270   /*
271     
272   if (length == 1) {
273   __asm__ __volatile__ (
274   "outb %b0, %w1"
275   :
276   : "a" (*dst), "Nd" (port)
277   );
278   } else if (length == 2) {
279   __asm__ __volatile__ (
280   "outw %b0, %w1"
281   :
282   : "a" (*dst), "Nd" (port)
283   );
284   } else if (length == 4) {
285   __asm__ __volatile__ (
286   "outw %b0, %w1"
287   :
288   : "a" (*dst), "Nd" (port)
289   );
290   }
291   */
292   return 0;
293 }
294
295 static int default_read(uint16_t port, void * dst, uint_t length, void * priv_data) {
296
297   /*    
298         uint8_t value;
299
300     __asm__ __volatile__ (
301         "inb %w1, %b0"
302         : "=a" (value)
303         : "Nd" (port)
304     );
305
306     return value;
307   */
308
309   return 0;
310 }