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.


8b303521db8e5bdceb1c10047b8306c19e1e9f55
[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
31 static int v3_major_num = 0;
32
33 static u8 v3_minor_map[MAX_VMS / 8] = {[0 ... (MAX_VMS / 8) - 1] = 0}; 
34
35
36 struct class * v3_class = NULL;
37 static struct cdev ctrl_dev;
38
39 void * v3_base_addr = NULL;
40 unsigned int v3_pages = 0;
41
42 static int register_vm( void ) {
43     int i, j = 0;
44     int avail = 0;
45
46     for (i = 0; i < sizeof(v3_minor_map); i++) {
47         if (v3_minor_map[i] != 0xff) {
48             for (j = 0; j < 8; j++) {
49                 if (!v3_minor_map[i] & (0x1 << j)) {
50                     avail = 1;
51                     v3_minor_map[i] |= (0x1 << j);
52                     break;
53                 }
54             }
55         
56             if (avail == 1) {
57                 break;
58             }
59         }
60     }
61
62     if (avail == 0) {
63         return -1;
64     }
65         
66     return (i * 8) + j;
67 }
68
69
70
71 static long v3_dev_ioctl(struct file * filp,
72                          unsigned int ioctl, unsigned long arg) {
73     void __user * argp = (void __user *)arg;
74     printk("V3 IOCTL %d\n", ioctl);
75
76
77     switch (ioctl) {
78         case V3_START_GUEST:{
79             struct v3_guest_img user_image;
80             struct v3_guest * guest = kmalloc(sizeof(struct v3_guest), GFP_KERNEL);
81             int vm_minor = 0;
82
83             if (IS_ERR(guest)) {
84                 printk("Error allocating Kernel guest_image\n");
85                 return -EFAULT;
86             }
87
88             memset(guest, 0, sizeof(struct v3_guest));
89
90             printk("Starting V3 Guest...\n");
91
92             vm_minor = register_vm();
93
94             if (vm_minor == -1) {
95                 printk("Too many VMs are currently running\n");
96                 return -EFAULT;
97             }
98
99             guest->vm_dev = MKDEV(v3_major_num, vm_minor);
100
101             if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
102                 printk("copy from user error getting guest image...\n");
103                 return -EFAULT;
104             }
105
106             guest->img_size = user_image.size;
107
108             printk("Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
109             guest->img = kmalloc(guest->img_size, GFP_KERNEL);
110
111             if (IS_ERR(guest->img)) {
112                 printk("Error: Could not allocate space for guest image\n");
113                 return -EFAULT;
114             }
115
116             if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
117                 printk("Error loading guest data\n");
118                 return -EFAULT;
119             }      
120
121             strncpy(guest->name, user_image.name, 127);
122
123             printk("Launching VM\n");
124
125             INIT_LIST_HEAD(&(guest->streams));
126             INIT_LIST_HEAD(&(guest->files));
127             INIT_LIST_HEAD(&(guest->sockets));
128             init_completion(&(guest->start_done));
129             init_completion(&(guest->thread_done));
130
131             kthread_run(start_palacios_vm, guest, guest->name);
132
133             wait_for_completion(&(guest->start_done));
134
135             return guest->vm_dev;
136             break;
137         }
138         case V3_ADD_MEMORY: {
139             struct v3_mem_region mem;
140             
141             memset(&mem, 0, sizeof(struct v3_mem_region));
142             
143             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
144                 printk("copy from user error getting mem_region...\n");
145                 return -EFAULT;
146             }
147
148             printk("Adding %llu pages to Palacios memory\n", mem.num_pages);
149
150             if (add_palacios_memory(mem.base_addr, mem.num_pages) == -1) {
151                 printk("Error adding memory to Palacios\n");
152                 return -EFAULT;
153             }
154
155             // Mem test...
156             /*
157               {
158               void * vaddr = __va(alloc_palacios_pgs(131072, 4096));
159               memset(vaddr, 0xfe492fe2, mem.num_pages * 4096);
160               }
161             */
162
163             break;
164         }
165         default: 
166             printk("\tUnhandled\n");
167             return -EINVAL;
168     }
169
170     return 0;
171 }
172
173
174
175 static struct file_operations v3_ctrl_fops = {
176     .owner = THIS_MODULE,
177     .unlocked_ioctl = v3_dev_ioctl,
178     .compat_ioctl = v3_dev_ioctl,
179 };
180
181
182 extern unsigned int v3_pages;
183 extern void * v3_base_addr;
184
185 static int __init v3_init(void) {
186     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
187     int ret = 0;
188
189
190     palacios_init_mm();
191
192     v3_class = class_create(THIS_MODULE, "vms");
193     if (IS_ERR(v3_class)) {
194         printk("Failed to register V3 VM device class\n");
195         return PTR_ERR(v3_class);
196     }
197
198     printk("intializing V3 Control device\n");
199
200     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
201
202     if (ret < 0) {
203         printk("Error registering device region for V3 devices\n");
204         goto failure2;
205     }
206
207     v3_major_num = MAJOR(dev);
208
209     dev = MKDEV(v3_major_num, MAX_VMS + 1);
210
211     
212     printk("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
213     cdev_init(&ctrl_dev, &v3_ctrl_fops);
214     ctrl_dev.owner = THIS_MODULE;
215     ctrl_dev.ops = &v3_ctrl_fops;
216     cdev_add(&ctrl_dev, dev, 1);
217     
218     device_create(v3_class, NULL, dev, NULL, "v3vee");
219
220     if (ret != 0) {
221         printk("Error adding v3 control device\n");
222         goto failure1;
223     }
224
225     if ((v3_pages > 0) && (v3_base_addr != NULL)) {
226         add_palacios_memory(__pa(v3_base_addr), v3_pages);
227     }
228
229     // Initialize Palacios
230     
231     palacios_vmm_init();
232
233     palacios_init_stream();
234     palacios_file_init();
235     palacios_init_console();
236
237     return 0;
238
239  failure1:
240     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
241  failure2:
242     class_destroy(v3_class);
243
244     return ret;
245 }
246
247
248 static void __exit v3_exit(void) {
249     extern u32 pg_allocs;
250     extern u32 pg_frees;
251     extern u32 mallocs;
252     extern u32 frees;
253
254     dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
255
256     printk("Removing V3 Control device\n");
257
258
259     palacios_vmm_exit();
260
261     printk("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
262     printk("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
263
264     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
265
266     cdev_del(&ctrl_dev);
267
268     device_destroy(v3_class, dev);
269     class_destroy(v3_class);
270 }
271
272
273
274 module_init(v3_init);
275 module_exit(v3_exit);