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.


931763557742e635bca6101aed89011e9eaaca29
[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_START_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: Starting 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             printk("Palacios: Launching VM\n");
110
111             INIT_LIST_HEAD(&(guest->exts));
112
113             if (start_palacios_vm(guest) == -1) {
114                 printk("Palacios: Error starting guest\n");
115                 return -EFAULT;
116             }
117
118             return guest->vm_dev;
119             break;
120         }
121         case V3_STOP_GUEST: {
122             unsigned long vm_idx = arg;
123             struct v3_guest * guest = guest_map[vm_idx];
124
125             printk("Stopping VM idx=%d\n", vm_idx);
126             printk("Stopping VM (%s) (%p)\n", guest->name, guest);
127
128
129             if (irqs_disabled()) {
130                 printk("WHAT!!?? IRQs are disabled??\n");
131                 break;
132             }
133
134             stop_palacios_vm(guest);
135             guest_map[vm_idx] = NULL;
136             break;
137         }
138         case V3_ADD_MEMORY: {
139             struct v3_mem_region mem;
140             
141             memset(&mem, 0, sizeof(struct v3_mem_region));
142             
143             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
144                 printk("copy from user error getting mem_region...\n");
145                 return -EFAULT;
146             }
147
148             printk("Adding %llu pages to Palacios memory\n", mem.num_pages);
149
150             if (add_palacios_memory(mem.base_addr, mem.num_pages) == -1) {
151                 printk("Error adding memory to Palacios\n");
152                 return -EFAULT;
153             }
154
155             break;
156         }
157
158         default: 
159             printk("\tUnhandled\n");
160             return -EINVAL;
161     }
162
163     return 0;
164 }
165
166
167
168 static struct file_operations v3_ctrl_fops = {
169     .owner = THIS_MODULE,
170     .unlocked_ioctl = v3_dev_ioctl,
171     .compat_ioctl = v3_dev_ioctl,
172 };
173
174
175
176 static int __init v3_init(void) {
177     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
178     int ret = 0;
179
180
181     palacios_init_mm();
182
183
184     // Initialize Palacios
185     
186     palacios_vmm_init();
187
188
189     // initialize extensions
190     init_lnx_extensions();
191
192
193     v3_class = class_create(THIS_MODULE, "vms");
194     if (IS_ERR(v3_class)) {
195         printk("Failed to register V3 VM device class\n");
196         return PTR_ERR(v3_class);
197     }
198
199     printk("intializing V3 Control device\n");
200
201     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
202
203     if (ret < 0) {
204         printk("Error registering device region for V3 devices\n");
205         goto failure2;
206     }
207
208     v3_major_num = MAJOR(dev);
209
210     dev = MKDEV(v3_major_num, MAX_VMS + 1);
211
212     
213     printk("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
214     cdev_init(&ctrl_dev, &v3_ctrl_fops);
215     ctrl_dev.owner = THIS_MODULE;
216     ctrl_dev.ops = &v3_ctrl_fops;
217     cdev_add(&ctrl_dev, dev, 1);
218     
219     device_create(v3_class, NULL, dev, NULL, "v3vee");
220
221     if (ret != 0) {
222         printk("Error adding v3 control device\n");
223         goto failure1;
224     }
225
226
227
228     return 0;
229
230  failure1:
231     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
232  failure2:
233     class_destroy(v3_class);
234
235     return ret;
236 }
237
238
239 static void __exit v3_exit(void) {
240     extern u32 pg_allocs;
241     extern u32 pg_frees;
242     extern u32 mallocs;
243     extern u32 frees;
244
245
246     // should probably try to stop any guests
247
248
249
250     dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
251
252     printk("Removing V3 Control device\n");
253
254
255     palacios_vmm_exit();
256
257     printk("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
258     printk("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
259
260     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
261
262     cdev_del(&ctrl_dev);
263
264     device_destroy(v3_class, dev);
265     class_destroy(v3_class);
266
267
268     deinit_lnx_extensions();
269
270     palacios_deinit_mm();
271
272     printk("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
273 }
274
275
276
277 module_init(v3_init);
278 module_exit(v3_exit);
279
280
281
282 void * trace_malloc(size_t size, gfp_t flags) {
283     void * addr = NULL;
284
285     mod_allocs++;
286     addr = kmalloc(size, flags);
287
288     return addr;
289 }
290
291
292 void trace_free(const void * objp) {
293     mod_frees++;
294     kfree(objp);
295 }