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.


hooked checkpoint code up to the linux module and added user space tools
[palacios.git] / linux_module / 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 #include <linux/vmalloc.h>
16 #include <linux/file.h>
17 #include <linux/spinlock.h>
18 #include <linux/rbtree.h>
19
20 #include <palacios/vmm.h>
21
22 #include "palacios.h"
23 #include "vm.h"
24 #include "linux-exts.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
115
116
117
118
119 extern struct class * v3_class;
120
121
122 static long v3_vm_ioctl(struct file * filp,
123                         unsigned int ioctl, unsigned long arg) {
124
125     struct v3_guest * guest = filp->private_data;
126
127     printk("V3 IOCTL %d\n", ioctl);
128
129     switch (ioctl) {
130         case V3_VM_PAUSE: {
131             printk("Pausing VM (%s)\n", guest->name);
132             v3_pause_vm(guest->v3_ctx);
133             break;
134         }
135         case V3_VM_CONTINUE: {
136             printk("Continuing VM (%s)\n", guest->name);
137             v3_continue_vm(guest->v3_ctx);
138             break;
139         }
140 #ifdef V3_CONFIG_CHECKPOINT
141         case V3_VM_SAVE: {
142             struct v3_chkpt_info chkpt;
143             void __user * argp = (void __user *)arg;
144
145             memset(&chkpt, 0, sizeof(struct v3_chkpt_info));
146
147             if (copy_from_user(&chkpt, argp, sizeof(struct v3_chkpt_info))) {
148                 printk("Copy from user error getting checkpoint info\n");
149                 return -EFAULT;
150             }
151             
152             printk("Saving Guest to %s:%s\n", chkpt.store, chkpt.url);
153
154             if (v3_save_vm(guest->v3_ctx, chkpt.store, chkpt.url) == -1) {
155                 printk("Error checkpointing VM state\n");
156                 return -EFAULT;
157             }
158             
159             break;
160         }
161         case V3_VM_LOAD: {
162             struct v3_chkpt_info chkpt;
163             void __user * argp = (void __user *)arg;
164
165             memset(&chkpt, 0, sizeof(struct v3_chkpt_info));
166
167             if (copy_from_user(&chkpt, argp, sizeof(struct v3_chkpt_info))) {
168                 printk("Copy from user error getting checkpoint info\n");
169                 return -EFAULT;
170             }
171             
172             printk("Loading Guest to %s:%s\n", chkpt.store, chkpt.url);
173
174             if (v3_load_vm(guest->v3_ctx, chkpt.store, chkpt.url) == -1) {
175                 printk("Error Loading VM state\n");
176                 return -EFAULT;
177             }
178             
179             break;
180         }
181 #endif
182         case V3_VM_MOVE_CORE: {
183             struct v3_core_move_cmd cmd;
184             void __user * argp = (void __user *)arg;
185
186             memset(&cmd, 0, sizeof(struct v3_core_move_cmd));
187             
188             if (copy_from_user(&cmd, argp, sizeof(struct v3_core_move_cmd))) {
189                 printk("copy from user error getting migrate command...\n");
190                 return -EFAULT;
191             }
192         
193             printk("moving guest %s vcore %d to CPU %d\n", guest->name, cmd.vcore_id, cmd.pcore_id);
194
195             v3_move_vm_core(guest->v3_ctx, cmd.vcore_id, cmd.pcore_id);
196
197             break;
198         }
199         default: {
200             struct vm_ctrl * ctrl = get_ctrl(guest, ioctl);
201
202             if (ctrl) {
203                 return ctrl->handler(guest, ioctl, arg, ctrl->priv_data);
204             }
205             
206             
207             printk("\tUnhandled ctrl cmd: %d\n", ioctl);
208             return -EINVAL;
209         }
210     }
211
212     return 0;
213 }
214
215 static int v3_vm_open(struct inode * inode, struct file * filp) {
216     struct v3_guest * guest = container_of(inode->i_cdev, struct v3_guest, cdev);
217     filp->private_data = guest;
218     return 0;
219 }
220
221
222 static ssize_t v3_vm_read(struct file * filp, char __user * buf, size_t size, loff_t * offset) {
223     
224     return 0;
225 }
226
227
228 static ssize_t v3_vm_write(struct file * filp, const char __user * buf, size_t size, loff_t * offset) {
229
230     return 0;
231 }
232
233
234 static struct file_operations v3_vm_fops = {
235     .owner = THIS_MODULE,
236     .unlocked_ioctl = v3_vm_ioctl,
237     .compat_ioctl = v3_vm_ioctl,
238     .open = v3_vm_open,
239     .read = v3_vm_read, 
240     .write = v3_vm_write,
241 };
242
243
244 extern u32 pg_allocs;
245 extern u32 pg_frees;
246 extern u32 mallocs;
247 extern u32 frees;
248
249 int start_palacios_vm(void * arg)  {
250     struct v3_guest * guest = (struct v3_guest *)arg;
251     int err;
252
253
254     daemonize(guest->name);
255     // allow_signal(SIGKILL);
256
257     
258     init_vm_extensions(guest);
259
260     guest->v3_ctx = v3_create_vm(guest->img, (void *)guest, guest->name);
261
262     if (guest->v3_ctx == NULL) { 
263         printk("palacios: failed to create vm\n");
264         complete(&(guest->start_done));
265         return -1;
266     }
267
268
269     printk("Creating VM device: Major %d, Minor %d\n", MAJOR(guest->vm_dev), MINOR(guest->vm_dev));
270
271     cdev_init(&(guest->cdev), &v3_vm_fops);
272
273     guest->cdev.owner = THIS_MODULE;
274     guest->cdev.ops = &v3_vm_fops;
275
276
277     printk("Adding VM device\n");
278     err = cdev_add(&(guest->cdev), guest->vm_dev, 1);
279
280     if (err) {
281         printk("Fails to add cdev\n");
282         v3_free_vm(guest->v3_ctx);
283         complete(&(guest->start_done));
284         return -1;
285     }
286
287     if (device_create(v3_class, NULL, guest->vm_dev, guest, "v3-vm%d", MINOR(guest->vm_dev)) == NULL){
288         printk("Fails to create device\n");
289         cdev_del(&(guest->cdev));
290         v3_free_vm(guest->v3_ctx);
291         complete(&(guest->start_done));
292         return -1;
293     }
294
295     complete(&(guest->start_done));
296
297     printk("palacios: launching vm\n");
298
299     if (v3_start_vm(guest->v3_ctx, 0xffffffff) < 0) { 
300         printk("palacios: launch of vm failed\n");
301         device_destroy(v3_class, guest->vm_dev);
302         cdev_del(&(guest->cdev));
303         v3_free_vm(guest->v3_ctx);
304         return -1;
305     }
306     
307     complete(&(guest->thread_done));
308
309     printk("palacios: vm completed.  returning.\n");
310
311     return 0;
312 }
313
314
315
316
317 int stop_palacios_vm(struct v3_guest * guest) {
318
319
320     v3_stop_vm(guest->v3_ctx);
321
322     wait_for_completion(&(guest->thread_done));
323
324     v3_free_vm(guest->v3_ctx);
325
326     device_destroy(v3_class, guest->vm_dev);
327
328     cdev_del(&(guest->cdev));
329
330     vfree(guest->img);
331     kfree(guest);
332
333     return 0;
334 }