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.


585e80785dc839f05f170cea1825269ecc749326
[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->thread_done));
129
130             kthread_run(start_palacios_vm, guest, guest->name);
131
132             wait_for_completion(&(guest->thread_done));
133
134             return guest->vm_dev;
135             break;
136         }
137         case V3_ADD_MEMORY: {
138             struct v3_mem_region mem;
139             
140             memset(&mem, 0, sizeof(struct v3_mem_region));
141             
142             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
143                 printk("copy from user error getting mem_region...\n");
144                 return -EFAULT;
145             }
146
147             printk("Adding %llu pages to Palacios memory\n", mem.num_pages);
148
149             if (add_palacios_memory(mem.base_addr, mem.num_pages) == -1) {
150                 printk("Error adding memory to Palacios\n");
151                 return -EFAULT;
152             }
153
154             // Mem test...
155             /*
156               {
157               void * vaddr = __va(alloc_palacios_pgs(131072, 4096));
158               memset(vaddr, 0xfe492fe2, mem.num_pages * 4096);
159               }
160             */
161
162             break;
163         }
164         default: 
165             printk("\tUnhandled\n");
166             return -EINVAL;
167     }
168
169     return 0;
170 }
171
172
173
174 static struct file_operations v3_ctrl_fops = {
175     .owner = THIS_MODULE,
176     .unlocked_ioctl = v3_dev_ioctl,
177     .compat_ioctl = v3_dev_ioctl,
178 };
179
180
181 extern unsigned int v3_pages;
182 extern void * v3_base_addr;
183
184 static int __init v3_init(void) {
185     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
186     int ret = 0;
187
188
189     palacios_init_mm();
190
191     v3_class = class_create(THIS_MODULE, "vms");
192     if (IS_ERR(v3_class)) {
193         printk("Failed to register V3 VM device class\n");
194         return PTR_ERR(v3_class);
195     }
196
197     printk("intializing V3 Control device\n");
198
199     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
200
201     if (ret < 0) {
202         printk("Error registering device region for V3 devices\n");
203         goto failure2;
204     }
205
206     v3_major_num = MAJOR(dev);
207
208     dev = MKDEV(v3_major_num, MAX_VMS + 1);
209
210     
211     printk("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
212     cdev_init(&ctrl_dev, &v3_ctrl_fops);
213     ctrl_dev.owner = THIS_MODULE;
214     ctrl_dev.ops = &v3_ctrl_fops;
215     cdev_add(&ctrl_dev, dev, 1);
216     
217     device_create(v3_class, NULL, dev, NULL, "v3vee");
218
219     if (ret != 0) {
220         printk("Error adding v3 control device\n");
221         goto failure1;
222     }
223
224     if ((v3_pages > 0) && (v3_base_addr != NULL)) {
225         add_palacios_memory(__pa(v3_base_addr), v3_pages);
226     }
227
228     // Initialize Palacios
229     
230     palacios_vmm_init();
231
232     palacios_init_stream();
233     palacios_file_init();
234     palacios_init_console();
235     
236
237
238     return 0;
239
240  failure1:
241     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
242  failure2:
243     class_destroy(v3_class);
244
245     return ret;
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     printk("Removing V3 Control device\n");
255
256     palacios_vmm_exit();
257
258
259     printk("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
260     printk("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
261
262
263     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
264 }
265
266
267
268 module_init(v3_init);
269 module_exit(v3_exit);