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.


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