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