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.


added host_pci passthrough PCI support
[palacios.git] / linux_module / main.c
1 /* 
2    Palacios main control interface
3    (c) Jack Lange, 2010
4  */
5
6
7 #include <linux/module.h>
8 #include <linux/moduleparam.h>
9 #include <linux/errno.h>
10 #include <linux/percpu.h>
11 #include <linux/fs.h>
12 #include <linux/uaccess.h>
13 #include <linux/device.h>
14 #include <linux/cdev.h>
15
16 #include <linux/io.h>
17
18 #include <linux/file.h>
19 #include <linux/spinlock.h>
20 #include <linux/kthread.h>
21
22 #include <linux/proc_fs.h>
23
24 #include <palacios/vmm.h>
25
26 #include "palacios.h"
27 #include "mm.h"
28 #include "vm.h"
29
30 #include "linux-exts.h"
31
32
33
34 MODULE_LICENSE("GPL");
35
36 // Module parameter
37 int cpu_list[NR_CPUS] = {};
38 int cpu_list_len = 0;
39 module_param_array(cpu_list, int, &cpu_list_len, 0644);
40 MODULE_PARM_DESC(cpu_list, "Comma-delimited list of CPUs that Palacios will run on");
41
42 int mod_allocs = 0;
43 int mod_frees = 0;
44
45
46 static int v3_major_num = 0;
47
48 static struct v3_guest * guest_map[MAX_VMS] = {[0 ... MAX_VMS - 1] = 0};
49 static struct proc_dir_entry *dir = 0;
50
51 struct class * v3_class = NULL;
52 static struct cdev ctrl_dev;
53
54 static int register_vm(struct v3_guest * guest) {
55     int i = 0;
56
57     for (i = 0; i < MAX_VMS; i++) {
58         if (guest_map[i] == NULL) {
59             guest_map[i] = guest;
60             return i;
61         }
62     }
63
64     return -1;
65 }
66
67
68
69 static long v3_dev_ioctl(struct file * filp,
70                          unsigned int ioctl, unsigned long arg) {
71     void __user * argp = (void __user *)arg;
72     DEBUG("V3 IOCTL %d\n", ioctl);
73
74
75     switch (ioctl) {
76         case V3_CREATE_GUEST:{
77             int vm_minor = 0;
78             struct v3_guest_img user_image;
79             struct v3_guest * guest = palacios_alloc(sizeof(struct v3_guest));
80
81             if (IS_ERR(guest)) {
82                 ERROR("Palacios: Error allocating Kernel guest_image\n");
83                 return -EFAULT;
84             }
85
86             memset(guest, 0, sizeof(struct v3_guest));
87
88             INFO("Palacios: Creating V3 Guest...\n");
89
90             vm_minor = register_vm(guest);
91
92             if (vm_minor == -1) {
93                 ERROR("Palacios Error: Too many VMs are currently running\n");
94                 goto out_err;
95             }
96
97             guest->vm_dev = MKDEV(v3_major_num, vm_minor);
98
99             if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
100                 ERROR("Palacios Error: copy from user error getting guest image...\n");
101                 goto out_err1;
102             }
103
104             guest->img_size = user_image.size;
105
106             DEBUG("Palacios: Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
107             guest->img = vmalloc(guest->img_size);
108
109             if (IS_ERR(guest->img)) {
110                 ERROR("Palacios Error: Could not allocate space for guest image\n");
111                 goto out_err1;
112             }
113
114             if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
115                 ERROR("Palacios: Error loading guest data\n");
116                 goto out_err2;
117             }      
118
119             strncpy(guest->name, user_image.name, 127);
120
121             INIT_LIST_HEAD(&(guest->exts));
122
123             if (create_palacios_vm(guest) == -1) {
124                 ERROR("Palacios: Error creating guest\n");
125                 goto out_err2;
126             }
127
128             return vm_minor;
129
130
131 out_err2:
132             vfree(guest->img);
133 out_err1:
134             guest_map[vm_minor] = NULL; 
135 out_err:
136             palacios_free(guest);
137
138             return -1;
139
140             break;
141         }
142         case V3_FREE_GUEST: {
143             unsigned long vm_idx = arg;
144             struct v3_guest * guest = guest_map[vm_idx];
145
146             if (!guest) {
147                 ERROR("No VM at index %ld\n",vm_idx);
148                 return -1;
149             }
150
151             INFO("Freeing VM (%s) (%p)\n", guest->name, guest);
152
153             free_palacios_vm(guest);
154             guest_map[vm_idx] = NULL;
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                 ERROR("copy from user error getting mem_region...\n");
164                 return -EFAULT;
165             }
166
167             DEBUG("Adding %llu pages to Palacios memory\n", mem.num_pages);
168
169             if (add_palacios_memory(mem.base_addr, mem.num_pages) == -1) {
170                 ERROR("Error adding memory to Palacios\n");
171                 return -EFAULT;
172             }
173
174             break;
175         }
176
177
178         default: {
179             struct global_ctrl * ctrl = get_global_ctrl(ioctl);
180             
181             if (ctrl) {
182                 return ctrl->handler(ioctl, arg);
183             }
184
185             WARNING("\tUnhandled global ctrl cmd: %d\n", ioctl);
186
187             return -EINVAL;
188         }
189     }
190
191     return 0;
192 }
193
194
195
196 static struct file_operations v3_ctrl_fops = {
197     .owner = THIS_MODULE,
198     .unlocked_ioctl = v3_dev_ioctl,
199     .compat_ioctl = v3_dev_ioctl,
200 };
201
202
203
204 struct proc_dir_entry *palacios_get_procdir(void) 
205 {
206     return dir;
207 }
208
209 static int read_guests(char * buf, char ** start, off_t off, int count,
210                        int * eof, void * data)
211 {
212     int len = 0;
213     unsigned int i = 0;
214     
215     for(i = 0; i < MAX_VMS; i++) {
216         if (guest_map[i] != NULL) {
217             if (len<count) { 
218                 len += snprintf(buf+len, count-len,
219                                 "%s\t/dev/v3-vm%d\n", 
220                                 guest_map[i]->name, i);
221             }
222         }
223     }
224     
225     return len;
226 }
227
228 static int show_mem(char * buf, char ** start, off_t off, int count,
229                     int * eof, void * data)
230 {
231     int len = 0;
232     
233     len = snprintf(buf,count, "%p\n", (void *)get_palacios_base_addr());
234     len += snprintf(buf+len,count-len, "%lld\n", get_palacios_num_pages());
235     
236     return len;
237 }
238
239
240 static int __init v3_init(void) {
241     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
242     int ret = 0;
243
244
245     palacios_init_mm();
246
247     // Initialize Palacios
248     palacios_vmm_init();
249
250
251     // initialize extensions
252     init_lnx_extensions();
253
254
255     v3_class = class_create(THIS_MODULE, "vms");
256     if (IS_ERR(v3_class)) {
257         ERROR("Failed to register V3 VM device class\n");
258         return PTR_ERR(v3_class);
259     }
260
261     INFO("intializing V3 Control device\n");
262
263     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
264
265     if (ret < 0) {
266         ERROR("Error registering device region for V3 devices\n");
267         goto failure2;
268     }
269
270     v3_major_num = MAJOR(dev);
271
272     dev = MKDEV(v3_major_num, MAX_VMS + 1);
273
274     
275     DEBUG("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
276     cdev_init(&ctrl_dev, &v3_ctrl_fops);
277     ctrl_dev.owner = THIS_MODULE;
278     ctrl_dev.ops = &v3_ctrl_fops;
279     cdev_add(&ctrl_dev, dev, 1);
280     
281     device_create(v3_class, NULL, dev, NULL, "v3vee");
282
283     if (ret != 0) {
284         ERROR("Error adding v3 control device\n");
285         goto failure1;
286     }
287
288     dir = proc_mkdir("v3vee", NULL);
289     if(dir) {
290         struct proc_dir_entry *entry;
291
292         entry = create_proc_read_entry("v3-guests", 0444, dir, 
293                                        read_guests, NULL);
294         if (entry) {
295             INFO("/proc/v3vee/v3-guests successfully created\n");
296         } else {
297             ERROR("Could not create proc entry\n");
298             goto failure1;
299         }
300         
301         entry = create_proc_read_entry("v3-mem", 0444, dir,
302                                        show_mem, NULL);
303         if (entry) {
304             INFO("/proc/v3vee/v3-mem successfully added\n");
305         } else {
306             ERROR("Could not create proc entry\n");
307             goto failure1;
308         }
309     } else {
310         ERROR("Could not create proc entry\n");
311         goto failure1;
312     }
313         
314     return 0;
315
316  failure1:
317     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
318  failure2:
319     class_destroy(v3_class);
320
321     return ret;
322 }
323
324
325 static void __exit v3_exit(void) {
326     extern u32 pg_allocs;
327     extern u32 pg_frees;
328     extern u32 mallocs;
329     extern u32 frees;
330     int i = 0;
331     struct v3_guest * guest;
332     dev_t dev;
333
334
335     /* Stop and free any running VMs */ 
336     for (i = 0; i < MAX_VMS; i++) {
337         if (guest_map[i] != NULL) {
338                 guest = (struct v3_guest *)guest_map[i];
339
340                 if (v3_stop_vm(guest->v3_ctx) < 0) 
341                         ERROR("Couldn't stop VM %d\n", i);
342
343                 free_palacios_vm(guest);
344                 guest_map[i] = NULL;
345         }
346     }
347
348     dev = MKDEV(v3_major_num, MAX_VMS + 1);
349
350     INFO("Removing V3 Control device\n");
351
352
353     palacios_vmm_exit();
354
355     DEBUG("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
356     DEBUG("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
357
358     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
359
360     cdev_del(&ctrl_dev);
361
362     device_destroy(v3_class, dev);
363     class_destroy(v3_class);
364
365
366     deinit_lnx_extensions();
367
368     palacios_deinit_mm();
369
370     remove_proc_entry("v3-guests", dir);
371     remove_proc_entry("v3-mem", dir);
372     remove_proc_entry("v3vee", NULL);
373
374     DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
375 }
376
377
378
379 module_init(v3_init);
380 module_exit(v3_exit);
381
382
383
384 void * trace_malloc(size_t size, gfp_t flags) {
385     void * addr = NULL;
386
387     mod_allocs++;
388     addr = kmalloc(size, flags);
389
390     return addr;
391 }
392
393
394 void trace_free(const void * objp) {
395     mod_frees++;
396     kfree(objp);
397 }