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.


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