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.


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