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.


Update to the device framework.
[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 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 num_devices = (__stop__v3_devices - __start__v3_devices) / sizeof(struct v3_device_info);
52     int i = 0;
53
54
55     PrintDebug("%d Virtual devices registered with Palacios\n", num_devices);
56     PrintDebug("Start addres=%p, Stop address=%p\n", __start__v3_devices, __stop__v3_devices);
57
58     master_dev_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
59
60
61
62     while (tmp_dev != __stop__v3_devices) {
63         PrintDebug("Device: %s\n", tmp_dev->name);
64
65         if (v3_htable_search(master_dev_table, (addr_t)(tmp_dev->name))) {
66             PrintError("Multiple instance of device (%s)\n", tmp_dev->name);
67             return -1;
68         }
69
70         if (v3_htable_insert(master_dev_table, 
71                              (addr_t)(tmp_dev->name), 
72                              (addr_t)(tmp_dev->init)) == 0) {
73             PrintError("Could not add device %s to master list\n", tmp_dev->name);
74             return -1;
75         }
76
77         tmp_dev = &(__start__v3_devices[++i]);
78     }
79
80
81     return 0;
82 }
83
84
85 int v3_init_dev_mgr(struct guest_info * info) {
86     struct vmm_dev_mgr * mgr = &(info->dev_mgr);
87
88     INIT_LIST_HEAD(&(mgr->dev_list));
89     mgr->num_devs = 0;
90
91     mgr->dev_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
92
93     return 0;
94 }
95
96
97 int v3_dev_mgr_deinit(struct guest_info * info) {
98     struct vm_device * dev;
99     struct vmm_dev_mgr * mgr = &(info->dev_mgr);
100     struct vm_device * tmp;
101
102     list_for_each_entry_safe(dev, tmp, &(mgr->dev_list), dev_link) {
103         v3_detach_device(dev);
104         v3_free_device(dev);
105     }
106
107     return 0;
108 }
109
110
111
112 int v3_create_device(struct guest_info * info, const char * dev_name, void * cfg_data) {
113     int (*dev_init)(struct guest_info * info, void * cfg_data);
114
115     dev_init = (void *)v3_htable_search(master_dev_table, (addr_t)dev_name);
116
117     if (dev_init == NULL) {
118         PrintError("Could not find device %s in master device table\n", dev_name);
119         return -1;
120     }
121
122
123     if (dev_init(info, cfg_data) == -1) {
124         PrintError("Could not initialize Device %s\n", dev_name);
125         return -1;
126     }
127
128     return 0;
129 }
130
131
132 void v3_free_device(struct vm_device * dev) {
133     V3_Free(dev);
134 }
135
136
137
138 struct vm_device * v3_find_dev(struct guest_info * info, const char * dev_name) {
139     struct vmm_dev_mgr * mgr = &(info->dev_mgr);
140
141     return (struct vm_device *)v3_htable_search(mgr->dev_table, (addr_t)dev_name);
142 }
143
144
145 /****************************************************************/
146 /* The remaining functions are called by the devices themselves */
147 /****************************************************************/
148
149 /* IO HOOKS */
150 int v3_dev_hook_io(struct vm_device * dev, uint16_t port,
151                    int (*read)(uint16_t port, void * dst, uint_t length, struct vm_device * dev),
152                    int (*write)(uint16_t port, void * src, uint_t length, struct vm_device * dev)) {
153     return v3_hook_io_port(dev->vm, port, 
154                            (int (*)(ushort_t, void *, uint_t, void *))read, 
155                            (int (*)(ushort_t, void *, uint_t, void *))write, 
156                            (void *)dev);
157 }
158
159
160 int v3_dev_unhook_io(struct vm_device * dev, uint16_t port) {
161     return v3_unhook_io_port(dev->vm, port);
162 }
163
164
165
166 int v3_detach_device(struct vm_device * dev) {
167     struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
168
169     dev->ops->free(dev);
170
171     list_del(&(dev->dev_link));
172     mgr->num_devs--;
173
174     dev->vm = NULL;
175
176     return -1;
177 }
178
179
180 struct vm_device * v3_allocate_device(char * name, 
181                                       struct v3_device_ops * ops, 
182                                       void * private_data) {
183     struct vm_device * dev = NULL;
184
185     dev = (struct vm_device*)V3_Malloc(sizeof(struct vm_device));
186
187     strncpy(dev->name, name, 32);
188     dev->ops = ops;
189     dev->private_data = private_data;
190
191     dev->vm = NULL;
192
193     return dev;
194 }
195
196
197 int v3_attach_device(struct guest_info * vm, struct vm_device * dev ) {
198     struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
199
200     dev->vm = vm;
201
202     list_add(&(dev->dev_link), &(mgr->dev_list));
203     mgr->num_devs++;
204
205
206     v3_htable_insert(mgr->dev_table, (addr_t)(dev->name), (addr_t)dev);
207
208     return 0;
209 }
210
211
212 #ifdef DEBUG_DEV_MGR
213
214 void PrintDebugDevMgr(struct guest_info * info) {
215     struct vmm_dev_mgr * mgr = &(info->dev_mgr);
216     struct vm_device * dev;
217
218     PrintDebug("%d devices registered with manager\n", mgr->num_devs);
219
220     list_for_each_entry(dev, &(mgr->dev_list), dev_link) {
221         PrintDebugDev(dev);
222         PrintDebug("next..\n");
223     }
224
225     return;
226 }
227
228
229 void PrintDebugDev(struct vm_device * dev) {
230     PrintDebug("Device: %s\n", dev->name);
231 }
232
233
234
235
236 #else 
237 void PrintDebugDevMgr(struct guest_info * info) {}
238 void PrintDebugDev(struct vm_device * dev) {}
239 #endif