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.


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