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.


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