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 full device support
[palacios.git] / palacios / src / palacios / vmm_dev_mgr.c
1 #include <palacios/vm_dev.h>
2 #include <palacios/vmm_dev_mgr.h>
3 #include <palacios/vm_guest.h>
4 #include <palacios/vmm.h>
5
6
7 extern struct vmm_os_hooks *os_hooks;
8
9 #ifndef NULL
10 #define NULL 0
11 #endif
12
13 int dev_mgr_init(struct vmm_dev_mgr * mgr) {
14   mgr->dev_list.head = NULL;
15   mgr->dev_list.num_devs = 0;
16   return 0;
17 }
18
19
20 int dev_mgr_deinit(struct vmm_dev_mgr * mgr)
21 {
22   struct vm_device * dev = mgr->dev_list.head;
23
24   while (dev) { 
25     unattach_device(dev);
26     free_device(dev);
27     dev = dev->next;
28   }
29   return 0;
30 }
31
32
33
34
35 int dev_mgr_add_device(struct vmm_dev_mgr * mgr, struct vm_device * dev) {
36   dev->next = mgr->dev_list.head;
37   dev->prev = 0;
38   if (dev->next) { 
39     dev->next->prev = dev;
40   }
41   mgr->dev_list.head = dev;
42
43   mgr->dev_list.num_devs++;
44
45   return 0;
46 }
47
48 int dev_mgr_remove_device(struct vmm_dev_mgr * mgr, struct vm_device * dev) {
49   if (mgr->dev_list.head == dev) { 
50     mgr->dev_list.head = dev->next;
51   } else {
52     dev->prev->next = dev->next;
53   }
54   if (dev->next) { 
55     dev->next->prev = dev->prev;
56   }
57   
58   mgr->dev_list.num_devs--;
59
60   return 0;
61 }
62
63
64 int dev_mgr_add_io_hook(struct vmm_dev_mgr * mgr, struct dev_io_hook * hook) {
65   hook->mgr_next = mgr->io_hooks.head;
66   hook->mgr_prev = NULL;
67   if (hook->mgr_next) {
68     hook->mgr_next->mgr_prev = hook;
69   }
70   mgr->io_hooks.head = hook;
71
72   mgr->io_hooks.num_hooks++;
73
74   return 0;
75 }
76
77
78 int dev_mgr_remove_io_hook(struct vmm_dev_mgr * mgr, struct dev_io_hook * hook) {
79   if (mgr->io_hooks.head == hook) {
80     mgr->io_hooks.head = hook->mgr_next;
81   } else {
82     hook->mgr_prev->mgr_next = hook->mgr_next;
83   }
84
85   if (hook->mgr_next) {
86     hook->mgr_next->mgr_prev = hook->mgr_prev;
87   }
88   
89   mgr->io_hooks.num_hooks--;
90
91   return 0;
92 }
93
94
95 int dev_add_io_hook(struct vm_device * dev, struct dev_io_hook * hook) {
96   hook->dev_next = dev->io_hooks.head;
97   hook->dev_prev = NULL;
98   if (hook->dev_next) {
99     hook->dev_next->dev_prev = hook;
100   }
101   dev->io_hooks.head = hook;
102
103   dev->io_hooks.num_hooks++;
104
105   return 0;
106 }
107
108
109 int dev_remove_io_hook(struct vm_device * dev, struct dev_io_hook * hook) {
110   if (dev->io_hooks.head == hook) {
111     dev->io_hooks.head = hook->dev_next;
112   } else {
113     hook->dev_prev->dev_next = hook->dev_next;
114   }
115
116   if (hook->dev_next) {
117     hook->dev_next->dev_prev = hook->dev_prev;
118   }
119   
120   dev->io_hooks.num_hooks--;
121
122   return 0;
123 }
124
125
126 struct dev_io_hook * dev_mgr_find_io_hook(struct vmm_dev_mgr * mgr, ushort_t port) {
127   struct dev_io_hook * tmp = mgr->io_hooks.head;
128
129   while (tmp) {
130     if (tmp->port == port) {
131       break;
132     }
133     tmp = tmp->mgr_next;
134   }
135
136   return tmp;
137 }
138
139 struct dev_io_hook * dev_find_io_hook(struct vm_device * dev, ushort_t port) {
140   struct dev_io_hook * tmp = dev->io_hooks.head;
141
142   while (tmp) {
143     if (tmp->port == port) {
144       break;
145     }
146     tmp = tmp->dev_next;
147   }
148
149   return tmp;
150 }
151
152
153
154
155 int attach_device(struct guest_info * vm, struct vm_device * dev) {
156   struct vmm_dev_mgr *mgr= &(vm->dev_mgr);
157   
158   dev->vm = vm;
159   dev_mgr_add_device(mgr, dev);
160   dev->ops->init(dev);
161
162   return 0;
163 }
164
165 int unattach_device(struct vm_device * dev) {
166   struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
167
168   dev->ops->deinit(dev);
169   dev_mgr_remove_device(mgr, dev);
170   dev->vm = NULL;
171
172   return 0;
173 }
174
175
176
177 int dev_hook_io(struct vm_device   *dev,
178                 ushort_t            port,
179                 int (*read)(ushort_t port, void * dst, uint_t length, struct vm_device * dev),
180                 int (*write)(ushort_t port, void * src, uint_t length, struct vm_device * dev)) {
181
182   struct dev_io_hook *hook = os_hooks->malloc(sizeof(struct dev_io_hook));
183   
184   if (!hook) { 
185     return -1;
186   }
187
188
189   if (hook_io_port(&(dev->vm->io_map), port, 
190                    (int (*)(ushort_t, void *, uint_t, void *))read, 
191                    (int (*)(ushort_t, void *, uint_t, void *))write, 
192                    (void *)dev) == 0) {
193
194     hook->dev = dev;
195     hook->port = port;
196     hook->read = read;
197     hook->write = write;
198     
199     dev_mgr_add_io_hook(&(dev->vm->dev_mgr), hook);
200     dev_add_io_hook(dev, hook);
201   } else {
202     return -1;
203   }
204
205   return 0;
206 }
207
208
209 int dev_unhook_io(struct vm_device   *dev,
210                   ushort_t            port) {
211
212   struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
213   struct dev_io_hook * hook = dev_mgr_find_io_hook(mgr, port);
214
215   if (!hook) { 
216     return -1;
217   }
218
219   dev_mgr_remove_io_hook(mgr, hook);
220   dev_remove_io_hook(dev, hook);
221
222   return unhook_io_port(&(dev->vm->io_map), port);
223 }
224
225
226
227 int dev_mgr_hook_mem(struct guest_info    *vm,
228                      struct vm_device   *device,
229                      void               *start,
230                      void               *end)
231 {
232
233   struct dev_mem_hook *hook = os_hooks->malloc(sizeof(struct dev_mem_hook));
234   
235   if (!hook) { 
236     return -1;
237   }
238
239
240     
241
242   /* not implemented yet
243   hook_memory(vm->mem_map, 
244               guest_physical_address_start, 
245               guest_physical_address_end, 
246               read,
247               write,
248               device);
249
250   */
251
252   return -1;   // remove when hook_memory works
253
254
255   hook->addr_start = start;
256   hook->addr_end = end;
257
258   return 0;
259   
260 }
261
262
263 int dev_mgr_unhook_mem(struct guest_info    *vm,
264                        struct vm_device   *device,
265                        void               *start,
266                        void               *end) 
267 {
268   struct dev_mem_hook *hook = device->mem_hooks.head;
269
270   while (hook) { 
271     if (((hook->addr_start) == start) && (hook->addr_end == end)) {
272       break;
273     }
274   }
275
276   if (!hook) { 
277     // Very bad - unhooking something that doesn't exist!
278     return -1;
279   }
280
281
282   /* not implemented yet
283   return unhook_mem_port(vm->mem_map,
284                          guest_physical_start,
285                          guest_physical_end) ;
286
287   */
288   return -1;
289 }
290
291
292
293
294 void PrintDebugDevMgr(struct vmm_dev_mgr * mgr) {
295   struct vm_device * dev = mgr->dev_list.head;
296
297   while (dev) {
298     PrintDebugDev(dev);
299     dev = dev->next;
300   }
301
302   return;
303 }
304
305
306 void PrintDebugDev(struct vm_device * dev) {
307   
308   PrintDebug("Device: %s\n", dev->name);
309   PrintDebugDevIO(dev);
310 }
311
312 void PrintDebugDevMgrIO(struct vmm_dev_mgr * mgr) {
313
314 }
315
316 void PrintDebugDevIO(struct vm_device * dev) {
317   struct dev_io_hook * hook = dev->io_hooks.head;
318   
319   PrintDebug("IO Hooks (%d) for Device: %s\n", dev->io_hooks.num_hooks, dev->name);
320   
321   while (hook) {
322     PrintDebug("\tPort: 0x%x (read=0x%x), (write=0x%x)\n", hook->port, hook->read, hook->write);
323     hook = hook->dev_next;
324   }
325
326   return;
327 }