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.


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