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.


abb798fce74abc7dfbc695b204bcef710e766f89
[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(struct v3_guest * guest)  {
250     int err;
251
252     init_vm_extensions(guest);
253
254     guest->v3_ctx = v3_create_vm(guest->img, (void *)guest, guest->name);
255
256     if (guest->v3_ctx == NULL) { 
257         printk("palacios: failed to create vm\n");
258         return -1;
259     }
260
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         return -1;
277     }
278
279     if (device_create(v3_class, NULL, guest->vm_dev, guest, "v3-vm%d", MINOR(guest->vm_dev)) == NULL){
280         printk("Fails to create device\n");
281         cdev_del(&(guest->cdev));
282         v3_free_vm(guest->v3_ctx);
283         return -1;
284     }
285
286     printk("palacios: launching vm\n");
287
288     if (v3_start_vm(guest->v3_ctx, 0xffffffff) < 0) { 
289         printk("palacios: launch of vm failed\n");
290         device_destroy(v3_class, guest->vm_dev);
291         cdev_del(&(guest->cdev));
292         v3_free_vm(guest->v3_ctx);
293         return -1;
294     }
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
307     v3_stop_vm(guest->v3_ctx);
308
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     vfree(guest->img);
317     kfree(guest);
318
319     return 0;
320 }