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.


bb9598f403dfc011b483abaa57da81d35a05d33c
[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-debugfs.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             // Mem test...
166             /*
167               {
168               void * vaddr = __va(alloc_palacios_pgs(131072, 4096));
169               memset(vaddr, 0xfe492fe2, mem.num_pages * 4096);
170               }
171             */
172
173             break;
174         }
175
176         default: 
177             printk("\tUnhandled\n");
178             return -EINVAL;
179     }
180
181     return 0;
182 }
183
184
185
186 static struct file_operations v3_ctrl_fops = {
187     .owner = THIS_MODULE,
188     .unlocked_ioctl = v3_dev_ioctl,
189     .compat_ioctl = v3_dev_ioctl,
190 };
191
192
193 extern unsigned int v3_pages;
194 extern void * v3_base_addr;
195
196 static int __init v3_init(void) {
197     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
198     int ret = 0;
199
200
201     palacios_init_mm();
202
203     v3_class = class_create(THIS_MODULE, "vms");
204     if (IS_ERR(v3_class)) {
205         printk("Failed to register V3 VM device class\n");
206         return PTR_ERR(v3_class);
207     }
208
209     printk("intializing V3 Control device\n");
210
211     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
212
213     if (ret < 0) {
214         printk("Error registering device region for V3 devices\n");
215         goto failure2;
216     }
217
218     v3_major_num = MAJOR(dev);
219
220     dev = MKDEV(v3_major_num, MAX_VMS + 1);
221
222     
223     printk("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
224     cdev_init(&ctrl_dev, &v3_ctrl_fops);
225     ctrl_dev.owner = THIS_MODULE;
226     ctrl_dev.ops = &v3_ctrl_fops;
227     cdev_add(&ctrl_dev, dev, 1);
228     
229     device_create(v3_class, NULL, dev, NULL, "v3vee");
230
231     if (ret != 0) {
232         printk("Error adding v3 control device\n");
233         goto failure1;
234     }
235
236     if ((v3_pages > 0) && (v3_base_addr != NULL)) {
237         add_palacios_memory(__pa(v3_base_addr), v3_pages);
238     }
239
240     // Initialize Palacios
241     
242     palacios_vmm_init();
243
244 #ifdef V3_CONFIG_STREAM
245     palacios_init_stream();
246 #endif
247
248 #ifdef V3_CONFIG_FILE
249     palacios_file_init();
250 #endif
251
252 #ifdef V3_CONFIG_CONSOLE
253     palacios_init_console();
254 #endif
255
256 #ifdef V3_CONFIG_INSPECTOR
257     palacios_init_debugfs();
258 #endif
259
260 #ifdef V3_CONFIG_SOCKET
261     palacios_socket_init();
262 #endif
263
264 #ifdef V3_CONFIG_PACKET
265     palacios_init_packet(NULL);
266 #endif
267
268 #ifdef V3_CONFIG_VNET
269     palacios_init_vnet();
270 #endif
271
272     return 0;
273
274  failure1:
275     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
276  failure2:
277     class_destroy(v3_class);
278
279     return ret;
280 }
281
282
283 static void __exit v3_exit(void) {
284     extern u32 pg_allocs;
285     extern u32 pg_frees;
286     extern u32 mallocs;
287     extern u32 frees;
288
289
290     // should probably try to stop any guests
291
292
293
294     dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
295
296     printk("Removing V3 Control device\n");
297
298
299     palacios_vmm_exit();
300
301     printk("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
302     printk("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
303
304     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
305
306     cdev_del(&ctrl_dev);
307
308     device_destroy(v3_class, dev);
309     class_destroy(v3_class);
310
311
312
313 #ifdef V3_CONFIG_EXT_INSPECTOR
314     palacios_deinit_debugfs();
315 #endif
316
317 #ifdef V3_CONFIG_FILE
318     palacios_file_deinit();
319 #endif
320
321 #ifdef V3_CONFIG_STREAM
322     palacios_deinit_stream();
323 #endif
324
325     palacios_deinit_mm();
326
327     printk("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
328 }
329
330
331
332 module_init(v3_init);
333 module_exit(v3_exit);
334
335
336
337 void * trace_malloc(size_t size, gfp_t flags) {
338     void * addr = NULL;
339
340     mod_allocs++;
341     addr = kmalloc(size, flags);
342
343     return addr;
344 }
345
346
347 void trace_free(const void * objp) {
348     mod_frees++;
349     kfree(objp);
350 }