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.


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