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 packet to extension framework and fixed type in socket 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 #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
253     printk("Creating VM device: Major %d, Minor %d\n", MAJOR(guest->vm_dev), MINOR(guest->vm_dev));
254
255     cdev_init(&(guest->cdev), &v3_vm_fops);
256
257     guest->cdev.owner = THIS_MODULE;
258     guest->cdev.ops = &v3_vm_fops;
259
260
261     printk("Adding VM device\n");
262     err = cdev_add(&(guest->cdev), guest->vm_dev, 1);
263
264     if (err) {
265         printk("Fails to add cdev\n");
266         v3_free_vm(guest->v3_ctx);
267         complete(&(guest->start_done));
268         return -1;
269     }
270
271     if (device_create(v3_class, NULL, guest->vm_dev, guest, "v3-vm%d", MINOR(guest->vm_dev)) == NULL){
272         printk("Fails to create device\n");
273         cdev_del(&(guest->cdev));
274         v3_free_vm(guest->v3_ctx);
275         complete(&(guest->start_done));
276         return -1;
277     }
278
279     complete(&(guest->start_done));
280
281     printk("palacios: launching vm\n");
282
283     if (v3_start_vm(guest->v3_ctx, 0xffffffff) < 0) { 
284         printk("palacios: launch of vm failed\n");
285         device_destroy(v3_class, guest->vm_dev);
286         cdev_del(&(guest->cdev));
287         v3_free_vm(guest->v3_ctx);
288         return -1;
289     }
290     
291     complete(&(guest->thread_done));
292
293     printk("palacios: vm completed.  returning.\n");
294
295     return 0;
296 }
297
298
299
300
301 int stop_palacios_vm(struct v3_guest * guest) {
302
303     v3_stop_vm(guest->v3_ctx);
304
305     wait_for_completion(&(guest->thread_done));
306
307     v3_free_vm(guest->v3_ctx);
308     
309     device_destroy(v3_class, guest->vm_dev);
310
311     cdev_del(&(guest->cdev));
312
313     kfree(guest->img);
314     kfree(guest);
315
316     return 0;
317 }