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.


9cdaa6d4b26007e466c3fd19c168b9eca8df86f2
[palacios.git] / linux_module / palacios-vm.c
1 /* 
2  * VM specific Controls
3  * (c) Jack Lange, 2010
4  */
5
6 #include <linux/device.h>
7 #include <linux/cdev.h>
8 #include <linux/errno.h>
9 #include <linux/percpu.h>
10 #include <linux/fs.h>
11 #include <linux/uaccess.h>
12 #include <linux/poll.h>
13 #include <linux/anon_inodes.h>
14 #include <linux/sched.h>
15
16 #include <linux/smp_lock.h>
17 #include <linux/file.h>
18 #include <linux/spinlock.h>
19 #include <linux/rbtree.h>
20
21 #include <palacios/vmm.h>
22
23 #include "palacios.h"
24 #include "palacios-vm.h"
25
26
27 struct vm_ctrl {
28     unsigned int cmd;
29
30     int (*handler)(struct v3_guest * guest, 
31                    unsigned int cmd, unsigned long arg, 
32                    void * priv_data);
33
34     void * priv_data;
35
36     struct rb_node tree_node;
37 };
38
39
40 static inline struct vm_ctrl * __insert_ctrl(struct v3_guest * vm, 
41                                              struct vm_ctrl * ctrl) {
42     struct rb_node ** p = &(vm->vm_ctrls.rb_node);
43     struct rb_node * parent = NULL;
44     struct vm_ctrl * tmp_ctrl = NULL;
45
46     while (*p) {
47         parent = *p;
48         tmp_ctrl = rb_entry(parent, struct vm_ctrl, tree_node);
49
50         if (ctrl->cmd < tmp_ctrl->cmd) {
51             p = &(*p)->rb_left;
52         } else if (ctrl->cmd > tmp_ctrl->cmd) {
53             p = &(*p)->rb_right;
54         } else {
55             return tmp_ctrl;
56         }
57     }
58
59     rb_link_node(&(ctrl->tree_node), parent, p);
60
61     return NULL;
62 }
63
64
65
66 int add_guest_ctrl(struct v3_guest * guest, unsigned int cmd, 
67                    int (*handler)(struct v3_guest * guest, 
68                                   unsigned int cmd, unsigned long arg, 
69                                   void * priv_data),
70                    void * priv_data) {
71     struct vm_ctrl * ctrl = kmalloc(sizeof(struct vm_ctrl), GFP_KERNEL);
72
73     if (ctrl == NULL) {
74         printk("Error: Could not allocate vm ctrl %d\n", cmd);
75         return -1;
76     }
77
78     ctrl->cmd = cmd;
79     ctrl->handler = handler;
80     ctrl->priv_data = priv_data;
81
82     if (__insert_ctrl(guest, ctrl) != NULL) {
83         printk("Could not insert guest ctrl %d\n", cmd);
84         kfree(ctrl);
85         return -1;
86     }
87     
88     rb_insert_color(&(ctrl->tree_node), &(guest->vm_ctrls));
89
90     return 0;
91 }
92
93
94 static struct vm_ctrl * get_ctrl(struct v3_guest * guest, unsigned int cmd) {
95     struct rb_node * n = guest->vm_ctrls.rb_node;
96     struct vm_ctrl * ctrl = NULL;
97
98     while (n) {
99         ctrl = rb_entry(n, struct vm_ctrl, tree_node);
100
101         if (cmd < ctrl->cmd) {
102             n = n->rb_left;
103         } else if (cmd > ctrl->cmd) {
104             n = n->rb_right;
105         } else {
106             return ctrl;
107         }
108     }
109
110     return NULL;
111 }
112
113
114 #ifdef V3_CONFIG_STREAM
115 #include "palacios-stream.h"
116 #endif
117
118 #ifdef V3_CONFIG_CONSOLE
119 #include "palacios-console.h"
120 #endif
121
122 #ifdef V3_CONFIG_EXT_INSPECTOR
123 #include "palacios-inspector.h"
124 #endif
125
126 #ifdef V3_CONFIG_GRAPHICS_CONSOLE
127 #include "palacios-graphics-console.h"
128 #endif
129
130 #ifdef V3_CONFIG_HOST_DEVICE
131 #include "palacios-host-dev.h"
132 #define HOST_DEV_URL_LEN 256
133 #endif
134
135 extern struct class * v3_class;
136 #define STREAM_NAME_LEN 128
137
138 static long v3_vm_ioctl(struct file * filp,
139                         unsigned int ioctl, unsigned long arg) {
140
141     struct v3_guest * guest = filp->private_data;
142
143     printk("V3 IOCTL %d\n", ioctl);
144
145     switch (ioctl) {
146
147         case V3_VM_STOP: {
148             printk("Stopping VM\n");
149             stop_palacios_vm(guest);
150             break;
151         }
152
153         case V3_VM_CONSOLE_CONNECT: {
154 #ifdef V3_CONFIG_CONSOLE
155             return connect_console(guest);
156 #else
157             printk("Console support not available\n");
158             return -EFAULT;
159 #endif
160             break;
161         }
162
163         case V3_VM_STREAM_CONNECT: {
164 #ifdef V3_CONFIG_STREAM
165             void __user * argp = (void __user *)arg;
166             char path_name[STREAM_NAME_LEN];
167
168             if (copy_from_user(path_name, argp, STREAM_NAME_LEN)) {
169                 printk("%s(%d): copy from user error...\n", __FILE__, __LINE__);
170                 return -EFAULT;
171             }
172
173             return open_stream(path_name);
174 #else
175             printk("Stream support Not available\n");
176             return -EFAULT;
177 #endif
178             break;
179         }
180
181         case V3_VM_HOST_DEV_CONNECT: {
182 #ifdef V3_CONFIG_HOST_DEVICE
183             void __user * argp = (void __user *)arg;
184             char host_dev_url[HOST_DEV_URL_LEN];
185
186             if (copy_from_user(host_dev_url, argp, HOST_DEV_URL_LEN)) {
187                 printk("copy from user error getting url for host device connect...\n");
188                 return -EFAULT;
189             }
190
191             return connect_host_dev(guest,host_dev_url);
192 #else
193             printk("palacios: Host device support not available\n");
194             return -EFAULT;
195 #endif
196             break;
197         }
198
199         case V3_VM_FB_INPUT: 
200 #ifdef V3_CONFIG_GRAPHICS_CONSOLE
201             return palacios_graphics_console_user_input(&(guest->graphics_console),
202                                                         (struct v3_fb_input __user *) arg) ;
203 #else
204             return -EFAULT;
205 #endif
206             break;
207             
208         case V3_VM_FB_QUERY: 
209 #ifdef V3_CONFIG_GRAPHICS_CONSOLE
210             return palacios_graphics_console_user_query(&(guest->graphics_console),
211                                                         (struct v3_fb_query_response __user *) arg);
212 #else
213             return -EFAULT;
214 #endif
215             break;
216
217
218         default: {
219             struct vm_ctrl * ctrl = get_ctrl(guest, ioctl);
220
221             if (ctrl) {
222                 return ctrl->handler(guest, ioctl, arg, ctrl->priv_data);
223             }
224             
225             
226             printk("\tUnhandled ctrl cmd: %d\n", ioctl);
227             return -EINVAL;
228         }
229     }
230
231     return 0;
232 }
233
234 static int v3_vm_open(struct inode * inode, struct file * filp) {
235     struct v3_guest * guest = container_of(inode->i_cdev, struct v3_guest, cdev);
236     filp->private_data = guest;
237     return 0;
238 }
239
240
241 static ssize_t v3_vm_read(struct file * filp, char __user * buf, size_t size, loff_t * offset) {
242     
243     return 0;
244 }
245
246
247 static ssize_t v3_vm_write(struct file * filp, const char __user * buf, size_t size, loff_t * offset) {
248
249     return 0;
250 }
251
252
253 static struct file_operations v3_vm_fops = {
254     .owner = THIS_MODULE,
255     .unlocked_ioctl = v3_vm_ioctl,
256     .compat_ioctl = v3_vm_ioctl,
257     .open = v3_vm_open,
258     .read = v3_vm_read, 
259     .write = v3_vm_write,
260 };
261
262
263 extern u32 pg_allocs;
264 extern u32 pg_frees;
265 extern u32 mallocs;
266 extern u32 frees;
267
268 int start_palacios_vm(void * arg)  {
269     struct v3_guest * guest = (struct v3_guest *)arg;
270     int err;
271
272     lock_kernel();
273     daemonize(guest->name);
274     // allow_signal(SIGKILL);
275     unlock_kernel();
276     
277
278     guest->v3_ctx = v3_create_vm(guest->img, (void *)guest, guest->name);
279
280     if (guest->v3_ctx == NULL) { 
281         printk("palacios: failed to create vm\n");
282         complete(&(guest->start_done));
283         return -1;
284     }
285
286     // init linux extensions
287 #ifdef V3_CONFIG_EXT_INSPECTOR
288     inspect_vm(guest);
289 #endif
290
291     printk("Creating VM device: Major %d, Minor %d\n", MAJOR(guest->vm_dev), MINOR(guest->vm_dev));
292
293     cdev_init(&(guest->cdev), &v3_vm_fops);
294
295     guest->cdev.owner = THIS_MODULE;
296     guest->cdev.ops = &v3_vm_fops;
297
298
299     printk("Adding VM device\n");
300     err = cdev_add(&(guest->cdev), guest->vm_dev, 1);
301
302     if (err) {
303         printk("Fails to add cdev\n");
304         v3_free_vm(guest->v3_ctx);
305         complete(&(guest->start_done));
306         return -1;
307     }
308
309     if (device_create(v3_class, NULL, guest->vm_dev, guest, "v3-vm%d", MINOR(guest->vm_dev)) == NULL){
310         printk("Fails to create device\n");
311         cdev_del(&(guest->cdev));
312         v3_free_vm(guest->v3_ctx);
313         complete(&(guest->start_done));
314         return -1;
315     }
316
317     complete(&(guest->start_done));
318
319     printk("palacios: launching vm\n");
320
321     if (v3_start_vm(guest->v3_ctx, 0xffffffff) < 0) { 
322         printk("palacios: launch of vm failed\n");
323         device_destroy(v3_class, guest->vm_dev);
324         cdev_del(&(guest->cdev));
325         v3_free_vm(guest->v3_ctx);
326         return -1;
327     }
328     
329     complete(&(guest->thread_done));
330
331     printk("palacios: vm completed.  returning.\n");
332
333     return 0;
334 }
335
336
337
338
339 int stop_palacios_vm(struct v3_guest * guest) {
340
341     v3_stop_vm(guest->v3_ctx);
342
343     wait_for_completion(&(guest->thread_done));
344
345     v3_free_vm(guest->v3_ctx);
346     
347     device_destroy(v3_class, guest->vm_dev);
348
349     cdev_del(&(guest->cdev));
350
351     kfree(guest->img);
352     kfree(guest);
353
354     return 0;
355 }