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.


Improved /proc/v3vee/v3-guests* output
[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 #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 "allow_devmem.h"
31 #include "memcheck.h"
32 #include "lockcheck.h"
33
34 #include "linux-exts.h"
35
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 (IS_ERR(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 (IS_ERR(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_RESET_MEMORY: {
201             if (palacios_init_mm() == -1) {
202                 ERROR("Error resetting Palacios memory\n");
203                 return -EFAULT;
204             }
205             break;  
206         }
207
208         default: {
209             struct global_ctrl * ctrl = get_global_ctrl(ioctl);
210             
211             if (ctrl) {
212                 return ctrl->handler(ioctl, arg);
213             }
214
215             WARNING("\tUnhandled global ctrl cmd: %d\n", ioctl);
216
217             return -EINVAL;
218         }
219     }
220
221     return 0;
222 }
223
224
225
226 static struct file_operations v3_ctrl_fops = {
227     .owner = THIS_MODULE,
228     .unlocked_ioctl = v3_dev_ioctl,
229     .compat_ioctl = v3_dev_ioctl,
230 };
231
232
233
234 struct proc_dir_entry *palacios_get_procdir(void) 
235 {
236     //    INFO("Returning procdir=%p\n",palacios_proc_dir);
237     return palacios_proc_dir;
238 }
239
240
241 #define MAX_VCORES  256
242 #define MAX_REGIONS 1024
243
244
245
246 static int read_guests_details(struct seq_file *s, void *v)
247 {
248     unsigned int i = 0;
249     unsigned int j = 0;
250     struct v3_vm_base_state *base=0;
251     struct v3_vm_core_state *core=0;
252     struct v3_vm_mem_state *mem=0;
253
254     base = palacios_alloc(sizeof(struct v3_vm_base_state));
255     
256     if (!base) { 
257       ERROR("No space for base state structure\n");
258       goto out;
259     }
260
261     core = palacios_alloc(sizeof(struct v3_vm_core_state) + MAX_VCORES*sizeof(struct v3_vm_vcore_state));
262     
263     if (!core) { 
264         ERROR("No space for core state structure\n");
265         goto out;
266     }
267     
268     mem = palacios_alloc(sizeof(struct v3_vm_mem_state) + MAX_REGIONS*sizeof(struct v3_vm_mem_region));
269     
270     if (!mem) { 
271         ERROR("No space for memory state structure\n");
272         goto out;
273     }
274     
275     for(i = 0; i < MAX_VMS; i++) {
276         if (guest_map[i] != NULL) {
277             seq_printf(s,
278                        "---------------------------------------------------------------------------------------\n");
279             seq_printf(s, 
280                        "Entry:        %d\n"
281                        "Name:         %s\n"
282                        "Device:       /dev/v3-vm%d\n", 
283                        i,guest_map[i]->name, i);
284             
285             // Get extended data
286             core->num_vcores=MAX_VCORES; // max we can handle
287             mem->num_regions=MAX_REGIONS; // max we can handle
288             
289             if (v3_get_state_vm(guest_map[i]->v3_ctx, base, core, mem)) {
290                 ERROR("Cannot get VM info\n");
291                 seq_printf(s, "<unable to get data for this VM>\n");
292             } else {
293                 seq_printf(s, 
294                            "State:        %s\n"
295                            "Cores:        %lu\n"
296                            "Regions:      %lu\n\n",
297                            base->state==V3_VM_INVALID ? "INVALID" :
298                            base->state==V3_VM_RUNNING ? "running" :
299                            base->state==V3_VM_STOPPED ? "stopped" :
300                            base->state==V3_VM_PAUSED ? "paused" :
301                            base->state==V3_VM_ERROR ? "ERROR" :
302                            base->state==V3_VM_SIMULATING ? "simulating" : "UNKNOWN",
303                            core->num_vcores,
304                            mem->num_regions);
305                 seq_printf(s, "Core States\n");
306                 
307                 for (j=0;j<core->num_vcores;j++) {
308                     seq_printf(s,
309                                "   vcore %u %s on pcore %lu %llu exits rip=0x%p %s %s %s\n",
310                                j, 
311                                core->vcore[j].state==V3_VCORE_INVALID ? "INVALID" :
312                                core->vcore[j].state==V3_VCORE_RUNNING ? "running" :
313                                core->vcore[j].state==V3_VCORE_STOPPED ? "stopped" : "UNKNOWN",
314                                core->vcore[j].pcore,
315                                core->vcore[j].num_exits,
316                                core->vcore[j].last_rip,
317                                core->vcore[j].cpu_mode==V3_VCORE_CPU_REAL ? "real" :
318                                core->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED ? "protected" :
319                                core->vcore[j].cpu_mode==V3_VCORE_CPU_PROTECTED_PAE ? "protectedpae" :
320                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG ? "long" :
321                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_32_COMPAT ? "long32" :
322                                core->vcore[j].cpu_mode==V3_VCORE_CPU_LONG_16_COMPAT ? "long16" : "UNKNOWN",
323                                core->vcore[j].mem_mode==V3_VCORE_MEM_MODE_PHYSICAL ? "physical" :
324                                core->vcore[j].mem_mode==V3_VCORE_MEM_MODE_VIRTUAL ? "virtual" : "UNKNOWN",
325                                core->vcore[j].mem_state==V3_VCORE_MEM_STATE_SHADOW ? "shadow" :
326                                core->vcore[j].mem_state==V3_VCORE_MEM_STATE_NESTED ? "nested" : "UNKNOWN");
327                 }
328
329                 seq_printf(s, "\nMemory Regions\n");
330                 for (j=0;j<mem->num_regions;j++) { 
331                     seq_printf(s,"   region %u has HPAs 0x%p-0x%p\n",
332                                j, mem->region[j].host_paddr, mem->region[j].host_paddr+mem->region[j].size);
333                 }
334             }
335             seq_printf(s,
336                        "---------------------------------------------------------------------------------------\n");
337         }
338     }
339     
340     
341  out:
342     if (mem) { palacios_free(mem); }
343     if (core) { palacios_free(core); }
344     if (base) { palacios_free(base); }
345     
346     return 0;
347 }
348
349 static int read_guests(struct seq_file *s, void *v)
350 {
351     unsigned int i = 0;
352     struct v3_vm_base_state *base=0;
353     struct v3_vm_core_state *core=0;
354     struct v3_vm_mem_state *mem=0;
355     
356     base = palacios_alloc(sizeof(struct v3_vm_base_state));
357     
358     if (!base) { 
359       ERROR("No space for base state structure\n");
360       goto out;
361     }
362
363     core = palacios_alloc(sizeof(struct v3_vm_core_state) + MAX_VCORES*sizeof(struct v3_vm_vcore_state));
364     
365     if (!core) { 
366         ERROR("No space for core state structure\n");
367         goto out;
368     }
369     
370     mem = palacios_alloc(sizeof(struct v3_vm_mem_state) + MAX_REGIONS*sizeof(struct v3_vm_mem_region));
371     
372     if (!mem) { 
373         ERROR("No space for memory state structure\n");
374         goto out;
375     }
376     
377     for(i = 0; i < MAX_VMS; i++) {
378         if (guest_map[i] != NULL) {
379             seq_printf(s,"%s\t/dev/v3-vm%d", guest_map[i]->name, i);
380             // Get extended data
381             core->num_vcores=MAX_VCORES; // max we can handle
382             mem->num_regions=MAX_REGIONS; // max we can handle
383             
384             if (v3_get_state_vm(guest_map[i]->v3_ctx, base, core, mem)) {
385                 ERROR("Cannot get VM info\n");
386                 seq_printf(s, "\t<unable to get data for this VM>\n");
387             } else {
388                 seq_printf(s,"\t%s\t%lu vcores\t%lu regions\n",
389                            base->state==V3_VM_INVALID ? "INVALID" :
390                            base->state==V3_VM_RUNNING ? "running" :
391                            base->state==V3_VM_STOPPED ? "stopped" :
392                            base->state==V3_VM_PAUSED ? "paused" :
393                            base->state==V3_VM_ERROR ? "ERROR" :
394                            base->state==V3_VM_SIMULATING ? "simulating" : "UNKNOWN",
395                            core->num_vcores,
396                            mem->num_regions);
397             }
398         }
399     }
400         
401         
402  out:
403     if (mem) { palacios_free(mem); }
404     if (core) { palacios_free(core); }
405     if (base) { palacios_free(base); }
406     
407     return 0;
408 }
409
410
411 static int guests_short_proc_open(struct inode * inode, struct file * filp) 
412 {
413     struct proc_dir_entry * proc_entry = PDE(inode);
414     return single_open(filp, read_guests, proc_entry->data);
415 }
416
417 static int guests_full_proc_open(struct inode * inode, struct file * filp) 
418 {
419     struct proc_dir_entry * proc_entry = PDE(inode);
420     return single_open(filp, read_guests_details, proc_entry->data);
421 }
422
423
424
425 static struct file_operations guest_full_proc_ops = {
426     .owner = THIS_MODULE,
427     .open = guests_full_proc_open, 
428     .read = seq_read,
429     .llseek = seq_lseek, 
430     .release = single_release,
431 };
432
433 static struct file_operations guest_short_proc_ops = {
434     .owner = THIS_MODULE,
435     .open = guests_short_proc_open, 
436     .read = seq_read,
437     .llseek = seq_lseek, 
438     .release = single_release,
439 };
440
441
442 static int __init v3_init(void) {
443
444     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
445     int ret = 0;
446
447     LOCKCHECK_INIT();
448     MEMCHECK_INIT();
449
450     palacios_proc_dir = proc_mkdir("v3vee", NULL);
451     if (!palacios_proc_dir) {
452         ERROR("Could not create proc entry\n");
453         ret = -1;
454         goto failure1;
455     }
456
457     // this will populate the v3vee tree...
458     if (palacios_init_mm()) { 
459         goto failure2;
460     }
461
462     if (allow_devmem) {
463       palacios_allow_devmem();
464     }
465
466     // Initialize Palacios
467     palacios_vmm_init(options);
468
469     // initialize extensions
470     init_lnx_extensions();
471
472
473     v3_class = class_create(THIS_MODULE, "vms");
474     if (IS_ERR(v3_class)) {
475         ERROR("Failed to register V3 VM device class\n");
476         ret =  PTR_ERR(v3_class);
477         goto failure3;
478     }
479
480     INFO("intializing V3 Control device\n");
481
482     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
483
484     if (ret < 0) {
485         ERROR("Error registering device region for V3 devices\n");
486         goto failure4;
487     }
488
489     v3_major_num = MAJOR(dev);
490
491     dev = MKDEV(v3_major_num, MAX_VMS + 1);
492
493     
494     DEBUG("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
495     cdev_init(&ctrl_dev, &v3_ctrl_fops);
496     ctrl_dev.owner = THIS_MODULE;
497     ctrl_dev.ops = &v3_ctrl_fops;
498     cdev_add(&ctrl_dev, dev, 1);
499     
500     device_create(v3_class, NULL, dev, NULL, "v3vee");
501
502     if (ret != 0) {
503         ERROR("Error adding v3 control device\n");
504         goto failure5;
505     }
506
507     {
508         struct proc_dir_entry *entry;
509
510         entry = create_proc_entry("v3-guests", 0444, palacios_proc_dir);
511         if (entry) {
512             entry->proc_fops = &guest_short_proc_ops;
513             INFO("/proc/v3vee/v3-guests successfully created\n");
514         } else {
515             ERROR("Could not create proc entry\n");
516             goto failure6;
517         }
518         entry = create_proc_entry("v3-guests-details", 0444, palacios_proc_dir);
519         if (entry) {
520             entry->proc_fops = &guest_full_proc_ops;
521             INFO("/proc/v3vee/v3-guests-details successfully created\n");
522         } else {
523             ERROR("Could not create proc entry\n");
524             goto failure7;
525         }
526     }
527         
528     return 0;
529
530  failure7:
531     remove_proc_entry("v3-guests-details", palacios_proc_dir);
532  failure6:
533     remove_proc_entry("v3-guests", palacios_proc_dir);
534  failure5:
535     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
536  failure4:
537     class_destroy(v3_class);
538  failure3:
539     if (allow_devmem) {
540       palacios_restore_devmem();
541     }
542     palacios_deinit_mm();
543  failure2:
544     remove_proc_entry("v3vee", NULL);
545  failure1:   
546     MEMCHECK_DEINIT();
547     LOCKCHECK_DEINIT();
548
549     return ret;
550 }
551
552
553 static void __exit v3_exit(void) {
554     extern u32 pg_allocs;
555     extern u32 pg_frees;
556     extern u32 mallocs;
557     extern u32 frees;
558     extern u32 vmallocs;
559     extern u32 vfrees;
560     int i = 0;
561     struct v3_guest * guest;
562     dev_t dev;
563
564
565     /* Stop and free any running VMs */ 
566     for (i = 0; i < MAX_VMS; i++) {
567         if (guest_map[i] != NULL) {
568                 guest = (struct v3_guest *)guest_map[i];
569
570                 if (v3_stop_vm(guest->v3_ctx) < 0) 
571                         ERROR("Couldn't stop VM %d\n", i);
572
573                 free_palacios_vm(guest);
574                 guest_map[i] = NULL;
575         }
576     }
577
578     dev = MKDEV(v3_major_num, MAX_VMS + 1);
579
580     INFO("Removing V3 Control device\n");
581
582
583     palacios_vmm_exit();
584
585     DEBUG("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
586     DEBUG("Palacios Vmallocs = %d, Vfrees = %d\n", vmallocs, vfrees);
587     DEBUG("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
588
589     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
590
591     cdev_del(&ctrl_dev);
592
593     device_destroy(v3_class, dev);
594     class_destroy(v3_class);
595
596
597     deinit_lnx_extensions();
598
599     if (allow_devmem) {
600       palacios_restore_devmem();
601     }
602
603     palacios_deinit_mm();
604
605     remove_proc_entry("v3-guests-details", palacios_proc_dir);
606     remove_proc_entry("v3-guests", palacios_proc_dir);
607     remove_proc_entry("v3vee", NULL);
608
609     DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
610     
611     MEMCHECK_DEINIT();
612     LOCKCHECK_DEINIT();
613 }
614
615
616
617 module_init(v3_init);
618 module_exit(v3_exit);
619
620
621
622 void * trace_malloc(size_t size, gfp_t flags) {
623     void * addr = NULL;
624
625     mod_allocs++;
626     addr = palacios_alloc_extended(size, flags, -1);
627
628     return addr;
629 }
630
631
632 void trace_free(const void * objp) {
633     mod_frees++;
634     palacios_free((void*)objp);
635 }