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.


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