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.


Merge branch 'devel' of palacios@newskysaw.cs.northwestern.edu:/home/palacios/palacio...
[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
131         case V3_VM_STOP: {
132             printk("Stopping VM (%s)\n", guest->name);
133             stop_palacios_vm(guest);
134             break;
135         }
136         case V3_VM_PAUSE: {
137             printk("Pausing VM (%s)\n", guest->name);
138             v3_pause_vm(guest->v3_ctx);
139             break;
140         }
141         case V3_VM_CONTINUE: {
142             printk("Continuing VM (%s)\n", guest->name);
143             v3_continue_vm(guest->v3_ctx);
144             break;
145         }
146         case V3_VM_MOVE_CORE: {
147             struct v3_core_move_cmd cmd;
148             void __user * argp = (void __user *)arg;
149
150             memset(&cmd, 0, sizeof(struct v3_core_move_cmd));
151             
152             if (copy_from_user(&cmd, argp, sizeof(struct v3_core_move_cmd))) {
153                 printk("copy from user error getting migrate command...\n");
154                 return -EFAULT;
155             }
156         
157             printk("moving guest %s vcore %d to CPU %d\n", guest->name, cmd.vcore_id, cmd.pcore_id);
158
159             v3_move_vm_core(guest->v3_ctx, cmd.vcore_id, cmd.pcore_id);
160         }
161         break;
162
163         default: {
164             struct vm_ctrl * ctrl = get_ctrl(guest, ioctl);
165
166             if (ctrl) {
167                 return ctrl->handler(guest, ioctl, arg, ctrl->priv_data);
168             }
169             
170             
171             printk("\tUnhandled ctrl cmd: %d\n", ioctl);
172             return -EINVAL;
173         }
174     }
175
176     return 0;
177 }
178
179 static int v3_vm_open(struct inode * inode, struct file * filp) {
180     struct v3_guest * guest = container_of(inode->i_cdev, struct v3_guest, cdev);
181     filp->private_data = guest;
182     return 0;
183 }
184
185
186 static ssize_t v3_vm_read(struct file * filp, char __user * buf, size_t size, loff_t * offset) {
187     
188     return 0;
189 }
190
191
192 static ssize_t v3_vm_write(struct file * filp, const char __user * buf, size_t size, loff_t * offset) {
193
194     return 0;
195 }
196
197
198 static struct file_operations v3_vm_fops = {
199     .owner = THIS_MODULE,
200     .unlocked_ioctl = v3_vm_ioctl,
201     .compat_ioctl = v3_vm_ioctl,
202     .open = v3_vm_open,
203     .read = v3_vm_read, 
204     .write = v3_vm_write,
205 };
206
207
208 extern u32 pg_allocs;
209 extern u32 pg_frees;
210 extern u32 mallocs;
211 extern u32 frees;
212
213 int start_palacios_vm(void * arg)  {
214     struct v3_guest * guest = (struct v3_guest *)arg;
215     int err;
216
217
218     daemonize(guest->name);
219     // allow_signal(SIGKILL);
220
221     
222     init_vm_extensions(guest);
223
224     guest->v3_ctx = v3_create_vm(guest->img, (void *)guest, guest->name);
225
226     if (guest->v3_ctx == NULL) { 
227         printk("palacios: failed to create vm\n");
228         complete(&(guest->start_done));
229         return -1;
230     }
231
232
233     printk("Creating VM device: Major %d, Minor %d\n", MAJOR(guest->vm_dev), MINOR(guest->vm_dev));
234
235     cdev_init(&(guest->cdev), &v3_vm_fops);
236
237     guest->cdev.owner = THIS_MODULE;
238     guest->cdev.ops = &v3_vm_fops;
239
240
241     printk("Adding VM device\n");
242     err = cdev_add(&(guest->cdev), guest->vm_dev, 1);
243
244     if (err) {
245         printk("Fails to add cdev\n");
246         v3_free_vm(guest->v3_ctx);
247         complete(&(guest->start_done));
248         return -1;
249     }
250
251     if (device_create(v3_class, NULL, guest->vm_dev, guest, "v3-vm%d", MINOR(guest->vm_dev)) == NULL){
252         printk("Fails to create device\n");
253         cdev_del(&(guest->cdev));
254         v3_free_vm(guest->v3_ctx);
255         complete(&(guest->start_done));
256         return -1;
257     }
258
259     complete(&(guest->start_done));
260
261     printk("palacios: launching vm\n");
262
263     if (v3_start_vm(guest->v3_ctx, 0xffffffff) < 0) { 
264         printk("palacios: launch of vm failed\n");
265         device_destroy(v3_class, guest->vm_dev);
266         cdev_del(&(guest->cdev));
267         v3_free_vm(guest->v3_ctx);
268         return -1;
269     }
270     
271     complete(&(guest->thread_done));
272
273     printk("palacios: vm completed.  returning.\n");
274
275     return 0;
276 }
277
278
279
280
281 int stop_palacios_vm(struct v3_guest * guest) {
282
283     v3_stop_vm(guest->v3_ctx);
284
285     wait_for_completion(&(guest->thread_done));
286
287     v3_free_vm(guest->v3_ctx);
288     
289     device_destroy(v3_class, guest->vm_dev);
290
291     cdev_del(&(guest->cdev));
292
293     vfree(guest->img);
294     kfree(guest);
295
296     return 0;
297 }