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.


Memory management enhancements: dynamic removal, cleanup at module remove time
[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 #include <linux/seq_file.h>
24
25 #include <palacios/vmm.h>
26
27 #include "palacios.h"
28 #include "mm.h"
29 #include "vm.h"
30 #include "allow_devmem.h"
31 #include "memcheck.h"
32 #include "lockcheck.h"
33
34 #include "linux-exts.h"
35
36
37 MODULE_LICENSE("GPL");
38
39 // Module parameter
40 int cpu_list[NR_CPUS] = {};
41 int cpu_list_len = 0;
42 module_param_array(cpu_list, int, &cpu_list_len, 0644);
43 MODULE_PARM_DESC(cpu_list, "Comma-delimited list of CPUs that Palacios will run on");
44
45 static int allow_devmem = 0;
46 module_param(allow_devmem, int, 0);
47 MODULE_PARM_DESC(allow_devmem, "Allow general user-space /dev/mem access even if kernel is strict");
48
49 // Palacios options parameter
50 static char *options;
51 module_param(options, charp, 0);
52 MODULE_PARM_DESC(options, "Generic options to internal Palacios modules");
53
54
55 int mod_allocs = 0;
56 int mod_frees = 0;
57
58 static int v3_major_num = 0;
59
60 static struct v3_guest * guest_map[MAX_VMS] = {[0 ... MAX_VMS - 1] = 0};
61 static struct proc_dir_entry * palacios_proc_dir = NULL;
62
63 struct class * v3_class = NULL;
64 static struct cdev ctrl_dev;
65
66 static int register_vm(struct v3_guest * guest) {
67     int i = 0;
68
69     for (i = 0; i < MAX_VMS; i++) {
70         if (guest_map[i] == NULL) {
71             guest_map[i] = guest;
72             return i;
73         }
74     }
75
76     return -1;
77 }
78
79
80
81 static long v3_dev_ioctl(struct file * filp,
82                          unsigned int ioctl, unsigned long arg) {
83     void __user * argp = (void __user *)arg;
84     DEBUG("V3 IOCTL %d\n", ioctl);
85
86
87     switch (ioctl) {
88         case V3_CREATE_GUEST:{
89             int vm_minor = 0;
90             struct v3_guest_img user_image;
91             struct v3_guest * guest = palacios_alloc(sizeof(struct v3_guest));
92
93             if (IS_ERR(guest)) {
94                 ERROR("Palacios: Error allocating Kernel guest_image\n");
95                 return -EFAULT;
96             }
97
98             memset(guest, 0, sizeof(struct v3_guest));
99
100             INFO("Palacios: Creating V3 Guest...\n");
101
102             vm_minor = register_vm(guest);
103
104             if (vm_minor == -1) {
105                 ERROR("Palacios Error: Too many VMs are currently running\n");
106                 goto out_err;
107             }
108
109             guest->vm_dev = MKDEV(v3_major_num, vm_minor);
110
111             if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
112                 ERROR("Palacios Error: copy from user error getting guest image...\n");
113                 goto out_err1;
114             }
115
116             guest->img_size = user_image.size;
117
118             DEBUG("Palacios: Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
119             guest->img = palacios_valloc(guest->img_size);
120
121             if (IS_ERR(guest->img)) {
122                 ERROR("Palacios Error: Could not allocate space for guest image\n");
123                 goto out_err1;
124             }
125
126             if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
127                 ERROR("Palacios: Error loading guest data\n");
128                 goto out_err2;
129             }      
130
131             strncpy(guest->name, user_image.name, 127);
132
133             INIT_LIST_HEAD(&(guest->exts));
134
135             if (create_palacios_vm(guest) == -1) {
136                 ERROR("Palacios: Error creating guest\n");
137                 goto out_err2;
138             }
139
140             return vm_minor;
141
142
143 out_err2:
144             palacios_vfree(guest->img);
145 out_err1:
146             guest_map[vm_minor] = NULL; 
147 out_err:
148             palacios_free(guest);
149
150             return -1;
151
152             break;
153         }
154         case V3_FREE_GUEST: {
155             unsigned long vm_idx = arg;
156             struct v3_guest * guest;
157
158             if (vm_idx > MAX_VMS) {
159                 ERROR("Invalid VM index: %ld\n", vm_idx);
160                 return -1;
161             }
162
163             guest = guest_map[vm_idx];
164
165             if (!guest) {
166                 ERROR("No VM at index %ld\n",vm_idx);
167                 return -1;
168             }
169
170             INFO("Freeing VM (%s) (%p)\n", guest->name, guest);
171
172             if (free_palacios_vm(guest)<0) { 
173                 ERROR("Cannot free guest at index %ld\n",vm_idx);
174                 return -1;
175             }
176
177             guest_map[vm_idx] = NULL;
178             break;
179         }
180         case V3_ADD_MEMORY: {
181             struct v3_mem_region mem;
182             
183             memset(&mem, 0, sizeof(struct v3_mem_region));
184             
185             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
186                 ERROR("copy from user error getting mem_region...\n");
187                 return -EFAULT;
188             }
189
190             DEBUG("Adding %llu pages to Palacios memory\n", mem.num_pages);
191
192             if (add_palacios_memory(&mem) == -1) {
193                 ERROR("Error adding memory to Palacios\n");
194                 return -EFAULT;
195             }
196
197             break;
198         }
199
200         case V3_REMOVE_MEMORY: {
201             struct v3_mem_region mem;
202             
203             memset(&mem, 0, sizeof(struct v3_mem_region));
204             
205             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
206                 ERROR("copy from user error getting mem_region...\n");
207                 return -EFAULT;
208             }
209
210             DEBUG("Removing memory at address %p\n", (void*)(mem.base_addr));
211
212             if (remove_palacios_memory(&mem) == -1) {
213                 ERROR("Error removing memory from Palacios\n");
214                 return -EFAULT;
215             }
216
217             break;
218         }
219             
220             
221
222         case V3_RESET_MEMORY: {
223             DEBUG("Resetting memory\n");
224             if (palacios_deinit_mm() == -1) {
225                 ERROR("Error resetting Palacios memory\n");
226                 return -EFAULT;
227             }
228             break;  
229         }
230
231         default: {
232             struct global_ctrl * ctrl = get_global_ctrl(ioctl);
233             
234             if (ctrl) {
235                 return ctrl->handler(ioctl, arg);
236             }
237
238             WARNING("\tUnhandled global ctrl cmd: %d\n", ioctl);
239
240             return -EINVAL;
241         }
242     }
243
244     return 0;
245 }
246
247
248
249 static struct file_operations v3_ctrl_fops = {
250     .owner = THIS_MODULE,
251     .unlocked_ioctl = v3_dev_ioctl,
252     .compat_ioctl = v3_dev_ioctl,
253 };
254
255
256
257 struct proc_dir_entry *palacios_get_procdir(void) 
258 {
259     //    INFO("Returning procdir=%p\n",palacios_proc_dir);
260     return palacios_proc_dir;
261 }
262
263
264 #define MAX_VCORES  256
265 #define MAX_REGIONS 1024
266
267
268
269 static int read_guests_details(struct seq_file *s, void *v)
270 {
271     unsigned int i = 0;
272     unsigned int j = 0;
273     struct v3_vm_base_state *base=0;
274     struct v3_vm_core_state *core=0;
275     struct v3_vm_mem_state *mem=0;
276
277     base = palacios_alloc(sizeof(struct v3_vm_base_state));
278     
279     if (!base) { 
280       ERROR("No space for base state structure\n");
281       goto out;
282     }
283
284     core = palacios_alloc(sizeof(struct v3_vm_core_state) + MAX_VCORES*sizeof(struct v3_vm_vcore_state));
285     
286     if (!core) { 
287         ERROR("No space for core state structure\n");
288         goto out;
289     }
290     
291     mem = palacios_alloc(sizeof(struct v3_vm_mem_state) + MAX_REGIONS*sizeof(struct v3_vm_mem_region));
292     
293     if (!mem) { 
294         ERROR("No space for memory state structure\n");
295         goto out;
296     }
297     
298     for(i = 0; i < MAX_VMS; i++) {
299         if (guest_map[i] != NULL) {
300             seq_printf(s,
301                        "---------------------------------------------------------------------------------------\n");
302             seq_printf(s, 
303                        "Entry:        %d\n"
304                        "Name:         %s\n"
305                        "Device:       /dev/v3-vm%d\n", 
306                        i,guest_map[i]->name, i);
307             
308             // Get extended data
309             core->num_vcores=MAX_VCORES; // max we can handle
310             mem->num_regions=MAX_REGIONS; // max we can handle
311             
312             if (v3_get_state_vm(guest_map[i]->v3_ctx, base, core, mem)) {
313                 ERROR("Cannot get VM info\n");
314                 seq_printf(s, "<unable to get data for this VM>\n");
315             } else {
316                 seq_printf(s, 
317                            "State:        %s\n"
318                            "Cores:        %lu\n"
319                            "Regions:      %lu\n\n",
320                            base->state==V3_VM_INVALID ? "INVALID" :
321                            base->state==V3_VM_RUNNING ? "running" :
322                            base->state==V3_VM_STOPPED ? "stopped" :
323                            base->state==V3_VM_PAUSED ? "paused" :
324                            base->state==V3_VM_ERROR ? "ERROR" :
325                            base->state==V3_VM_SIMULATING ? "simulating" : "UNKNOWN",
326                            core->num_vcores,
327                            mem->num_regions);
328                 seq_printf(s, "Core States\n");
329                 
330                 for (j=0;j<core->num_vcores;j++) {
331                     seq_printf(s,
332                                "   vcore %u %s on pcore %lu %llu exits rip=0x%p %s %s %s\n",
333                                j, 
334                                core->vcore[j].state==V3_VCORE_INVALID ? "INVALID" :
335                                core->vcore[j].state==V3_VCORE_RUNNING ? "running" :
336                                core->vcore[j].state==V3_VCORE_STOPPED ? "stopped" : "UNKNOWN",
337                                core->vcore[j].pcore,
338                                core->vcore[j].num_exits,
339                                core->vcore[j].last_rip,
340                                core->vcore[j].cpu_mode==V3_VCORE_CPU_REAL ? "real" :
341                                core->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED ? "protected" :
342                                core->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED_PAE ? "protectedpae" :
343                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG ? "long" :
344                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_32_COMPAT ? "long32" :
345                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_16_COMPAT ? "long16" : "UNKNOWN",
346                                core->vcore[j].mem_mode==V3_VCORE_MEM_MODE_PHYSICAL ? "physical" :
347                                core->vcore[j].mem_mode==V3_VCORE_MEM_MODE_VIRTUAL ? "virtual" : "UNKNOWN",
348                                core->vcore[j].mem_state==V3_VCORE_MEM_STATE_SHADOW ? "shadow" :
349                                core->vcore[j].mem_state==V3_VCORE_MEM_STATE_NESTED ? "nested" : "UNKNOWN");
350                 }
351
352                 seq_printf(s, "\nMemory Regions\n");
353                 for (j=0;j<mem->num_regions;j++) { 
354                     seq_printf(s,"   region %u has HPAs 0x%p-0x%p\n",
355                                j, mem->region[j].host_paddr, mem->region[j].host_paddr+mem->region[j].size);
356                 }
357             }
358             seq_printf(s,
359                        "---------------------------------------------------------------------------------------\n");
360         }
361     }
362     
363     
364  out:
365     if (mem) { palacios_free(mem); }
366     if (core) { palacios_free(core); }
367     if (base) { palacios_free(base); }
368     
369     return 0;
370 }
371
372 static int read_guests(struct seq_file *s, void *v)
373 {
374     unsigned int i = 0;
375     struct v3_vm_base_state *base=0;
376     struct v3_vm_core_state *core=0;
377     struct v3_vm_mem_state *mem=0;
378     
379     base = palacios_alloc(sizeof(struct v3_vm_base_state));
380     
381     if (!base) { 
382       ERROR("No space for base state structure\n");
383       goto out;
384     }
385
386     core = palacios_alloc(sizeof(struct v3_vm_core_state) + MAX_VCORES*sizeof(struct v3_vm_vcore_state));
387     
388     if (!core) { 
389         ERROR("No space for core state structure\n");
390         goto out;
391     }
392     
393     mem = palacios_alloc(sizeof(struct v3_vm_mem_state) + MAX_REGIONS*sizeof(struct v3_vm_mem_region));
394     
395     if (!mem) { 
396         ERROR("No space for memory state structure\n");
397         goto out;
398     }
399     
400     for(i = 0; i < MAX_VMS; i++) {
401         if (guest_map[i] != NULL) {
402             seq_printf(s,"%s\t/dev/v3-vm%d", guest_map[i]->name, i);
403             // Get extended data
404             core->num_vcores=MAX_VCORES; // max we can handle
405             mem->num_regions=MAX_REGIONS; // max we can handle
406             
407             if (v3_get_state_vm(guest_map[i]->v3_ctx, base, core, mem)) {
408                 ERROR("Cannot get VM info\n");
409                 seq_printf(s, "\t<unable to get data for this VM>\n");
410             } else {
411                 seq_printf(s,"\t%s\t%lu vcores\t%lu regions\n",
412                            base->state==V3_VM_INVALID ? "INVALID" :
413                            base->state==V3_VM_RUNNING ? "running" :
414                            base->state==V3_VM_STOPPED ? "stopped" :
415                            base->state==V3_VM_PAUSED ? "paused" :
416                            base->state==V3_VM_ERROR ? "ERROR" :
417                            base->state==V3_VM_SIMULATING ? "simulating" : "UNKNOWN",
418                            core->num_vcores,
419                            mem->num_regions);
420             }
421         }
422     }
423         
424         
425  out:
426     if (mem) { palacios_free(mem); }
427     if (core) { palacios_free(core); }
428     if (base) { palacios_free(base); }
429     
430     return 0;
431 }
432
433
434 static int guests_short_proc_open(struct inode * inode, struct file * filp) 
435 {
436     struct proc_dir_entry * proc_entry = PDE(inode);
437     return single_open(filp, read_guests, proc_entry->data);
438 }
439
440 static int guests_full_proc_open(struct inode * inode, struct file * filp) 
441 {
442     struct proc_dir_entry * proc_entry = PDE(inode);
443     return single_open(filp, read_guests_details, proc_entry->data);
444 }
445
446
447
448 static struct file_operations guest_full_proc_ops = {
449     .owner = THIS_MODULE,
450     .open = guests_full_proc_open, 
451     .read = seq_read,
452     .llseek = seq_lseek, 
453     .release = single_release,
454 };
455
456 static struct file_operations guest_short_proc_ops = {
457     .owner = THIS_MODULE,
458     .open = guests_short_proc_open, 
459     .read = seq_read,
460     .llseek = seq_lseek, 
461     .release = single_release,
462 };
463
464
465 static int __init v3_init(void) {
466
467     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
468     int ret = 0;
469
470     LOCKCHECK_INIT();
471     MEMCHECK_INIT();
472
473     palacios_proc_dir = proc_mkdir("v3vee", NULL);
474     if (!palacios_proc_dir) {
475         ERROR("Could not create proc entry\n");
476         ret = -1;
477         goto failure1;
478     }
479
480     // this will populate the v3vee tree...
481     if (palacios_init_mm()) { 
482         goto failure2;
483     }
484
485     if (allow_devmem) {
486       palacios_allow_devmem();
487     }
488
489     // Initialize Palacios
490     palacios_vmm_init(options);
491
492     // initialize extensions
493     init_lnx_extensions();
494
495
496     v3_class = class_create(THIS_MODULE, "vms");
497     if (IS_ERR(v3_class)) {
498         ERROR("Failed to register V3 VM device class\n");
499         ret =  PTR_ERR(v3_class);
500         goto failure3;
501     }
502
503     INFO("intializing V3 Control device\n");
504
505     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
506
507     if (ret < 0) {
508         ERROR("Error registering device region for V3 devices\n");
509         goto failure4;
510     }
511
512     v3_major_num = MAJOR(dev);
513
514     dev = MKDEV(v3_major_num, MAX_VMS + 1);
515
516     
517     DEBUG("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
518     cdev_init(&ctrl_dev, &v3_ctrl_fops);
519     ctrl_dev.owner = THIS_MODULE;
520     ctrl_dev.ops = &v3_ctrl_fops;
521     cdev_add(&ctrl_dev, dev, 1);
522     
523     device_create(v3_class, NULL, dev, NULL, "v3vee");
524
525     if (ret != 0) {
526         ERROR("Error adding v3 control device\n");
527         goto failure5;
528     }
529
530     {
531         struct proc_dir_entry *entry;
532
533         entry = create_proc_entry("v3-guests", 0444, palacios_proc_dir);
534         if (entry) {
535             entry->proc_fops = &guest_short_proc_ops;
536             INFO("/proc/v3vee/v3-guests successfully created\n");
537         } else {
538             ERROR("Could not create proc entry\n");
539             goto failure6;
540         }
541         entry = create_proc_entry("v3-guests-details", 0444, palacios_proc_dir);
542         if (entry) {
543             entry->proc_fops = &guest_full_proc_ops;
544             INFO("/proc/v3vee/v3-guests-details successfully created\n");
545         } else {
546             ERROR("Could not create proc entry\n");
547             goto failure7;
548         }
549     }
550         
551     return 0;
552
553  failure7:
554     remove_proc_entry("v3-guests-details", palacios_proc_dir);
555  failure6:
556     remove_proc_entry("v3-guests", palacios_proc_dir);
557  failure5:
558     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
559  failure4:
560     class_destroy(v3_class);
561  failure3:
562     if (allow_devmem) {
563       palacios_restore_devmem();
564     }
565     palacios_deinit_mm();
566  failure2:
567     remove_proc_entry("v3vee", NULL);
568  failure1:   
569     MEMCHECK_DEINIT();
570     LOCKCHECK_DEINIT();
571
572     return ret;
573 }
574
575
576 static void __exit v3_exit(void) {
577     extern u32 pg_allocs;
578     extern u32 pg_frees;
579     extern u32 mallocs;
580     extern u32 frees;
581     extern u32 vmallocs;
582     extern u32 vfrees;
583     int i = 0;
584     struct v3_guest * guest;
585     dev_t dev;
586
587
588     /* Stop and free any running VMs */ 
589     for (i = 0; i < MAX_VMS; i++) {
590         if (guest_map[i] != NULL) {
591                 guest = (struct v3_guest *)guest_map[i];
592
593                 if (v3_stop_vm(guest->v3_ctx) < 0) 
594                         ERROR("Couldn't stop VM %d\n", i);
595
596                 free_palacios_vm(guest);
597                 guest_map[i] = NULL;
598         }
599     }
600
601     dev = MKDEV(v3_major_num, MAX_VMS + 1);
602
603     INFO("Removing V3 Control device\n");
604
605
606     palacios_vmm_exit();
607
608     DEBUG("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
609     DEBUG("Palacios Vmallocs = %d, Vfrees = %d\n", vmallocs, vfrees);
610     DEBUG("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
611
612     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
613
614     cdev_del(&ctrl_dev);
615
616     device_destroy(v3_class, dev);
617     class_destroy(v3_class);
618
619
620     deinit_lnx_extensions();
621
622     if (allow_devmem) {
623       palacios_restore_devmem();
624     }
625
626     palacios_deinit_mm();
627
628     remove_proc_entry("v3-guests-details", palacios_proc_dir);
629     remove_proc_entry("v3-guests", palacios_proc_dir);
630     remove_proc_entry("v3vee", NULL);
631
632     DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
633     
634     MEMCHECK_DEINIT();
635     LOCKCHECK_DEINIT();
636 }
637
638
639
640 module_init(v3_init);
641 module_exit(v3_exit);
642
643
644
645 void * trace_malloc(size_t size, gfp_t flags) {
646     void * addr = NULL;
647
648     mod_allocs++;
649     addr = palacios_alloc_extended(size, flags, -1);
650
651     return addr;
652 }
653
654
655 void trace_free(const void * objp) {
656     mod_frees++;
657     palacios_free((void*)objp);
658 }