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.


VNET compatibility with NUMA interfaces
[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 * palacios_proc_dir = NULL;
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) == -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     //    INFO("Returning procdir=%p\n",palacios_proc_dir);
236     return palacios_proc_dir;
237 }
238
239
240 #define MAX_VCORES  256
241 #define MAX_REGIONS 256
242
243 static int read_guests(char * buf, char ** start, off_t off, int count,
244                        int * eof, void * data)
245 {
246     int len = 0;
247     unsigned int i = 0;
248     struct v3_vm_base_state *base=0;
249     struct v3_vm_core_state *core=0;
250     struct v3_vm_mem_state *mem=0;
251
252     base = palacios_alloc(sizeof(struct v3_vm_base_state));
253     
254     if (!base) { 
255       ERROR("No space for base state structure\n");
256       goto out;
257     }
258
259     core = palacios_alloc(sizeof(struct v3_vm_core_state) + MAX_VCORES*sizeof(struct v3_vm_vcore_state));
260     
261     if (!core) { 
262       ERROR("No space for core state structure\n");
263       goto out;
264     }
265
266     mem = palacios_alloc(sizeof(struct v3_vm_mem_state) + MAX_REGIONS*sizeof(struct v3_vm_mem_region));
267     
268     if (!mem) { 
269       ERROR("No space for memory state structure\n");
270       goto out;
271     }
272
273     for(i = 0; i < MAX_VMS; i++) {
274       if (guest_map[i] != NULL) {
275         if (len>=count) { 
276           goto out;
277         } else {
278           len += snprintf(buf+len, count-len,
279                           "%s\t/dev/v3-vm%d ", 
280                           guest_map[i]->name, i);
281           
282           if (len>=count) { 
283             *(buf+len-1)='\n';
284             goto out;
285           } else {
286             // Get extended data
287             core->num_vcores=MAX_VCORES; // max we can handle
288             mem->num_regions=MAX_REGIONS; // max we can handle
289             if (v3_get_state_vm(guest_map[i]->v3_ctx, base, core, mem)) {
290               ERROR("Cannot get VM info\n");
291               *(buf+len-1)='\n';
292               goto out;
293             } else {
294               unsigned long j;
295
296               len+=snprintf(buf+len, count-len,
297                             "%s %lu regions [ ", 
298                             base->state==V3_VM_INVALID ? "INVALID" :
299                             base->state==V3_VM_RUNNING ? "running" :
300                             base->state==V3_VM_STOPPED ? "stopped" :
301                             base->state==V3_VM_PAUSED ? "paused" :
302                             base->state==V3_VM_ERROR ? "ERROR" :
303                             base->state==V3_VM_SIMULATING ? "simulating" : "UNKNOWN",
304                             mem->num_regions);
305
306               if (len>=count) { 
307                 *(buf+len-1)='\n';
308                 goto out;
309               }
310
311               for (j=0;j<mem->num_regions;j++) { 
312                   len+=snprintf(buf+len, count-len,
313                                 "(region %lu 0x%p-0x%p) ",
314                                 j, mem->region[j].host_paddr, mem->region[j].host_paddr+mem->region[j].size);
315                   if (len>=count) { 
316                       *(buf+len-1)='\n';
317                       goto out;
318                   }
319               }
320                   
321               len+=snprintf(buf+len, count-len,
322                             "] %lu vcores [ ", 
323                             core->num_vcores);
324
325               if (len>=count) { 
326                 *(buf+len-1)='\n';
327                 goto out;
328               }
329                   
330               for (j=0;j<core->num_vcores;j++) {
331                 len+=snprintf(buf+len, count-len,
332                               "(vcore %lu %s on pcore %lu %llu exits rip=0x%p %s %s %s) ",
333                               j, 
334                               core->vcore[j].state==V3_VCORE_INVALID ? "INVALID" :
335                               core->vcore[j].state==V3_VCORE_RUNNING ? "running" :
336                               core->vcore[j].state==V3_VCORE_STOPPED ? "stopped" : "UNKNOWN",
337                               core->vcore[j].pcore,
338                               core->vcore[j].num_exits,
339                               core->vcore[j].last_rip,
340                               core->vcore[j].cpu_mode==V3_VCORE_CPU_REAL ? "real" :
341                               core->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED ? "protected" :
342                               core->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED_PAE ? "protectedpae" :
343                               core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG ? "long" :
344                               core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_32_COMPAT ? "long32" :
345                               core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_16_COMPAT ? "long16" : "UNKNOWN",
346                               core->vcore[j].mem_mode==V3_VCORE_MEM_MODE_PHYSICAL ? "physical" :
347                               core->vcore[j].mem_mode==V3_VCORE_MEM_MODE_VIRTUAL ? "virtual" : "UNKNOWN",
348                               core->vcore[j].mem_state==V3_VCORE_MEM_STATE_SHADOW ? "shadow" :
349                               core->vcore[j].mem_state==V3_VCORE_MEM_STATE_NESTED ? "nested" : "UNKNOWN");
350                 if (len>=count) {
351                     *(buf+len-1)='\n';
352                     goto out;
353                 }
354               }
355
356               len+=snprintf(buf+len, count-len,
357                             "] ");
358
359               if (len>=count) { 
360                 *(buf+len-1)='\n';
361                 goto out;
362               }
363                   
364               *(buf+len-1)='\n';
365
366             }
367           }
368         }
369       }
370     }
371  
372  out:
373     if (mem) { palacios_free(mem); }
374     if (core) { palacios_free(core); }
375     if (base) { palacios_free(base); }
376
377     return len;
378 }
379
380
381
382
383
384 static int __init v3_init(void) {
385
386     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
387     int ret = 0;
388
389     LOCKCHECK_INIT();
390     MEMCHECK_INIT();
391
392     palacios_proc_dir = proc_mkdir("v3vee", NULL);
393     if (!palacios_proc_dir) {
394         ERROR("Could not create proc entry\n");
395         ret = -1;
396         goto failure1;
397     }
398
399     // this will populate the v3vee tree...
400     if (palacios_init_mm()) { 
401         goto failure2;
402     }
403
404     if (allow_devmem) {
405       palacios_allow_devmem();
406     }
407
408     // Initialize Palacios
409     palacios_vmm_init(options);
410
411     // initialize extensions
412     init_lnx_extensions();
413
414
415     v3_class = class_create(THIS_MODULE, "vms");
416     if (IS_ERR(v3_class)) {
417         ERROR("Failed to register V3 VM device class\n");
418         ret =  PTR_ERR(v3_class);
419         goto failure3;
420     }
421
422     INFO("intializing V3 Control device\n");
423
424     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
425
426     if (ret < 0) {
427         ERROR("Error registering device region for V3 devices\n");
428         goto failure4;
429     }
430
431     v3_major_num = MAJOR(dev);
432
433     dev = MKDEV(v3_major_num, MAX_VMS + 1);
434
435     
436     DEBUG("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
437     cdev_init(&ctrl_dev, &v3_ctrl_fops);
438     ctrl_dev.owner = THIS_MODULE;
439     ctrl_dev.ops = &v3_ctrl_fops;
440     cdev_add(&ctrl_dev, dev, 1);
441     
442     device_create(v3_class, NULL, dev, NULL, "v3vee");
443
444     if (ret != 0) {
445         ERROR("Error adding v3 control device\n");
446         goto failure5;
447     }
448
449     {
450         struct proc_dir_entry *entry;
451
452         INFO("palacios_proc_dir=%p before v3-guests\n",palacios_proc_dir);
453         entry = create_proc_read_entry("v3-guests", 0444, palacios_proc_dir, read_guests, NULL);
454         if (entry) {
455             INFO("/proc/v3vee/v3-guests successfully created\n");
456         } else {
457             ERROR("Could not create proc entry\n");
458             goto failure6;
459         }
460     }
461         
462     return 0;
463
464  failure6:
465     remove_proc_entry("v3-guests", palacios_proc_dir);
466  failure5:
467     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
468  failure4:
469     class_destroy(v3_class);
470  failure3:
471     if (allow_devmem) {
472       palacios_restore_devmem();
473     }
474     palacios_deinit_mm();
475  failure2:
476     remove_proc_entry("v3vee", NULL);
477  failure1:   
478     MEMCHECK_DEINIT();
479     LOCKCHECK_DEINIT();
480
481     return ret;
482 }
483
484
485 static void __exit v3_exit(void) {
486     extern u32 pg_allocs;
487     extern u32 pg_frees;
488     extern u32 mallocs;
489     extern u32 frees;
490     extern u32 vmallocs;
491     extern u32 vfrees;
492     int i = 0;
493     struct v3_guest * guest;
494     dev_t dev;
495
496
497     /* Stop and free any running VMs */ 
498     for (i = 0; i < MAX_VMS; i++) {
499         if (guest_map[i] != NULL) {
500                 guest = (struct v3_guest *)guest_map[i];
501
502                 if (v3_stop_vm(guest->v3_ctx) < 0) 
503                         ERROR("Couldn't stop VM %d\n", i);
504
505                 free_palacios_vm(guest);
506                 guest_map[i] = NULL;
507         }
508     }
509
510     dev = MKDEV(v3_major_num, MAX_VMS + 1);
511
512     INFO("Removing V3 Control device\n");
513
514
515     palacios_vmm_exit();
516
517     DEBUG("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
518     DEBUG("Palacios Vmallocs = %d, Vfrees = %d\n", vmallocs, vfrees);
519     DEBUG("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
520
521     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
522
523     cdev_del(&ctrl_dev);
524
525     device_destroy(v3_class, dev);
526     class_destroy(v3_class);
527
528
529     deinit_lnx_extensions();
530
531     if (allow_devmem) {
532       palacios_restore_devmem();
533     }
534
535     palacios_deinit_mm();
536
537     remove_proc_entry("v3-guests", palacios_proc_dir);
538     remove_proc_entry("v3vee", NULL);
539
540     DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
541     
542     MEMCHECK_DEINIT();
543     LOCKCHECK_DEINIT();
544 }
545
546
547
548 module_init(v3_init);
549 module_exit(v3_exit);
550
551
552
553 void * trace_malloc(size_t size, gfp_t flags) {
554     void * addr = NULL;
555
556     mod_allocs++;
557     addr = palacios_alloc_extended(size, flags);
558
559     return addr;
560 }
561
562
563 void trace_free(const void * objp) {
564     mod_frees++;
565     palacios_free((void*)objp);
566 }