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.


changed shadow memory map to use Red Black Tree
[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(ushort_t port, void *src, uint_t length, void * priv_data);
34 static int default_read(ushort_t port, void * dst, uint_t length, void * priv_data);
35
36
37 void v3_init_io_map(struct guest_info * info) {
38   info->io_map.rb_node = NULL;
39 }
40
41
42
43
44
45 static inline struct v3_io_hook * __insert_io_hook(struct guest_info * info, struct v3_io_hook * hook) {
46   struct rb_node ** p = &(info->io_map.rb_node);
47   struct rb_node * parent = NULL;
48   struct v3_io_hook * tmp_hook = NULL;
49
50   while (*p) {
51     parent = *p;
52     tmp_hook = rb_entry(parent, struct v3_io_hook, tree_node);
53
54     if (hook->port < tmp_hook->port) {
55       p = &(*p)->rb_left;
56     } else if (hook->port > tmp_hook->port) {
57       p = &(*p)->rb_right;
58     } else {
59       return tmp_hook;
60     }
61   }
62   rb_link_node(&(hook->tree_node), parent, p);
63
64   return NULL;
65 }
66
67
68 static inline struct v3_io_hook * insert_io_hook(struct guest_info * info, struct v3_io_hook * hook) {
69   struct v3_io_hook * ret;
70
71   if ((ret = __insert_io_hook(info, hook))) {
72     return ret;
73   }
74
75   v3_rb_insert_color(&(hook->tree_node), &(info->io_map));
76
77   return NULL;
78 }
79
80
81 struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint_t port) {
82   struct rb_node * n = info->io_map.rb_node;
83   struct v3_io_hook * hook = NULL;
84
85   while (n) {
86     hook = rb_entry(n, struct v3_io_hook, tree_node);
87     
88     if (port < hook->port) {
89       n = n->rb_left;
90     } else if (port > hook->port) {
91       n = n->rb_right;
92     } else {
93       return hook;
94     }
95   }
96
97   return NULL;
98 }
99
100
101
102
103
104
105 int v3_hook_io_port(struct guest_info * info, uint_t port, 
106                     int (*read)(ushort_t port, void * dst, uint_t length, void * priv_data),
107                     int (*write)(ushort_t port, void * src, uint_t length, void * priv_data), 
108                     void * priv_data) {
109   struct v3_io_hook * io_hook = (struct v3_io_hook *)V3_Malloc(sizeof(struct v3_io_hook));
110
111   io_hook->port = port;
112
113   if (!read) {
114     io_hook->read = &default_read;
115   } else {
116     io_hook->read = read;
117   }
118
119   if (!write) {
120     io_hook->write = &default_write;
121   } else {
122     io_hook->write = write;
123   }
124
125
126   io_hook->priv_data = priv_data;
127
128   if (insert_io_hook(info, io_hook)) {
129     V3_Free(io_hook);
130     return -1;
131   }
132
133   return 0;
134 }
135
136 int v3_unhook_io_port(struct guest_info * info, uint_t port) {
137   struct v3_io_hook * hook = v3_get_io_hook(info, port);
138
139   if (hook == NULL) {
140     return -1;
141   }
142
143   v3_rb_erase(&(hook->tree_node), &(info->io_map));
144
145   V3_Free(hook);
146
147   return 0;
148 }
149
150
151
152
153
154
155 void v3_print_io_map(struct guest_info * info) {
156   struct v3_io_hook * tmp_hook = NULL;
157   struct rb_node * node = v3_rb_first(&(info->io_map));
158
159   PrintDebug("VMM IO Map (Entries=%d)\n", io_map->num_ports);
160
161   do {
162     tmp_hook = rb_entry(node, struct v3_io_hook, tree_node);
163
164     PrintDebug("IO Port: %hu (Read=%p) (Write=%p)\n", 
165                tmp_hook->port, 
166                (void *)(tmp_hook->read), (void *)(tmp_hook->write));
167   } while ((node = v3_rb_next(node)));
168 }
169
170
171
172 /*
173  * Write a byte to an I/O port.
174  */
175 void v3_outb(ushort_t port, uchar_t value) {
176     __asm__ __volatile__ (
177         "outb %b0, %w1"
178         :
179         : "a" (value), "Nd" (port)
180     );
181 }
182
183 /*
184  * Read a byte from an I/O port.
185  */
186 uchar_t v3_inb(ushort_t port) {
187     uchar_t value;
188
189     __asm__ __volatile__ (
190         "inb %w1, %b0"
191         : "=a" (value)
192         : "Nd" (port)
193     );
194
195     return value;
196 }
197
198 /*
199  * Write a word to an I/O port.
200  */
201 void v3_outw(ushort_t port, ushort_t value) {
202     __asm__ __volatile__ (
203         "outw %w0, %w1"
204         :
205         : "a" (value), "Nd" (port)
206     );
207 }
208
209 /*
210  * Read a word from an I/O port.
211  */
212 ushort_t v3_inw(ushort_t port) {
213     ushort_t value;
214
215     __asm__ __volatile__ (
216         "inw %w1, %w0"
217         : "=a" (value)
218         : "Nd" (port)
219     );
220
221     return value;
222 }
223
224 /*
225  * Write a double word to an I/O port.
226  */
227 void v3_outdw(ushort_t port, uint_t value) {
228     __asm__ __volatile__ (
229         "outl %0, %1"
230         :
231         : "a" (value), "Nd" (port)
232     );
233 }
234
235 /*
236  * Read a double word from an I/O port.
237  */
238 uint_t v3_indw(ushort_t port) {
239     uint_t value;
240
241     __asm__ __volatile__ (
242         "inl %1, %0"
243         : "=a" (value)
244         : "Nd" (port)
245     );
246
247     return value;
248 }
249
250
251
252
253 /* FIX ME */
254 static int default_write(ushort_t port, void *src, uint_t length, void * priv_data) {
255   /*
256     
257   if (length == 1) {
258   __asm__ __volatile__ (
259   "outb %b0, %w1"
260   :
261   : "a" (*dst), "Nd" (port)
262   );
263   } else if (length == 2) {
264   __asm__ __volatile__ (
265   "outw %b0, %w1"
266   :
267   : "a" (*dst), "Nd" (port)
268   );
269   } else if (length == 4) {
270   __asm__ __volatile__ (
271   "outw %b0, %w1"
272   :
273   : "a" (*dst), "Nd" (port)
274   );
275   }
276   */
277   return 0;
278 }
279
280 static int default_read(ushort_t port, void * dst, uint_t length, void * priv_data) {
281
282   /*    
283         uchar_t value;
284
285     __asm__ __volatile__ (
286         "inb %w1, %b0"
287         : "=a" (value)
288         : "Nd" (port)
289     );
290
291     return value;
292   */
293
294   return 0;
295 }