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.


bug fixes for extension framework, and porting of console to new interface
[palacios.git] / linux_module / palacios-dev.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 "palacios-mm.h"
23 #include "palacios-vm.h"
24 #include "palacios-stream.h"
25 #include "palacios-file.h"
26 #include "palacios-serial.h"
27 #include "palacios-socket.h"
28 #include "palacios-vnet.h"
29 #include "palacios-packet.h"
30
31 #include "linux-exts.h"
32
33 #ifdef V3_CONFIG_EXT_INSPECTOR
34 #include "palacios-inspector.h"
35 #endif
36
37 #ifdef V3_CONFIG_KEYED_STREAMS
38 #include "palacios-keyed-stream.h"
39 #endif
40
41
42 MODULE_LICENSE("GPL");
43
44 int mod_allocs = 0;
45 int mod_frees = 0;
46
47
48 static int v3_major_num = 0;
49
50 static u8 v3_minor_map[MAX_VMS / 8] = {[0 ... (MAX_VMS / 8) - 1] = 0}; 
51
52
53 struct class * v3_class = NULL;
54 static struct cdev ctrl_dev;
55
56 static int register_vm( void ) {
57     int i, j = 0;
58     int avail = 0;
59
60     for (i = 0; i < sizeof(v3_minor_map); i++) {
61         if (v3_minor_map[i] != 0xff) {
62             for (j = 0; j < 8; j++) {
63                 if (!(v3_minor_map[i] & (0x1 << j))) {
64                     avail = 1;
65                     v3_minor_map[i] |= (0x1 << j);
66                     break;
67                 }
68             }
69         
70             if (avail == 1) {
71                 break;
72             }
73         }
74     }
75
76     if (avail == 0) {
77         return -1;
78     }
79         
80     return (i * 8) + j;
81 }
82
83
84
85 static long v3_dev_ioctl(struct file * filp,
86                          unsigned int ioctl, unsigned long arg) {
87     void __user * argp = (void __user *)arg;
88     printk("V3 IOCTL %d\n", ioctl);
89
90
91     switch (ioctl) {
92         case V3_START_GUEST:{
93             int vm_minor = 0;
94             struct v3_guest_img user_image;
95             struct v3_guest * guest = kmalloc(sizeof(struct v3_guest), GFP_KERNEL);
96
97             if (IS_ERR(guest)) {
98                 printk("Error allocating Kernel guest_image\n");
99                 return -EFAULT;
100             }
101
102             memset(guest, 0, sizeof(struct v3_guest));
103
104             printk("Starting V3 Guest...\n");
105
106             vm_minor = register_vm();
107
108             if (vm_minor == -1) {
109                 printk("Too many VMs are currently running\n");
110                 return -EFAULT;
111             }
112
113             guest->vm_dev = MKDEV(v3_major_num, vm_minor);
114
115             if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
116                 printk("copy from user error getting guest image...\n");
117                 return -EFAULT;
118             }
119
120             guest->img_size = user_image.size;
121
122             printk("Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
123             guest->img = vmalloc(guest->img_size);
124
125             if (IS_ERR(guest->img)) {
126                 printk("Error: Could not allocate space for guest image\n");
127                 return -EFAULT;
128             }
129
130             if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
131                 printk("Error loading guest data\n");
132                 return -EFAULT;
133             }      
134
135             strncpy(guest->name, user_image.name, 127);
136
137             printk("Launching VM\n");
138
139             INIT_LIST_HEAD(&(guest->exts));
140
141
142             INIT_LIST_HEAD(&(guest->streams));
143             INIT_LIST_HEAD(&(guest->files));
144             INIT_LIST_HEAD(&(guest->sockets));
145 #ifdef V3_CONFIG_HOST_DEVICE
146             INIT_LIST_HEAD(&(guest->hostdev.devs));
147 #endif
148             init_completion(&(guest->start_done));
149             init_completion(&(guest->thread_done));
150
151             { 
152                 struct task_struct * launch_thread = NULL;
153                 // At some point we're going to want to allow the user to specify a CPU mask
154                 // But for now, well just launch from the local core, and rely on the global cpu mask
155
156                 preempt_disable();
157                 launch_thread = kthread_create(start_palacios_vm, guest, guest->name);
158                 
159                 if (IS_ERR(launch_thread)) {
160                     preempt_enable();
161                     printk("Palacios error creating launch thread for vm (%s)\n", guest->name);
162                     return -EFAULT;
163                 }
164
165                 kthread_bind(launch_thread, smp_processor_id());
166                 preempt_enable();
167
168                 wake_up_process(launch_thread);
169             }
170
171             wait_for_completion(&(guest->start_done));
172
173             return guest->vm_dev;
174             break;
175         }
176         case V3_ADD_MEMORY: {
177             struct v3_mem_region mem;
178             
179             memset(&mem, 0, sizeof(struct v3_mem_region));
180             
181             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
182                 printk("copy from user error getting mem_region...\n");
183                 return -EFAULT;
184             }
185
186             printk("Adding %llu pages to Palacios memory\n", mem.num_pages);
187
188             if (add_palacios_memory(mem.base_addr, mem.num_pages) == -1) {
189                 printk("Error adding memory to Palacios\n");
190                 return -EFAULT;
191             }
192
193             break;
194         }
195
196         default: 
197             printk("\tUnhandled\n");
198             return -EINVAL;
199     }
200
201     return 0;
202 }
203
204
205
206 static struct file_operations v3_ctrl_fops = {
207     .owner = THIS_MODULE,
208     .unlocked_ioctl = v3_dev_ioctl,
209     .compat_ioctl = v3_dev_ioctl,
210 };
211
212
213
214 static int __init v3_init(void) {
215     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
216     int ret = 0;
217
218
219     palacios_init_mm();
220
221
222     // Initialize Palacios
223     
224     palacios_vmm_init();
225
226
227     // initialize extensions
228     init_lnx_extensions();
229
230
231     v3_class = class_create(THIS_MODULE, "vms");
232     if (IS_ERR(v3_class)) {
233         printk("Failed to register V3 VM device class\n");
234         return PTR_ERR(v3_class);
235     }
236
237     printk("intializing V3 Control device\n");
238
239     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
240
241     if (ret < 0) {
242         printk("Error registering device region for V3 devices\n");
243         goto failure2;
244     }
245
246     v3_major_num = MAJOR(dev);
247
248     dev = MKDEV(v3_major_num, MAX_VMS + 1);
249
250     
251     printk("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
252     cdev_init(&ctrl_dev, &v3_ctrl_fops);
253     ctrl_dev.owner = THIS_MODULE;
254     ctrl_dev.ops = &v3_ctrl_fops;
255     cdev_add(&ctrl_dev, dev, 1);
256     
257     device_create(v3_class, NULL, dev, NULL, "v3vee");
258
259     if (ret != 0) {
260         printk("Error adding v3 control device\n");
261         goto failure1;
262     }
263
264
265
266 #ifdef V3_CONFIG_STREAM
267     palacios_init_stream();
268 #endif
269
270 #ifdef V3_CONFIG_FILE
271     palacios_file_init();
272 #endif
273
274 #ifdef V3_CONFIG_KEYED_STREAMS
275     palacios_init_keyed_streams();
276 #endif
277
278 #ifdef V3_CONFIG_GRAPHICS_CONSOLE
279     palacios_init_graphics_console();
280 #endif
281
282 #ifdef V3_CONFIG_EXT_INSPECTOR
283     palacios_init_inspector();
284 #endif
285
286 #ifdef V3_CONFIG_SOCKET
287     palacios_socket_init();
288 #endif
289
290 #ifdef V3_CONFIG_PACKET
291     palacios_init_packet(NULL);
292 #endif
293
294 #ifdef V3_CONFIG_VNET
295     palacios_vnet_init();
296 #endif
297
298 #ifdef V3_CONFIG_HOST_DEVICE
299     palacios_init_host_dev();
300 #endif
301
302     return 0;
303
304  failure1:
305     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
306  failure2:
307     class_destroy(v3_class);
308
309     return ret;
310 }
311
312
313 static void __exit v3_exit(void) {
314     extern u32 pg_allocs;
315     extern u32 pg_frees;
316     extern u32 mallocs;
317     extern u32 frees;
318
319
320     // should probably try to stop any guests
321
322
323
324     dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
325
326     printk("Removing V3 Control device\n");
327
328
329     palacios_vmm_exit();
330
331     printk("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
332     printk("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
333
334     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
335
336     cdev_del(&ctrl_dev);
337
338     device_destroy(v3_class, dev);
339     class_destroy(v3_class);
340
341
342
343 #ifdef V3_CONFIG_EXT_INSPECTOR
344     palacios_deinit_inspector();
345 #endif
346
347 #ifdef V3_CONFIG_FILE
348     palacios_file_deinit();
349 #endif
350
351 #ifdef V3_CONFIG_STREAM
352     palacios_deinit_stream();
353 #endif
354
355 #ifdef V3_CONFIG_SOCKET
356     palacios_socket_deinit();
357 #endif
358
359 #ifdef V3_CONFIG_PACKET
360     palacios_deinit_packet(NULL);
361 #endif
362
363 #ifdef V3_CONFIG_VNET
364     palacios_vnet_deinit();
365 #endif
366
367     palacios_deinit_mm();
368
369     printk("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
370 }
371
372
373
374 module_init(v3_init);
375 module_exit(v3_exit);
376
377
378
379 void * trace_malloc(size_t size, gfp_t flags) {
380     void * addr = NULL;
381
382     mod_allocs++;
383     addr = kmalloc(size, flags);
384
385     return addr;
386 }
387
388
389 void trace_free(const void * objp) {
390     mod_frees++;
391     kfree(objp);
392 }