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.


more linux changes
[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
28 MODULE_LICENSE("GPL");
29
30 int mod_allocs = 0;
31 int mod_frees = 0;
32
33
34 static int v3_major_num = 0;
35
36 static u8 v3_minor_map[MAX_VMS / 8] = {[0 ... (MAX_VMS / 8) - 1] = 0}; 
37
38
39 struct class * v3_class = NULL;
40 static struct cdev ctrl_dev;
41
42 void * v3_base_addr = NULL;
43 unsigned int v3_pages = 0;
44
45 static int register_vm( void ) {
46     int i, j = 0;
47     int avail = 0;
48
49     for (i = 0; i < sizeof(v3_minor_map); i++) {
50         if (v3_minor_map[i] != 0xff) {
51             for (j = 0; j < 8; j++) {
52                 if (!v3_minor_map[i] & (0x1 << j)) {
53                     avail = 1;
54                     v3_minor_map[i] |= (0x1 << j);
55                     break;
56                 }
57             }
58         
59             if (avail == 1) {
60                 break;
61             }
62         }
63     }
64
65     if (avail == 0) {
66         return -1;
67     }
68         
69     return (i * 8) + j;
70 }
71
72
73
74 static long v3_dev_ioctl(struct file * filp,
75                          unsigned int ioctl, unsigned long arg) {
76     void __user * argp = (void __user *)arg;
77     printk("V3 IOCTL %d\n", ioctl);
78
79
80     switch (ioctl) {
81         case V3_START_GUEST:{
82             int vm_minor = 0;
83             struct v3_guest_img user_image;
84             struct v3_guest * guest = kmalloc(sizeof(struct v3_guest), GFP_KERNEL);
85
86             if (IS_ERR(guest)) {
87                 printk("Error allocating Kernel guest_image\n");
88                 return -EFAULT;
89             }
90
91             memset(guest, 0, sizeof(struct v3_guest));
92
93             printk("Starting V3 Guest...\n");
94
95             vm_minor = register_vm();
96
97             if (vm_minor == -1) {
98                 printk("Too many VMs are currently running\n");
99                 return -EFAULT;
100             }
101
102             guest->vm_dev = MKDEV(v3_major_num, vm_minor);
103
104             if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
105                 printk("copy from user error getting guest image...\n");
106                 return -EFAULT;
107             }
108
109             guest->img_size = user_image.size;
110
111             printk("Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
112             guest->img = kmalloc(guest->img_size, GFP_KERNEL);
113
114             if (IS_ERR(guest->img)) {
115                 printk("Error: Could not allocate space for guest image\n");
116                 return -EFAULT;
117             }
118
119             if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
120                 printk("Error loading guest data\n");
121                 return -EFAULT;
122             }      
123
124             strncpy(guest->name, user_image.name, 127);
125
126             printk("Launching VM\n");
127
128             INIT_LIST_HEAD(&(guest->streams));
129             INIT_LIST_HEAD(&(guest->files));
130             INIT_LIST_HEAD(&(guest->sockets));
131             init_completion(&(guest->start_done));
132             init_completion(&(guest->thread_done));
133
134             kthread_run(start_palacios_vm, guest, guest->name);
135
136             wait_for_completion(&(guest->start_done));
137
138             return guest->vm_dev;
139             break;
140         }
141         case V3_ADD_MEMORY: {
142             struct v3_mem_region mem;
143             
144             memset(&mem, 0, sizeof(struct v3_mem_region));
145             
146             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
147                 printk("copy from user error getting mem_region...\n");
148                 return -EFAULT;
149             }
150
151             printk("Adding %llu pages to Palacios memory\n", mem.num_pages);
152
153             if (add_palacios_memory(mem.base_addr, mem.num_pages) == -1) {
154                 printk("Error adding memory to Palacios\n");
155                 return -EFAULT;
156             }
157
158             // Mem test...
159             /*
160               {
161               void * vaddr = __va(alloc_palacios_pgs(131072, 4096));
162               memset(vaddr, 0xfe492fe2, mem.num_pages * 4096);
163               }
164             */
165
166             break;
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     palacios_init_stream();
237     palacios_file_init();
238     palacios_init_console();
239
240     return 0;
241
242  failure1:
243     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
244  failure2:
245     class_destroy(v3_class);
246
247     return ret;
248 }
249
250
251 static void __exit v3_exit(void) {
252     extern u32 pg_allocs;
253     extern u32 pg_frees;
254     extern u32 mallocs;
255     extern u32 frees;
256
257
258     // should probably try to stop any guests
259
260
261
262     dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
263
264     printk("Removing V3 Control device\n");
265
266
267     palacios_vmm_exit();
268
269     printk("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
270     printk("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
271
272     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
273
274     cdev_del(&ctrl_dev);
275
276     device_destroy(v3_class, dev);
277     class_destroy(v3_class);
278
279
280     palacios_file_deinit();
281     palacios_deinit_stream();
282
283     palacios_deinit_mm();
284
285     printk("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
286 }
287
288
289
290 module_init(v3_init);
291 module_exit(v3_exit);
292
293
294
295 void * trace_malloc(size_t size, gfp_t flags) {
296     void * addr = NULL;
297
298     mod_allocs++;
299     addr = kmalloc(size, flags);
300
301     return addr;
302 }
303
304
305 void trace_free(const void * objp) {
306     mod_frees++;
307     kfree(objp);
308 }