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.


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