X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=linux_module%2Flinux-exts.c;h=19160bbcb43d95e0d4b6b35f069b8a7cd0a0a643;hb=4e43946f01f687361197dc9571b7df02ae20de30;hp=089e67ea39d659dda447d366f47ab395d0eef1aa;hpb=07aa8f3c18a33af0961e7546980a63ab5f6fba4f;p=palacios.git diff --git a/linux_module/linux-exts.c b/linux_module/linux-exts.c index 089e67e..19160bb 100644 --- a/linux_module/linux-exts.c +++ b/linux_module/linux-exts.c @@ -1,15 +1,129 @@ - #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 *)))); + + +/* */ +/* Global controls */ +/* */ + +struct rb_root global_ctrls; + +static inline struct global_ctrl * __insert_global_ctrl(struct global_ctrl * ctrl) { + struct rb_node ** p = &(global_ctrls.rb_node); + struct rb_node * parent = NULL; + struct global_ctrl * tmp_ctrl = NULL; + + while (*p) { + parent = *p; + tmp_ctrl = rb_entry(parent, struct global_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_global_ctrl(unsigned int cmd, + int (*handler)(unsigned int cmd, unsigned long arg)) { + struct global_ctrl * ctrl = palacios_alloc_extended(sizeof(struct global_ctrl), GFP_KERNEL,-1); + + if (ctrl == NULL) { + printk("Error: Could not allocate global ctrl %d\n", cmd); + return -1; + } + + ctrl->cmd = cmd; + ctrl->handler = handler; + + if (__insert_global_ctrl(ctrl) != NULL) { + printk("Could not insert guest ctrl %d\n", cmd); + palacios_free(ctrl); + return -1; + } + + rb_insert_color(&(ctrl->tree_node), &(global_ctrls)); + + return 0; +} + + +static struct rb_node * find_match(unsigned int cmd) { + struct rb_node * n = global_ctrls.rb_node; + struct global_ctrl *ctrl; + + while (n) { + ctrl = rb_entry(n, struct global_ctrl, tree_node); + + if (cmd < ctrl->cmd) { + n = n->rb_left; + } else if (cmd > ctrl->cmd) { + n = n->rb_right; + } else { + return n; + } + } + + return NULL; +} + + +struct global_ctrl * get_global_ctrl(unsigned int cmd) { + struct rb_node *n = find_match(cmd); + + if (n) { + return rb_entry(n, struct global_ctrl, tree_node); + } else { + return NULL; + } +} + + +int remove_global_ctrl(unsigned int cmd) +{ + struct rb_node *n = find_match(cmd); + struct global_ctrl *c; + + if (!n) { + return -1; + } + + c = rb_entry(n, struct global_ctrl, tree_node); + + rb_erase(n,&global_ctrls); + + if (c) { + palacios_free(c); + } + + return 0; +} + + + + + +/* */ +/* VM Controls */ +/* */ + struct vm_ext { struct linux_ext * impl; void * vm_data; @@ -86,6 +200,7 @@ int deinit_vm_extensions(struct v3_guest * guest) { return 0; } + int init_lnx_extensions( void ) { extern struct linux_ext * __start__lnx_exts[]; extern struct linux_ext * __stop__lnx_exts[]; @@ -116,6 +231,7 @@ int deinit_lnx_extensions( void ) { while (tmp_ext != __stop__lnx_exts[0]) { INFO("Cleaning up Linux Extension (%s)\n", tmp_ext->name); + if (tmp_ext->deinit != NULL) { tmp_ext->deinit(); } else { @@ -127,3 +243,4 @@ int deinit_lnx_extensions( void ) { return 0; } +