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 fixes for extension framework, and porting of console to new interface
[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
119 #ifdef V3_CONFIG_EXT_INSPECTOR
120 #include "palacios-inspector.h"
121 #endif
122
123 #ifdef V3_CONFIG_GRAPHICS_CONSOLE
124 #include "palacios-graphics-console.h"
125 #endif
126
127 #ifdef V3_CONFIG_HOST_DEVICE
128 #include "palacios-host-dev.h"
129 #define HOST_DEV_URL_LEN 256
130 #endif
131
132 extern struct class * v3_class;
133 #define STREAM_NAME_LEN 128
134
135 static long v3_vm_ioctl(struct file * filp,
136                         unsigned int ioctl, unsigned long arg) {
137
138     struct v3_guest * guest = filp->private_data;
139
140     printk("V3 IOCTL %d\n", ioctl);
141
142     switch (ioctl) {
143
144         case V3_VM_STOP: {
145             printk("Stopping VM\n");
146             stop_palacios_vm(guest);
147             break;
148         }
149
150
151         case V3_VM_STREAM_CONNECT: {
152 #ifdef V3_CONFIG_STREAM
153             void __user * argp = (void __user *)arg;
154             char path_name[STREAM_NAME_LEN];
155
156             if (copy_from_user(path_name, argp, STREAM_NAME_LEN)) {
157                 printk("%s(%d): copy from user error...\n", __FILE__, __LINE__);
158                 return -EFAULT;
159             }
160
161             return open_stream(path_name);
162 #else
163             printk("Stream support Not available\n");
164             return -EFAULT;
165 #endif
166             break;
167         }
168
169         case V3_VM_HOST_DEV_CONNECT: {
170 #ifdef V3_CONFIG_HOST_DEVICE
171             void __user * argp = (void __user *)arg;
172             char host_dev_url[HOST_DEV_URL_LEN];
173
174             if (copy_from_user(host_dev_url, argp, HOST_DEV_URL_LEN)) {
175                 printk("copy from user error getting url for host device connect...\n");
176                 return -EFAULT;
177             }
178
179             return connect_host_dev(guest,host_dev_url);
180 #else
181             printk("palacios: Host device support not available\n");
182             return -EFAULT;
183 #endif
184             break;
185         }
186
187         case V3_VM_FB_INPUT: 
188 #ifdef V3_CONFIG_GRAPHICS_CONSOLE
189             return palacios_graphics_console_user_input(&(guest->graphics_console),
190                                                         (struct v3_fb_input __user *) arg) ;
191 #else
192             return -EFAULT;
193 #endif
194             break;
195             
196         case V3_VM_FB_QUERY: 
197 #ifdef V3_CONFIG_GRAPHICS_CONSOLE
198             return palacios_graphics_console_user_query(&(guest->graphics_console),
199                                                         (struct v3_fb_query_response __user *) arg);
200 #else
201             return -EFAULT;
202 #endif
203             break;
204
205
206         default: {
207             struct vm_ctrl * ctrl = get_ctrl(guest, ioctl);
208
209             if (ctrl) {
210                 return ctrl->handler(guest, ioctl, arg, ctrl->priv_data);
211             }
212             
213             
214             printk("\tUnhandled ctrl cmd: %d\n", ioctl);
215             return -EINVAL;
216         }
217     }
218
219     return 0;
220 }
221
222 static int v3_vm_open(struct inode * inode, struct file * filp) {
223     struct v3_guest * guest = container_of(inode->i_cdev, struct v3_guest, cdev);
224     filp->private_data = guest;
225     return 0;
226 }
227
228
229 static ssize_t v3_vm_read(struct file * filp, char __user * buf, size_t size, loff_t * offset) {
230     
231     return 0;
232 }
233
234
235 static ssize_t v3_vm_write(struct file * filp, const char __user * buf, size_t size, loff_t * offset) {
236
237     return 0;
238 }
239
240
241 static struct file_operations v3_vm_fops = {
242     .owner = THIS_MODULE,
243     .unlocked_ioctl = v3_vm_ioctl,
244     .compat_ioctl = v3_vm_ioctl,
245     .open = v3_vm_open,
246     .read = v3_vm_read, 
247     .write = v3_vm_write,
248 };
249
250
251 extern u32 pg_allocs;
252 extern u32 pg_frees;
253 extern u32 mallocs;
254 extern u32 frees;
255
256 int start_palacios_vm(void * arg)  {
257     struct v3_guest * guest = (struct v3_guest *)arg;
258     int err;
259
260     lock_kernel();
261     daemonize(guest->name);
262     // allow_signal(SIGKILL);
263     unlock_kernel();
264     
265
266     guest->v3_ctx = v3_create_vm(guest->img, (void *)guest, guest->name);
267
268     if (guest->v3_ctx == NULL) { 
269         printk("palacios: failed to create vm\n");
270         complete(&(guest->start_done));
271         return -1;
272     }
273
274     // init linux extensions
275     
276
277 #ifdef V3_CONFIG_EXT_INSPECTOR
278     inspect_vm(guest);
279 #endif
280
281     printk("Creating VM device: Major %d, Minor %d\n", MAJOR(guest->vm_dev), MINOR(guest->vm_dev));
282
283     cdev_init(&(guest->cdev), &v3_vm_fops);
284
285     guest->cdev.owner = THIS_MODULE;
286     guest->cdev.ops = &v3_vm_fops;
287
288
289     printk("Adding VM device\n");
290     err = cdev_add(&(guest->cdev), guest->vm_dev, 1);
291
292     if (err) {
293         printk("Fails to add cdev\n");
294         v3_free_vm(guest->v3_ctx);
295         complete(&(guest->start_done));
296         return -1;
297     }
298
299     if (device_create(v3_class, NULL, guest->vm_dev, guest, "v3-vm%d", MINOR(guest->vm_dev)) == NULL){
300         printk("Fails to create device\n");
301         cdev_del(&(guest->cdev));
302         v3_free_vm(guest->v3_ctx);
303         complete(&(guest->start_done));
304         return -1;
305     }
306
307     complete(&(guest->start_done));
308
309     printk("palacios: launching vm\n");
310
311     if (v3_start_vm(guest->v3_ctx, 0xffffffff) < 0) { 
312         printk("palacios: launch of vm failed\n");
313         device_destroy(v3_class, guest->vm_dev);
314         cdev_del(&(guest->cdev));
315         v3_free_vm(guest->v3_ctx);
316         return -1;
317     }
318     
319     complete(&(guest->thread_done));
320
321     printk("palacios: vm completed.  returning.\n");
322
323     return 0;
324 }
325
326
327
328
329 int stop_palacios_vm(struct v3_guest * guest) {
330
331     v3_stop_vm(guest->v3_ctx);
332
333     wait_for_completion(&(guest->thread_done));
334
335     v3_free_vm(guest->v3_ctx);
336     
337     device_destroy(v3_class, guest->vm_dev);
338
339     cdev_del(&(guest->cdev));
340
341     kfree(guest->img);
342     kfree(guest);
343
344     return 0;
345 }