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.


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