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