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.


moved host device to extension framework
[palacios-OLD.git] / linux_module / palacios-dev.c
1 /* 
2    Palacios main control interface
3    (c) Jack Lange, 2010
4  */
5
6
7 #include <linux/module.h>
8 #include <linux/errno.h>
9 #include <linux/percpu.h>
10 #include <linux/fs.h>
11 #include <linux/uaccess.h>
12 #include <linux/device.h>
13 #include <linux/cdev.h>
14
15 #include <linux/io.h>
16
17 #include <linux/file.h>
18 #include <linux/spinlock.h>
19 #include <linux/kthread.h>
20
21 #include "palacios.h"
22 #include "palacios-mm.h"
23 #include "palacios-vm.h"
24 #include "palacios-vnet.h"
25
26 #include "linux-exts.h"
27
28
29
30 MODULE_LICENSE("GPL");
31
32 int mod_allocs = 0;
33 int mod_frees = 0;
34
35
36 static int v3_major_num = 0;
37
38 static u8 v3_minor_map[MAX_VMS / 8] = {[0 ... (MAX_VMS / 8) - 1] = 0}; 
39
40
41 struct class * v3_class = NULL;
42 static struct cdev ctrl_dev;
43
44 static int register_vm( void ) {
45     int i, j = 0;
46     int avail = 0;
47
48     for (i = 0; i < sizeof(v3_minor_map); i++) {
49         if (v3_minor_map[i] != 0xff) {
50             for (j = 0; j < 8; j++) {
51                 if (!(v3_minor_map[i] & (0x1 << j))) {
52                     avail = 1;
53                     v3_minor_map[i] |= (0x1 << j);
54                     break;
55                 }
56             }
57         
58             if (avail == 1) {
59                 break;
60             }
61         }
62     }
63
64     if (avail == 0) {
65         return -1;
66     }
67         
68     return (i * 8) + j;
69 }
70
71
72
73 static long v3_dev_ioctl(struct file * filp,
74                          unsigned int ioctl, unsigned long arg) {
75     void __user * argp = (void __user *)arg;
76     printk("V3 IOCTL %d\n", ioctl);
77
78
79     switch (ioctl) {
80         case V3_START_GUEST:{
81             int vm_minor = 0;
82             struct v3_guest_img user_image;
83             struct v3_guest * guest = kmalloc(sizeof(struct v3_guest), GFP_KERNEL);
84
85             if (IS_ERR(guest)) {
86                 printk("Error allocating Kernel guest_image\n");
87                 return -EFAULT;
88             }
89
90             memset(guest, 0, sizeof(struct v3_guest));
91
92             printk("Starting V3 Guest...\n");
93
94             vm_minor = register_vm();
95
96             if (vm_minor == -1) {
97                 printk("Too many VMs are currently running\n");
98                 return -EFAULT;
99             }
100
101             guest->vm_dev = MKDEV(v3_major_num, vm_minor);
102
103             if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
104                 printk("copy from user error getting guest image...\n");
105                 return -EFAULT;
106             }
107
108             guest->img_size = user_image.size;
109
110             printk("Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
111             guest->img = vmalloc(guest->img_size);
112
113             if (IS_ERR(guest->img)) {
114                 printk("Error: Could not allocate space for guest image\n");
115                 return -EFAULT;
116             }
117
118             if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
119                 printk("Error loading guest data\n");
120                 return -EFAULT;
121             }      
122
123             strncpy(guest->name, user_image.name, 127);
124
125             printk("Launching VM\n");
126
127             INIT_LIST_HEAD(&(guest->exts));
128
129             init_completion(&(guest->start_done));
130             init_completion(&(guest->thread_done));
131
132             { 
133                 struct task_struct * launch_thread = NULL;
134                 // At some point we're going to want to allow the user to specify a CPU mask
135                 // But for now, well just launch from the local core, and rely on the global cpu mask
136
137                 preempt_disable();
138                 launch_thread = kthread_create(start_palacios_vm, guest, guest->name);
139                 
140                 if (IS_ERR(launch_thread)) {
141                     preempt_enable();
142                     printk("Palacios error creating launch thread for vm (%s)\n", guest->name);
143                     return -EFAULT;
144                 }
145
146                 kthread_bind(launch_thread, smp_processor_id());
147                 preempt_enable();
148
149                 wake_up_process(launch_thread);
150             }
151
152             wait_for_completion(&(guest->start_done));
153
154             return guest->vm_dev;
155             break;
156         }
157         case V3_ADD_MEMORY: {
158             struct v3_mem_region mem;
159             
160             memset(&mem, 0, sizeof(struct v3_mem_region));
161             
162             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
163                 printk("copy from user error getting mem_region...\n");
164                 return -EFAULT;
165             }
166
167             printk("Adding %llu pages to Palacios memory\n", mem.num_pages);
168
169             if (add_palacios_memory(mem.base_addr, mem.num_pages) == -1) {
170                 printk("Error adding memory to Palacios\n");
171                 return -EFAULT;
172             }
173
174             break;
175         }
176
177         default: 
178             printk("\tUnhandled\n");
179             return -EINVAL;
180     }
181
182     return 0;
183 }
184
185
186
187 static struct file_operations v3_ctrl_fops = {
188     .owner = THIS_MODULE,
189     .unlocked_ioctl = v3_dev_ioctl,
190     .compat_ioctl = v3_dev_ioctl,
191 };
192
193
194
195 static int __init v3_init(void) {
196     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
197     int ret = 0;
198
199
200     palacios_init_mm();
201
202
203     // Initialize Palacios
204     
205     palacios_vmm_init();
206
207
208     // initialize extensions
209     init_lnx_extensions();
210
211
212     v3_class = class_create(THIS_MODULE, "vms");
213     if (IS_ERR(v3_class)) {
214         printk("Failed to register V3 VM device class\n");
215         return PTR_ERR(v3_class);
216     }
217
218     printk("intializing V3 Control device\n");
219
220     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
221
222     if (ret < 0) {
223         printk("Error registering device region for V3 devices\n");
224         goto failure2;
225     }
226
227     v3_major_num = MAJOR(dev);
228
229     dev = MKDEV(v3_major_num, MAX_VMS + 1);
230
231     
232     printk("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
233     cdev_init(&ctrl_dev, &v3_ctrl_fops);
234     ctrl_dev.owner = THIS_MODULE;
235     ctrl_dev.ops = &v3_ctrl_fops;
236     cdev_add(&ctrl_dev, dev, 1);
237     
238     device_create(v3_class, NULL, dev, NULL, "v3vee");
239
240     if (ret != 0) {
241         printk("Error adding v3 control device\n");
242         goto failure1;
243     }
244
245
246
247
248
249
250 #ifdef V3_CONFIG_VNET
251     palacios_vnet_init();
252 #endif
253
254     return 0;
255
256  failure1:
257     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
258  failure2:
259     class_destroy(v3_class);
260
261     return ret;
262 }
263
264
265 static void __exit v3_exit(void) {
266     extern u32 pg_allocs;
267     extern u32 pg_frees;
268     extern u32 mallocs;
269     extern u32 frees;
270
271
272     // should probably try to stop any guests
273
274
275
276     dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
277
278     printk("Removing V3 Control device\n");
279
280
281     palacios_vmm_exit();
282
283     printk("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
284     printk("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
285
286     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
287
288     cdev_del(&ctrl_dev);
289
290     device_destroy(v3_class, dev);
291     class_destroy(v3_class);
292
293
294     deinit_lnx_extensions();
295
296
297
298 #ifdef V3_CONFIG_VNET
299     palacios_vnet_deinit();
300 #endif
301
302     palacios_deinit_mm();
303
304     printk("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
305 }
306
307
308
309 module_init(v3_init);
310 module_exit(v3_exit);
311
312
313
314 void * trace_malloc(size_t size, gfp_t flags) {
315     void * addr = NULL;
316
317     mod_allocs++;
318     addr = kmalloc(size, flags);
319
320     return addr;
321 }
322
323
324 void trace_free(const void * objp) {
325     mod_frees++;
326     kfree(objp);
327 }