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