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.


/proc info showing vm device and vm name mapping, and memory use
[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;
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 static int read_guests(char * buf, char ** start, off_t off, int count,
178                        int * eof, void * data)
179 {
180     int len = 0;
181     unsigned int i = 0;
182     
183     for(i = 0; i < MAX_VMS; i++) {
184         if (guest_map[i] != NULL) {
185             if (len<count) { 
186                 len += snprintf(buf+len, count-len,
187                                 "%s\t/dev/v3-vm%d\n", 
188                                 guest_map[i]->name, i);
189             }
190         }
191     }
192     
193     return len;
194 }
195
196 static int show_mem(char * buf, char ** start, off_t off, int count,
197                     int * eof, void * data)
198 {
199     int len = 0;
200     
201     len = snprintf(buf,count, "%p\n", (void *)get_palacios_base_addr());
202     len += snprintf(buf+len,count-len, "%lld\n", get_palacios_num_pages());
203     
204     return len;
205 }
206
207
208 static int __init v3_init(void) {
209     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
210     int ret = 0;
211
212
213     palacios_init_mm();
214
215     // Initialize Palacios
216     palacios_vmm_init();
217
218
219     // initialize extensions
220     init_lnx_extensions();
221
222
223     v3_class = class_create(THIS_MODULE, "vms");
224     if (IS_ERR(v3_class)) {
225         ERROR("Failed to register V3 VM device class\n");
226         return PTR_ERR(v3_class);
227     }
228
229     INFO("intializing V3 Control device\n");
230
231     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
232
233     if (ret < 0) {
234         ERROR("Error registering device region for V3 devices\n");
235         goto failure2;
236     }
237
238     v3_major_num = MAJOR(dev);
239
240     dev = MKDEV(v3_major_num, MAX_VMS + 1);
241
242     
243     DEBUG("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
244     cdev_init(&ctrl_dev, &v3_ctrl_fops);
245     ctrl_dev.owner = THIS_MODULE;
246     ctrl_dev.ops = &v3_ctrl_fops;
247     cdev_add(&ctrl_dev, dev, 1);
248     
249     device_create(v3_class, NULL, dev, NULL, "v3vee");
250
251     if (ret != 0) {
252         ERROR("Error adding v3 control device\n");
253         goto failure1;
254     }
255
256     dir = proc_mkdir("v3vee", NULL);
257     if(dir) {
258         struct proc_dir_entry *entry;
259
260         entry = create_proc_read_entry("v3-guests", 0444, dir, 
261                                        read_guests, NULL);
262         if (entry) {
263             INFO("/proc/v3vee/v3-guests successfully created\n");
264         } else {
265             ERROR("Could not create proc entry\n");
266             goto failure1;
267         }
268         
269         entry = create_proc_read_entry("v3-mem", 0444, dir,
270                                        show_mem, NULL);
271         if (entry) {
272             INFO("/proc/v3vee/v3-mem successfully added\n");
273         } else {
274             ERROR("Could not create proc entry\n");
275             goto failure1;
276         }
277     } else {
278         ERROR("Could not create proc entry\n");
279         goto failure1;
280     }
281         
282     return 0;
283
284  failure1:
285     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
286  failure2:
287     class_destroy(v3_class);
288
289     return ret;
290 }
291
292
293 static void __exit v3_exit(void) {
294     extern u32 pg_allocs;
295     extern u32 pg_frees;
296     extern u32 mallocs;
297     extern u32 frees;
298
299
300     // should probably try to stop any guests
301
302
303
304     dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
305
306     INFO("Removing V3 Control device\n");
307
308
309     palacios_vmm_exit();
310
311     DEBUG("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
312     DEBUG("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
313
314     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
315
316     cdev_del(&ctrl_dev);
317
318     device_destroy(v3_class, dev);
319     class_destroy(v3_class);
320
321
322     deinit_lnx_extensions();
323
324     palacios_deinit_mm();
325
326     remove_proc_entry("v3-guests", dir);
327     remove_proc_entry("v3-mem", dir);
328     remove_proc_entry("v3vee", NULL);
329
330     DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
331 }
332
333
334
335 module_init(v3_init);
336 module_exit(v3_exit);
337
338
339
340 void * trace_malloc(size_t size, gfp_t flags) {
341     void * addr = NULL;
342
343     mod_allocs++;
344     addr = kmalloc(size, flags);
345
346     return addr;
347 }
348
349
350 void trace_free(const void * objp) {
351     mod_frees++;
352     kfree(objp);
353 }