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