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 devices, device manager, and nvram device
[palacios.git] / palacios / src / palacios / vmm_dev_mgr.c
1
2 #include <palacios/vmm_dev.h>
3 #include <palacios/vmm_dev_mgr.h>
4 #include <palacios/vm_guest.h>
5 #include <palacios/vmm.h>
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, struct guest_info *vm)
14 {
15   mgr->vm=vm;
16   mgr->dev_list=NULL;
17   mgr->num_devices=0;
18   return 0;
19 }
20
21
22 int dev_mgr_deinit(struct vmm_dev_mgr *mgr)
23 {
24   int rc;
25
26   while (mgr->dev_list) { 
27     rc=dev_mgr_detach_device(mgr->vm,mgr->dev_list);
28     if (rc) { 
29       // Bad bad bad
30     }
31   }
32   return 0;
33 }
34
35 int dev_mgr_attach_device(struct guest_info *vm, struct vm_device *device)
36 {
37   struct vmm_dev_mgr *mgr= &(vm->dev_mgr);
38   
39   if (device->io_hooks || device->mem_hooks) { 
40     return -1;
41   }
42
43   device->next = mgr->dev_list;
44   device->prev = 0;
45   if (device->next) { 
46     device->next->prev = device;
47   }
48   mgr->dev_list = device;
49   
50   device->vm=vm;
51
52   return 0;
53 }
54
55 int dev_mgr_detach_device(struct guest_info *vm, struct vm_device *device)
56 {
57   if (device->prev==0) { 
58     vm->dev_mgr.dev_list = device->next;
59   } else {
60     device->prev->next = device->next;
61   }
62   if (device->next) { 
63     device->next->prev=device->prev;
64   }
65   
66   // avoid interrupts here
67
68   device->deinit_device(device);
69
70   device->vm=NULL;
71   return 0;
72 }
73
74
75 #define INSERT_FRONT(listhead,item)         \
76   do {                                      \
77     if (!(listhead)) {                      \
78       (listhead)=(item);                    \
79       (item)->prev=NULL;                    \
80       (item)->next=NULL;                    \
81     }  else {                               \
82       (item)->prev=NULL;                    \
83       (item)->next=(listhead);              \
84       if ((listhead)->next) {               \
85         (listhead)->next->prev=(item);      \
86       }                                     \
87       (listhead)=(item);                    \
88     }                                       \
89   } while (0)
90
91 #define DELETE(listhead,item)               \
92   do {                                      \
93     if ((item)->prev) {                     \
94       (item)->prev->next=(item)->next;      \
95     } else {                                \
96       (listhead)=(item)->next;              \
97     }                                       \
98     if ((item)->next) {                     \
99       (item)->next->prev=(item)->prev;      \
100     }                                       \
101   } while (0)
102     
103
104    
105
106 int dev_mgr_hook_io(struct guest_info    *vm,
107                     struct vm_device   *device,
108                     ushort_t            portno,
109                     enum access_control control,
110                     enum access_type    atype)
111 {
112   struct vm_device_io_hook *hook = os_hooks->malloc(sizeof(struct vm_device_io_hook));
113   
114   if (!hook) { 
115     return -1;
116   }
117
118   int (*read)(ushort_t, void *, uint_t, void *) = NULL;
119   int (*write)(ushort_t, void *, uint_t, void *) = NULL;
120
121   switch (control) { 
122   case DEVICE_EMULATED:
123     switch (atype) { 
124     case DEVICE_READ:
125       read = (int (*)(ushort_t, void *,uint_t, void *))  (device->read_io_port);
126       break;
127     case DEVICE_WRITE:
128       write = (int (*)(ushort_t, void *, uint_t, void *)) (device->write_io_port);
129       break;
130     case DEVICE_READWRITE:
131       read = (int (*)(ushort_t, void *, uint_t, void *)) (device->read_io_port);
132       write = (int (*)(ushort_t, void *, uint_t, void *)) (device->write_io_port);
133       break;
134     }
135     break;
136   case DEVICE_PASSTHROUGH:
137     read=write=NULL;
138     break;
139   }
140     
141   hook_io_port(&(vm->io_map), 
142                portno, 
143                read,
144                write,
145                device);
146
147   hook->control=control;
148   hook->atype=atype;
149   hook->guest_port = portno;
150   
151   INSERT_FRONT(device->io_hooks,hook);
152   
153   return 0;
154 }
155
156
157 int dev_mgr_unhook_io(struct guest_info    *vm,
158                       struct vm_device   *device,
159                       ushort_t            portno)
160 {
161   struct vm_device_io_hook *hook = device->io_hooks;
162
163   while (hook) { 
164     if (hook->guest_port==portno) { 
165       DELETE(device->io_hooks,hook);
166       break;
167     }
168   }
169
170   if (!hook) { 
171     // Very bad - unhooking something that doesn't exist!
172     return -1;
173   }
174
175   return unhook_io_port(&(vm->io_map),
176                         portno);
177 }
178
179
180
181 int dev_mgr_hook_mem(struct guest_info    *vm,
182                      struct vm_device   *device,
183                      void               *guest_physical_address_start,
184                      void               *guest_physical_address_end,
185                      enum access_control control,
186                      enum access_type    atype)
187 {
188
189   struct vm_device_mem_hook *hook = os_hooks->malloc(sizeof(struct vm_device_mem_hook));
190   
191   if (!hook) { 
192     return -1;
193   }
194
195   int (*read)(ushort_t, void *, uint_t, void *) = NULL;
196   int (*write)(ushort_t, void *, uint_t, void *) = NULL;
197
198   switch (control) { 
199   case DEVICE_EMULATED:
200     switch (atype) { 
201     case DEVICE_READ:
202       read = (int (*)(ushort_t, void *, uint_t, void *))(device->read_mapped_memory);
203       break;
204     case DEVICE_WRITE:
205       write = (int (*)(ushort_t, void *, uint_t, void *))(device->write_mapped_memory);
206       break;
207     case DEVICE_READWRITE:
208       read = (int (*)(ushort_t, void *, uint_t, void *))(device->read_mapped_memory);
209       write = (int (*)(ushort_t, void *, uint_t, void *))(device->write_mapped_memory);
210       break;
211     }
212     break;
213   case DEVICE_PASSTHROUGH:
214     read=write=NULL;
215     break;
216   }
217     
218
219   /* not implemented yet
220   hook_memory(vm->mem_map, 
221               guest_physical_address_start, 
222               guest_physical_address_end, 
223               read,
224               write,
225               device);
226
227   */
228
229   return -1;   // remove when hook_memory works
230
231   hook->control=control;
232   hook->atype=atype;
233   hook->guest_physical_start = guest_physical_address_start;
234   hook->guest_physical_end = guest_physical_address_end;
235
236   
237   INSERT_FRONT(device->mem_hooks,hook);
238
239   return 0;
240   
241 }
242
243
244 int dev_mgr_unhook_mem(struct guest_info    *vm,
245                        struct vm_device   *device,
246                        void               *guest_physical_start,
247                        void               *guest_physical_end) 
248 {
249   struct vm_device_mem_hook *hook = device->mem_hooks;
250
251   while (hook) { 
252     if (hook->guest_physical_start==guest_physical_start &&
253         hook->guest_physical_end==guest_physical_end) {
254       DELETE(device->mem_hooks,hook);
255       break;
256     }
257   }
258
259   if (!hook) { 
260     // Very bad - unhooking something that doesn't exist!
261     return -1;
262   }
263
264
265   /* not implemented yet
266   return unhook_mem_port(vm->mem_map,
267                          guest_physical_start,
268                          guest_physical_end) ;
269
270   */
271   return -1;
272 }
273
274
275 int dev_mgr_unhook_device(struct guest_info  *vm,
276                           struct vm_device *device)
277 {
278   struct vm_device_io_hook *iohook=device->io_hooks;
279   struct vm_device_mem_hook *memhook=device->mem_hooks;
280
281   while (iohook) { 
282     if (dev_mgr_unhook_io(vm,device,iohook->guest_port)) { 
283       return -1;
284     }
285   }
286
287   while (memhook) { 
288     if (dev_mgr_unhook_mem(vm,device,memhook->guest_physical_start, memhook->guest_physical_end)) {
289       return -1;
290     }
291   }
292
293   return 0;
294 }
295