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.


userspace changes to break apart VM lifecycle management
[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/errno.h>
9 #include <linux/percpu.h>
10 #include <linux/fs.h>
11 #include <linux/uaccess.h>
12 #include <linux/device.h>
13 #include <linux/cdev.h>
14
15 #include <linux/io.h>
16
17 #include <linux/file.h>
18 #include <linux/spinlock.h>
19 #include <linux/kthread.h>
20
21 #include "palacios.h"
22 #include "mm.h"
23 #include "vm.h"
24
25 #include "linux-exts.h"
26
27
28
29 MODULE_LICENSE("GPL");
30
31 int mod_allocs = 0;
32 int mod_frees = 0;
33
34
35 static int v3_major_num = 0;
36
37 static struct v3_guest * guest_map[MAX_VMS] = {[0 ... MAX_VMS - 1] = 0};
38
39 struct class * v3_class = NULL;
40 static struct cdev ctrl_dev;
41
42 static int register_vm(struct v3_guest * guest) {
43     int i = 0;
44
45     for (i = 0; i < MAX_VMS; i++) {
46         if (guest_map[i] == NULL) {
47             guest_map[i] = guest;
48             return i;
49         }
50     }
51
52     return -1;
53 }
54
55
56
57 static long v3_dev_ioctl(struct file * filp,
58                          unsigned int ioctl, unsigned long arg) {
59     void __user * argp = (void __user *)arg;
60     printk("V3 IOCTL %d\n", ioctl);
61
62
63     switch (ioctl) {
64         case V3_CREATE_GUEST:{
65             int vm_minor = 0;
66             struct v3_guest_img user_image;
67             struct v3_guest * guest = kmalloc(sizeof(struct v3_guest), GFP_KERNEL);
68
69             if (IS_ERR(guest)) {
70                 printk("Palacios: Error allocating Kernel guest_image\n");
71                 return -EFAULT;
72             }
73
74             memset(guest, 0, sizeof(struct v3_guest));
75
76             printk("Palacios: Creating V3 Guest...\n");
77
78             vm_minor = register_vm(guest);
79
80             if (vm_minor == -1) {
81                 printk("Palacios Error: Too many VMs are currently running\n");
82                 return -EFAULT;
83             }
84
85             guest->vm_dev = MKDEV(v3_major_num, vm_minor);
86
87             if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
88                 printk("Palacios Error: copy from user error getting guest image...\n");
89                 return -EFAULT;
90             }
91
92             guest->img_size = user_image.size;
93
94             printk("Palacios: Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
95             guest->img = vmalloc(guest->img_size);
96
97             if (IS_ERR(guest->img)) {
98                 printk("Palacios Error: Could not allocate space for guest image\n");
99                 return -EFAULT;
100             }
101
102             if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
103                 printk("Palacios: Error loading guest data\n");
104                 return -EFAULT;
105             }      
106
107             strncpy(guest->name, user_image.name, 127);
108
109             INIT_LIST_HEAD(&(guest->exts));
110
111             if (create_palacios_vm(guest) == -1) {
112                 printk("Palacios: Error creating guest\n");
113                 return -EFAULT;
114             }
115
116             return vm_minor;
117             break;
118         }
119         case V3_FREE_GUEST: {
120             unsigned long vm_idx = arg;
121             struct v3_guest * guest = guest_map[vm_idx];
122
123             printk("Freeing VM (%s) (%p)\n", guest->name, guest);
124
125             free_palacios_vm(guest);
126             guest_map[vm_idx] = NULL;
127             break;
128         }
129         case V3_ADD_MEMORY: {
130             struct v3_mem_region mem;
131             
132             memset(&mem, 0, sizeof(struct v3_mem_region));
133             
134             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
135                 printk("copy from user error getting mem_region...\n");
136                 return -EFAULT;
137             }
138
139             printk("Adding %llu pages to Palacios memory\n", mem.num_pages);
140
141             if (add_palacios_memory(mem.base_addr, mem.num_pages) == -1) {
142                 printk("Error adding memory to Palacios\n");
143                 return -EFAULT;
144             }
145
146             break;
147         }
148
149         default: 
150             printk("\tUnhandled\n");
151             return -EINVAL;
152     }
153
154     return 0;
155 }
156
157
158
159 static struct file_operations v3_ctrl_fops = {
160     .owner = THIS_MODULE,
161     .unlocked_ioctl = v3_dev_ioctl,
162     .compat_ioctl = v3_dev_ioctl,
163 };
164
165
166
167 static int __init v3_init(void) {
168     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
169     int ret = 0;
170
171
172     palacios_init_mm();
173
174
175     // Initialize Palacios
176     
177     palacios_vmm_init();
178
179
180     // initialize extensions
181     init_lnx_extensions();
182
183
184     v3_class = class_create(THIS_MODULE, "vms");
185     if (IS_ERR(v3_class)) {
186         printk("Failed to register V3 VM device class\n");
187         return PTR_ERR(v3_class);
188     }
189
190     printk("intializing V3 Control device\n");
191
192     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
193
194     if (ret < 0) {
195         printk("Error registering device region for V3 devices\n");
196         goto failure2;
197     }
198
199     v3_major_num = MAJOR(dev);
200
201     dev = MKDEV(v3_major_num, MAX_VMS + 1);
202
203     
204     printk("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
205     cdev_init(&ctrl_dev, &v3_ctrl_fops);
206     ctrl_dev.owner = THIS_MODULE;
207     ctrl_dev.ops = &v3_ctrl_fops;
208     cdev_add(&ctrl_dev, dev, 1);
209     
210     device_create(v3_class, NULL, dev, NULL, "v3vee");
211
212     if (ret != 0) {
213         printk("Error adding v3 control device\n");
214         goto failure1;
215     }
216
217
218
219     return 0;
220
221  failure1:
222     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
223  failure2:
224     class_destroy(v3_class);
225
226     return ret;
227 }
228
229
230 static void __exit v3_exit(void) {
231     extern u32 pg_allocs;
232     extern u32 pg_frees;
233     extern u32 mallocs;
234     extern u32 frees;
235
236
237     // should probably try to stop any guests
238
239
240
241     dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
242
243     printk("Removing V3 Control device\n");
244
245
246     palacios_vmm_exit();
247
248     printk("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
249     printk("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
250
251     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
252
253     cdev_del(&ctrl_dev);
254
255     device_destroy(v3_class, dev);
256     class_destroy(v3_class);
257
258
259     deinit_lnx_extensions();
260
261     palacios_deinit_mm();
262
263     printk("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
264 }
265
266
267
268 module_init(v3_init);
269 module_exit(v3_exit);
270
271
272
273 void * trace_malloc(size_t size, gfp_t flags) {
274     void * addr = NULL;
275
276     mod_allocs++;
277     addr = kmalloc(size, flags);
278
279     return addr;
280 }
281
282
283 void trace_free(const void * objp) {
284     mod_frees++;
285     kfree(objp);
286 }