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 the io_map implementation to use red-black trees instead of linked list
[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   return 0;
146 }
147
148
149
150
151
152
153 void v3_print_io_map(struct guest_info * info) {
154   struct v3_io_hook * tmp_hook = NULL;
155   struct rb_node * node = v3_rb_first(&(info->io_map));
156
157   PrintDebug("VMM IO Map (Entries=%d)\n", io_map->num_ports);
158
159   do {
160     tmp_hook = rb_entry(node, struct v3_io_hook, tree_node);
161
162     PrintDebug("IO Port: %hu (Read=%p) (Write=%p)\n", 
163                tmp_hook->port, 
164                (void *)(tmp_hook->read), (void *)(tmp_hook->write));
165   } while ((node = v3_rb_next(node)));
166 }
167
168
169
170 /*
171  * Write a byte to an I/O port.
172  */
173 void v3_outb(ushort_t port, uchar_t value) {
174     __asm__ __volatile__ (
175         "outb %b0, %w1"
176         :
177         : "a" (value), "Nd" (port)
178     );
179 }
180
181 /*
182  * Read a byte from an I/O port.
183  */
184 uchar_t v3_inb(ushort_t port) {
185     uchar_t value;
186
187     __asm__ __volatile__ (
188         "inb %w1, %b0"
189         : "=a" (value)
190         : "Nd" (port)
191     );
192
193     return value;
194 }
195
196 /*
197  * Write a word to an I/O port.
198  */
199 void v3_outw(ushort_t port, ushort_t value) {
200     __asm__ __volatile__ (
201         "outw %w0, %w1"
202         :
203         : "a" (value), "Nd" (port)
204     );
205 }
206
207 /*
208  * Read a word from an I/O port.
209  */
210 ushort_t v3_inw(ushort_t port) {
211     ushort_t value;
212
213     __asm__ __volatile__ (
214         "inw %w1, %w0"
215         : "=a" (value)
216         : "Nd" (port)
217     );
218
219     return value;
220 }
221
222 /*
223  * Write a double word to an I/O port.
224  */
225 void v3_outdw(ushort_t port, uint_t value) {
226     __asm__ __volatile__ (
227         "outl %0, %1"
228         :
229         : "a" (value), "Nd" (port)
230     );
231 }
232
233 /*
234  * Read a double word from an I/O port.
235  */
236 uint_t v3_indw(ushort_t port) {
237     uint_t value;
238
239     __asm__ __volatile__ (
240         "inl %1, %0"
241         : "=a" (value)
242         : "Nd" (port)
243     );
244
245     return value;
246 }
247
248
249
250
251 /* FIX ME */
252 static int default_write(ushort_t port, void *src, uint_t length, void * priv_data) {
253   /*
254     
255   if (length == 1) {
256   __asm__ __volatile__ (
257   "outb %b0, %w1"
258   :
259   : "a" (*dst), "Nd" (port)
260   );
261   } else if (length == 2) {
262   __asm__ __volatile__ (
263   "outw %b0, %w1"
264   :
265   : "a" (*dst), "Nd" (port)
266   );
267   } else if (length == 4) {
268   __asm__ __volatile__ (
269   "outw %b0, %w1"
270   :
271   : "a" (*dst), "Nd" (port)
272   );
273   }
274   */
275   return 0;
276 }
277
278 static int default_read(ushort_t port, void * dst, uint_t length, void * priv_data) {
279
280   /*    
281         uchar_t value;
282
283     __asm__ __volatile__ (
284         "inb %w1, %b0"
285         : "=a" (value)
286         : "Nd" (port)
287     );
288
289     return value;
290   */
291
292   return 0;
293 }