From: Jack Lange Date: Wed, 8 Jun 2011 17:53:44 +0000 (-0500) Subject: added initial extension framework X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=fed3449f4fd2fab7f27a17e0970e954bd2d69abc;p=palacios.git added initial extension framework --- diff --git a/linux_module/Makefile b/linux_module/Makefile index b3bd558..e3cb52a 100644 --- a/linux_module/Makefile +++ b/linux_module/Makefile @@ -14,8 +14,9 @@ v3vee-objs := palacios.o \ palacios-vm.o \ palacios-mm.o \ palacios-queue.o \ - palacios-hashtable.o - + palacios-hashtable.o \ + linux-exts.o + ifdef V3_CONFIG_CONSOLE v3vee-objs += palacios-console.o endif diff --git a/linux_module/ld.cmd b/linux_module/ld.cmd index 7dd7747..fd97c26 100644 --- a/linux_module/ld.cmd +++ b/linux_module/ld.cmd @@ -22,5 +22,11 @@ SECTIONS __stop__v3_extensions = .; } + _lnx_exts : + { + __start__lnx_exts = .; + *(_lnx_exts); + __stop__lnx_exts = .; + } } diff --git a/linux_module/linux-exts.c b/linux_module/linux-exts.c new file mode 100644 index 0000000..f4afafd --- /dev/null +++ b/linux_module/linux-exts.c @@ -0,0 +1,62 @@ + +#include "linux-exts.h" + +/* + * This is a place holder to ensure that the _lnx_exts section gets created by gcc + */ +static struct {} null_ext __attribute__((__used__)) \ + __attribute__((unused, __section__ ("_lnx_exts"), \ + aligned(sizeof(void *)))); + + + + +int init_vm_extensions(struct v3_guest * guest) { + extern struct linux_ext * __start__lnx_exts; + extern struct linux_ext * __stop__lnx_exts; + struct linux_ext * tmp_ext = __start__lnx_exts; + int i = 0; + + while (tmp_ext != __stop__lnx_exts) { + printk("Registering Linux Extension (%s)\n", tmp_ext->name); + tmp_ext->init(); + + tmp_ext = &(__start__lnx_exts[++i]); + } + + return 0; + +} + +int init_lnx_extensions( void ) { + extern struct linux_ext * __start__lnx_exts; + extern struct linux_ext * __stop__lnx_exts; + struct linux_ext * tmp_ext = __start__lnx_exts; + int i = 0; + + while (tmp_ext != __stop__lnx_exts) { + printk("Registering Linux Extension (%s)\n", tmp_ext->name); + tmp_ext->init(); + + tmp_ext = &(__start__lnx_exts[++i]); + } + + return 0; +} + + +int deinit_lnx_extensions( void ) { + extern struct linux_ext * __start__lnx_exts; + extern struct linux_ext * __stop__lnx_exts; + struct linux_ext * tmp_ext = __start__lnx_exts; + int i = 0; + + while (tmp_ext != __stop__lnx_exts) { + printk("Cleaning up Linux Extension (%s)\n", tmp_ext->name); + tmp_ext->deinit(); + + tmp_ext = &(__start__lnx_exts[++i]); + } + + return 0; +} diff --git a/linux_module/linux-exts.h b/linux_module/linux-exts.h new file mode 100644 index 0000000..72e4800 --- /dev/null +++ b/linux_module/linux-exts.h @@ -0,0 +1,29 @@ +#include "palacios.h" + + +int add_mod_cmd(struct v3_guest * guest, unsigned int cmd, + int (*handler)(struct v3_guest * guest, + unsigned int cmd, unsigned long arg)); + + +struct linux_ext { + char * name; + int (*init)( void ); + int (*deinit)( void ); + int (*guest_init)(struct v3_guest * guest, void ** priv_data); + int (*guest_deinit)(struct v3_guest * guest, void * priv_data); +} __attribute__((packed)); + + + +int init_lnx_extensions( void ); +int deinit_lnx_extensions( void ); + + + +#define register_extension(ext) \ + static struct linux_ext * _lnx_ext \ + __attribute__((used)) \ + __attribute__((unused, __section("_lnx_exts"), \ + aligned(sizeof(void *)))) \ + = ext; diff --git a/linux_module/palacios-vm.c b/linux_module/palacios-vm.c index dd422c3..a434f17 100644 --- a/linux_module/palacios-vm.c +++ b/linux_module/palacios-vm.c @@ -16,13 +16,101 @@ #include #include #include - +#include #include #include "palacios.h" #include "palacios-vm.h" + +struct vm_ctrl { + unsigned int cmd; + + int (*handler)(struct v3_guest * guest, + unsigned int cmd, unsigned long arg, + void * priv_data); + + void * priv_data; + + struct rb_node tree_node; +}; + + +static inline struct vm_ctrl * __insert_ctrl(struct v3_guest * vm, + struct vm_ctrl * ctrl) { + struct rb_node ** p = &(vm->vm_ctrls.rb_node); + struct rb_node * parent = NULL; + struct vm_ctrl * tmp_ctrl = NULL; + + while (*p) { + parent = *p; + tmp_ctrl = rb_entry(parent, struct vm_ctrl, tree_node); + + if (ctrl->cmd < tmp_ctrl->cmd) { + p = &(*p)->rb_left; + } else if (ctrl->cmd > tmp_ctrl->cmd) { + p = &(*p)->rb_right; + } else { + return tmp_ctrl; + } + } + + rb_link_node(&(ctrl->tree_node), parent, p); + + return NULL; +} + + + +int add_guest_ctrl(struct v3_guest * guest, unsigned int cmd, + int (*handler)(struct v3_guest * guest, + unsigned int cmd, unsigned long arg, + void * priv_data), + void * priv_data) { + struct vm_ctrl * ctrl = kmalloc(sizeof(struct vm_ctrl), GFP_KERNEL); + + if (ctrl == NULL) { + printk("Error: Could not allocate vm ctrl %d\n", cmd); + return -1; + } + + ctrl->cmd = cmd; + ctrl->handler = handler; + ctrl->priv_data = priv_data; + + if (__insert_ctrl(guest, ctrl) != NULL) { + printk("Could not insert guest ctrl %d\n", cmd); + kfree(ctrl); + return -1; + } + + rb_insert_color(&(ctrl->tree_node), &(guest->vm_ctrls)); + + return 0; +} + + +static struct vm_ctrl * get_ctrl(struct v3_guest * guest, unsigned int cmd) { + struct rb_node * n = guest->vm_ctrls.rb_node; + struct vm_ctrl * ctrl = NULL; + + while (n) { + ctrl = rb_entry(n, struct vm_ctrl, tree_node); + + if (cmd < ctrl->cmd) { + n = n->rb_left; + } else if (cmd > ctrl->cmd) { + n = n->rb_right; + } else { + return ctrl; + } + } + + return NULL; +} + + #ifdef V3_CONFIG_STREAM #include "palacios-stream.h" #endif @@ -123,9 +211,17 @@ static long v3_vm_ioctl(struct file * filp, break; - default: - printk("\tUnhandled\n"); + default: { + struct vm_ctrl * ctrl = get_ctrl(guest, ioctl); + + if (ctrl) { + return ctrl->handler(guest, ioctl, arg, ctrl->priv_data); + } + + + printk("\tUnhandled ctrl cmd: %d\n", ioctl); return -EINVAL; + } } return 0; @@ -184,6 +280,11 @@ int start_palacios_vm(void * arg) { return -1; } + // init linux extensions +#ifdef V3_CONFIG_EXT_INSPECTOR + inspect_vm(guest); +#endif + printk("Creating VM device: Major %d, Minor %d\n", MAJOR(guest->vm_dev), MINOR(guest->vm_dev)); cdev_init(&(guest->cdev), &v3_vm_fops); @@ -215,9 +316,7 @@ int start_palacios_vm(void * arg) { printk("palacios: launching vm\n"); -#ifdef V3_CONFIG_EXT_INSPECTOR - inspect_vm(guest); -#endif + if (v3_start_vm(guest->v3_ctx, 0xffffffff) < 0) { diff --git a/linux_module/palacios-vm.h b/linux_module/palacios-vm.h index e0c5f74..3423d34 100644 --- a/linux_module/palacios-vm.h +++ b/linux_module/palacios-vm.h @@ -11,4 +11,13 @@ int start_palacios_vm(void * arg); int stop_palacios_vm(struct v3_guest * guest); + +int add_guest_ctrl(struct v3_guest * guest, unsigned int cmd, + int (*handler)(struct v3_guest * guest, + unsigned int cmd, unsigned long arg, + void * priv_data), + void * priv_data); + + + #endif diff --git a/linux_module/palacios.h b/linux_module/palacios.h index 9fe9c29..8923361 100644 --- a/linux_module/palacios.h +++ b/linux_module/palacios.h @@ -64,6 +64,10 @@ struct v3_guest { char name[128]; + + struct rb_root vm_ctrls; + + struct list_head files; struct list_head streams; struct list_head sockets;