2 Palacios main control interface
7 #include <linux/module.h>
8 #include <linux/errno.h>
9 #include <linux/percpu.h>
11 #include <linux/uaccess.h>
12 #include <linux/device.h>
13 #include <linux/cdev.h>
17 #include <linux/file.h>
18 #include <linux/spinlock.h>
19 #include <linux/kthread.h>
22 #include "palacios-mm.h"
23 #include "palacios-vm.h"
24 #include "palacios-serial.h"
25 #include "palacios-socket.h"
26 #include "palacios-vnet.h"
27 #include "palacios-packet.h"
29 #include "linux-exts.h"
31 #ifdef V3_CONFIG_EXT_INSPECTOR
32 #include "palacios-inspector.h"
35 #ifdef V3_CONFIG_KEYED_STREAMS
36 #include "palacios-keyed-stream.h"
40 MODULE_LICENSE("GPL");
46 static int v3_major_num = 0;
48 static u8 v3_minor_map[MAX_VMS / 8] = {[0 ... (MAX_VMS / 8) - 1] = 0};
51 struct class * v3_class = NULL;
52 static struct cdev ctrl_dev;
54 static int register_vm( void ) {
58 for (i = 0; i < sizeof(v3_minor_map); i++) {
59 if (v3_minor_map[i] != 0xff) {
60 for (j = 0; j < 8; j++) {
61 if (!(v3_minor_map[i] & (0x1 << j))) {
63 v3_minor_map[i] |= (0x1 << j);
83 static long v3_dev_ioctl(struct file * filp,
84 unsigned int ioctl, unsigned long arg) {
85 void __user * argp = (void __user *)arg;
86 printk("V3 IOCTL %d\n", ioctl);
92 struct v3_guest_img user_image;
93 struct v3_guest * guest = kmalloc(sizeof(struct v3_guest), GFP_KERNEL);
96 printk("Error allocating Kernel guest_image\n");
100 memset(guest, 0, sizeof(struct v3_guest));
102 printk("Starting V3 Guest...\n");
104 vm_minor = register_vm();
106 if (vm_minor == -1) {
107 printk("Too many VMs are currently running\n");
111 guest->vm_dev = MKDEV(v3_major_num, vm_minor);
113 if (copy_from_user(&user_image, argp, sizeof(struct v3_guest_img))) {
114 printk("copy from user error getting guest image...\n");
118 guest->img_size = user_image.size;
120 printk("Allocating kernel memory for guest image (%llu bytes)\n", user_image.size);
121 guest->img = vmalloc(guest->img_size);
123 if (IS_ERR(guest->img)) {
124 printk("Error: Could not allocate space for guest image\n");
128 if (copy_from_user(guest->img, user_image.guest_data, guest->img_size)) {
129 printk("Error loading guest data\n");
133 strncpy(guest->name, user_image.name, 127);
135 printk("Launching VM\n");
137 INIT_LIST_HEAD(&(guest->exts));
140 INIT_LIST_HEAD(&(guest->sockets));
141 #ifdef V3_CONFIG_HOST_DEVICE
142 INIT_LIST_HEAD(&(guest->hostdev.devs));
144 init_completion(&(guest->start_done));
145 init_completion(&(guest->thread_done));
148 struct task_struct * launch_thread = NULL;
149 // At some point we're going to want to allow the user to specify a CPU mask
150 // But for now, well just launch from the local core, and rely on the global cpu mask
153 launch_thread = kthread_create(start_palacios_vm, guest, guest->name);
155 if (IS_ERR(launch_thread)) {
157 printk("Palacios error creating launch thread for vm (%s)\n", guest->name);
161 kthread_bind(launch_thread, smp_processor_id());
164 wake_up_process(launch_thread);
167 wait_for_completion(&(guest->start_done));
169 return guest->vm_dev;
172 case V3_ADD_MEMORY: {
173 struct v3_mem_region mem;
175 memset(&mem, 0, sizeof(struct v3_mem_region));
177 if (copy_from_user(&mem, argp, sizeof(struct v3_mem_region))) {
178 printk("copy from user error getting mem_region...\n");
182 printk("Adding %llu pages to Palacios memory\n", mem.num_pages);
184 if (add_palacios_memory(mem.base_addr, mem.num_pages) == -1) {
185 printk("Error adding memory to Palacios\n");
193 printk("\tUnhandled\n");
202 static struct file_operations v3_ctrl_fops = {
203 .owner = THIS_MODULE,
204 .unlocked_ioctl = v3_dev_ioctl,
205 .compat_ioctl = v3_dev_ioctl,
210 static int __init v3_init(void) {
211 dev_t dev = MKDEV(0, 0); // We dynamicallly assign the major number
218 // Initialize Palacios
223 // initialize extensions
224 init_lnx_extensions();
227 v3_class = class_create(THIS_MODULE, "vms");
228 if (IS_ERR(v3_class)) {
229 printk("Failed to register V3 VM device class\n");
230 return PTR_ERR(v3_class);
233 printk("intializing V3 Control device\n");
235 ret = alloc_chrdev_region(&dev, 0, MAX_VMS + 1, "v3vee");
238 printk("Error registering device region for V3 devices\n");
242 v3_major_num = MAJOR(dev);
244 dev = MKDEV(v3_major_num, MAX_VMS + 1);
247 printk("Creating V3 Control device: Major %d, Minor %d\n", v3_major_num, MINOR(dev));
248 cdev_init(&ctrl_dev, &v3_ctrl_fops);
249 ctrl_dev.owner = THIS_MODULE;
250 ctrl_dev.ops = &v3_ctrl_fops;
251 cdev_add(&ctrl_dev, dev, 1);
253 device_create(v3_class, NULL, dev, NULL, "v3vee");
256 printk("Error adding v3 control device\n");
263 #ifdef V3_CONFIG_KEYED_STREAMS
264 palacios_init_keyed_streams();
267 #ifdef V3_CONFIG_GRAPHICS_CONSOLE
268 palacios_init_graphics_console();
271 #ifdef V3_CONFIG_EXT_INSPECTOR
272 palacios_init_inspector();
275 #ifdef V3_CONFIG_SOCKET
276 palacios_socket_init();
279 #ifdef V3_CONFIG_PACKET
280 palacios_init_packet(NULL);
283 #ifdef V3_CONFIG_VNET
284 palacios_vnet_init();
287 #ifdef V3_CONFIG_HOST_DEVICE
288 palacios_init_host_dev();
294 unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
296 class_destroy(v3_class);
302 static void __exit v3_exit(void) {
303 extern u32 pg_allocs;
309 // should probably try to stop any guests
313 dev_t dev = MKDEV(v3_major_num, MAX_VMS + 1);
315 printk("Removing V3 Control device\n");
320 printk("Palacios Mallocs = %d, Frees = %d\n", mallocs, frees);
321 printk("Palacios Page Allocs = %d, Page Frees = %d\n", pg_allocs, pg_frees);
323 unregister_chrdev_region(MKDEV(v3_major_num, 0), MAX_VMS + 1);
327 device_destroy(v3_class, dev);
328 class_destroy(v3_class);
331 deinit_lnx_extensions();
334 #ifdef V3_CONFIG_EXT_INSPECTOR
335 palacios_deinit_inspector();
340 #ifdef V3_CONFIG_SOCKET
341 palacios_socket_deinit();
344 #ifdef V3_CONFIG_PACKET
345 palacios_deinit_packet(NULL);
348 #ifdef V3_CONFIG_VNET
349 palacios_vnet_deinit();
352 palacios_deinit_mm();
354 printk("Palacios Module Mallocs = %d, Frees = %d\n", mod_allocs, mod_frees);
359 module_init(v3_init);
360 module_exit(v3_exit);
364 void * trace_malloc(size_t size, gfp_t flags) {
368 addr = kmalloc(size, flags);
374 void trace_free(const void * objp) {