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.


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