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.


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