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.


update palacios mempool status when onlining memory in userspace
[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 int mod_allocs = 0;
43 int mod_frees = 0;
44
45
46 static int v3_major_num = 0;
47
48 static struct v3_guest * guest_map[MAX_VMS] = {[0 ... MAX_VMS - 1] = 0};
49 static struct proc_dir_entry *dir = 0;
50
51 struct class * v3_class = NULL;
52 static struct cdev ctrl_dev;
53
54 static int register_vm(struct v3_guest * guest) {
55     int i = 0;
56
57     for (i = 0; i < MAX_VMS; i++) {
58         if (guest_map[i] == NULL) {
59             guest_map[i] = guest;
60             return i;
61         }
62     }
63
64     return -1;
65 }
66
67
68
69 static long v3_dev_ioctl(struct file * filp,
70                          unsigned int ioctl, unsigned long arg) {
71     void __user * argp = (void __user *)arg;
72     DEBUG("V3 IOCTL %d\n", ioctl);
73
74
75     switch (ioctl) {
76         case V3_CREATE_GUEST:{
77             int vm_minor = 0;
78             struct v3_guest_img user_image;
79             struct v3_guest * guest = palacios_alloc(sizeof(struct v3_guest));
80
81             if (IS_ERR(guest)) {
82                 ERROR("Palacios: Error allocating Kernel guest_image\n");
83                 return -EFAULT;
84             }
85
86             memset(guest, 0, sizeof(struct v3_guest));
87
88             INFO("Palacios: Creating V3 Guest...\n");
89
90             vm_minor = register_vm(guest);
91
92             if (vm_minor == -1) {
93                 ERROR("Palacios Error: Too many VMs are currently running\n");
94                 goto out_err;
95             }
96
97             guest->vm_dev = MKDEV(v3_major_num, vm_minor);
98
99             if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
100                 ERROR("Palacios Error: copy from user error getting guest image...\n");
101                 goto out_err1;
102             }
103
104             guest->img_size = user_image.size;
105
106             DEBUG("Palacios: Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
107             guest->img = vmalloc(guest->img_size);
108
109             if (IS_ERR(guest->img)) {
110                 ERROR("Palacios Error: Could not allocate space for guest image\n");
111                 goto out_err1;
112             }
113
114             if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
115                 ERROR("Palacios: Error loading guest data\n");
116                 goto out_err2;
117             }      
118
119             strncpy(guest->name, user_image.name, 127);
120
121             INIT_LIST_HEAD(&(guest->exts));
122
123             if (create_palacios_vm(guest) == -1) {
124                 ERROR("Palacios: Error creating guest\n");
125                 goto out_err2;
126             }
127
128             return vm_minor;
129
130
131 out_err2:
132             vfree(guest->img);
133 out_err1:
134             guest_map[vm_minor] = NULL; 
135 out_err:
136             palacios_free(guest);
137
138             return -1;
139
140             break;
141         }
142         case V3_FREE_GUEST: {
143             unsigned long vm_idx = arg;
144             struct v3_guest * guest = guest_map[vm_idx];
145
146             if (!guest) {
147                 ERROR("No VM at index %ld\n",vm_idx);
148                 return -1;
149             }
150
151             INFO("Freeing VM (%s) (%p)\n", guest->name, guest);
152
153             free_palacios_vm(guest);
154             guest_map[vm_idx] = NULL;
155             break;
156         }
157         case V3_ADD_MEMORY: {
158             struct v3_mem_region mem;
159             
160             memset(&mem, 0, sizeof(struct v3_mem_region));
161             
162             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
163                 ERROR("copy from user error getting mem_region...\n");
164                 return -EFAULT;
165             }
166
167             DEBUG("Adding %llu pages to Palacios memory\n", mem.num_pages);
168
169             if (add_palacios_memory(mem.base_addr, mem.num_pages) == -1) {
170                 ERROR("Error adding memory to Palacios\n");
171                 return -EFAULT;
172             }
173
174             break;
175         }
176
177         case V3_RESET_MEMORY: {
178             if (palacios_init_mm() == -1) {
179                 ERROR("Error resetting Palacios memory\n");
180                 return -EFAULT;
181             }
182             break;  
183         }
184
185         default: {
186             struct global_ctrl * ctrl = get_global_ctrl(ioctl);
187             
188             if (ctrl) {
189                 return ctrl->handler(ioctl, arg);
190             }
191
192             WARNING("\tUnhandled global ctrl cmd: %d\n", ioctl);
193
194             return -EINVAL;
195         }
196     }
197
198     return 0;
199 }
200
201
202
203 static struct file_operations v3_ctrl_fops = {
204     .owner = THIS_MODULE,
205     .unlocked_ioctl = v3_dev_ioctl,
206     .compat_ioctl = v3_dev_ioctl,
207 };
208
209
210
211 struct proc_dir_entry *palacios_get_procdir(void) 
212 {
213     return dir;
214 }
215
216 static int read_guests(char * buf, char ** start, off_t off, int count,
217                        int * eof, void * data)
218 {
219     int len = 0;
220     unsigned int i = 0;
221     
222     for(i = 0; i < MAX_VMS; i++) {
223         if (guest_map[i] != NULL) {
224             if (len<count) { 
225                 len += snprintf(buf+len, count-len,
226                                 "%s\t/dev/v3-vm%d\n", 
227                                 guest_map[i]->name, i);
228             }
229         }
230     }
231     
232     return len;
233 }
234
235 static int show_mem(char * buf, char ** start, off_t off, int count,
236                     int * eof, void * data)
237 {
238     int len = 0;
239     
240     len = snprintf(buf,count, "%p\n", (void *)get_palacios_base_addr());
241     len += snprintf(buf+len,count-len, "%lld\n", get_palacios_num_pages());
242     
243     return len;
244 }
245
246
247 static int __init v3_init(void) {
248     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
249     int ret = 0;
250
251
252     palacios_init_mm();
253
254     // Initialize Palacios
255     palacios_vmm_init();
256
257
258     // initialize extensions
259     init_lnx_extensions();
260
261
262     v3_class = class_create(THIS_MODULE, "vms");
263     if (IS_ERR(v3_class)) {
264         ERROR("Failed to register V3 VM device class\n");
265         return PTR_ERR(v3_class);
266     }
267
268     INFO("intializing V3 Control device\n");
269
270     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
271
272     if (ret < 0) {
273         ERROR("Error registering device region for V3 devices\n");
274         goto failure2;
275     }
276
277     v3_major_num = MAJOR(dev);
278
279     dev = MKDEV(v3_major_num, MAX_VMS + 1);
280
281     
282     DEBUG("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
283     cdev_init(&ctrl_dev, &v3_ctrl_fops);
284     ctrl_dev.owner = THIS_MODULE;
285     ctrl_dev.ops = &v3_ctrl_fops;
286     cdev_add(&ctrl_dev, dev, 1);
287     
288     device_create(v3_class, NULL, dev, NULL, "v3vee");
289
290     if (ret != 0) {
291         ERROR("Error adding v3 control device\n");
292         goto failure1;
293     }
294
295     dir = proc_mkdir("v3vee", NULL);
296     if(dir) {
297         struct proc_dir_entry *entry;
298
299         entry = create_proc_read_entry("v3-guests", 0444, dir, 
300                                        read_guests, NULL);
301         if (entry) {
302             INFO("/proc/v3vee/v3-guests successfully created\n");
303         } else {
304             ERROR("Could not create proc entry\n");
305             goto failure1;
306         }
307         
308         entry = create_proc_read_entry("v3-mem", 0444, dir,
309                                        show_mem, NULL);
310         if (entry) {
311             INFO("/proc/v3vee/v3-mem successfully added\n");
312         } else {
313             ERROR("Could not create proc entry\n");
314             goto failure1;
315         }
316     } else {
317         ERROR("Could not create proc entry\n");
318         goto failure1;
319     }
320         
321     return 0;
322
323  failure1:
324     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
325  failure2:
326     class_destroy(v3_class);
327
328     return ret;
329 }
330
331
332 static void __exit v3_exit(void) {
333     extern u32 pg_allocs;
334     extern u32 pg_frees;
335     extern u32 mallocs;
336     extern u32 frees;
337     int i = 0;
338     struct v3_guest * guest;
339     dev_t dev;
340
341
342     /* Stop and free any running VMs */ 
343     for (i = 0; i < MAX_VMS; i++) {
344         if (guest_map[i] != NULL) {
345                 guest = (struct v3_guest *)guest_map[i];
346
347                 if (v3_stop_vm(guest->v3_ctx) < 0) 
348                         ERROR("Couldn't stop VM %d\n", i);
349
350                 free_palacios_vm(guest);
351                 guest_map[i] = NULL;
352         }
353     }
354
355     dev = MKDEV(v3_major_num, MAX_VMS + 1);
356
357     INFO("Removing V3 Control device\n");
358
359
360     palacios_vmm_exit();
361
362     DEBUG("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
363     DEBUG("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
364
365     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
366
367     cdev_del(&ctrl_dev);
368
369     device_destroy(v3_class, dev);
370     class_destroy(v3_class);
371
372
373     deinit_lnx_extensions();
374
375     palacios_deinit_mm();
376
377     remove_proc_entry("v3-guests", dir);
378     remove_proc_entry("v3-mem", dir);
379     remove_proc_entry("v3vee", NULL);
380
381     DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
382 }
383
384
385
386 module_init(v3_init);
387 module_exit(v3_exit);
388
389
390
391 void * trace_malloc(size_t size, gfp_t flags) {
392     void * addr = NULL;
393
394     mod_allocs++;
395     addr = kmalloc(size, flags);
396
397     return addr;
398 }
399
400
401 void trace_free(const void * objp) {
402     mod_frees++;
403     kfree(objp);
404 }