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.


Cleaned up deinitialization of VMM and free of VMs
[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 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 deiniting the Palacios memory manager\n");
226                 return -EFAULT;
227             }
228             if (palacios_init_mm()) { 
229                 ERROR("Error initing the Palacios memory manager\n");
230                 return -EFAULT;
231             }
232             break;  
233         }
234
235         default: {
236             struct global_ctrl * ctrl = get_global_ctrl(ioctl);
237             
238             if (ctrl) {
239                 return ctrl->handler(ioctl, arg);
240             }
241
242             WARNING("\tUnhandled global ctrl cmd: %d\n", ioctl);
243
244             return -EINVAL;
245         }
246     }
247
248     return 0;
249 }
250
251
252
253 static struct file_operations v3_ctrl_fops = {
254     .owner = THIS_MODULE,
255     .unlocked_ioctl = v3_dev_ioctl,
256     .compat_ioctl = v3_dev_ioctl,
257 };
258
259
260
261 struct proc_dir_entry *palacios_get_procdir(void) 
262 {
263     //    INFO("Returning procdir=%p\n",palacios_proc_dir);
264     return palacios_proc_dir;
265 }
266
267
268 #define MAX_VCORES  256
269 #define MAX_REGIONS 1024
270
271
272
273 static int read_guests_details(struct seq_file *s, void *v)
274 {
275     unsigned int i = 0;
276     unsigned int j = 0;
277     struct v3_vm_base_state *base=0;
278     struct v3_vm_core_state *core=0;
279     struct v3_vm_mem_state *mem=0;
280
281     base = palacios_alloc(sizeof(struct v3_vm_base_state));
282     
283     if (!base) { 
284       ERROR("No space for base state structure\n");
285       goto out;
286     }
287
288     core = palacios_alloc(sizeof(struct v3_vm_core_state) + MAX_VCORES*sizeof(struct v3_vm_vcore_state));
289     
290     if (!core) { 
291         ERROR("No space for core state structure\n");
292         goto out;
293     }
294     
295     mem = palacios_alloc(sizeof(struct v3_vm_mem_state) + MAX_REGIONS*sizeof(struct v3_vm_mem_region));
296     
297     if (!mem) { 
298         ERROR("No space for memory state structure\n");
299         goto out;
300     }
301     
302     for(i = 0; i < MAX_VMS; i++) {
303         if (guest_map[i] != NULL) {
304             seq_printf(s,
305                        "---------------------------------------------------------------------------------------\n");
306             seq_printf(s, 
307                        "Entry:        %d\n"
308                        "Name:         %s\n"
309                        "Device:       /dev/v3-vm%d\n", 
310                        i,guest_map[i]->name, i);
311             
312             // Get extended data
313             core->num_vcores=MAX_VCORES; // max we can handle
314             mem->num_regions=MAX_REGIONS; // max we can handle
315             
316             if (v3_get_state_vm(guest_map[i]->v3_ctx, base, core, mem)) {
317                 ERROR("Cannot get VM info\n");
318                 seq_printf(s, "<unable to get data for this VM>\n");
319             } else {
320                 seq_printf(s, 
321                            "State:        %s\n"
322                            "Cores:        %lu\n"
323                            "Regions:      %lu\n\n",
324                            base->state==V3_VM_INVALID ? "INVALID" :
325                            base->state==V3_VM_RUNNING ? "running" :
326                            base->state==V3_VM_STOPPED ? "stopped" :
327                            base->state==V3_VM_PAUSED ? "paused" :
328                            base->state==V3_VM_ERROR ? "ERROR" :
329                            base->state==V3_VM_SIMULATING ? "simulating" : "UNKNOWN",
330                            core->num_vcores,
331                            mem->num_regions);
332                 seq_printf(s, "Core States\n");
333                 
334                 for (j=0;j<core->num_vcores;j++) {
335                     seq_printf(s,
336                                "   vcore %u %s on pcore %lu %llu exits rip=0x%p %s %s %s\n",
337                                j, 
338                                core->vcore[j].state==V3_VCORE_INVALID ? "INVALID" :
339                                core->vcore[j].state==V3_VCORE_RUNNING ? "running" :
340                                core->vcore[j].state==V3_VCORE_STOPPED ? "stopped" : "UNKNOWN",
341                                core->vcore[j].pcore,
342                                core->vcore[j].num_exits,
343                                core->vcore[j].last_rip,
344                                core->vcore[j].cpu_mode==V3_VCORE_CPU_REAL ? "real" :
345                                core->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED ? "protected" :
346                                core->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED_PAE ? "protectedpae" :
347                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG ? "long" :
348                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_32_COMPAT ? "long32" :
349                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_16_COMPAT ? "long16" : "UNKNOWN",
350                                core->vcore[j].mem_mode==V3_VCORE_MEM_MODE_PHYSICAL ? "physical" :
351                                core->vcore[j].mem_mode==V3_VCORE_MEM_MODE_VIRTUAL ? "virtual" : "UNKNOWN",
352                                core->vcore[j].mem_state==V3_VCORE_MEM_STATE_SHADOW ? "shadow" :
353                                core->vcore[j].mem_state==V3_VCORE_MEM_STATE_NESTED ? "nested" : "UNKNOWN");
354                 }
355
356                 seq_printf(s, "\nMemory Regions\n");
357                 for (j=0;j<mem->num_regions;j++) { 
358                     seq_printf(s,"   region %u has HPAs 0x%p-0x%p\n",
359                                j, mem->region[j].host_paddr, mem->region[j].host_paddr+mem->region[j].size);
360                 }
361             }
362             seq_printf(s,
363                        "---------------------------------------------------------------------------------------\n");
364         }
365     }
366     
367     
368  out:
369     if (mem) { palacios_free(mem); }
370     if (core) { palacios_free(core); }
371     if (base) { palacios_free(base); }
372     
373     return 0;
374 }
375
376 static int read_guests(struct seq_file *s, void *v)
377 {
378     unsigned int i = 0;
379     struct v3_vm_base_state *base=0;
380     struct v3_vm_core_state *core=0;
381     struct v3_vm_mem_state *mem=0;
382     
383     base = palacios_alloc(sizeof(struct v3_vm_base_state));
384     
385     if (!base) { 
386       ERROR("No space for base state structure\n");
387       goto out;
388     }
389
390     core = palacios_alloc(sizeof(struct v3_vm_core_state) + MAX_VCORES*sizeof(struct v3_vm_vcore_state));
391     
392     if (!core) { 
393         ERROR("No space for core state structure\n");
394         goto out;
395     }
396     
397     mem = palacios_alloc(sizeof(struct v3_vm_mem_state) + MAX_REGIONS*sizeof(struct v3_vm_mem_region));
398     
399     if (!mem) { 
400         ERROR("No space for memory state structure\n");
401         goto out;
402     }
403     
404     for(i = 0; i < MAX_VMS; i++) {
405         if (guest_map[i] != NULL) {
406             seq_printf(s,"%s\t/dev/v3-vm%d", guest_map[i]->name, i);
407             // Get extended data
408             core->num_vcores=MAX_VCORES; // max we can handle
409             mem->num_regions=MAX_REGIONS; // max we can handle
410             
411             if (v3_get_state_vm(guest_map[i]->v3_ctx, base, core, mem)) {
412                 ERROR("Cannot get VM info\n");
413                 seq_printf(s, "\t<unable to get data for this VM>\n");
414             } else {
415                 seq_printf(s,"\t%s\t%lu vcores\t%lu regions\n",
416                            base->state==V3_VM_INVALID ? "INVALID" :
417                            base->state==V3_VM_RUNNING ? "running" :
418                            base->state==V3_VM_STOPPED ? "stopped" :
419                            base->state==V3_VM_PAUSED ? "paused" :
420                            base->state==V3_VM_ERROR ? "ERROR" :
421                            base->state==V3_VM_SIMULATING ? "simulating" : "UNKNOWN",
422                            core->num_vcores,
423                            mem->num_regions);
424             }
425         }
426     }
427         
428         
429  out:
430     if (mem) { palacios_free(mem); }
431     if (core) { palacios_free(core); }
432     if (base) { palacios_free(base); }
433     
434     return 0;
435 }
436
437
438 static int guests_short_proc_open(struct inode * inode, struct file * filp) 
439 {
440     struct proc_dir_entry * proc_entry = PDE(inode);
441     return single_open(filp, read_guests, proc_entry->data);
442 }
443
444 static int guests_full_proc_open(struct inode * inode, struct file * filp) 
445 {
446     struct proc_dir_entry * proc_entry = PDE(inode);
447     return single_open(filp, read_guests_details, proc_entry->data);
448 }
449
450
451
452
453 static struct file_operations guest_full_proc_ops = {
454     .owner = THIS_MODULE,
455     .open = guests_full_proc_open, 
456     .read = seq_read,
457     .llseek = seq_lseek, 
458     .release = single_release,
459 };
460
461 static struct file_operations guest_short_proc_ops = {
462     .owner = THIS_MODULE,
463     .open = guests_short_proc_open, 
464     .read = seq_read,
465     .llseek = seq_lseek, 
466     .release = single_release,
467 };
468
469 // Supply basic information that the user-space tools need
470 // to manipulate Palacios.   The current use case here is to 
471 // convey memory information
472 static int read_info(struct seq_file *s, void *v)
473 {
474     uint64_t mem_block_size;
475     int i,j;
476     int max_node=-1;
477     seq_printf(s,"kernel MAX_ORDER:\t%d\n",MAX_ORDER);
478     seq_printf(s,"number of nodes:\t%d\n", numa_num_nodes());
479     seq_printf(s,"number of cpus: \t%d\n", num_online_cpus());
480     seq_printf(s,"\npalacios compiled mem_block_size:\t%d\n", V3_CONFIG_MEM_BLOCK_SIZE);
481     if (!v3_lookup_option("mem_block_size")) { 
482         mem_block_size = V3_CONFIG_MEM_BLOCK_SIZE;
483     } else {
484         if (strict_strtoull(v3_lookup_option("mem_block_size"), 0, &mem_block_size)) {
485             // huh?
486             mem_block_size=-1;
487         }
488     }
489     seq_printf(s,"palacios run-time mem_block_size:\t%llu\n", mem_block_size);
490     
491     seq_printf(s,"\nCPU to node mappings\n");
492     for (i=0;i<num_online_cpus();i++) { 
493         seq_printf(s,"cpu %d -> node %d\n", i, numa_cpu_to_node(i));
494         if (numa_cpu_to_node(i)>max_node) { 
495             max_node=numa_cpu_to_node(i);
496         }
497     }
498     seq_printf(s,"\nNode to node distances\n");
499     for (j=0;j<=max_node;j++) { 
500         seq_printf(s,"   \t%2d", j);
501     }
502     seq_printf(s,"\n");
503     for (i=0;i<=max_node;i++) { 
504         seq_printf(s,"%2d ",i);
505         for (j=0;j<=max_node;j++) { 
506             seq_printf(s,"\t%2d", numa_get_distance(i,j));
507         }
508         seq_printf(s,"\n");
509     }
510     seq_printf(s,"\nCPU to CPU distances\n");
511     for (j=0;j<num_online_cpus();j++) { 
512         seq_printf(s,"   \t%2d", j);
513     }
514     seq_printf(s,"\n");
515     for (i=0;i<num_online_cpus();i++) { 
516         seq_printf(s,"%2d ",i);
517         for (j=0;j<num_online_cpus();j++) { 
518             seq_printf(s,"\t%2d", numa_get_distance(numa_cpu_to_node(i),numa_cpu_to_node(j)));
519         }
520         seq_printf(s,"\n");
521     }
522     return 0;
523 }
524
525 static int info_proc_open(struct inode * inode, struct file * filp) 
526 {
527     struct proc_dir_entry * proc_entry = PDE(inode);
528     return single_open(filp, read_info, proc_entry->data);
529 }
530
531
532
533 static struct file_operations info_proc_ops = {
534     .owner = THIS_MODULE,
535     .open = info_proc_open, 
536     .read = seq_read,
537     .llseek = seq_lseek, 
538     .release = single_release,
539 };
540
541
542 static int __init v3_init(void) {
543
544     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
545     int ret = 0;
546
547     LOCKCHECK_INIT();
548     MEMCHECK_INIT();
549
550     palacios_proc_dir = proc_mkdir("v3vee", NULL);
551     if (!palacios_proc_dir) {
552         ERROR("Could not create proc entry\n");
553         ret = -1;
554         goto failure1;
555     }
556
557     // this will populate the v3vee tree...
558     if (palacios_init_mm()) { 
559         goto failure2;
560     }
561
562     if (allow_devmem) {
563       palacios_allow_devmem();
564     }
565
566     // Initialize Palacios
567     palacios_vmm_init(options);
568
569     // initialize extensions
570     init_lnx_extensions();
571
572
573     v3_class = class_create(THIS_MODULE, "vms");
574     if (IS_ERR(v3_class)) {
575         ERROR("Failed to register V3 VM device class\n");
576         ret =  PTR_ERR(v3_class);
577         goto failure3;
578     }
579
580     INFO("intializing V3 Control device\n");
581
582     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
583
584     if (ret < 0) {
585         ERROR("Error registering device region for V3 devices\n");
586         goto failure4;
587     }
588
589     v3_major_num = MAJOR(dev);
590
591     dev = MKDEV(v3_major_num, MAX_VMS + 1);
592
593     
594     DEBUG("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
595     cdev_init(&ctrl_dev, &v3_ctrl_fops);
596     ctrl_dev.owner = THIS_MODULE;
597     ctrl_dev.ops = &v3_ctrl_fops;
598     cdev_add(&ctrl_dev, dev, 1);
599     
600     device_create(v3_class, NULL, dev, NULL, "v3vee");
601
602     if (ret != 0) {
603         ERROR("Error adding v3 control device\n");
604         goto failure5;
605     }
606
607     {
608         struct proc_dir_entry *entry;
609
610         entry = create_proc_entry("v3-guests", 0444, palacios_proc_dir);
611         if (entry) {
612             entry->proc_fops = &guest_short_proc_ops;
613             INFO("/proc/v3vee/v3-guests successfully created\n");
614         } else {
615             ERROR("Could not create proc entry\n");
616             goto failure6;
617         }
618         entry = create_proc_entry("v3-guests-details", 0444, palacios_proc_dir);
619         if (entry) {
620             entry->proc_fops = &guest_full_proc_ops;
621             INFO("/proc/v3vee/v3-guests-details successfully created\n");
622         } else {
623             ERROR("Could not create proc entry\n");
624             goto failure7;
625         }
626
627         entry = create_proc_entry("v3-info", 0444, palacios_proc_dir);
628         if (entry) {
629             entry->proc_fops = &info_proc_ops;
630             INFO("/proc/v3vee/v3-info successfully created\n");
631         } else {
632             ERROR("Could not create proc entry\n");
633             goto failure8;
634         }
635
636
637     }
638         
639     return 0;
640
641  failure8:
642     remove_proc_entry("v3-guests-details", palacios_proc_dir);
643  failure7:
644     remove_proc_entry("v3-guests", palacios_proc_dir);
645  failure6:
646     device_destroy(v3_class, dev);
647  failure5:
648     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
649  failure4:
650     class_destroy(v3_class);
651  failure3:
652     if (allow_devmem) {
653       palacios_restore_devmem();
654     }
655     palacios_deinit_mm();
656  failure2:
657     remove_proc_entry("v3vee", NULL);
658  failure1:   
659     MEMCHECK_DEINIT();
660     LOCKCHECK_DEINIT();
661
662     return ret;
663 }
664
665
666 static void __exit v3_exit(void) {
667     extern u32 pg_allocs;
668     extern u32 pg_frees;
669     extern u32 mallocs;
670     extern u32 frees;
671     extern u32 vmallocs;
672     extern u32 vfrees;
673     int i = 0;
674     struct v3_guest * guest;
675     dev_t dev;
676
677
678     /* Stop and free any running VMs */ 
679     for (i = 0; i < MAX_VMS; i++) {
680         if (guest_map[i] != NULL) {
681                 guest = (struct v3_guest *)guest_map[i];
682
683                 if (v3_stop_vm(guest->v3_ctx) < 0) 
684                         ERROR("Couldn't stop VM %d\n", i);
685
686                 free_palacios_vm(guest);
687                 guest_map[i] = NULL;
688         }
689     }
690
691     dev = MKDEV(v3_major_num, MAX_VMS + 1);
692
693     INFO("Removing V3 Control device\n");
694
695
696     palacios_vmm_exit();
697
698     DEBUG("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
699     DEBUG("Palacios Vmallocs = %d, Vfrees = %d\n", vmallocs, vfrees);
700     DEBUG("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
701
702     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
703
704     cdev_del(&ctrl_dev);
705
706     device_destroy(v3_class, dev);
707     class_destroy(v3_class);
708
709
710     deinit_lnx_extensions();
711
712     if (allow_devmem) {
713       palacios_restore_devmem();
714     }
715
716     palacios_deinit_mm();
717
718     remove_proc_entry("v3-info", palacios_proc_dir);
719     remove_proc_entry("v3-guests-details", palacios_proc_dir);
720     remove_proc_entry("v3-guests", palacios_proc_dir);
721     remove_proc_entry("v3vee", NULL);
722
723     DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
724     
725     MEMCHECK_DEINIT();
726     LOCKCHECK_DEINIT();
727 }
728
729
730
731 module_init(v3_init);
732 module_exit(v3_exit);
733
734
735
736 void * trace_malloc(size_t size, gfp_t flags) {
737     void * addr = NULL;
738
739     mod_allocs++;
740     addr = palacios_alloc_extended(size, flags, -1);
741
742     return addr;
743 }
744
745
746 void trace_free(const void * objp) {
747     mod_frees++;
748     palacios_free((void*)objp);
749 }