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.


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