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.


c21295846b26801e536a4321430a1d7dd84d6a79
[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 guest_info * info) {
90     struct vmm_dev_mgr * mgr = &(info->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     return 0;
98 }
99
100
101 int v3_dev_mgr_deinit(struct guest_info * info) {
102     struct vm_device * dev;
103     struct vmm_dev_mgr * mgr = &(info->dev_mgr);
104     struct vm_device * tmp;
105
106     list_for_each_entry_safe(dev, tmp, &(mgr->dev_list), dev_link) {
107         v3_detach_device(dev);
108         v3_free_device(dev);
109     }
110
111     return 0;
112 }
113
114
115
116 int v3_create_device(struct guest_info * info, const char * dev_name, void * cfg_data) {
117     int (*dev_init)(struct guest_info * info, void * cfg_data);
118
119     dev_init = (void *)v3_htable_search(master_dev_table, (addr_t)dev_name);
120
121     if (dev_init == NULL) {
122         PrintError("Could not find device %s in master device table\n", dev_name);
123         return -1;
124     }
125
126
127     if (dev_init(info, cfg_data) == -1) {
128         PrintError("Could not initialize Device %s\n", dev_name);
129         return -1;
130     }
131
132     return 0;
133 }
134
135
136 void v3_free_device(struct vm_device * dev) {
137     V3_Free(dev);
138 }
139
140
141
142 struct vm_device * v3_find_dev(struct guest_info * info, const char * dev_name) {
143     struct vmm_dev_mgr * mgr = &(info->dev_mgr);
144
145     return (struct vm_device *)v3_htable_search(mgr->dev_table, (addr_t)dev_name);
146 }
147
148
149 /****************************************************************/
150 /* The remaining functions are called by the devices themselves */
151 /****************************************************************/
152
153 /* IO HOOKS */
154 int v3_dev_hook_io(struct vm_device * dev, uint16_t port,
155                    int (*read)(uint16_t port, void * dst, uint_t length, struct vm_device * dev),
156                    int (*write)(uint16_t port, void * src, uint_t length, struct vm_device * dev)) {
157     return v3_hook_io_port(dev->vm, port, 
158                            (int (*)(ushort_t, void *, uint_t, void *))read, 
159                            (int (*)(ushort_t, void *, uint_t, void *))write, 
160                            (void *)dev);
161 }
162
163
164 int v3_dev_unhook_io(struct vm_device * dev, uint16_t port) {
165     return v3_unhook_io_port(dev->vm, port);
166 }
167
168
169
170 int v3_detach_device(struct vm_device * dev) {
171     struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
172
173     dev->ops->free(dev);
174
175     list_del(&(dev->dev_link));
176     mgr->num_devs--;
177
178     dev->vm = NULL;
179
180     return -1;
181 }
182
183
184 struct vm_device * v3_allocate_device(char * name, 
185                                       struct v3_device_ops * ops, 
186                                       void * private_data) {
187     struct vm_device * dev = NULL;
188
189     dev = (struct vm_device*)V3_Malloc(sizeof(struct vm_device));
190
191     strncpy(dev->name, name, 32);
192     dev->ops = ops;
193     dev->private_data = private_data;
194
195     dev->vm = NULL;
196
197     return dev;
198 }
199
200
201 int v3_attach_device(struct guest_info * vm, struct vm_device * dev ) {
202     struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
203
204     dev->vm = vm;
205
206     list_add(&(dev->dev_link), &(mgr->dev_list));
207     mgr->num_devs++;
208
209
210     v3_htable_insert(mgr->dev_table, (addr_t)(dev->name), (addr_t)dev);
211
212     return 0;
213 }
214
215
216 #ifdef CONFIG_DEBUG_DEV_MGR
217
218 void PrintDebugDevMgr(struct guest_info * info) {
219     struct vmm_dev_mgr * mgr = &(info->dev_mgr);
220     struct vm_device * dev;
221
222     PrintDebug("%d devices registered with manager\n", mgr->num_devs);
223
224     list_for_each_entry(dev, &(mgr->dev_list), dev_link) {
225         PrintDebugDev(dev);
226         PrintDebug("next..\n");
227     }
228
229     return;
230 }
231
232
233 void PrintDebugDev(struct vm_device * dev) {
234     PrintDebug("Device: %s\n", dev->name);
235 }
236
237
238
239
240 #else 
241 void PrintDebugDevMgr(struct guest_info * info) {}
242 void PrintDebugDev(struct vm_device * dev) {}
243 #endif