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.


more extension ports
[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 #ifdef V3_CONFIG_HOST_DEVICE
119 #include "palacios-host-dev.h"
120 #define HOST_DEV_URL_LEN 256
121 #endif
122
123 extern struct class * v3_class;
124
125
126 static long v3_vm_ioctl(struct file * filp,
127                         unsigned int ioctl, unsigned long arg) {
128
129     struct v3_guest * guest = filp->private_data;
130
131     printk("V3 IOCTL %d\n", ioctl);
132
133     switch (ioctl) {
134
135         case V3_VM_STOP: {
136             printk("Stopping VM\n");
137             stop_palacios_vm(guest);
138             break;
139         }
140
141
142
143         case V3_VM_HOST_DEV_CONNECT: {
144 #ifdef V3_CONFIG_HOST_DEVICE
145             void __user * argp = (void __user *)arg;
146             char host_dev_url[HOST_DEV_URL_LEN];
147
148             if (copy_from_user(host_dev_url, argp, HOST_DEV_URL_LEN)) {
149                 printk("copy from user error getting url for host device connect...\n");
150                 return -EFAULT;
151             }
152
153             return connect_host_dev(guest,host_dev_url);
154 #else
155             printk("palacios: Host device support not available\n");
156             return -EFAULT;
157 #endif
158             break;
159         }
160
161
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     lock_kernel();
218     daemonize(guest->name);
219     // allow_signal(SIGKILL);
220     unlock_kernel();
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     kfree(guest->img);
294     kfree(guest);
295
296     return 0;
297 }