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.


cleaned up dev manager implementation
[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/vm_dev.h>
21 #include <palacios/vmm_dev_mgr.h>
22 #include <palacios/vm_guest.h>
23 #include <palacios/vmm.h>
24 #include <palacios/vmm_decoder.h>
25
26
27 #ifndef DEBUG_DEV_MGR
28 #undef PrintDebug
29 #define PrintDebug(fmt, args...)
30 #endif
31
32
33
34 int v3_init_dev_mgr(struct guest_info * info) {
35   struct vmm_dev_mgr * mgr = &(info->dev_mgr);
36   INIT_LIST_HEAD(&(mgr->dev_list));
37   mgr->num_devs = 0;
38
39   INIT_LIST_HEAD(&(mgr->io_hooks));
40   mgr->num_io_hooks = 0;
41
42   INIT_LIST_HEAD(&(mgr->mem_hooks));
43   mgr->num_mem_hooks = 0;
44
45   INIT_LIST_HEAD(&(mgr->msr_hooks));
46   mgr->num_msr_hook = 0;
47
48   return 0;
49 }
50
51
52 int v3_dev_mgr_deinit(struct guest_info * info) {
53   struct vm_device * dev;
54   struct vmm_dev_mgr * mgr = &(info->dev_mgr);
55   struct vm_device * tmp;
56
57   list_for_each_entry_safe(dev, tmp, &(mgr->dev_list), dev_link) {
58     v3_unattach_device(dev);
59     v3_free_device(dev);
60   }
61
62   return 0;
63 }
64
65
66
67 int v3_attach_device(struct guest_info * vm, struct vm_device * dev) {
68   struct vmm_dev_mgr *mgr= &(vm->dev_mgr);
69   
70   dev->vm = vm;
71
72   list_add(&(dev->dev_link), &(mgr->dev_list));
73   mgr->num_devs++;
74
75   dev->ops->init(dev);
76
77   return 0;
78 }
79
80 int v3_unattach_device(struct vm_device * dev) {
81   struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
82
83   dev->ops->deinit(dev);
84
85   list_del(&(dev->dev_link));
86   mgr->num_devs--;
87
88   dev->vm = NULL;
89
90   return 0;
91 }
92
93
94
95
96
97 /* IO HOOKS */
98 static struct dev_io_hook * dev_mgr_find_io_hook(struct vmm_dev_mgr * mgr, ushort_t port) {
99   struct dev_io_hook * tmp = NULL;
100
101   list_for_each_entry(tmp, &(mgr->io_hooks), mgr_list) {
102     if (tmp->port == port) {
103       return tmp;
104     }
105   }
106   return NULL;
107 }
108
109
110
111
112
113 int v3_dev_hook_io(struct vm_device   *dev,
114                    ushort_t            port,
115                    int (*read)(ushort_t port, void * dst, uint_t length, struct vm_device * dev),
116                    int (*write)(ushort_t port, void * src, uint_t length, struct vm_device * dev)) {
117   
118   struct dev_io_hook *hook = (struct dev_io_hook *)V3_Malloc(sizeof(struct dev_io_hook));
119   struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
120
121   if (!hook) { 
122     return -1;
123   }
124
125
126   if (v3_hook_io_port(dev->vm, port, 
127                       (int (*)(ushort_t, void *, uint_t, void *))read, 
128                       (int (*)(ushort_t, void *, uint_t, void *))write, 
129                       (void *)dev) == 0) {
130
131     hook->dev = dev;
132     hook->port = port;
133     hook->read = read;
134     hook->write = write;
135     
136     list_add(&(hook->mgr_list), &(mgr->io_hooks));
137     mgr->num_io_hooks++;
138     
139     list_add(&(hook->dev_list), &(dev->io_hooks));
140     dev->num_io_hooks++;
141   } else {
142
143     return -1;
144   }
145
146   return 0;
147 }
148
149
150 int v3_dev_unhook_io(struct vm_device   *dev,
151                   ushort_t            port) {
152   struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
153   struct dev_io_hook * hook = dev_mgr_find_io_hook(mgr, port);
154
155   if (!hook) { 
156     return -1;
157   }
158
159   list_del(&(hook->mgr_list));
160   mgr->num_io_hooks--;
161
162   list_del(&(hook->dev_list));
163   dev->num_io_hooks--;
164
165
166   return v3_unhook_io_port(dev->vm, port);
167 }
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186 #if 0
187 static int dev_mgr_hook_mem(struct guest_info    *vm,
188                             struct vm_device   *device,
189                             void               *start,
190                             void               *end)
191 {
192
193   struct dev_mem_hook * hook = (struct dev_mem_hook*)V3_Malloc(sizeof(struct dev_mem_hook));
194   //  V3_Malloc(struct dev_mem_hook *, hook,sizeof(struct dev_mem_hook));
195
196   if (!hook) { 
197     return -1;
198   }
199
200   /* not implemented yet
201   hook_memory(vm->mem_map, 
202               guest_physical_address_start, 
203               guest_physical_address_end, 
204               read,
205               write,
206               device);
207
208   */
209
210   return -1;   // remove when hook_memory works
211
212
213   hook->addr_start = start;
214   hook->addr_end = end;
215
216   return 0;
217   
218 }
219
220
221 static int dev_mgr_unhook_mem(struct vm_device   *dev,
222                               addr_t start,
223                               addr_t end)  {
224   /*
225   struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
226   struct dev_mem_hook *hook = dev_mgr_find_mem_hook(mgr, start, end);
227   
228   if (!hook) { 
229     // Very bad - unhooking something that doesn't exist!
230     return -1;
231   }
232   */
233
234   /* not implemented yet
235   return unhook_mem_port(vm->mem_map,
236                          guest_physical_start,
237                          guest_physical_end) ;
238
239   */
240   return -1;
241 }
242 #endif
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266 #ifdef DEBUG_DEV_MGR
267
268 void PrintDebugDevMgr(struct guest_info * info) {
269   struct vmm_dev_mgr * mgr = &(info->dev_mgr);
270   struct vm_device * dev;
271   PrintDebug("%d devices registered with manager\n", mgr->num_devs);
272
273   list_for_each_entry(dev, &(mgr->dev_list), dev_link) {
274     PrintDebugDev(dev);
275     PrintDebug("next..\n");
276   }
277
278   return;
279 }
280
281
282 void PrintDebugDev(struct vm_device * dev) {
283   
284   PrintDebug("Device: %s\n", dev->name);
285   PrintDebugDevIO(dev);
286 }
287
288 void PrintDebugDevMgrIO(struct vmm_dev_mgr * mgr) {
289
290 }
291
292 void PrintDebugDevIO(struct vm_device * dev) {
293   struct dev_io_hook * hook;
294
295   PrintDebug("IO Hooks(%d)  for Device: %s\n", dev->num_io_hooks,  dev->name);
296
297   list_for_each_entry(hook, &(dev->io_hooks), dev_list) {
298     PrintDebug("\tPort: 0x%x (read=0x%p), (write=0x%p)\n", hook->port, 
299                (void *)(addr_t)(hook->read), 
300                (void *)(addr_t)(hook->write));
301   }
302
303   return;
304 }
305
306 #else 
307 void PrintDebugDevMgr(struct guest_info * info) {}
308 void PrintDebugDev(struct vm_device * dev) {}
309 void PrintDebugDevMgrIO(struct vmm_dev_mgr * mgr) {}
310 void PrintDebugDevIO(struct vm_device * dev) {}
311 #endif