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.


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