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.


Updates to linux module to use linux print macros
[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/moduleparam.h>
9 #include <linux/errno.h>
10 #include <linux/percpu.h>
11 #include <linux/fs.h>
12 #include <linux/uaccess.h>
13 #include <linux/device.h>
14 #include <linux/cdev.h>
15
16 #include <linux/io.h>
17
18 #include <linux/file.h>
19 #include <linux/spinlock.h>
20 #include <linux/kthread.h>
21
22 #include "palacios.h"
23 #include "mm.h"
24 #include "vm.h"
25
26 #include "linux-exts.h"
27
28
29
30 MODULE_LICENSE("GPL");
31
32 // Module parameter
33 int cpu_list[NR_CPUS] = {};
34 int cpu_list_len = 0;
35 module_param_array(cpu_list, int, &cpu_list_len, 0644);
36 MODULE_PARM_DESC(cpu_list, "Comma-delimited list of CPUs that Palacios will run on");
37
38 int mod_allocs = 0;
39 int mod_frees = 0;
40
41
42 static int v3_major_num = 0;
43
44 static struct v3_guest * guest_map[MAX_VMS] = {[0 ... MAX_VMS - 1] = 0};
45
46 struct class * v3_class = NULL;
47 static struct cdev ctrl_dev;
48
49 static int register_vm(struct v3_guest * guest) {
50     int i = 0;
51
52     for (i = 0; i < MAX_VMS; i++) {
53         if (guest_map[i] == NULL) {
54             guest_map[i] = guest;
55             return i;
56         }
57     }
58
59     return -1;
60 }
61
62
63
64 static long v3_dev_ioctl(struct file * filp,
65                          unsigned int ioctl, unsigned long arg) {
66     void __user * argp = (void __user *)arg;
67     DEBUG("V3 IOCTL %d\n", ioctl);
68
69
70     switch (ioctl) {
71         case V3_CREATE_GUEST:{
72             int vm_minor = 0;
73             struct v3_guest_img user_image;
74             struct v3_guest * guest = kmalloc(sizeof(struct v3_guest), GFP_KERNEL);
75
76             if (IS_ERR(guest)) {
77                 ERROR("Palacios: Error allocating Kernel guest_image\n");
78                 return -EFAULT;
79             }
80
81             memset(guest, 0, sizeof(struct v3_guest));
82
83             INFO("Palacios: Creating V3 Guest...\n");
84
85             vm_minor = register_vm(guest);
86
87             if (vm_minor == -1) {
88                 ERROR("Palacios Error: Too many VMs are currently running\n");
89                 return -EFAULT;
90             }
91
92             guest->vm_dev = MKDEV(v3_major_num, vm_minor);
93
94             if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
95                 ERROR("Palacios Error: copy from user error getting guest image...\n");
96                 return -EFAULT;
97             }
98
99             guest->img_size = user_image.size;
100
101             DEBUG("Palacios: Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
102             guest->img = vmalloc(guest->img_size);
103
104             if (IS_ERR(guest->img)) {
105                 ERROR("Palacios Error: Could not allocate space for guest image\n");
106                 return -EFAULT;
107             }
108
109             if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
110                 ERROR("Palacios: Error loading guest data\n");
111                 return -EFAULT;
112             }      
113
114             strncpy(guest->name, user_image.name, 127);
115
116             INIT_LIST_HEAD(&(guest->exts));
117
118             if (create_palacios_vm(guest) == -1) {
119                 ERROR("Palacios: Error creating guest\n");
120                 return -EFAULT;
121             }
122
123             return vm_minor;
124             break;
125         }
126         case V3_FREE_GUEST: {
127             unsigned long vm_idx = arg;
128             struct v3_guest * guest = guest_map[vm_idx];
129
130             INFO("Freeing VM (%s) (%p)\n", guest->name, guest);
131
132             free_palacios_vm(guest);
133             guest_map[vm_idx] = NULL;
134             break;
135         }
136         case V3_ADD_MEMORY: {
137             struct v3_mem_region mem;
138             
139             memset(&mem, 0, sizeof(struct v3_mem_region));
140             
141             if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
142                 ERROR("copy from user error getting mem_region...\n");
143                 return -EFAULT;
144             }
145
146             DEBUG("Adding %llu pages to Palacios memory\n", mem.num_pages);
147
148             if (add_palacios_memory(mem.base_addr, mem.num_pages) == -1) {
149                 ERROR("Error adding memory to Palacios\n");
150                 return -EFAULT;
151             }
152
153             break;
154         }
155
156         default: 
157             ERROR("\tUnhandled\n");
158             return -EINVAL;
159     }
160
161     return 0;
162 }
163
164
165
166 static struct file_operations v3_ctrl_fops = {
167     .owner = THIS_MODULE,
168     .unlocked_ioctl = v3_dev_ioctl,
169     .compat_ioctl = v3_dev_ioctl,
170 };
171
172
173
174 static int __init v3_init(void) {
175     dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
176     int ret = 0;
177
178
179     palacios_init_mm();
180
181     // Initialize Palacios
182     palacios_vmm_init();
183
184
185     // initialize extensions
186     init_lnx_extensions();
187
188
189     v3_class = class_create(THIS_MODULE, "vms");
190     if (IS_ERR(v3_class)) {
191         ERROR("Failed to register V3 VM device class\n");
192         return PTR_ERR(v3_class);
193     }
194
195     INFO("intializing V3 Control device\n");
196
197     ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
198
199     if (ret < 0) {
200         ERROR("Error registering device region for V3 devices\n");
201         goto failure2;
202     }
203
204     v3_major_num = MAJOR(dev);
205
206     dev = MKDEV(v3_major_num, MAX_VMS + 1);
207
208     
209     DEBUG("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
210     cdev_init(&ctrl_dev, &v3_ctrl_fops);
211     ctrl_dev.owner = THIS_MODULE;
212     ctrl_dev.ops = &v3_ctrl_fops;
213     cdev_add(&ctrl_dev, dev, 1);
214     
215     device_create(v3_class, NULL, dev, NULL, "v3vee");
216
217     if (ret != 0) {
218         ERROR("Error adding v3 control device\n");
219         goto failure1;
220     }
221
222
223
224     return 0;
225
226  failure1:
227     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
228  failure2:
229     class_destroy(v3_class);
230
231     return ret;
232 }
233
234
235 static void __exit v3_exit(void) {
236     extern u32 pg_allocs;
237     extern u32 pg_frees;
238     extern u32 mallocs;
239     extern u32 frees;
240
241
242     // should probably try to stop any guests
243
244
245
246     dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
247
248     INFO("Removing V3 Control device\n");
249
250
251     palacios_vmm_exit();
252
253     DEBUG("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
254     DEBUG("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
255
256     unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
257
258     cdev_del(&ctrl_dev);
259
260     device_destroy(v3_class, dev);
261     class_destroy(v3_class);
262
263
264     deinit_lnx_extensions();
265
266     palacios_deinit_mm();
267
268     DEBUG("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
269 }
270
271
272
273 module_init(v3_init);
274 module_exit(v3_exit);
275
276
277
278 void * trace_malloc(size_t size, gfp_t flags) {
279     void * addr = NULL;
280
281     mod_allocs++;
282     addr = kmalloc(size, flags);
283
284     return addr;
285 }
286
287
288 void trace_free(const void * objp) {
289     mod_frees++;
290     kfree(objp);
291 }