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.


Linux kernel compatability enhancements (through 3.19)
[palacios.git] / linux_module / main.c
1 /* 
2    Palacios main control interface
3    (c) Jack Lange, 2010
4  */
5
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/moduleparam.h>
9 #include <linux/errno.h>
10 #include <linux/percpu.h>
11 #include <linux/fs.h>
12 #include <linux/uaccess.h>
13 #include <linux/device.h>
14 #include <linux/cdev.h>
15
16 #include <linux/io.h>
17
18 #include <linux/file.h>
19 #include <linux/spinlock.h>
20 #include <linux/kthread.h>
21
22 #include <linux/proc_fs.h>
23 #include <linux/seq_file.h>
24
25 #include <palacios/vmm.h>
26
27 #include "palacios.h"
28 #include "mm.h"
29 #include "vm.h"
30 #include "numa.h"
31 #include "allow_devmem.h"
32 #include "memcheck.h"
33 #include "lockcheck.h"
34
35 #include "linux-exts.h"
36
37 #include "util-hashtable.h"
38
39
40 MODULE_LICENSE("GPL");
41
42 // Module parameter
43 int cpu_list[NR_CPUS] = {};
44 int cpu_list_len = 0;
45 module_param_array(cpu_list, int, &cpu_list_len, 0644);
46 MODULE_PARM_DESC(cpu_list, "Comma-delimited list of CPUs that Palacios will run on");
47
48 static int allow_devmem = 0;
49 module_param(allow_devmem, int, 0);
50 MODULE_PARM_DESC(allow_devmem, "Allow general user-space /dev/mem access even if kernel is strict");
51
52 // Palacios options parameter
53 static char *options;
54 module_param(options, charp, 0);
55 MODULE_PARM_DESC(options, "Generic options to internal Palacios modules");
56
57
58 int mod_allocs = 0;
59 int mod_frees = 0;
60
61 static int v3_major_num = 0;
62
63 static struct v3_guest * guest_map[MAX_VMS] = {[0 ... MAX_VMS - 1] = 0};
64 static struct proc_dir_entry * palacios_proc_dir = NULL;
65
66 struct class * v3_class = NULL;
67 static struct cdev ctrl_dev;
68
69
70 // mapping from thread ids to their resource control blocks
71 struct hashtable *v3_thread_resource_map=0;
72
73 static int register_vm(struct v3_guest * guest) {
74     int i = 0;
75
76     for (i = 0; i < MAX_VMS; i++) {
77         if (guest_map[i] == NULL) {
78             guest_map[i] = guest;
79             return i;
80         }
81     }
82
83     return -1;
84 }
85
86
87
88 static long v3_dev_ioctl(struct file * filp,
89                          unsigned int ioctl, unsigned long arg) {
90     void __user * argp = (void __user *)arg;
91     DEBUG("V3 IOCTL %d\n", ioctl);
92
93
94     switch (ioctl) {
95         case V3_CREATE_GUEST:{
96             int vm_minor = 0;
97             struct v3_guest_img user_image;
98             struct v3_guest * guest = palacios_alloc(sizeof(struct v3_guest));
99
100             if (!(guest)) {
101                 ERROR("Palacios: Error allocating Kernel guest_image\n");
102                 return -EFAULT;
103             }
104
105             memset(guest, 0, sizeof(struct v3_guest));
106
107             INFO("Palacios: Creating V3 Guest...\n");
108
109             vm_minor = register_vm(guest);
110
111             if (vm_minor == -1) {
112                 ERROR("Palacios Error: Too many VMs are currently running\n");
113                 goto out_err;
114             }
115
116             guest->vm_dev = MKDEV(v3_major_num, vm_minor);
117
118             if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
119                 ERROR("Palacios Error: copy from user error getting guest image...\n");
120                 goto out_err1;
121             }
122
123             guest->img_size = user_image.size;
124
125             DEBUG("Palacios: Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
126             // overflow possible here, but only if guest image is probably to large for kernel anyway...
127             guest->img = palacios_valloc(guest->img_size);
128
129             if (!guest->img) {
130                 ERROR("Palacios Error: Could not allocate space for guest image\n");
131                 goto out_err1;
132             }
133
134             if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
135                 ERROR("Palacios: Error loading guest data\n");
136                 goto out_err2;
137             }      
138
139             strncpy(guest->name, user_image.name, 128);
140             guest->name[127] = 0;
141
142             INIT_LIST_HEAD(&(guest->exts));
143
144             if (create_palacios_vm(guest) == -1) {
145                 ERROR("Palacios: Error creating guest\n");
146                 goto out_err2;
147             }
148
149             return vm_minor;
150
151
152 out_err2:
153             palacios_vfree(guest->img);
154 out_err1:
155             guest_map[vm_minor] = NULL; 
156 out_err:
157             palacios_free(guest);
158
159             return -1;
160
161             break;
162         }
163         case V3_FREE_GUEST: {
164             unsigned long vm_idx = arg;
165             struct v3_guest * guest;
166
167             if (vm_idx >= MAX_VMS) {
168                 ERROR("Invalid VM index: %ld\n", vm_idx);
169                 return -1;
170             }
171
172             guest = guest_map[vm_idx];
173
174             if (!guest) {
175                 ERROR("No VM at index %ld\n",vm_idx);
176                 return -1;
177             }
178
179             INFO("Freeing VM (%s) (%p)\n", guest->name, guest);
180
181             if (free_palacios_vm(guest)<0) { 
182                 ERROR("Cannot free guest at index %ld\n",vm_idx);
183                 return -1;
184             }
185
186             guest_map[vm_idx] = NULL;
187             break;
188         }
189         case V3_ADD_MEMORY: {
190             struct v3_mem_region mem;
191             
192             memset(&mem, 0, sizeof(struct v3_mem_region));
193             
194             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
195                 ERROR("copy from user error getting mem_region...\n");
196                 return -EFAULT;
197             }
198
199             DEBUG("Adding %llu pages to Palacios memory\n", mem.num_pages);
200
201             if (add_palacios_memory(&mem) == -1) {
202                 ERROR("Error adding memory to Palacios\n");
203                 return -EFAULT;
204             }
205
206             break;
207         }
208
209         case V3_REMOVE_MEMORY: {
210             struct v3_mem_region mem;
211             
212             memset(&mem, 0, sizeof(struct v3_mem_region));
213             
214             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
215                 ERROR("copy from user error getting mem_region...\n");
216                 return -EFAULT;
217             }
218
219             DEBUG("Removing memory at address %p\n", (void*)(mem.base_addr));
220
221             if (remove_palacios_memory(&mem) == -1) {
222                 ERROR("Error removing memory from Palacios\n");
223                 return -EFAULT;
224             }
225
226             break;
227         }
228             
229             
230
231         case V3_RESET_MEMORY: {
232             DEBUG("Resetting memory\n");
233             if (palacios_deinit_mm() == -1) {
234                 ERROR("Error deiniting the Palacios memory manager\n");
235                 return -EFAULT;
236             }
237             if (palacios_init_mm()) { 
238                 ERROR("Error initing the Palacios memory manager\n");
239                 return -EFAULT;
240             }
241             break;  
242         }
243
244         default: {
245             struct global_ctrl * ctrl = get_global_ctrl(ioctl);
246             
247             if (ctrl) {
248                 return ctrl->handler(ioctl, arg);
249             }
250
251             WARNING("\tUnhandled global ctrl cmd: %d\n", ioctl);
252
253             return -EINVAL;
254         }
255     }
256
257     return 0;
258 }
259
260
261
262 static struct file_operations v3_ctrl_fops = {
263     .owner = THIS_MODULE,
264     .unlocked_ioctl = v3_dev_ioctl,
265     .compat_ioctl = v3_dev_ioctl,
266 };
267
268
269
270 struct proc_dir_entry *palacios_get_procdir(void) 
271 {
272     //    INFO("Returning procdir=%p\n",palacios_proc_dir);
273     return palacios_proc_dir;
274 }
275
276
277 #define MAX_CORES   1024
278 #define MAX_REGIONS 1024
279 #define MIN(x,y) ((x)<(y) ? (x) : (y))
280
281 static int read_guests_details(struct seq_file *s, void *v)
282 {
283     unsigned int i = 0;
284     unsigned int j = 0;
285     uint64_t num_vcores, num_regions;
286     uint64_t alloc_num_vcores, alloc_num_regions;
287     struct v3_vm_base_state *base=0;
288     struct v3_vm_core_state *core=0;
289     struct v3_vm_mem_state *mem=0;
290
291
292     base = palacios_valloc(sizeof(struct v3_vm_base_state));
293     
294
295     if (!base) { 
296       ERROR("No space for base state structure\n");
297       goto out;
298     }
299
300
301     for(i = 0; i < MAX_VMS; i++) {
302
303         if (guest_map[i] != NULL) {
304             
305             v3_get_state_sizes_vm(guest_map[i]->v3_ctx,&num_vcores,&num_regions);
306
307             alloc_num_vcores = MIN(num_vcores,MAX_CORES);
308             alloc_num_regions = MIN(num_regions,MAX_REGIONS);
309
310             core = palacios_valloc(sizeof(struct v3_vm_core_state) + alloc_num_vcores*sizeof(struct v3_vm_vcore_state));
311             
312             if (!core) { 
313                 ERROR("No space for core state structure\n");
314                 goto out;
315             }
316     
317             mem = palacios_valloc(sizeof(struct v3_vm_mem_state) + alloc_num_regions*sizeof(struct v3_vm_mem_region));
318     
319             if (!mem) { 
320                 ERROR("No space for memory state structure\n");
321                 goto out;
322             }
323     
324             seq_printf(s,
325                        "---------------------------------------------------------------------------------------\n");
326             seq_printf(s, 
327                        "Entry:        %d\n"
328                        "Name:         %s\n"
329                        "Device:       /dev/v3-vm%d\n", 
330                        i,guest_map[i]->name, i);
331             
332             // Get extended data
333             core->num_vcores=alloc_num_vcores;
334             mem->num_regions=alloc_num_regions;
335             
336             if (v3_get_state_vm(guest_map[i]->v3_ctx, base, core, mem)) {
337                 ERROR("Cannot get VM info\n");
338                 seq_printf(s, "<unable to get data for this VM>\n");
339             } else {
340                 seq_printf(s, 
341                            "Type:         %s\n"
342                            "State:        %s\n"
343                            "Cores:        %llu (%llu shown)\n"
344                            "Regions:      %llu (%llu shown)\n"
345                            "Memsize:      %llu (%llu ROS)\n\n",
346                            base->vm_type==V3_VM_GENERAL ? "general" :
347                            base->vm_type==V3_VM_HVM ? "HVM" : "UNKNOWN",
348                            base->state==V3_VM_INVALID ? "INVALID" :
349                            base->state==V3_VM_RUNNING ? "running" :
350                            base->state==V3_VM_STOPPED ? "stopped" :
351                            base->state==V3_VM_PAUSED ? "paused" :
352                            base->state==V3_VM_ERROR ? "ERROR" :
353                            base->state==V3_VM_SIMULATING ? "simulating" : 
354                            base->state==V3_VM_RESETTING ? "resetting"  : "UNKNOWN",
355                            num_vcores,
356                            core->num_vcores,
357                            num_regions,
358                            mem->num_regions,
359                            mem->mem_size,
360                            mem->ros_mem_size);
361
362                 seq_printf(s, "Core States\n");
363                 
364                 for (j=0;j<core->num_vcores;j++) {
365                     seq_printf(s,
366                                "   vcore %u %s on pcore %lu %llu exits rip=0x%p %s %s %s %s\n",
367                                j, 
368                                core->vcore[j].state==V3_VCORE_INVALID ? "INVALID" :
369                                core->vcore[j].state==V3_VCORE_RUNNING ? "running" :
370                                core->vcore[j].state==V3_VCORE_STOPPED ? "stopped" :
371                                core->vcore[j].state==V3_VCORE_RESETTING ? "resetting" : "UNKNOWN",
372                                core->vcore[j].pcore,
373                                core->vcore[j].num_exits,
374                                core->vcore[j].last_rip,
375                                core->vcore[j].cpu_mode==V3_VCORE_CPU_REAL ? "real" :
376                                core->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED ? "protected" :
377                                core->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED_PAE ? "protectedpae" :
378                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG ? "long" :
379                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_32_COMPAT ? "long32" :
380                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_16_COMPAT ? "long16" : "UNKNOWN",
381                                core->vcore[j].mem_mode==V3_VCORE_MEM_MODE_PHYSICAL ? "physical" :
382                                core->vcore[j].mem_mode==V3_VCORE_MEM_MODE_VIRTUAL ? "virtual" : "UNKNOWN",
383                                core->vcore[j].mem_state==V3_VCORE_MEM_STATE_SHADOW ? "shadow" :
384                                core->vcore[j].mem_state==V3_VCORE_MEM_STATE_NESTED ? "nested" : "UNKNOWN",
385                                core->vcore[j].vcore_type==V3_VCORE_GENERAL ? "" :
386                                core->vcore[j].vcore_type==V3_VCORE_ROS ? "ros" :
387                                core->vcore[j].vcore_type==V3_VCORE_HRT ? "hrt" : "UNKNOWN");
388                 }
389
390
391                 seq_printf(s, "\nMemory Regions\n");
392                 for (j=0;j<mem->num_regions;j++) { 
393                     seq_printf(s,"   region %u has HPAs 0x%016llx-0x%016llx (node %d) GPA 0x%016llx %s %s\n",
394                                j, (uint64_t)mem->region[j].host_paddr, (uint64_t)mem->region[j].host_paddr+mem->region[j].size,
395                                numa_addr_to_node((uintptr_t)(mem->region[j].host_paddr)),
396                                (uint64_t)mem->region[j].guest_paddr,
397                                mem->region[j].swapped ? "swapped" : "",
398                                mem->region[j].pinned ? "pinned" : "");
399                 }
400
401             }
402             seq_printf(s,
403                        "---------------------------------------------------------------------------------------\n");
404
405             palacios_vfree(mem); mem=0;
406             palacios_vfree(core); core=0;
407
408         }
409
410     }
411     
412     
413  out:
414     if (mem) { palacios_vfree(mem); } // dead code but kept for clarity
415     if (core) { palacios_vfree(core); }
416     if (base) { palacios_vfree(base); }
417     
418     return 0;
419 }
420
421 static int read_guests(struct seq_file *s, void *v)
422 {
423     unsigned int i = 0;
424     struct v3_vm_base_state *base=0;
425     struct v3_vm_core_state *core=0;
426     struct v3_vm_mem_state *mem=0;
427     uint64_t num_vcores, num_regions;
428
429
430     INFO("READ GUEST\n");
431     
432     base = palacios_valloc(sizeof(struct v3_vm_base_state));
433     
434     if (!base) { 
435       ERROR("No space for base state structure\n");
436       goto out;
437     }
438
439     core = palacios_valloc(sizeof(struct v3_vm_core_state));
440     
441     if (!core) { 
442         ERROR("No space for core state structure\n");
443         goto out;
444     }
445     
446     mem = palacios_valloc(sizeof(struct v3_vm_mem_state));
447     
448     if (!mem) { 
449         ERROR("No space for memory state structure\n");
450         goto out;
451     }
452     
453
454     for(i = 0; i < MAX_VMS; i++) {
455         if (guest_map[i] != NULL) {
456
457             v3_get_state_sizes_vm(guest_map[i]->v3_ctx,&num_vcores,&num_regions);
458
459             seq_printf(s,"%s\t/dev/v3-vm%d", guest_map[i]->name, i);
460
461             // Skip getting per core and per-region 
462             core->num_vcores=0;
463             mem->num_regions=0;
464             
465             if (v3_get_state_vm(guest_map[i]->v3_ctx, base, core, mem)) {
466                 ERROR("Cannot get VM info\n");
467                 seq_printf(s, "\t<unable to get data for this VM>\n");
468             } else {
469                 seq_printf(s,"\t%s\t%llu vcores\t%llu regions\t%llu mem\t%s\n",
470                            base->state==V3_VM_INVALID ? "INVALID" :
471                            base->state==V3_VM_RUNNING ? "running" :
472                            base->state==V3_VM_STOPPED ? "stopped" :
473                            base->state==V3_VM_PAUSED ? "paused" :
474                            base->state==V3_VM_ERROR ? "ERROR" :
475                            base->state==V3_VM_SIMULATING ? "simulating" : "UNKNOWN",
476                            num_vcores,
477                            num_regions,
478                            mem->mem_size,
479                            base->vm_type == V3_VM_GENERAL ? "general" :
480                            base->vm_type == V3_VM_HVM ? "hvm" : "UNKNOWN");
481             }
482         }
483     }
484         
485         
486  out:
487     if (mem) { palacios_vfree(mem); }
488     if (core) { palacios_vfree(core); }
489     if (base) { palacios_vfree(base); }
490     
491     return 0;
492 }
493
494
495 static int guests_short_proc_open(struct inode * inode, struct file * filp) 
496 {
497     return single_open(filp, read_guests, PAL_PROC_GETDATA(inode));
498 }
499
500 static int guests_full_proc_open(struct inode * inode, struct file * filp) 
501 {
502     return single_open(filp, read_guests_details, PAL_PROC_GETDATA(inode));
503 }
504
505
506
507
508 static struct file_operations guest_full_proc_ops = {
509     .owner = THIS_MODULE,
510     .open = guests_full_proc_open, 
511     .read = seq_read,
512     .llseek = seq_lseek, 
513     .release = single_release,
514 };
515
516 static struct file_operations guest_short_proc_ops = {
517     .owner = THIS_MODULE,
518     .open = guests_short_proc_open, 
519     .read = seq_read,
520     .llseek = seq_lseek, 
521     .release = single_release,
522 };
523
524 // Supply basic information that the user-space tools need
525 // to manipulate Palacios.   The current use case here is to 
526 // convey memory information
527 static int read_info(struct seq_file *s, void *v)
528 {
529     uint64_t mem_block_size;
530     int i,j;
531     int max_node=-1;
532     seq_printf(s,"kernel MAX_ORDER:\t%d\n",MAX_ORDER);
533     seq_printf(s,"number of nodes:\t%d\n", numa_num_nodes());
534     seq_printf(s,"number of cpus: \t%d\n", num_online_cpus());
535     seq_printf(s,"\npalacios compiled mem_block_size:\t%d\n", V3_CONFIG_MEM_BLOCK_SIZE);
536     if (!v3_lookup_option("mem_block_size")) { 
537         mem_block_size = V3_CONFIG_MEM_BLOCK_SIZE;
538     } else {
539         if (strict_strtoull(v3_lookup_option("mem_block_size"), 0, &mem_block_size)) {
540             // huh?
541             mem_block_size=-1;
542         }
543     }
544     seq_printf(s,"palacios run-time mem_block_size:\t%llu\n", mem_block_size);
545     
546     seq_printf(s,"\nCPU to node mappings\n");
547     for (i=0;i<num_online_cpus();i++) { 
548         seq_printf(s,"cpu %d -> node %d\n", i, numa_cpu_to_node(i));
549         if (numa_cpu_to_node(i)>max_node) { 
550             max_node=numa_cpu_to_node(i);
551         }
552     }
553     seq_printf(s,"\nNode to node distances\n");
554     for (j=0;j<=max_node;j++) { 
555         seq_printf(s,"   \t%2d", j);
556     }
557     seq_printf(s,"\n");
558     for (i=0;i<=max_node;i++) { 
559         seq_printf(s,"%2d ",i);
560         for (j=0;j<=max_node;j++) { 
561             seq_printf(s,"\t%2d", numa_get_distance(i,j));
562         }
563         seq_printf(s,"\n");
564     }
565     seq_printf(s,"\nCPU to CPU distances\n");
566     for (j=0;j<num_online_cpus();j++) { 
567         seq_printf(s,"   \t%2d", j);
568     }
569     seq_printf(s,"\n");
570     for (i=0;i<num_online_cpus();i++) { 
571         seq_printf(s,"%2d ",i);
572         for (j=0;j<num_online_cpus();j++) { 
573             seq_printf(s,"\t%2d", numa_get_distance(numa_cpu_to_node(i),numa_cpu_to_node(j)));
574         }
575         seq_printf(s,"\n");
576     }
577     return 0;
578 }
579
580 static int info_proc_open(struct inode * inode, struct file * filp) 
581 {
582     return single_open(filp, read_info, PAL_PROC_GETDATA(inode));
583 }
584
585
586
587 static struct file_operations info_proc_ops = {
588     .owner = THIS_MODULE,
589     .open = info_proc_open, 
590     .read = seq_read,
591     .llseek = seq_lseek, 
592     .release = single_release,
593 };
594
595
596 static inline uint_t thr_hash_func(addr_t key)
597 {
598     return palacios_hash_long((long)key,64);
599 }
600
601 static inline int thr_hash_comp(addr_t k1, addr_t k2)
602 {
603     return k1==k2;
604 }
605
606 static int __init v3_init(void) {
607
608     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
609     int ret = 0;
610
611     LOCKCHECK_INIT();
612     MEMCHECK_INIT();
613
614
615     if (!(v3_thread_resource_map = palacios_create_htable(MAX_THREADS,thr_hash_func,thr_hash_comp))) { 
616         ERROR("Could not create thread/resource map\n");
617         ret = -1;
618         goto failure0;
619     }
620
621     palacios_proc_dir = proc_mkdir("v3vee", NULL);
622     if (!palacios_proc_dir) {
623         ERROR("Could not create proc entry\n");
624         ret = -1;
625         goto failure1;
626     }
627
628     // this will populate the v3vee tree...
629     if (palacios_init_mm()) { 
630         goto failure2;
631     }
632
633     if (allow_devmem) {
634       palacios_allow_devmem();
635     }
636
637     // numa is now a required interface and we need it
638     // up before primary initiatilization
639     palacios_init_numa();
640
641     // Initialize Palacios
642     palacios_vmm_init(options);
643
644     // initialize extensions
645     init_lnx_extensions();
646
647
648     v3_class = class_create(THIS_MODULE, "vms");
649     if (!v3_class || IS_ERR(v3_class)) {
650         ERROR("Failed to register V3 VM device class\n");
651         ret =  PTR_ERR(v3_class);
652         goto failure3;
653     }
654
655     INFO("intializing V3 Control device\n");
656
657     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
658
659     if (ret < 0) {
660         ERROR("Error registering device region for V3 devices\n");
661         goto failure4;
662     }
663
664     v3_major_num = MAJOR(dev);
665
666     dev = MKDEV(v3_major_num, MAX_VMS + 1);
667
668     
669     DEBUG("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
670     cdev_init(&ctrl_dev, &v3_ctrl_fops);
671     ctrl_dev.owner = THIS_MODULE;
672     ctrl_dev.ops = &v3_ctrl_fops;
673     cdev_add(&ctrl_dev, dev, 1);
674     
675     device_create(v3_class, NULL, dev, NULL, "v3vee");
676
677     if (ret != 0) {
678         ERROR("Error adding v3 control device\n");
679         goto failure5;
680     }
681
682     {
683         struct proc_dir_entry *entry;
684
685 #define PALPROC(ent, success, error, out_target, fname, perm, parent, fops) \
686     PAL_PROC_CREATE(ent, fname, perm, parent, fops); \
687     if (ent) {                                    \
688         INFO(success);                            \
689     } else {                                      \
690         ERROR(error);                             \
691         goto out_target;                          \
692     }
693
694     PALPROC(entry, "/proc/v3vee/v3-guests succesfully created\n", 
695             "Could not create proc entry\n", failure6,
696             "v3-guests", 0444, palacios_proc_dir, &guest_short_proc_ops);
697
698     PALPROC(entry, "/proc/v3vee/v3-guests-details successfully created\n",
699             "Could not create proc entry\n", failure7, 
700             "v3-guests-details", 0444, palacios_proc_dir, &guest_full_proc_ops);
701
702     PALPROC(entry, "/proc/v3vee/v3-info successfully created\n", 
703             "Could not create proc entry\n", failure8, 
704             "v3-info", 0444, palacios_proc_dir, &info_proc_ops);
705
706
707     }
708         
709     return 0;
710
711  failure8:
712     remove_proc_entry("v3-guests-details", palacios_proc_dir);
713  failure7:
714     remove_proc_entry("v3-guests", palacios_proc_dir);
715  failure6:
716     device_destroy(v3_class, dev);
717  failure5:
718     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
719  failure4:
720     class_destroy(v3_class);
721  failure3:
722     if (allow_devmem) {
723       palacios_restore_devmem();
724     }
725     palacios_deinit_mm();
726  failure2:
727     remove_proc_entry("v3vee", NULL);
728  failure1:   
729     palacios_free_htable(v3_thread_resource_map,0,0);
730  failure0:   
731     MEMCHECK_DEINIT();
732     LOCKCHECK_DEINIT();
733
734     return ret;
735 }
736
737
738 static void __exit v3_exit(void) {
739     extern u32 pg_allocs;
740     extern u32 pg_frees;
741     extern u32 mallocs;
742     extern u32 frees;
743     extern u32 vmallocs;
744     extern u32 vfrees;
745     int i = 0;
746     struct v3_guest * guest;
747     dev_t dev;
748
749
750     /* Stop and free any running VMs */ 
751     for (i = 0; i < MAX_VMS; i++) {
752                 if (guest_map[i] != NULL) {
753                     guest = (struct v3_guest *)(guest_map[i]);
754
755                 if (!guest->v3_ctx) { 
756                     ERROR("Orphan VM detected and skipped: index=%d name=%s\n", i, guest->name);
757                     continue;
758                 }
759
760                 if (v3_stop_vm(guest->v3_ctx) < 0) 
761                         ERROR("Couldn't stop VM %d\n", i);
762
763                 free_palacios_vm(guest);
764                 guest_map[i] = NULL;
765         }
766     }
767
768     dev = MKDEV(v3_major_num, MAX_VMS + 1);
769
770     INFO("Removing V3 Control device\n");
771
772
773     palacios_vmm_exit();
774
775     palacios_deinit_numa();
776
777     DEBUG("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
778     DEBUG("Palacios Vmallocs = %d, Vfrees = %d\n", vmallocs, vfrees);
779     DEBUG("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
780
781     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
782
783     cdev_del(&ctrl_dev);
784
785     device_destroy(v3_class, dev);
786     class_destroy(v3_class);
787
788
789     deinit_lnx_extensions();
790
791     if (allow_devmem) {
792       palacios_restore_devmem();
793     }
794
795     palacios_deinit_mm();
796
797     remove_proc_entry("v3-info", palacios_proc_dir);
798     remove_proc_entry("v3-guests-details", palacios_proc_dir);
799     remove_proc_entry("v3-guests", palacios_proc_dir);
800     remove_proc_entry("v3vee", NULL);
801
802     DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
803     
804     palacios_free_htable(v3_thread_resource_map,0,0);
805
806     MEMCHECK_DEINIT();
807     LOCKCHECK_DEINIT();
808 }
809
810
811
812 module_init(v3_init);
813 module_exit(v3_exit);
814
815
816
817 void * trace_malloc(size_t size, gfp_t flags) {
818     void * addr = NULL;
819
820     mod_allocs++;
821     addr = palacios_alloc_extended(size, flags, -1);
822
823     return addr;
824 }
825
826
827 void trace_free(const void * objp) {
828     mod_frees++;
829     palacios_free((void*)objp);
830 }