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.


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