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.


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