X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=linux_module%2Flinux-exts.c;h=19160bbcb43d95e0d4b6b35f069b8a7cd0a0a643;hb=d240aa16811174593dc6e6ca9c796db05948c353;hp=d6409b8ad715f8f53970a8b98dd3dd3ac211e875;hpb=c94c9b19999f937b32627794c80e19c9be555822;p=palacios.git diff --git a/linux_module/linux-exts.c b/linux_module/linux-exts.c index d6409b8..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; @@ -17,6 +131,18 @@ struct vm_ext { }; +void * get_vm_ext_data(struct v3_guest * guest, char * ext_name) { + struct vm_ext * ext = NULL; + + list_for_each_entry(ext, &(guest->exts), node) { + if (strncmp(ext->impl->name, ext_name, strlen(ext->impl->name)) == 0) { + return ext->vm_data; + } + } + + return NULL; +} + int init_vm_extensions(struct v3_guest * guest) { extern struct linux_ext * __start__lnx_exts[]; @@ -29,15 +155,16 @@ int init_vm_extensions(struct v3_guest * guest) { if (ext_impl->guest_init == NULL) { // We can have global extensions without per guest state + ext_impl = __start__lnx_exts[++i]; continue; } - printk("Registering Linux Extension (%s)\n", ext_impl->name); + INFO("Registering Linux Extension (%s)\n", ext_impl->name); - ext = kmalloc(sizeof(struct vm_ext), GFP_KERNEL); + ext = palacios_alloc(sizeof(struct vm_ext)); if (!ext) { - printk("Error allocating VM extension (%s)\n", ext_impl->name); + WARNING("Error allocating VM extension (%s)\n", ext_impl->name); return -1; } @@ -54,6 +181,7 @@ int init_vm_extensions(struct v3_guest * guest) { } + int deinit_vm_extensions(struct v3_guest * guest) { struct vm_ext * ext = NULL; struct vm_ext * tmp = NULL; @@ -62,16 +190,17 @@ int deinit_vm_extensions(struct v3_guest * guest) { if (ext->impl->guest_deinit) { ext->impl->guest_deinit(guest, ext->vm_data); } else { - printk("WARNING: Extension %s, does not have a guest deinit function\n", ext->impl->name); + WARNING("WARNING: Extension %s, does not have a guest deinit function\n", ext->impl->name); } list_del(&(ext->node)); - kfree(ext); + palacios_free(ext); } return 0; } + int init_lnx_extensions( void ) { extern struct linux_ext * __start__lnx_exts[]; extern struct linux_ext * __stop__lnx_exts[]; @@ -80,10 +209,10 @@ int init_lnx_extensions( void ) { while (tmp_ext != __stop__lnx_exts[0]) { - printk("tmp_ext=%p\n", tmp_ext); + DEBUG("tmp_ext=%p\n", tmp_ext); if (tmp_ext->init != NULL) { - printk("Registering Linux Extension (%s)\n", tmp_ext->name); + INFO("Registering Linux Extension (%s)\n", tmp_ext->name); tmp_ext->init(); } @@ -101,11 +230,12 @@ int deinit_lnx_extensions( void ) { int i = 0; while (tmp_ext != __stop__lnx_exts[0]) { - printk("Cleaning up Linux Extension (%s)\n", tmp_ext->name); + INFO("Cleaning up Linux Extension (%s)\n", tmp_ext->name); + if (tmp_ext->deinit != NULL) { tmp_ext->deinit(); } else { - printk("WARNING: Extension %s does not have a global deinit function\n", tmp_ext->name); + WARNING("WARNING: Extension %s does not have a global deinit function\n", tmp_ext->name); } tmp_ext = __start__lnx_exts[++i]; @@ -113,3 +243,4 @@ int deinit_lnx_extensions( void ) { return 0; } +