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.


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