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.


return type fix
[palacios.git] / linux_module / palacios-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/smp_lock.h>
17 #include <linux/file.h>
18 #include <linux/spinlock.h>
19 #include <linux/rbtree.h>
20
21 #include <palacios/vmm.h>
22
23 #include "palacios.h"
24 #include "palacios-vm.h"
25 #include "linux-exts.h"
26
27
28 struct vm_ctrl {
29     unsigned int cmd;
30
31     int (*handler)(struct v3_guest * guest, 
32                    unsigned int cmd, unsigned long arg, 
33                    void * priv_data);
34
35     void * priv_data;
36
37     struct rb_node tree_node;
38 };
39
40
41 static inline struct vm_ctrl * __insert_ctrl(struct v3_guest * vm, 
42                                              struct vm_ctrl * ctrl) {
43     struct rb_node ** p = &(vm->vm_ctrls.rb_node);
44     struct rb_node * parent = NULL;
45     struct vm_ctrl * tmp_ctrl = NULL;
46
47     while (*p) {
48         parent = *p;
49         tmp_ctrl = rb_entry(parent, struct vm_ctrl, tree_node);
50
51         if (ctrl->cmd < tmp_ctrl->cmd) {
52             p = &(*p)->rb_left;
53         } else if (ctrl->cmd > tmp_ctrl->cmd) {
54             p = &(*p)->rb_right;
55         } else {
56             return tmp_ctrl;
57         }
58     }
59
60     rb_link_node(&(ctrl->tree_node), parent, p);
61
62     return NULL;
63 }
64
65
66
67 int add_guest_ctrl(struct v3_guest * guest, unsigned int cmd, 
68                    int (*handler)(struct v3_guest * guest, 
69                                   unsigned int cmd, unsigned long arg, 
70                                   void * priv_data),
71                    void * priv_data) {
72     struct vm_ctrl * ctrl = kmalloc(sizeof(struct vm_ctrl), GFP_KERNEL);
73
74     if (ctrl == NULL) {
75         printk("Error: Could not allocate vm ctrl %d\n", cmd);
76         return -1;
77     }
78
79     ctrl->cmd = cmd;
80     ctrl->handler = handler;
81     ctrl->priv_data = priv_data;
82
83     if (__insert_ctrl(guest, ctrl) != NULL) {
84         printk("Could not insert guest ctrl %d\n", cmd);
85         kfree(ctrl);
86         return -1;
87     }
88     
89     rb_insert_color(&(ctrl->tree_node), &(guest->vm_ctrls));
90
91     return 0;
92 }
93
94
95 static struct vm_ctrl * get_ctrl(struct v3_guest * guest, unsigned int cmd) {
96     struct rb_node * n = guest->vm_ctrls.rb_node;
97     struct vm_ctrl * ctrl = NULL;
98
99     while (n) {
100         ctrl = rb_entry(n, struct vm_ctrl, tree_node);
101
102         if (cmd < ctrl->cmd) {
103             n = n->rb_left;
104         } else if (cmd > ctrl->cmd) {
105             n = n->rb_right;
106         } else {
107             return ctrl;
108         }
109     }
110
111     return NULL;
112 }
113
114
115
116
117
118
119
120 extern struct class * v3_class;
121
122
123 static long v3_vm_ioctl(struct file * filp,
124                         unsigned int ioctl, unsigned long arg) {
125
126     struct v3_guest * guest = filp->private_data;
127
128     printk("V3 IOCTL %d\n", ioctl);
129
130     switch (ioctl) {
131
132         case V3_VM_STOP: {
133             printk("Stopping VM\n");
134             stop_palacios_vm(guest);
135             break;
136         }
137
138         default: {
139             struct vm_ctrl * ctrl = get_ctrl(guest, ioctl);
140
141             if (ctrl) {
142                 return ctrl->handler(guest, ioctl, arg, ctrl->priv_data);
143             }
144             
145             
146             printk("\tUnhandled ctrl cmd: %d\n", ioctl);
147             return -EINVAL;
148         }
149     }
150
151     return 0;
152 }
153
154 static int v3_vm_open(struct inode * inode, struct file * filp) {
155     struct v3_guest * guest = container_of(inode->i_cdev, struct v3_guest, cdev);
156     filp->private_data = guest;
157     return 0;
158 }
159
160
161 static ssize_t v3_vm_read(struct file * filp, char __user * buf, size_t size, loff_t * offset) {
162     
163     return 0;
164 }
165
166
167 static ssize_t v3_vm_write(struct file * filp, const char __user * buf, size_t size, loff_t * offset) {
168
169     return 0;
170 }
171
172
173 static struct file_operations v3_vm_fops = {
174     .owner = THIS_MODULE,
175     .unlocked_ioctl = v3_vm_ioctl,
176     .compat_ioctl = v3_vm_ioctl,
177     .open = v3_vm_open,
178     .read = v3_vm_read, 
179     .write = v3_vm_write,
180 };
181
182
183 extern u32 pg_allocs;
184 extern u32 pg_frees;
185 extern u32 mallocs;
186 extern u32 frees;
187
188 int start_palacios_vm(void * arg)  {
189     struct v3_guest * guest = (struct v3_guest *)arg;
190     int err;
191
192     lock_kernel();
193     daemonize(guest->name);
194     // allow_signal(SIGKILL);
195     unlock_kernel();
196     
197     init_vm_extensions(guest);
198
199     guest->v3_ctx = v3_create_vm(guest->img, (void *)guest, guest->name);
200
201     if (guest->v3_ctx == NULL) { 
202         printk("palacios: failed to create vm\n");
203         complete(&(guest->start_done));
204         return -1;
205     }
206
207
208     printk("Creating VM device: Major %d, Minor %d\n", MAJOR(guest->vm_dev), MINOR(guest->vm_dev));
209
210     cdev_init(&(guest->cdev), &v3_vm_fops);
211
212     guest->cdev.owner = THIS_MODULE;
213     guest->cdev.ops = &v3_vm_fops;
214
215
216     printk("Adding VM device\n");
217     err = cdev_add(&(guest->cdev), guest->vm_dev, 1);
218
219     if (err) {
220         printk("Fails to add cdev\n");
221         v3_free_vm(guest->v3_ctx);
222         complete(&(guest->start_done));
223         return -1;
224     }
225
226     if (device_create(v3_class, NULL, guest->vm_dev, guest, "v3-vm%d", MINOR(guest->vm_dev)) == NULL){
227         printk("Fails to create device\n");
228         cdev_del(&(guest->cdev));
229         v3_free_vm(guest->v3_ctx);
230         complete(&(guest->start_done));
231         return -1;
232     }
233
234     complete(&(guest->start_done));
235
236     printk("palacios: launching vm\n");
237
238     if (v3_start_vm(guest->v3_ctx, 0xffffffff) < 0) { 
239         printk("palacios: launch of vm failed\n");
240         device_destroy(v3_class, guest->vm_dev);
241         cdev_del(&(guest->cdev));
242         v3_free_vm(guest->v3_ctx);
243         return -1;
244     }
245     
246     complete(&(guest->thread_done));
247
248     printk("palacios: vm completed.  returning.\n");
249
250     return 0;
251 }
252
253
254
255
256 int stop_palacios_vm(struct v3_guest * guest) {
257
258     v3_stop_vm(guest->v3_ctx);
259
260     wait_for_completion(&(guest->thread_done));
261
262     v3_free_vm(guest->v3_ctx);
263     
264     device_destroy(v3_class, guest->vm_dev);
265
266     cdev_del(&(guest->cdev));
267
268     kfree(guest->img);
269     kfree(guest);
270
271     return 0;
272 }