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.


e1143f89f34ea6d3300cab4d0a7f25198cdfdf94
[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 CONFIG_DEBUG_FS
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     palacios_init_stream();
245     palacios_file_init();
246     palacios_init_console();
247
248
249 #ifdef CONFIG_DEBUG_FS
250     palacios_init_debugfs();
251 #endif
252
253 #ifdef CONFIG_PALACIOS_SOCKET
254     palacios_socket_init();
255 #endif
256
257 #ifdef CONFIG_PALACIOS_PACKET
258     palacios_init_packet(NULL);
259 #endif
260
261 #ifdef CONFIG_PALACIOS_VNET
262     palacios_init_vnet();
263 #endif
264
265     return 0;
266
267  failure1:
268     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
269  failure2:
270     class_destroy(v3_class);
271
272     return ret;
273 }
274
275
276 static void __exit v3_exit(void) {
277     extern u32 pg_allocs;
278     extern u32 pg_frees;
279     extern u32 mallocs;
280     extern u32 frees;
281
282
283     // should probably try to stop any guests
284
285
286
287     dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
288
289     printk("Removing V3 Control device\n");
290
291
292     palacios_vmm_exit();
293
294     printk("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
295     printk("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
296
297     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
298
299     cdev_del(&ctrl_dev);
300
301     device_destroy(v3_class, dev);
302     class_destroy(v3_class);
303
304
305
306 #ifdef CONFIG_DEBUG_FS
307     palacios_deinit_debugfs();
308 #endif
309
310     palacios_file_deinit();
311     palacios_deinit_stream();
312
313     palacios_deinit_mm();
314
315     printk("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
316 }
317
318
319
320 module_init(v3_init);
321 module_exit(v3_exit);
322
323
324
325 void * trace_malloc(size_t size, gfp_t flags) {
326     void * addr = NULL;
327
328     mod_allocs++;
329     addr = kmalloc(size, flags);
330
331     return addr;
332 }
333
334
335 void trace_free(const void * objp) {
336     mod_frees++;
337     kfree(objp);
338 }