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