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.


Memory allocation checking framework
[palacios.git] / linux_module / main.c
1 /* 
2    Palacios main control interface
3    (c) Jack Lange, 2010
4  */
5
6
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
24 #include <palacios/vmm.h>
25
26 #include "palacios.h"
27 #include "mm.h"
28 #include "vm.h"
29 #include "allow_devmem.h"
30 #include "memcheck.h"
31 #include "lockcheck.h"
32
33 #include "linux-exts.h"
34
35
36 MODULE_LICENSE("GPL");
37
38 // Module parameter
39 int cpu_list[NR_CPUS] = {};
40 int cpu_list_len = 0;
41 module_param_array(cpu_list, int, &cpu_list_len, 0644);
42 MODULE_PARM_DESC(cpu_list, "Comma-delimited list of CPUs that Palacios will run on");
43
44 static int allow_devmem = 0;
45 module_param(allow_devmem, int, 0);
46 MODULE_PARM_DESC(allow_devmem, "Allow general user-space /dev/mem access even if kernel is strict");
47
48 // Palacios options parameter
49 static char *options;
50 module_param(options, charp, 0);
51 MODULE_PARM_DESC(options, "Generic options to internal Palacios modules");
52
53
54 int mod_allocs = 0;
55 int mod_frees = 0;
56
57 static int v3_major_num = 0;
58
59 static struct v3_guest * guest_map[MAX_VMS] = {[0 ... MAX_VMS - 1] = 0};
60 static struct proc_dir_entry *dir = 0;
61
62 struct class * v3_class = NULL;
63 static struct cdev ctrl_dev;
64
65 static int register_vm(struct v3_guest * guest) {
66     int i = 0;
67
68     for (i = 0; i < MAX_VMS; i++) {
69         if (guest_map[i] == NULL) {
70             guest_map[i] = guest;
71             return i;
72         }
73     }
74
75     return -1;
76 }
77
78
79
80 static long v3_dev_ioctl(struct file * filp,
81                          unsigned int ioctl, unsigned long arg) {
82     void __user * argp = (void __user *)arg;
83     DEBUG("V3 IOCTL %d\n", ioctl);
84
85
86     switch (ioctl) {
87         case V3_CREATE_GUEST:{
88             int vm_minor = 0;
89             struct v3_guest_img user_image;
90             struct v3_guest * guest = palacios_alloc(sizeof(struct v3_guest));
91
92             if (IS_ERR(guest)) {
93                 ERROR("Palacios: Error allocating Kernel guest_image\n");
94                 return -EFAULT;
95             }
96
97             memset(guest, 0, sizeof(struct v3_guest));
98
99             INFO("Palacios: Creating V3 Guest...\n");
100
101             vm_minor = register_vm(guest);
102
103             if (vm_minor == -1) {
104                 ERROR("Palacios Error: Too many VMs are currently running\n");
105                 goto out_err;
106             }
107
108             guest->vm_dev = MKDEV(v3_major_num, vm_minor);
109
110             if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
111                 ERROR("Palacios Error: copy from user error getting guest image...\n");
112                 goto out_err1;
113             }
114
115             guest->img_size = user_image.size;
116
117             DEBUG("Palacios: Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
118             guest->img = palacios_valloc(guest->img_size);
119
120             if (IS_ERR(guest->img)) {
121                 ERROR("Palacios Error: Could not allocate space for guest image\n");
122                 goto out_err1;
123             }
124
125             if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
126                 ERROR("Palacios: Error loading guest data\n");
127                 goto out_err2;
128             }      
129
130             strncpy(guest->name, user_image.name, 127);
131
132             INIT_LIST_HEAD(&(guest->exts));
133
134             if (create_palacios_vm(guest) == -1) {
135                 ERROR("Palacios: Error creating guest\n");
136                 goto out_err2;
137             }
138
139             return vm_minor;
140
141
142 out_err2:
143             palacios_vfree(guest->img);
144 out_err1:
145             guest_map[vm_minor] = NULL; 
146 out_err:
147             palacios_free(guest);
148
149             return -1;
150
151             break;
152         }
153         case V3_FREE_GUEST: {
154             unsigned long vm_idx = arg;
155             struct v3_guest * guest;
156
157             if (vm_idx > MAX_VMS) {
158                 ERROR("Invalid VM index: %ld\n", vm_idx);
159                 return -1;
160             }
161
162             guest = guest_map[vm_idx];
163
164             if (!guest) {
165                 ERROR("No VM at index %ld\n",vm_idx);
166                 return -1;
167             }
168
169             INFO("Freeing VM (%s) (%p)\n", guest->name, guest);
170
171             if (free_palacios_vm(guest)<0) { 
172                 ERROR("Cannot free guest at index %ld\n",vm_idx);
173                 return -1;
174             }
175
176             guest_map[vm_idx] = NULL;
177             break;
178         }
179         case V3_ADD_MEMORY: {
180             struct v3_mem_region mem;
181             
182             memset(&mem, 0, sizeof(struct v3_mem_region));
183             
184             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
185                 ERROR("copy from user error getting mem_region...\n");
186                 return -EFAULT;
187             }
188
189             DEBUG("Adding %llu pages to Palacios memory\n", mem.num_pages);
190
191             if (add_palacios_memory(mem.base_addr, mem.num_pages) == -1) {
192                 ERROR("Error adding memory to Palacios\n");
193                 return -EFAULT;
194             }
195
196             break;
197         }
198
199         case V3_RESET_MEMORY: {
200             if (palacios_init_mm() == -1) {
201                 ERROR("Error resetting Palacios memory\n");
202                 return -EFAULT;
203             }
204             break;  
205         }
206
207         default: {
208             struct global_ctrl * ctrl = get_global_ctrl(ioctl);
209             
210             if (ctrl) {
211                 return ctrl->handler(ioctl, arg);
212             }
213
214             WARNING("\tUnhandled global ctrl cmd: %d\n", ioctl);
215
216             return -EINVAL;
217         }
218     }
219
220     return 0;
221 }
222
223
224
225 static struct file_operations v3_ctrl_fops = {
226     .owner = THIS_MODULE,
227     .unlocked_ioctl = v3_dev_ioctl,
228     .compat_ioctl = v3_dev_ioctl,
229 };
230
231
232
233 struct proc_dir_entry *palacios_get_procdir(void) 
234 {
235     return dir;
236 }
237
238
239 #define MAX_VCORES 32
240
241 static int read_guests(char * buf, char ** start, off_t off, int count,
242                        int * eof, void * data)
243 {
244     int len = 0;
245     unsigned int i = 0;
246
247     struct v3_vm_state *s =palacios_alloc(sizeof(struct v3_vm_state)+MAX_VCORES*sizeof(struct v3_vcore_state));
248     
249     if (!s) { 
250       ERROR("No space for state structure\n");
251       goto out;
252     }
253     
254     for(i = 0; i < MAX_VMS; i++) {
255       if (guest_map[i] != NULL) {
256         if (len>=count) { 
257           goto out;
258         } else {
259           len += snprintf(buf+len, count-len,
260                           "%s\t/dev/v3-vm%d ", 
261                           guest_map[i]->name, i);
262           
263           if (len>=count) { 
264             *(buf+len-1)='\n';
265             goto out;
266           } else {
267             // Get extended data
268             s->num_vcores=MAX_VCORES; // max we can handle
269             if (v3_get_state_vm(guest_map[i]->v3_ctx, s)) {
270               ERROR("Cannot get VM info\n");
271               *(buf+len-1)='\n';
272               goto out;
273             } else {
274               unsigned long j;
275
276               len+=snprintf(buf+len, count-len,
277                             "%s [0x%p-0x%p] %lu vcores ",
278                             s->state==V3_VM_INVALID ? "INVALID" :
279                             s->state==V3_VM_RUNNING ? "running" :
280                             s->state==V3_VM_STOPPED ? "stopped" :
281                             s->state==V3_VM_PAUSED ? "paused" :
282                             s->state==V3_VM_ERROR ? "ERROR" :
283                             s->state==V3_VM_SIMULATING ? "simulating" : "UNKNOWN",
284                             s->mem_base_paddr, s->mem_base_paddr+s->mem_size-1,
285                             s->num_vcores);
286               if (len>=count) { 
287                 *(buf+len-1)='\n';
288                 goto out;
289               }
290               for (j=0;j<s->num_vcores;j++) {
291                 len+=snprintf(buf+len, count-len,
292                               "[vcore %lu %s on pcore %lu %llu exits rip=0x%p %s %s %s] ",
293                               j, 
294                               s->vcore[j].state==V3_VCORE_INVALID ? "INVALID" :
295                               s->vcore[j].state==V3_VCORE_RUNNING ? "running" :
296                               s->vcore[j].state==V3_VCORE_STOPPED ? "stopped" : "UNKNOWN",
297                               s->vcore[j].pcore,
298                               s->vcore[j].num_exits,
299                               s->vcore[j].last_rip,
300                               s->vcore[j].cpu_mode==V3_VCORE_CPU_REAL ? "real" :
301                               s->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED ? "protected" :
302                               s->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED_PAE ? "protectedpae" :
303                               s->vcore[j].cpu_mode==V3_VCORE_CPU_LONG ? "long" :
304                               s->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_32_COMPAT ? "long32" :
305                               s->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_16_COMPAT ? "long16" : "UNKNOWN",
306                               s->vcore[j].mem_mode==V3_VCORE_MEM_MODE_PHYSICAL ? "physical" :
307                               s->vcore[j].mem_mode==V3_VCORE_MEM_MODE_VIRTUAL ? "virtual" : "UNKNOWN",
308                               s->vcore[j].mem_state==V3_VCORE_MEM_STATE_SHADOW ? "shadow" :
309                               s->vcore[j].mem_state==V3_VCORE_MEM_STATE_NESTED ? "nested" : "UNKNOWN");
310                 if (len>=count) {
311                   *(buf+len-1)='\n';
312                   goto out;
313                 }
314               }
315
316               *(buf+len-1)='\n';
317
318             }
319           }
320         }
321       }
322     }
323  
324  out:
325     if (s) { palacios_free(s); }
326
327     return len;
328 }
329
330 static int show_mem(char * buf, char ** start, off_t off, int count,
331                     int * eof, void * data)
332 {
333     int len = 0;
334     
335     len = snprintf(buf,count, "%p\n", (void *)get_palacios_base_addr());
336     len += snprintf(buf+len,count-len, "%lld\n", get_palacios_num_pages());
337     
338     return len;
339 }
340
341
342
343
344
345 static int __init v3_init(void) {
346
347     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
348     int ret = 0;
349
350     LOCKCHECK_INIT();
351     MEMCHECK_INIT();
352
353     palacios_init_mm();
354
355     if (allow_devmem) {
356       palacios_allow_devmem();
357     }
358
359     // Initialize Palacios
360     palacios_vmm_init(options);
361
362
363     // initialize extensions
364     init_lnx_extensions();
365
366
367     v3_class = class_create(THIS_MODULE, "vms");
368     if (IS_ERR(v3_class)) {
369         ERROR("Failed to register V3 VM device class\n");
370         return PTR_ERR(v3_class);
371     }
372
373     INFO("intializing V3 Control device\n");
374
375     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
376
377     if (ret < 0) {
378         ERROR("Error registering device region for V3 devices\n");
379         goto failure2;
380     }
381
382     v3_major_num = MAJOR(dev);
383
384     dev = MKDEV(v3_major_num, MAX_VMS + 1);
385
386     
387     DEBUG("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
388     cdev_init(&ctrl_dev, &v3_ctrl_fops);
389     ctrl_dev.owner = THIS_MODULE;
390     ctrl_dev.ops = &v3_ctrl_fops;
391     cdev_add(&ctrl_dev, dev, 1);
392     
393     device_create(v3_class, NULL, dev, NULL, "v3vee");
394
395     if (ret != 0) {
396         ERROR("Error adding v3 control device\n");
397         goto failure1;
398     }
399
400     dir = proc_mkdir("v3vee", NULL);
401     if(dir) {
402         struct proc_dir_entry *entry;
403
404         entry = create_proc_read_entry("v3-guests", 0444, dir, 
405                                        read_guests, NULL);
406         if (entry) {
407             INFO("/proc/v3vee/v3-guests successfully created\n");
408         } else {
409             ERROR("Could not create proc entry\n");
410             goto failure1;
411         }
412         
413         entry = create_proc_read_entry("v3-mem", 0444, dir,
414                                        show_mem, NULL);
415         if (entry) {
416             INFO("/proc/v3vee/v3-mem successfully added\n");
417         } else {
418             ERROR("Could not create proc entry\n");
419             goto failure1;
420         }
421     } else {
422         ERROR("Could not create proc entry\n");
423         goto failure1;
424     }
425         
426     return 0;
427
428  failure1:
429     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
430  failure2:
431     class_destroy(v3_class);
432
433     return ret;
434 }
435
436
437 static void __exit v3_exit(void) {
438     extern u32 pg_allocs;
439     extern u32 pg_frees;
440     extern u32 mallocs;
441     extern u32 frees;
442     extern u32 vmallocs;
443     extern u32 vfrees;
444     int i = 0;
445     struct v3_guest * guest;
446     dev_t dev;
447
448
449     /* Stop and free any running VMs */ 
450     for (i = 0; i < MAX_VMS; i++) {
451         if (guest_map[i] != NULL) {
452                 guest = (struct v3_guest *)guest_map[i];
453
454                 if (v3_stop_vm(guest->v3_ctx) < 0) 
455                         ERROR("Couldn't stop VM %d\n", i);
456
457                 free_palacios_vm(guest);
458                 guest_map[i] = NULL;
459         }
460     }
461
462     dev = MKDEV(v3_major_num, MAX_VMS + 1);
463
464     INFO("Removing V3 Control device\n");
465
466
467     palacios_vmm_exit();
468
469     DEBUG("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
470     DEBUG("Palacios Vmallocs = %d, Vfrees = %d\n", vmallocs, vfrees);
471     DEBUG("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
472
473     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
474
475     cdev_del(&ctrl_dev);
476
477     device_destroy(v3_class, dev);
478     class_destroy(v3_class);
479
480
481     deinit_lnx_extensions();
482
483     if (allow_devmem) {
484       palacios_restore_devmem();
485     }
486
487     palacios_deinit_mm();
488
489     remove_proc_entry("v3-guests", dir);
490     remove_proc_entry("v3-mem", dir);
491     remove_proc_entry("v3vee", NULL);
492
493     DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
494     
495     MEMCHECK_DEINIT();
496     LOCKCHECK_DEINIT();
497 }
498
499
500
501 module_init(v3_init);
502 module_exit(v3_exit);
503
504
505
506 void * trace_malloc(size_t size, gfp_t flags) {
507     void * addr = NULL;
508
509     mod_allocs++;
510     addr = palacios_alloc_extended(size, flags);
511
512     return addr;
513 }
514
515
516 void trace_free(const void * objp) {
517     mod_frees++;
518     palacios_free((void*)objp);
519 }