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.


added host event hooks interface
[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
28 #ifndef NULL
29 #define NULL 0
30 #endif
31
32 int dev_mgr_init(struct guest_info * info) {
33   struct vmm_dev_mgr * mgr = &(info->dev_mgr);
34   INIT_LIST_HEAD(&(mgr->dev_list));
35   mgr->num_devs = 0;
36
37   INIT_LIST_HEAD(&(mgr->io_hooks));
38   mgr->num_io_hooks = 0;
39
40   return 0;
41 }
42
43
44 int dev_mgr_deinit(struct guest_info * info) {
45   struct vm_device * dev;
46   struct vmm_dev_mgr * mgr = &(info->dev_mgr);
47   struct vm_device * tmp;
48
49   list_for_each_entry_safe(dev, tmp, &(mgr->dev_list), dev_link) {
50     v3_unattach_device(dev);
51     free_device(dev);
52   }
53
54   return 0;
55 }
56
57
58
59
60 static int dev_mgr_add_device(struct vmm_dev_mgr * mgr, struct vm_device * dev) {
61   list_add(&(dev->dev_link), &(mgr->dev_list));
62   mgr->num_devs++;
63
64   return 0;
65 }
66
67 static int dev_mgr_remove_device(struct vmm_dev_mgr * mgr, struct vm_device * dev) {
68   list_del(&(dev->dev_link));
69   mgr->num_devs--;
70
71   return 0;
72 }
73
74
75
76 /* IO HOOKS */
77 int dev_mgr_add_io_hook(struct vmm_dev_mgr * mgr, struct dev_io_hook * hook) {
78   list_add(&(hook->mgr_list), &(mgr->io_hooks));
79   mgr->num_io_hooks++;
80   return 0;
81 }
82
83
84 int dev_mgr_remove_io_hook(struct vmm_dev_mgr * mgr, struct dev_io_hook * hook) {
85   list_del(&(hook->mgr_list));
86   mgr->num_io_hooks--;
87
88   return 0;
89 }
90
91
92 int dev_add_io_hook(struct vm_device * dev, struct dev_io_hook * hook) {
93   list_add(&(hook->dev_list), &(dev->io_hooks));
94   dev->num_io_hooks++;
95   return 0;
96 }
97
98
99 int dev_remove_io_hook(struct vm_device * dev, struct dev_io_hook * hook) {
100   list_del(&(hook->dev_list));
101   dev->num_io_hooks--;
102
103   return 0;
104 }
105
106
107
108
109
110 struct dev_io_hook * dev_mgr_find_io_hook(struct vmm_dev_mgr * mgr, ushort_t port) {
111   struct dev_io_hook * tmp = NULL;
112
113   list_for_each_entry(tmp, &(mgr->io_hooks), mgr_list) {
114     if (tmp->port == port) {
115       return tmp;
116     }
117   }
118   return NULL;
119 }
120
121 struct dev_io_hook * dev_find_io_hook(struct vm_device * dev, ushort_t port) {
122   struct dev_io_hook * tmp = NULL;
123
124   list_for_each_entry(tmp, &(dev->io_hooks), dev_list) {
125     if (tmp->port == port) {
126       return tmp;
127     }
128   }
129   return NULL;
130 }
131
132
133
134
135 int dev_hook_io(struct vm_device   *dev,
136                 ushort_t            port,
137                 int (*read)(ushort_t port, void * dst, uint_t length, struct vm_device * dev),
138                 int (*write)(ushort_t port, void * src, uint_t length, struct vm_device * dev)) {
139
140   struct dev_io_hook *hook = (struct dev_io_hook *)V3_Malloc(sizeof(struct dev_io_hook));
141   
142   if (!hook) { 
143     return -1;
144   }
145
146
147   if (v3_hook_io_port(dev->vm, port, 
148                       (int (*)(ushort_t, void *, uint_t, void *))read, 
149                       (int (*)(ushort_t, void *, uint_t, void *))write, 
150                       (void *)dev) == 0) {
151
152     hook->dev = dev;
153     hook->port = port;
154     hook->read = read;
155     hook->write = write;
156     
157     dev_mgr_add_io_hook(&(dev->vm->dev_mgr), hook);
158     dev_add_io_hook(dev, hook);
159   } else {
160
161     return -1;
162   }
163
164   return 0;
165 }
166
167
168 int dev_unhook_io(struct vm_device   *dev,
169                   ushort_t            port) {
170
171   struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
172   struct dev_io_hook * hook = dev_mgr_find_io_hook(mgr, port);
173
174   if (!hook) { 
175     return -1;
176   }
177
178   dev_mgr_remove_io_hook(mgr, hook);
179   dev_remove_io_hook(dev, hook);
180
181   return v3_unhook_io_port(dev->vm, port);
182 }
183
184
185 int v3_attach_device(struct guest_info * vm, struct vm_device * dev) {
186   struct vmm_dev_mgr *mgr= &(vm->dev_mgr);
187   
188   dev->vm = vm;
189   dev_mgr_add_device(mgr, dev);
190   dev->ops->init(dev);
191
192   return 0;
193 }
194
195 int v3_unattach_device(struct vm_device * dev) {
196   struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
197
198   dev->ops->deinit(dev);
199   dev_mgr_remove_device(mgr, dev);
200   dev->vm = NULL;
201
202   return 0;
203 }
204
205
206
207
208
209 int dev_mgr_hook_mem(struct guest_info    *vm,
210                      struct vm_device   *device,
211                      void               *start,
212                      void               *end)
213 {
214
215   struct dev_mem_hook * hook = (struct dev_mem_hook*)V3_Malloc(sizeof(struct dev_mem_hook));
216   //  V3_Malloc(struct dev_mem_hook *, hook,sizeof(struct dev_mem_hook));
217
218   if (!hook) { 
219     return -1;
220   }
221
222   /* not implemented yet
223   hook_memory(vm->mem_map, 
224               guest_physical_address_start, 
225               guest_physical_address_end, 
226               read,
227               write,
228               device);
229
230   */
231
232   return -1;   // remove when hook_memory works
233
234
235   hook->addr_start = start;
236   hook->addr_end = end;
237
238   return 0;
239   
240 }
241
242
243 int dev_mgr_unhook_mem(struct vm_device   *dev,
244                        addr_t start,
245                        addr_t end)  {
246   /*
247   struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
248   struct dev_mem_hook *hook = dev_mgr_find_mem_hook(mgr, start, end);
249   
250   if (!hook) { 
251     // Very bad - unhooking something that doesn't exist!
252     return -1;
253   }
254   */
255
256   /* not implemented yet
257   return unhook_mem_port(vm->mem_map,
258                          guest_physical_start,
259                          guest_physical_end) ;
260
261   */
262   return -1;
263 }
264
265
266
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%x), (write=0x%x)\n", hook->port, hook->read, hook->write);
299   }
300
301   return;
302 }