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.


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