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.


38a2fd4a28e33d1aacd812fc5f71189478a24a2b
[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 (!(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 (!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 (node %d) %s %s\n",
359                                j, mem->region[j].host_paddr, mem->region[j].host_paddr+mem->region[j].size,
360                                numa_addr_to_node((uintptr_t)(mem->region[j].host_paddr)),
361                                mem->region[j].swapped ? "swapped" : "",
362                                mem->region[j].pinned ? "pinned" : "");
363                 }
364             }
365             seq_printf(s,
366                        "---------------------------------------------------------------------------------------\n");
367         }
368     }
369     
370     
371  out:
372     if (mem) { palacios_free(mem); }
373     if (core) { palacios_free(core); }
374     if (base) { palacios_free(base); }
375     
376     return 0;
377 }
378
379 static int read_guests(struct seq_file *s, void *v)
380 {
381     unsigned int i = 0;
382     struct v3_vm_base_state *base=0;
383     struct v3_vm_core_state *core=0;
384     struct v3_vm_mem_state *mem=0;
385     
386     base = palacios_alloc(sizeof(struct v3_vm_base_state));
387     
388     if (!base) { 
389       ERROR("No space for base state structure\n");
390       goto out;
391     }
392
393     core = palacios_alloc(sizeof(struct v3_vm_core_state) + MAX_VCORES*sizeof(struct v3_vm_vcore_state));
394     
395     if (!core) { 
396         ERROR("No space for core state structure\n");
397         goto out;
398     }
399     
400     mem = palacios_alloc(sizeof(struct v3_vm_mem_state) + MAX_REGIONS*sizeof(struct v3_vm_mem_region));
401     
402     if (!mem) { 
403         ERROR("No space for memory state structure\n");
404         goto out;
405     }
406     
407     for(i = 0; i < MAX_VMS; i++) {
408         if (guest_map[i] != NULL) {
409             seq_printf(s,"%s\t/dev/v3-vm%d", guest_map[i]->name, i);
410             // Get extended data
411             core->num_vcores=MAX_VCORES; // max we can handle
412             mem->num_regions=MAX_REGIONS; // max we can handle
413             
414             if (v3_get_state_vm(guest_map[i]->v3_ctx, base, core, mem)) {
415                 ERROR("Cannot get VM info\n");
416                 seq_printf(s, "\t<unable to get data for this VM>\n");
417             } else {
418                 seq_printf(s,"\t%s\t%lu vcores\t%lu regions\n",
419                            base->state==V3_VM_INVALID ? "INVALID" :
420                            base->state==V3_VM_RUNNING ? "running" :
421                            base->state==V3_VM_STOPPED ? "stopped" :
422                            base->state==V3_VM_PAUSED ? "paused" :
423                            base->state==V3_VM_ERROR ? "ERROR" :
424                            base->state==V3_VM_SIMULATING ? "simulating" : "UNKNOWN",
425                            core->num_vcores,
426                            mem->num_regions);
427             }
428         }
429     }
430         
431         
432  out:
433     if (mem) { palacios_free(mem); }
434     if (core) { palacios_free(core); }
435     if (base) { palacios_free(base); }
436     
437     return 0;
438 }
439
440
441 static int guests_short_proc_open(struct inode * inode, struct file * filp) 
442 {
443     struct proc_dir_entry * proc_entry = PDE(inode);
444     return single_open(filp, read_guests, proc_entry->data);
445 }
446
447 static int guests_full_proc_open(struct inode * inode, struct file * filp) 
448 {
449     struct proc_dir_entry * proc_entry = PDE(inode);
450     return single_open(filp, read_guests_details, proc_entry->data);
451 }
452
453
454
455
456 static struct file_operations guest_full_proc_ops = {
457     .owner = THIS_MODULE,
458     .open = guests_full_proc_open, 
459     .read = seq_read,
460     .llseek = seq_lseek, 
461     .release = single_release,
462 };
463
464 static struct file_operations guest_short_proc_ops = {
465     .owner = THIS_MODULE,
466     .open = guests_short_proc_open, 
467     .read = seq_read,
468     .llseek = seq_lseek, 
469     .release = single_release,
470 };
471
472 // Supply basic information that the user-space tools need
473 // to manipulate Palacios.   The current use case here is to 
474 // convey memory information
475 static int read_info(struct seq_file *s, void *v)
476 {
477     uint64_t mem_block_size;
478     int i,j;
479     int max_node=-1;
480     seq_printf(s,"kernel MAX_ORDER:\t%d\n",MAX_ORDER);
481     seq_printf(s,"number of nodes:\t%d\n", numa_num_nodes());
482     seq_printf(s,"number of cpus: \t%d\n", num_online_cpus());
483     seq_printf(s,"\npalacios compiled mem_block_size:\t%d\n", V3_CONFIG_MEM_BLOCK_SIZE);
484     if (!v3_lookup_option("mem_block_size")) { 
485         mem_block_size = V3_CONFIG_MEM_BLOCK_SIZE;
486     } else {
487         if (strict_strtoull(v3_lookup_option("mem_block_size"), 0, &mem_block_size)) {
488             // huh?
489             mem_block_size=-1;
490         }
491     }
492     seq_printf(s,"palacios run-time mem_block_size:\t%llu\n", mem_block_size);
493     
494     seq_printf(s,"\nCPU to node mappings\n");
495     for (i=0;i<num_online_cpus();i++) { 
496         seq_printf(s,"cpu %d -> node %d\n", i, numa_cpu_to_node(i));
497         if (numa_cpu_to_node(i)>max_node) { 
498             max_node=numa_cpu_to_node(i);
499         }
500     }
501     seq_printf(s,"\nNode to node distances\n");
502     for (j=0;j<=max_node;j++) { 
503         seq_printf(s,"   \t%2d", j);
504     }
505     seq_printf(s,"\n");
506     for (i=0;i<=max_node;i++) { 
507         seq_printf(s,"%2d ",i);
508         for (j=0;j<=max_node;j++) { 
509             seq_printf(s,"\t%2d", numa_get_distance(i,j));
510         }
511         seq_printf(s,"\n");
512     }
513     seq_printf(s,"\nCPU to CPU distances\n");
514     for (j=0;j<num_online_cpus();j++) { 
515         seq_printf(s,"   \t%2d", j);
516     }
517     seq_printf(s,"\n");
518     for (i=0;i<num_online_cpus();i++) { 
519         seq_printf(s,"%2d ",i);
520         for (j=0;j<num_online_cpus();j++) { 
521             seq_printf(s,"\t%2d", numa_get_distance(numa_cpu_to_node(i),numa_cpu_to_node(j)));
522         }
523         seq_printf(s,"\n");
524     }
525     return 0;
526 }
527
528 static int info_proc_open(struct inode * inode, struct file * filp) 
529 {
530     struct proc_dir_entry * proc_entry = PDE(inode);
531     return single_open(filp, read_info, proc_entry->data);
532 }
533
534
535
536 static struct file_operations info_proc_ops = {
537     .owner = THIS_MODULE,
538     .open = info_proc_open, 
539     .read = seq_read,
540     .llseek = seq_lseek, 
541     .release = single_release,
542 };
543
544
545 static int __init v3_init(void) {
546
547     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
548     int ret = 0;
549
550     LOCKCHECK_INIT();
551     MEMCHECK_INIT();
552
553     palacios_proc_dir = proc_mkdir("v3vee", NULL);
554     if (!palacios_proc_dir) {
555         ERROR("Could not create proc entry\n");
556         ret = -1;
557         goto failure1;
558     }
559
560     // this will populate the v3vee tree...
561     if (palacios_init_mm()) { 
562         goto failure2;
563     }
564
565     if (allow_devmem) {
566       palacios_allow_devmem();
567     }
568
569     // numa is now a required interface and we need it
570     // up before primary initiatilization
571     palacios_init_numa();
572
573     // Initialize Palacios
574     palacios_vmm_init(options);
575
576     // initialize extensions
577     init_lnx_extensions();
578
579
580     v3_class = class_create(THIS_MODULE, "vms");
581     if (!v3_class || IS_ERR(v3_class)) {
582         ERROR("Failed to register V3 VM device class\n");
583         ret =  PTR_ERR(v3_class);
584         goto failure3;
585     }
586
587     INFO("intializing V3 Control device\n");
588
589     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
590
591     if (ret < 0) {
592         ERROR("Error registering device region for V3 devices\n");
593         goto failure4;
594     }
595
596     v3_major_num = MAJOR(dev);
597
598     dev = MKDEV(v3_major_num, MAX_VMS + 1);
599
600     
601     DEBUG("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
602     cdev_init(&ctrl_dev, &v3_ctrl_fops);
603     ctrl_dev.owner = THIS_MODULE;
604     ctrl_dev.ops = &v3_ctrl_fops;
605     cdev_add(&ctrl_dev, dev, 1);
606     
607     device_create(v3_class, NULL, dev, NULL, "v3vee");
608
609     if (ret != 0) {
610         ERROR("Error adding v3 control device\n");
611         goto failure5;
612     }
613
614     {
615         struct proc_dir_entry *entry;
616
617         entry = create_proc_entry("v3-guests", 0444, palacios_proc_dir);
618         if (entry) {
619             entry->proc_fops = &guest_short_proc_ops;
620             INFO("/proc/v3vee/v3-guests successfully created\n");
621         } else {
622             ERROR("Could not create proc entry\n");
623             goto failure6;
624         }
625         entry = create_proc_entry("v3-guests-details", 0444, palacios_proc_dir);
626         if (entry) {
627             entry->proc_fops = &guest_full_proc_ops;
628             INFO("/proc/v3vee/v3-guests-details successfully created\n");
629         } else {
630             ERROR("Could not create proc entry\n");
631             goto failure7;
632         }
633
634         entry = create_proc_entry("v3-info", 0444, palacios_proc_dir);
635         if (entry) {
636             entry->proc_fops = &info_proc_ops;
637             INFO("/proc/v3vee/v3-info successfully created\n");
638         } else {
639             ERROR("Could not create proc entry\n");
640             goto failure8;
641         }
642
643
644     }
645         
646     return 0;
647
648  failure8:
649     remove_proc_entry("v3-guests-details", palacios_proc_dir);
650  failure7:
651     remove_proc_entry("v3-guests", palacios_proc_dir);
652  failure6:
653     device_destroy(v3_class, dev);
654  failure5:
655     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
656  failure4:
657     class_destroy(v3_class);
658  failure3:
659     if (allow_devmem) {
660       palacios_restore_devmem();
661     }
662     palacios_deinit_mm();
663  failure2:
664     remove_proc_entry("v3vee", NULL);
665  failure1:   
666     MEMCHECK_DEINIT();
667     LOCKCHECK_DEINIT();
668
669     return ret;
670 }
671
672
673 static void __exit v3_exit(void) {
674     extern u32 pg_allocs;
675     extern u32 pg_frees;
676     extern u32 mallocs;
677     extern u32 frees;
678     extern u32 vmallocs;
679     extern u32 vfrees;
680     int i = 0;
681     struct v3_guest * guest;
682     dev_t dev;
683
684
685     /* Stop and free any running VMs */ 
686     for (i = 0; i < MAX_VMS; i++) {
687                 if (guest_map[i] != NULL) {
688                     guest = (struct v3_guest *)(guest_map[i]);
689
690                 if (!guest->v3_ctx) { 
691                     ERROR("Orphan VM detected and skipped: index=%d name=%s\n", i, guest->name);
692                     continue;
693                 }
694
695                 if (v3_stop_vm(guest->v3_ctx) < 0) 
696                         ERROR("Couldn't stop VM %d\n", i);
697
698                 free_palacios_vm(guest);
699                 guest_map[i] = NULL;
700         }
701     }
702
703     dev = MKDEV(v3_major_num, MAX_VMS + 1);
704
705     INFO("Removing V3 Control device\n");
706
707
708     palacios_vmm_exit();
709
710     palacios_deinit_numa();
711
712     DEBUG("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
713     DEBUG("Palacios Vmallocs = %d, Vfrees = %d\n", vmallocs, vfrees);
714     DEBUG("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
715
716     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
717
718     cdev_del(&ctrl_dev);
719
720     device_destroy(v3_class, dev);
721     class_destroy(v3_class);
722
723
724     deinit_lnx_extensions();
725
726     if (allow_devmem) {
727       palacios_restore_devmem();
728     }
729
730     palacios_deinit_mm();
731
732     remove_proc_entry("v3-info", palacios_proc_dir);
733     remove_proc_entry("v3-guests-details", palacios_proc_dir);
734     remove_proc_entry("v3-guests", palacios_proc_dir);
735     remove_proc_entry("v3vee", NULL);
736
737     DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
738     
739     MEMCHECK_DEINIT();
740     LOCKCHECK_DEINIT();
741 }
742
743
744
745 module_init(v3_init);
746 module_exit(v3_exit);
747
748
749
750 void * trace_malloc(size_t size, gfp_t flags) {
751     void * addr = NULL;
752
753     mod_allocs++;
754     addr = palacios_alloc_extended(size, flags, -1);
755
756     return addr;
757 }
758
759
760 void trace_free(const void * objp) {
761     mod_frees++;
762     palacios_free((void*)objp);
763 }