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.


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