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.


Linux compatibility fixes
[palacios.git] / linux_module / main.c
1 /* 
2    Palacios main control interface
3    (c) Jack Lange, 2010
4  */
5
6 #include <linux/kernel.h>
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 "numa.h"
31 #include "allow_devmem.h"
32 #include "memcheck.h"
33 #include "lockcheck.h"
34
35 #include "linux-exts.h"
36
37 #include "util-hashtable.h"
38
39 MODULE_LICENSE("GPL");
40
41 // Module parameter
42 int cpu_list[NR_CPUS] = {};
43 int cpu_list_len = 0;
44 module_param_array(cpu_list, int, &cpu_list_len, 0644);
45 MODULE_PARM_DESC(cpu_list, "Comma-delimited list of CPUs that Palacios will run on");
46
47 static int allow_devmem = 0;
48 module_param(allow_devmem, int, 0);
49 MODULE_PARM_DESC(allow_devmem, "Allow general user-space /dev/mem access even if kernel is strict");
50
51 // Palacios options parameter
52 static char *options;
53 module_param(options, charp, 0);
54 MODULE_PARM_DESC(options, "Generic options to internal Palacios modules");
55
56
57 int mod_allocs = 0;
58 int mod_frees = 0;
59
60 static int v3_major_num = 0;
61
62 static struct v3_guest * guest_map[MAX_VMS] = {[0 ... MAX_VMS - 1] = 0};
63 static struct proc_dir_entry * palacios_proc_dir = NULL;
64
65 struct class * v3_class = NULL;
66 static struct cdev ctrl_dev;
67
68
69 // mapping from thread ids to their resource control blocks
70 struct hashtable *v3_thread_resource_map=0;
71
72 static int register_vm(struct v3_guest * guest) {
73     int i = 0;
74
75     for (i = 0; i < MAX_VMS; i++) {
76         if (guest_map[i] == NULL) {
77             guest_map[i] = guest;
78             return i;
79         }
80     }
81
82     return -1;
83 }
84
85
86
87 static long v3_dev_ioctl(struct file * filp,
88                          unsigned int ioctl, unsigned long arg) {
89     void __user * argp = (void __user *)arg;
90     DEBUG("V3 IOCTL %d\n", ioctl);
91
92
93     switch (ioctl) {
94         case V3_CREATE_GUEST:{
95             int vm_minor = 0;
96             struct v3_guest_img user_image;
97             struct v3_guest * guest = palacios_alloc(sizeof(struct v3_guest));
98
99             if (!(guest)) {
100                 ERROR("Palacios: Error allocating Kernel guest_image\n");
101                 return -EFAULT;
102             }
103
104             memset(guest, 0, sizeof(struct v3_guest));
105
106             INFO("Palacios: Creating V3 Guest...\n");
107
108             vm_minor = register_vm(guest);
109
110             if (vm_minor == -1) {
111                 ERROR("Palacios Error: Too many VMs are currently running\n");
112                 goto out_err;
113             }
114
115             guest->vm_dev = MKDEV(v3_major_num, vm_minor);
116
117             if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
118                 ERROR("Palacios Error: copy from user error getting guest image...\n");
119                 goto out_err1;
120             }
121
122             guest->img_size = user_image.size;
123
124             DEBUG("Palacios: Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
125             // overflow possible here, but only if guest image is probably to large for kernel anyway...
126             guest->img = palacios_valloc(guest->img_size);
127
128             if (!guest->img) {
129                 ERROR("Palacios Error: Could not allocate space for guest image\n");
130                 goto out_err1;
131             }
132
133             if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
134                 ERROR("Palacios: Error loading guest data\n");
135                 goto out_err2;
136             }      
137
138             strncpy(guest->name, user_image.name, 128);
139             guest->name[127] = 0;
140
141             INIT_LIST_HEAD(&(guest->exts));
142
143             if (create_palacios_vm(guest) == -1) {
144                 ERROR("Palacios: Error creating guest\n");
145                 goto out_err2;
146             }
147
148             return vm_minor;
149
150
151 out_err2:
152             palacios_vfree(guest->img);
153 out_err1:
154             guest_map[vm_minor] = NULL; 
155 out_err:
156             palacios_free(guest);
157
158             return -1;
159
160             break;
161         }
162         case V3_FREE_GUEST: {
163             unsigned long vm_idx = arg;
164             struct v3_guest * guest;
165
166             if (vm_idx >= MAX_VMS) {
167                 ERROR("Invalid VM index: %ld\n", vm_idx);
168                 return -1;
169             }
170
171             guest = guest_map[vm_idx];
172
173             if (!guest) {
174                 ERROR("No VM at index %ld\n",vm_idx);
175                 return -1;
176             }
177
178             INFO("Freeing VM (%s) (%p)\n", guest->name, guest);
179
180             if (free_palacios_vm(guest)<0) { 
181                 ERROR("Cannot free guest at index %ld\n",vm_idx);
182                 return -1;
183             }
184
185             guest_map[vm_idx] = NULL;
186             break;
187         }
188         case V3_ADD_MEMORY: {
189             struct v3_mem_region mem;
190             
191             memset(&mem, 0, sizeof(struct v3_mem_region));
192             
193             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
194                 ERROR("copy from user error getting mem_region...\n");
195                 return -EFAULT;
196             }
197
198             DEBUG("Adding %llu pages to Palacios memory\n", mem.num_pages);
199
200             if (add_palacios_memory(&mem) == -1) {
201                 ERROR("Error adding memory to Palacios\n");
202                 return -EFAULT;
203             }
204
205             break;
206         }
207
208         case V3_REMOVE_MEMORY: {
209             struct v3_mem_region mem;
210             
211             memset(&mem, 0, sizeof(struct v3_mem_region));
212             
213             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
214                 ERROR("copy from user error getting mem_region...\n");
215                 return -EFAULT;
216             }
217
218             DEBUG("Removing memory at address %p\n", (void*)(mem.base_addr));
219
220             if (remove_palacios_memory(&mem) == -1) {
221                 ERROR("Error removing memory from Palacios\n");
222                 return -EFAULT;
223             }
224
225             break;
226         }
227             
228             
229
230         case V3_RESET_MEMORY: {
231             DEBUG("Resetting memory\n");
232             if (palacios_deinit_mm() == -1) {
233                 ERROR("Error deiniting the Palacios memory manager\n");
234                 return -EFAULT;
235             }
236             if (palacios_init_mm()) { 
237                 ERROR("Error initing the Palacios memory manager\n");
238                 return -EFAULT;
239             }
240             break;  
241         }
242
243         default: {
244             struct global_ctrl * ctrl = get_global_ctrl(ioctl);
245             
246             if (ctrl) {
247                 return ctrl->handler(ioctl, arg);
248             }
249
250             WARNING("\tUnhandled global ctrl cmd: %d\n", ioctl);
251
252             return -EINVAL;
253         }
254     }
255
256     return 0;
257 }
258
259
260
261 static struct file_operations v3_ctrl_fops = {
262     .owner = THIS_MODULE,
263     .unlocked_ioctl = v3_dev_ioctl,
264     .compat_ioctl = v3_dev_ioctl,
265 };
266
267
268
269 struct proc_dir_entry *palacios_get_procdir(void) 
270 {
271     //    INFO("Returning procdir=%p\n",palacios_proc_dir);
272     return palacios_proc_dir;
273 }
274
275
276 #define MAX_CORES   1024
277 #define MAX_REGIONS 1024
278 #define MIN(x,y) ((x)<(y) ? (x) : (y))
279
280 static int read_guests_details(struct seq_file *s, void *v)
281 {
282     unsigned int i = 0;
283     unsigned int j = 0;
284     uint64_t num_vcores, num_regions;
285     uint64_t alloc_num_vcores, alloc_num_regions;
286     struct v3_vm_base_state *base=0;
287     struct v3_vm_core_state *core=0;
288     struct v3_vm_mem_state *mem=0;
289
290
291     base = palacios_valloc(sizeof(struct v3_vm_base_state));
292     
293
294     if (!base) { 
295       ERROR("No space for base state structure\n");
296       goto out;
297     }
298
299
300     for(i = 0; i < MAX_VMS; i++) {
301
302         if (guest_map[i] != NULL) {
303             
304             v3_get_state_sizes_vm(guest_map[i]->v3_ctx,&num_vcores,&num_regions);
305
306             alloc_num_vcores = MIN(num_vcores,MAX_CORES);
307             alloc_num_regions = MIN(num_regions,MAX_REGIONS);
308
309             core = palacios_valloc(sizeof(struct v3_vm_core_state) + alloc_num_vcores*sizeof(struct v3_vm_vcore_state));
310             
311             if (!core) { 
312                 ERROR("No space for core state structure\n");
313                 goto out;
314             }
315     
316             mem = palacios_valloc(sizeof(struct v3_vm_mem_state) + alloc_num_regions*sizeof(struct v3_vm_mem_region));
317     
318             if (!mem) { 
319                 ERROR("No space for memory state structure\n");
320                 goto out;
321             }
322     
323             seq_printf(s,
324                        "---------------------------------------------------------------------------------------\n");
325             seq_printf(s, 
326                        "Entry:        %d\n"
327                        "Name:         %s\n"
328                        "Device:       /dev/v3-vm%d\n", 
329                        i,guest_map[i]->name, i);
330             
331             // Get extended data
332             core->num_vcores=alloc_num_vcores;
333             mem->num_regions=alloc_num_regions;
334             
335             if (v3_get_state_vm(guest_map[i]->v3_ctx, base, core, mem)) {
336                 ERROR("Cannot get VM info\n");
337                 seq_printf(s, "<unable to get data for this VM>\n");
338             } else {
339                 seq_printf(s, 
340                            "Type:         %s\n"
341                            "State:        %s\n"
342                            "Cores:        %llu (%llu shown)\n"
343                            "Regions:      %llu (%llu shown)\n"
344                            "Memsize:      %llu (%llu ROS)\n\n",
345                            base->vm_type==V3_VM_GENERAL ? "general" :
346                            base->vm_type==V3_VM_HVM ? "HVM" : "UNKNOWN",
347                            base->state==V3_VM_INVALID ? "INVALID" :
348                            base->state==V3_VM_RUNNING ? "running" :
349                            base->state==V3_VM_STOPPED ? "stopped" :
350                            base->state==V3_VM_PAUSED ? "paused" :
351                            base->state==V3_VM_ERROR ? "ERROR" :
352                            base->state==V3_VM_SIMULATING ? "simulating" : 
353                            base->state==V3_VM_RESETTING ? "resetting"  : "UNKNOWN",
354                            num_vcores,
355                            core->num_vcores,
356                            num_regions,
357                            mem->num_regions,
358                            mem->mem_size,
359                            mem->ros_mem_size);
360
361                 seq_printf(s, "Core States\n");
362                 
363                 for (j=0;j<core->num_vcores;j++) {
364                     seq_printf(s,
365                                "   vcore %u %s on pcore %lu %llu exits rip=0x%p %s %s %s %s\n",
366                                j, 
367                                core->vcore[j].state==V3_VCORE_INVALID ? "INVALID" :
368                                core->vcore[j].state==V3_VCORE_RUNNING ? "running" :
369                                core->vcore[j].state==V3_VCORE_STOPPED ? "stopped" :
370                                core->vcore[j].state==V3_VCORE_RESETTING ? "resetting" : "UNKNOWN",
371                                core->vcore[j].pcore,
372                                core->vcore[j].num_exits,
373                                core->vcore[j].last_rip,
374                                core->vcore[j].cpu_mode==V3_VCORE_CPU_REAL ? "real" :
375                                core->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED ? "protected" :
376                                core->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED_PAE ? "protectedpae" :
377                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG ? "long" :
378                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_32_COMPAT ? "long32" :
379                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_16_COMPAT ? "long16" : "UNKNOWN",
380                                core->vcore[j].mem_mode==V3_VCORE_MEM_MODE_PHYSICAL ? "physical" :
381                                core->vcore[j].mem_mode==V3_VCORE_MEM_MODE_VIRTUAL ? "virtual" : "UNKNOWN",
382                                core->vcore[j].mem_state==V3_VCORE_MEM_STATE_SHADOW ? "shadow" :
383                                core->vcore[j].mem_state==V3_VCORE_MEM_STATE_NESTED ? "nested" : "UNKNOWN",
384                                core->vcore[j].vcore_type==V3_VCORE_GENERAL ? "" :
385                                core->vcore[j].vcore_type==V3_VCORE_ROS ? "ros" :
386                                core->vcore[j].vcore_type==V3_VCORE_HRT ? "hrt" : "UNKNOWN");
387                 }
388
389
390                 seq_printf(s, "\nMemory Regions\n");
391                 for (j=0;j<mem->num_regions;j++) { 
392                     seq_printf(s,"   region %u has HPAs 0x%016llx-0x%016llx (node %d) GPA 0x%016llx %s %s\n",
393                                j, (uint64_t)mem->region[j].host_paddr, (uint64_t)mem->region[j].host_paddr+mem->region[j].size,
394                                numa_addr_to_node((uintptr_t)(mem->region[j].host_paddr)),
395                                (uint64_t)mem->region[j].guest_paddr,
396                                mem->region[j].swapped ? "swapped" : "",
397                                mem->region[j].pinned ? "pinned" : "");
398                 }
399
400             }
401             seq_printf(s,
402                        "---------------------------------------------------------------------------------------\n");
403
404             palacios_vfree(mem); mem=0;
405             palacios_vfree(core); core=0;
406
407         }
408
409     }
410     
411     
412  out:
413     if (mem) { palacios_vfree(mem); } // dead code but kept for clarity
414     if (core) { palacios_vfree(core); }
415     if (base) { palacios_vfree(base); }
416     
417     return 0;
418 }
419
420 static int read_guests(struct seq_file *s, void *v)
421 {
422     unsigned int i = 0;
423     struct v3_vm_base_state *base=0;
424     struct v3_vm_core_state *core=0;
425     struct v3_vm_mem_state *mem=0;
426     uint64_t num_vcores, num_regions;
427
428
429     INFO("READ GUEST\n");
430     
431     base = palacios_valloc(sizeof(struct v3_vm_base_state));
432     
433     if (!base) { 
434       ERROR("No space for base state structure\n");
435       goto out;
436     }
437
438     core = palacios_valloc(sizeof(struct v3_vm_core_state));
439     
440     if (!core) { 
441         ERROR("No space for core state structure\n");
442         goto out;
443     }
444     
445     mem = palacios_valloc(sizeof(struct v3_vm_mem_state));
446     
447     if (!mem) { 
448         ERROR("No space for memory state structure\n");
449         goto out;
450     }
451     
452
453     for(i = 0; i < MAX_VMS; i++) {
454         if (guest_map[i] != NULL) {
455
456             v3_get_state_sizes_vm(guest_map[i]->v3_ctx,&num_vcores,&num_regions);
457
458             seq_printf(s,"%s\t/dev/v3-vm%d", guest_map[i]->name, i);
459
460             // Skip getting per core and per-region 
461             core->num_vcores=0;
462             mem->num_regions=0;
463             
464             if (v3_get_state_vm(guest_map[i]->v3_ctx, base, core, mem)) {
465                 ERROR("Cannot get VM info\n");
466                 seq_printf(s, "\t<unable to get data for this VM>\n");
467             } else {
468                 seq_printf(s,"\t%s\t%llu vcores\t%llu regions\t%llu mem\t%s\n",
469                            base->state==V3_VM_INVALID ? "INVALID" :
470                            base->state==V3_VM_RUNNING ? "running" :
471                            base->state==V3_VM_STOPPED ? "stopped" :
472                            base->state==V3_VM_PAUSED ? "paused" :
473                            base->state==V3_VM_ERROR ? "ERROR" :
474                            base->state==V3_VM_SIMULATING ? "simulating" : "UNKNOWN",
475                            num_vcores,
476                            num_regions,
477                            mem->mem_size,
478                            base->vm_type == V3_VM_GENERAL ? "general" :
479                            base->vm_type == V3_VM_HVM ? "hvm" : "UNKNOWN");
480             }
481         }
482     }
483         
484         
485  out:
486     if (mem) { palacios_vfree(mem); }
487     if (core) { palacios_vfree(core); }
488     if (base) { palacios_vfree(base); }
489     
490     return 0;
491 }
492
493
494 static int guests_short_proc_open(struct inode * inode, struct file * filp) 
495 {
496     return single_open(filp, read_guests, PAL_PROC_GETDATA(inode));
497 }
498
499 static int guests_full_proc_open(struct inode * inode, struct file * filp) 
500 {
501     return single_open(filp, read_guests_details, PAL_PROC_GETDATA(inode));
502 }
503
504
505
506
507 static struct file_operations guest_full_proc_ops = {
508     .owner = THIS_MODULE,
509     .open = guests_full_proc_open, 
510     .read = seq_read,
511     .llseek = seq_lseek, 
512     .release = single_release,
513 };
514
515 static struct file_operations guest_short_proc_ops = {
516     .owner = THIS_MODULE,
517     .open = guests_short_proc_open, 
518     .read = seq_read,
519     .llseek = seq_lseek, 
520     .release = single_release,
521 };
522
523 // Supply basic information that the user-space tools need
524 // to manipulate Palacios.   The current use case here is to 
525 // convey memory information
526 static int read_info(struct seq_file *s, void *v)
527 {
528     uint64_t mem_block_size;
529     int i,j;
530     int max_node=-1;
531     seq_printf(s,"kernel MAX_ORDER:\t%d\n",MAX_ORDER);
532     seq_printf(s,"number of nodes:\t%d\n", numa_num_nodes());
533     seq_printf(s,"number of cpus: \t%d\n", num_online_cpus());
534     seq_printf(s,"\npalacios compiled mem_block_size:\t%d\n", V3_CONFIG_MEM_BLOCK_SIZE);
535     if (!v3_lookup_option("mem_block_size")) { 
536         mem_block_size = V3_CONFIG_MEM_BLOCK_SIZE;
537     } else {
538         if (strict_strtoull(v3_lookup_option("mem_block_size"), 0, &mem_block_size)) {
539             // huh?
540             mem_block_size=-1;
541         }
542     }
543     seq_printf(s,"palacios run-time mem_block_size:\t%llu\n", mem_block_size);
544     
545     seq_printf(s,"\nCPU to node mappings\n");
546     for (i=0;i<num_online_cpus();i++) { 
547         seq_printf(s,"cpu %d -> node %d\n", i, numa_cpu_to_node(i));
548         if (numa_cpu_to_node(i)>max_node) { 
549             max_node=numa_cpu_to_node(i);
550         }
551     }
552     seq_printf(s,"\nNode to node distances\n");
553     for (j=0;j<=max_node;j++) { 
554         seq_printf(s,"   \t%2d", j);
555     }
556     seq_printf(s,"\n");
557     for (i=0;i<=max_node;i++) { 
558         seq_printf(s,"%2d ",i);
559         for (j=0;j<=max_node;j++) { 
560             seq_printf(s,"\t%2d", numa_get_distance(i,j));
561         }
562         seq_printf(s,"\n");
563     }
564     seq_printf(s,"\nCPU to CPU distances\n");
565     for (j=0;j<num_online_cpus();j++) { 
566         seq_printf(s,"   \t%2d", j);
567     }
568     seq_printf(s,"\n");
569     for (i=0;i<num_online_cpus();i++) { 
570         seq_printf(s,"%2d ",i);
571         for (j=0;j<num_online_cpus();j++) { 
572             seq_printf(s,"\t%2d", numa_get_distance(numa_cpu_to_node(i),numa_cpu_to_node(j)));
573         }
574         seq_printf(s,"\n");
575     }
576     return 0;
577 }
578
579 static int info_proc_open(struct inode * inode, struct file * filp) 
580 {
581     return single_open(filp, read_info, PAL_PROC_GETDATA(inode));
582 }
583
584
585
586 static struct file_operations info_proc_ops = {
587     .owner = THIS_MODULE,
588     .open = info_proc_open, 
589     .read = seq_read,
590     .llseek = seq_lseek, 
591     .release = single_release,
592 };
593
594
595 static inline uint_t thr_hash_func(addr_t key)
596 {
597     return palacios_hash_long((long)key,64);
598 }
599
600 static inline int thr_hash_comp(addr_t k1, addr_t k2)
601 {
602     return k1==k2;
603 }
604
605 static int __init v3_init(void) {
606
607     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
608     int ret = 0;
609
610     LOCKCHECK_INIT();
611     MEMCHECK_INIT();
612
613
614     if (!(v3_thread_resource_map = palacios_create_htable(MAX_THREADS,thr_hash_func,thr_hash_comp))) { 
615         ERROR("Could not create thread/resource map\n");
616         ret = -1;
617         goto failure0;
618     }
619
620     palacios_proc_dir = proc_mkdir("v3vee", NULL);
621     if (!palacios_proc_dir) {
622         ERROR("Could not create proc entry\n");
623         ret = -1;
624         goto failure1;
625     }
626
627     // this will populate the v3vee tree...
628     if (palacios_init_mm()) { 
629         goto failure2;
630     }
631
632     if (allow_devmem) {
633       palacios_allow_devmem();
634     }
635
636     // numa is now a required interface and we need it
637     // up before primary initiatilization
638     palacios_init_numa();
639
640     // Initialize Palacios
641     palacios_vmm_init(options);
642
643     // initialize extensions
644     init_lnx_extensions();
645
646
647     v3_class = class_create(THIS_MODULE, "vms");
648     if (!v3_class || IS_ERR(v3_class)) {
649         ERROR("Failed to register V3 VM device class\n");
650         ret =  PTR_ERR(v3_class);
651         goto failure3;
652     }
653
654     INFO("intializing V3 Control device\n");
655
656     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
657
658     if (ret < 0) {
659         ERROR("Error registering device region for V3 devices\n");
660         goto failure4;
661     }
662
663     v3_major_num = MAJOR(dev);
664
665     dev = MKDEV(v3_major_num, MAX_VMS + 1);
666
667     
668     DEBUG("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
669     cdev_init(&ctrl_dev, &v3_ctrl_fops);
670     ctrl_dev.owner = THIS_MODULE;
671     ctrl_dev.ops = &v3_ctrl_fops;
672     cdev_add(&ctrl_dev, dev, 1);
673     
674     device_create(v3_class, NULL, dev, NULL, "v3vee");
675
676     if (ret != 0) {
677         ERROR("Error adding v3 control device\n");
678         goto failure5;
679     }
680
681     {
682         struct proc_dir_entry *entry;
683
684 #define PALPROC(ent, success, error, out_target, fname, perm, parent, fops) \
685     PAL_PROC_CREATE(ent, fname, perm, parent, fops); \
686     if (ent) {                                    \
687         INFO(success);                            \
688     } else {                                      \
689         ERROR(error);                             \
690         goto out_target;                          \
691     }
692
693     PALPROC(entry, "/proc/v3vee/v3-guests succesfully created\n", 
694             "Could not create proc entry\n", failure6,
695             "v3-guests", 0444, palacios_proc_dir, &guest_short_proc_ops);
696
697     PALPROC(entry, "/proc/v3vee/v3-guests-details successfully created\n",
698             "Could not create proc entry\n", failure7, 
699             "v3-guests-details", 0444, palacios_proc_dir, &guest_full_proc_ops);
700
701     PALPROC(entry, "/proc/v3vee/v3-info successfully created\n", 
702             "Could not create proc entry\n", failure8, 
703             "v3-info", 0444, palacios_proc_dir, &info_proc_ops);
704
705
706     }
707         
708     return 0;
709
710  failure8:
711     remove_proc_entry("v3-guests-details", palacios_proc_dir);
712  failure7:
713     remove_proc_entry("v3-guests", palacios_proc_dir);
714  failure6:
715     device_destroy(v3_class, dev);
716  failure5:
717     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
718  failure4:
719     class_destroy(v3_class);
720  failure3:
721     if (allow_devmem) {
722       palacios_restore_devmem();
723     }
724     palacios_deinit_mm();
725  failure2:
726     remove_proc_entry("v3vee", NULL);
727  failure1:   
728     palacios_free_htable(v3_thread_resource_map,0,0);
729  failure0:   
730     MEMCHECK_DEINIT();
731     LOCKCHECK_DEINIT();
732
733     return ret;
734 }
735
736
737 static void __exit v3_exit(void) {
738     extern u32 pg_allocs;
739     extern u32 pg_frees;
740     extern u32 mallocs;
741     extern u32 frees;
742     extern u32 vmallocs;
743     extern u32 vfrees;
744     int i = 0;
745     struct v3_guest * guest;
746     dev_t dev;
747
748
749     /* Stop and free any running VMs */ 
750     for (i = 0; i < MAX_VMS; i++) {
751                 if (guest_map[i] != NULL) {
752                     guest = (struct v3_guest *)(guest_map[i]);
753
754                 if (!guest->v3_ctx) { 
755                     ERROR("Orphan VM detected and skipped: index=%d name=%s\n", i, guest->name);
756                     continue;
757                 }
758
759                 if (v3_stop_vm(guest->v3_ctx) < 0) 
760                         ERROR("Couldn't stop VM %d\n", i);
761
762                 free_palacios_vm(guest);
763                 guest_map[i] = NULL;
764         }
765     }
766
767     dev = MKDEV(v3_major_num, MAX_VMS + 1);
768
769     INFO("Removing V3 Control device\n");
770
771
772     palacios_vmm_exit();
773
774     palacios_deinit_numa();
775
776     DEBUG("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
777     DEBUG("Palacios Vmallocs = %d, Vfrees = %d\n", vmallocs, vfrees);
778     DEBUG("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
779
780     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
781
782     cdev_del(&ctrl_dev);
783
784     device_destroy(v3_class, dev);
785     class_destroy(v3_class);
786
787
788     deinit_lnx_extensions();
789
790     if (allow_devmem) {
791       palacios_restore_devmem();
792     }
793
794     palacios_deinit_mm();
795
796     remove_proc_entry("v3-info", palacios_proc_dir);
797     remove_proc_entry("v3-guests-details", palacios_proc_dir);
798     remove_proc_entry("v3-guests", palacios_proc_dir);
799     remove_proc_entry("v3vee", NULL);
800
801     DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
802     
803     palacios_free_htable(v3_thread_resource_map,0,0);
804
805     MEMCHECK_DEINIT();
806     LOCKCHECK_DEINIT();
807 }
808
809
810
811 module_init(v3_init);
812 module_exit(v3_exit);
813
814
815
816 void * trace_malloc(size_t size, gfp_t flags) {
817     void * addr = NULL;
818
819     mod_allocs++;
820     addr = palacios_alloc_extended(size, flags, -1);
821
822     return addr;
823 }
824
825
826 void trace_free(const void * objp) {
827     mod_frees++;
828     palacios_free((void*)objp);
829 }