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.


refactoring to the point of compilation
[palacios.git] / palacios / src / palacios / vmm_dev_mgr.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_dev_mgr.h>
21 #include <palacios/vm_guest.h>
22 #include <palacios/vmm.h>
23 #include <palacios/vmm_decoder.h>
24
25
26 #ifndef CONFIG_DEBUG_DEV_MGR
27 #undef PrintDebug
28 #define PrintDebug(fmt, args...)
29 #endif
30
31
32 static struct hashtable * master_dev_table = NULL;
33
34 static uint_t dev_hash_fn(addr_t key) {
35     char * name = (char *)key;
36     return v3_hash_buffer((uchar_t *)name, strlen(name));
37 }
38
39 static int dev_eq_fn(addr_t key1, addr_t key2) {
40     char * name1 = (char *)key1;
41     char * name2 = (char *)key2;
42     
43     return (strcmp(name1, name2) == 0);
44 }
45
46
47 int v3_init_devices() {
48     extern struct v3_device_info __start__v3_devices[];
49     extern struct v3_device_info __stop__v3_devices[];
50     struct v3_device_info * tmp_dev =  __start__v3_devices;
51     int i = 0;
52
53 #ifdef CONFIG_DEBUG_DEV_MGR
54     {
55         int num_devices = (__stop__v3_devices - __start__v3_devices) / sizeof(struct v3_device_info);
56         PrintDebug("%d Virtual devices registered with Palacios\n", num_devices);
57     }
58 #endif
59
60     PrintDebug("Start addres=%p, Stop address=%p\n", __start__v3_devices, __stop__v3_devices);
61
62     master_dev_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
63
64
65
66     while (tmp_dev != __stop__v3_devices) {
67         PrintDebug("Device: %s\n", tmp_dev->name);
68
69         if (v3_htable_search(master_dev_table, (addr_t)(tmp_dev->name))) {
70             PrintError("Multiple instance of device (%s)\n", tmp_dev->name);
71             return -1;
72         }
73
74         if (v3_htable_insert(master_dev_table, 
75                              (addr_t)(tmp_dev->name), 
76                              (addr_t)(tmp_dev->init)) == 0) {
77             PrintError("Could not add device %s to master list\n", tmp_dev->name);
78             return -1;
79         }
80
81         tmp_dev = &(__start__v3_devices[++i]);
82     }
83
84
85     return 0;
86 }
87
88
89 int v3_init_dev_mgr(struct v3_vm_info * vm) {
90     struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
91
92     INIT_LIST_HEAD(&(mgr->dev_list));
93     mgr->num_devs = 0;
94
95     mgr->dev_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
96
97     INIT_LIST_HEAD(&(mgr->blk_list));
98     INIT_LIST_HEAD(&(mgr->net_list));
99     INIT_LIST_HEAD(&(mgr->console_list));
100
101     mgr->blk_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
102     mgr->net_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
103     mgr->console_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
104     
105     return 0;
106 }
107
108
109 int v3_dev_mgr_deinit(struct v3_vm_info * vm) {
110     struct vm_device * dev;
111     struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
112     struct vm_device * tmp;
113
114     list_for_each_entry_safe(dev, tmp, &(mgr->dev_list), dev_link) {
115         v3_detach_device(dev);
116         v3_free_device(dev);
117     }
118
119
120     /* TODO: Clear hash tables */
121
122     return 0;
123 }
124
125 /*
126 int v3_init_core_dev_mgr(struct v3_vm_info * vm) {
127     struct v3_core_dev_mgr * mgr = &(vm->core_dev_mgr);
128
129     INIT_LIST_HEAD(&(mgr->dev_list));
130     mgr->dev_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
131
132     return 0;
133 }
134
135 int v3_core_dev_mgr_deinit(struct v3_vm_info * vm) {
136     struct vm_device * dev;
137     struct v3_core_dev_mgr * mgr = &(vm->core_dev_mgr);
138     struct vm_device * tmp;
139
140     list_for_each_entry_safe(dev, tmp, &(mgr->dev_list), dev_link) {
141         v3_detach_device(dev);
142         v3_free_device(dev);
143     }
144
145     // TODO: Clear hash tables 
146
147 }
148 */
149
150
151 int v3_create_device(struct v3_vm_info * vm, const char * dev_name, v3_cfg_tree_t * cfg) {
152     int (*dev_init)(struct v3_vm_info * vm, void * cfg_data);
153
154     dev_init = (void *)v3_htable_search(master_dev_table, (addr_t)dev_name);
155
156     if (dev_init == NULL) {
157         PrintError("Could not find device %s in master device table\n", dev_name);
158         return -1;
159     }
160
161
162     if (dev_init(vm, cfg) == -1) {
163         PrintError("Could not initialize Device %s\n", dev_name);
164         return -1;
165     }
166
167     return 0;
168 }
169
170
171 void v3_free_device(struct vm_device * dev) {
172     V3_Free(dev);
173 }
174
175
176
177 struct vm_device * v3_find_dev(struct v3_vm_info * vm, const char * dev_name) {
178     struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
179
180     if (!dev_name) {
181         return NULL;
182     }
183
184     return (struct vm_device *)v3_htable_search(mgr->dev_table, (addr_t)dev_name);
185 }
186
187
188 /****************************************************************/
189 /* The remaining functions are called by the devices themselves */
190 /****************************************************************/
191
192 /* IO HOOKS */
193 int v3_dev_hook_io(struct vm_device * dev, uint16_t port,
194                    int (*read)(struct guest_info * core, uint16_t port, void * dst, uint_t length, struct vm_device * dev),
195                    int (*write)(struct guest_info * core, uint16_t port, void * src, uint_t length, struct vm_device * dev)) {
196     return v3_hook_io_port(dev->vm, port, 
197                            (int (*)(struct guest_info * core, ushort_t, void *, uint_t, void *))read, 
198                            (int (*)(struct guest_info * core, ushort_t, void *, uint_t, void *))write, 
199                            (void *)dev);
200 }
201
202
203 int v3_dev_unhook_io(struct vm_device * dev, uint16_t port) {
204     return v3_unhook_io_port(dev->vm, port);
205 }
206
207
208
209 int v3_detach_device(struct vm_device * dev) {
210     struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
211
212     dev->ops->free(dev);
213
214     list_del(&(dev->dev_link));
215     mgr->num_devs--;
216
217     dev->vm = NULL;
218
219     return -1;
220 }
221
222
223 struct vm_device * v3_allocate_device(char * name, 
224                                       struct v3_device_ops * ops, 
225                                       void * private_data) {
226     struct vm_device * dev = NULL;
227
228     dev = (struct vm_device*)V3_Malloc(sizeof(struct vm_device));
229
230     strncpy(dev->name, name, 32);
231     dev->ops = ops;
232     dev->private_data = private_data;
233
234     dev->vm = NULL;
235
236     return dev;
237 }
238
239
240 int v3_attach_device(struct v3_vm_info * vm, struct vm_device * dev ) {
241     struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
242
243     dev->vm = vm;
244
245     list_add(&(dev->dev_link), &(mgr->dev_list));
246     mgr->num_devs++;
247
248
249     v3_htable_insert(mgr->dev_table, (addr_t)(dev->name), (addr_t)dev);
250
251     return 0;
252 }
253
254
255
256 void v3_print_dev_mgr(struct v3_vm_info * vm) {
257     struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
258     struct vm_device * dev;
259
260     V3_Print("%d devices registered with manager\n", mgr->num_devs);
261
262     list_for_each_entry(dev, &(mgr->dev_list), dev_link) {
263         V3_Print("Device: %s\n", dev->name);
264     }
265
266     return;
267 }
268
269
270
271
272 struct blk_frontend {
273     int (*connect)(struct v3_vm_info * vm, 
274                     void * frontend_data, 
275                     struct v3_dev_blk_ops * ops, 
276                     v3_cfg_tree_t * cfg, 
277                     void * priv_data);
278         
279
280     struct list_head blk_node;
281
282     void * priv_data;
283 };
284
285
286
287 int v3_dev_add_blk_frontend(struct v3_vm_info * vm, 
288                             char * name, 
289                             int (*connect)(struct v3_vm_info * vm, 
290                                             void * frontend_data, 
291                                             struct v3_dev_blk_ops * ops, 
292                                             v3_cfg_tree_t * cfg, 
293                                             void * priv_data), 
294                             void * priv_data) {
295
296     struct blk_frontend * frontend = NULL;
297
298     frontend = (struct blk_frontend *)V3_Malloc(sizeof(struct blk_frontend));
299     memset(frontend, 0, sizeof(struct blk_frontend));
300     
301     frontend->connect = connect;
302     frontend->priv_data = priv_data;
303         
304     list_add(&(frontend->blk_node), &(vm->dev_mgr.blk_list));
305     v3_htable_insert(vm->dev_mgr.blk_table, (addr_t)(name), (addr_t)frontend);
306
307     return 0;
308 }
309
310 int v3_dev_connect_blk(struct v3_vm_info * vm, 
311                        char * frontend_name, 
312                        struct v3_dev_blk_ops * ops, 
313                        v3_cfg_tree_t * cfg, 
314                        void * private_data) {
315
316     struct blk_frontend * frontend = NULL;
317
318     frontend = (struct blk_frontend *)v3_htable_search(vm->dev_mgr.blk_table,
319                                                        (addr_t)frontend_name);
320     
321     if (frontend == NULL) {
322         PrintError("Could not find frontend blk device %s\n", frontend_name);
323         return 0;
324     }
325
326     if (frontend->connect(vm, frontend->priv_data, ops, cfg, private_data) == -1) {
327         PrintError("Error connecting to block frontend %s\n", frontend_name);
328         return -1;
329     }
330
331     return 0;
332 }
333
334
335
336 struct net_frontend {
337     int (*connect)(struct v3_vm_info * vm, 
338                     void * frontend_data, 
339                     struct v3_dev_net_ops * ops, 
340                     v3_cfg_tree_t * cfg, 
341                     void * priv_data);
342     
343
344     struct list_head net_node;
345
346     void * priv_data;
347 };
348
349
350 int v3_dev_add_net_frontend(struct v3_vm_info * vm, 
351                             char * name, 
352                             int (*connect)(struct v3_vm_info * vm, 
353                                             void * frontend_data, 
354                                             struct v3_dev_net_ops * ops, 
355                                             v3_cfg_tree_t * cfg, 
356                                             void * private_data), 
357                             void * priv_data)
358 {
359     struct net_frontend * frontend = NULL;
360
361     frontend = (struct net_frontend *)V3_Malloc(sizeof(struct net_frontend));
362     memset(frontend, 0, sizeof(struct net_frontend));
363     
364     frontend->connect = connect;
365     frontend->priv_data = priv_data;
366         
367     list_add(&(frontend->net_node), &(vm->dev_mgr.net_list));
368     v3_htable_insert(vm->dev_mgr.net_table, (addr_t)(name), (addr_t)frontend);
369
370     return 0;
371 }
372
373
374 int v3_dev_connect_net(struct v3_vm_info * vm, 
375                        char * frontend_name, 
376                        struct v3_dev_net_ops * ops, 
377                        v3_cfg_tree_t * cfg, 
378                        void * private_data)
379 {
380     struct net_frontend * frontend = NULL;
381
382     frontend = (struct net_frontend *)v3_htable_search(vm->dev_mgr.net_table,
383                                                        (addr_t)frontend_name);
384     
385     if (frontend == NULL) {
386         PrintError("Could not find frontend net device %s\n", frontend_name);
387         return 0;
388     }
389
390     if (frontend->connect(vm, frontend->priv_data, ops, cfg, private_data) == -1) {
391         PrintError("Error connecting to net frontend %s\n", frontend_name);
392         return -1;
393     }
394
395     return 0;
396 }
397