X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_dev_mgr.c;h=47834926cedfaf0cc5578e0dddc434653582fead;hb=a0d3be5212e7a5053ba213ce7bd26c7124cf01e3;hp=c7a8f957fc6e108ca20c58e1a4541f85391784cd;hpb=123a1ba27ea09c8fa77a1b36ce625b43d7c48b14;p=palacios.git diff --git a/palacios/src/palacios/vmm_dev_mgr.c b/palacios/src/palacios/vmm_dev_mgr.c index c7a8f95..4783492 100644 --- a/palacios/src/palacios/vmm_dev_mgr.c +++ b/palacios/src/palacios/vmm_dev_mgr.c @@ -86,8 +86,8 @@ int v3_init_devices() { } -int v3_init_dev_mgr(struct guest_info * info) { - struct vmm_dev_mgr * mgr = &(info->dev_mgr); +int v3_init_dev_mgr(struct v3_vm_info * vm) { + struct vmm_dev_mgr * mgr = &(vm->dev_mgr); INIT_LIST_HEAD(&(mgr->dev_list)); mgr->num_devs = 0; @@ -96,33 +96,41 @@ int v3_init_dev_mgr(struct guest_info * info) { INIT_LIST_HEAD(&(mgr->blk_list)); INIT_LIST_HEAD(&(mgr->net_list)); + INIT_LIST_HEAD(&(mgr->char_list)); INIT_LIST_HEAD(&(mgr->console_list)); mgr->blk_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn); mgr->net_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn); + mgr->char_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn); mgr->console_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn); return 0; } -int v3_dev_mgr_deinit(struct guest_info * info) { +int v3_dev_mgr_deinit(struct v3_vm_info * vm) { struct vm_device * dev; - struct vmm_dev_mgr * mgr = &(info->dev_mgr); + struct vmm_dev_mgr * mgr = &(vm->dev_mgr); struct vm_device * tmp; list_for_each_entry_safe(dev, tmp, &(mgr->dev_list), dev_link) { v3_detach_device(dev); - v3_free_device(dev); } + v3_free_htable(mgr->blk_table, 0, 0); + v3_free_htable(mgr->net_table, 0, 0); + v3_free_htable(mgr->char_table, 0, 0); + v3_free_htable(mgr->console_table, 0, 0); + + v3_free_htable(mgr->dev_table, 0, 0); + return 0; } -int v3_create_device(struct guest_info * info, const char * dev_name, v3_cfg_tree_t * cfg) { - int (*dev_init)(struct guest_info * info, void * cfg_data); +int v3_create_device(struct v3_vm_info * vm, const char * dev_name, v3_cfg_tree_t * cfg) { + int (*dev_init)(struct v3_vm_info * vm, void * cfg_data); dev_init = (void *)v3_htable_search(master_dev_table, (addr_t)dev_name); @@ -132,7 +140,7 @@ int v3_create_device(struct guest_info * info, const char * dev_name, v3_cfg_tre } - if (dev_init(info, cfg) == -1) { + if (dev_init(vm, cfg) == -1) { PrintError("Could not initialize Device %s\n", dev_name); return -1; } @@ -147,8 +155,8 @@ void v3_free_device(struct vm_device * dev) { -struct vm_device * v3_find_dev(struct guest_info * info, const char * dev_name) { - struct vmm_dev_mgr * mgr = &(info->dev_mgr); +struct vm_device * v3_find_dev(struct v3_vm_info * vm, const char * dev_name) { + struct vmm_dev_mgr * mgr = &(vm->dev_mgr); if (!dev_name) { return NULL; @@ -162,19 +170,58 @@ struct vm_device * v3_find_dev(struct guest_info * info, const char * dev_name) /* The remaining functions are called by the devices themselves */ /****************************************************************/ +struct dev_io_hook { + uint16_t port; + + struct list_head node; + +}; + /* IO HOOKS */ int v3_dev_hook_io(struct vm_device * dev, uint16_t port, - int (*read)(uint16_t port, void * dst, uint_t length, struct vm_device * dev), - int (*write)(uint16_t port, void * src, uint_t length, struct vm_device * dev)) { - return v3_hook_io_port(dev->vm, port, - (int (*)(ushort_t, void *, uint_t, void *))read, - (int (*)(ushort_t, void *, uint_t, void *))write, - (void *)dev); + int (*read)(struct guest_info * core, uint16_t port, void * dst, uint_t length, void * priv_data), + int (*write)(struct guest_info * core, uint16_t port, void * src, uint_t length, void * priv_data)) { + struct dev_io_hook * io_hook = NULL; + int ret = 0; + + ret = v3_hook_io_port(dev->vm, port, + (int (*)(struct guest_info * core, ushort_t, void *, uint_t, void *))read, + (int (*)(struct guest_info * core, ushort_t, void *, uint_t, void *))write, + (void *)dev->private_data); + + if (ret == -1) { + return -1; + } + + io_hook = V3_Malloc(sizeof(struct dev_io_hook)); + + if (io_hook == NULL) { + PrintError("Could not allocate io hook dev state\n"); + return -1; + } + + io_hook->port = port; + list_add(&(io_hook->node), &(dev->io_hooks)); + + return 0; } int v3_dev_unhook_io(struct vm_device * dev, uint16_t port) { - return v3_unhook_io_port(dev->vm, port); + struct dev_io_hook * io_hook = NULL; + struct dev_io_hook * tmp; + + list_for_each_entry_safe(io_hook, tmp, &(dev->io_hooks), node) { + if (io_hook->port == port) { + + list_del(&(io_hook->node)); + V3_Free(io_hook); + + return v3_unhook_io_port(dev->vm, port); + } + } + + return -1; } @@ -182,13 +229,18 @@ int v3_dev_unhook_io(struct vm_device * dev, uint16_t port) { int v3_detach_device(struct vm_device * dev) { struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr); - dev->ops->free(dev); + if (dev->ops->free) { + dev->ops->free(dev); + } else { + PrintError("Error: %s free() not implemented\n", dev->name); + } list_del(&(dev->dev_link)); mgr->num_devs--; dev->vm = NULL; + v3_free_device(dev); return -1; } @@ -200,6 +252,8 @@ struct vm_device * v3_allocate_device(char * name, dev = (struct vm_device*)V3_Malloc(sizeof(struct vm_device)); + INIT_LIST_HEAD(&(dev->io_hooks)); + strncpy(dev->name, name, 32); dev->ops = ops; dev->private_data = private_data; @@ -210,7 +264,7 @@ struct vm_device * v3_allocate_device(char * name, } -int v3_attach_device(struct guest_info * vm, struct vm_device * dev ) { +int v3_attach_device(struct v3_vm_info * vm, struct vm_device * dev ) { struct vmm_dev_mgr * mgr = &(vm->dev_mgr); dev->vm = vm; @@ -226,8 +280,8 @@ int v3_attach_device(struct guest_info * vm, struct vm_device * dev ) { -void v3_print_dev_mgr(struct guest_info * info) { - struct vmm_dev_mgr * mgr = &(info->dev_mgr); +void v3_print_dev_mgr(struct v3_vm_info * vm) { + struct vmm_dev_mgr * mgr = &(vm->dev_mgr); struct vm_device * dev; V3_Print("%d devices registered with manager\n", mgr->num_devs); @@ -243,7 +297,7 @@ void v3_print_dev_mgr(struct guest_info * info) { struct blk_frontend { - int (*connect)(struct guest_info * info, + int (*connect)(struct v3_vm_info * vm, void * frontend_data, struct v3_dev_blk_ops * ops, v3_cfg_tree_t * cfg, @@ -257,9 +311,9 @@ struct blk_frontend { -int v3_dev_add_blk_frontend(struct guest_info * info, +int v3_dev_add_blk_frontend(struct v3_vm_info * vm, char * name, - int (*connect)(struct guest_info * info, + int (*connect)(struct v3_vm_info * vm, void * frontend_data, struct v3_dev_blk_ops * ops, v3_cfg_tree_t * cfg, @@ -274,13 +328,13 @@ int v3_dev_add_blk_frontend(struct guest_info * info, frontend->connect = connect; frontend->priv_data = priv_data; - list_add(&(frontend->blk_node), &(info->dev_mgr.blk_list)); - v3_htable_insert(info->dev_mgr.blk_table, (addr_t)(name), (addr_t)frontend); + list_add(&(frontend->blk_node), &(vm->dev_mgr.blk_list)); + v3_htable_insert(vm->dev_mgr.blk_table, (addr_t)(name), (addr_t)frontend); return 0; } -int v3_dev_connect_blk(struct guest_info * info, +int v3_dev_connect_blk(struct v3_vm_info * vm, char * frontend_name, struct v3_dev_blk_ops * ops, v3_cfg_tree_t * cfg, @@ -288,7 +342,7 @@ int v3_dev_connect_blk(struct guest_info * info, struct blk_frontend * frontend = NULL; - frontend = (struct blk_frontend *)v3_htable_search(info->dev_mgr.blk_table, + frontend = (struct blk_frontend *)v3_htable_search(vm->dev_mgr.blk_table, (addr_t)frontend_name); if (frontend == NULL) { @@ -296,10 +350,142 @@ int v3_dev_connect_blk(struct guest_info * info, return 0; } - if (frontend->connect(info, frontend->priv_data, ops, cfg, private_data) == -1) { + if (frontend->connect(vm, frontend->priv_data, ops, cfg, private_data) == -1) { PrintError("Error connecting to block frontend %s\n", frontend_name); return -1; } return 0; } + + + +struct net_frontend { + int (*connect)(struct v3_vm_info * vm, + void * frontend_data, + struct v3_dev_net_ops * ops, + v3_cfg_tree_t * cfg, + void * priv_data); + + + struct list_head net_node; + + void * priv_data; +}; + + +int v3_dev_add_net_frontend(struct v3_vm_info * vm, + char * name, + int (*connect)(struct v3_vm_info * vm, + void * frontend_data, + struct v3_dev_net_ops * ops, + v3_cfg_tree_t * cfg, + void * private_data), + void * priv_data) +{ + struct net_frontend * frontend = NULL; + + frontend = (struct net_frontend *)V3_Malloc(sizeof(struct net_frontend)); + memset(frontend, 0, sizeof(struct net_frontend)); + + frontend->connect = connect; + frontend->priv_data = priv_data; + + list_add(&(frontend->net_node), &(vm->dev_mgr.net_list)); + v3_htable_insert(vm->dev_mgr.net_table, (addr_t)(name), (addr_t)frontend); + + return 0; +} + + +int v3_dev_connect_net(struct v3_vm_info * vm, + char * frontend_name, + struct v3_dev_net_ops * ops, + v3_cfg_tree_t * cfg, + void * private_data) +{ + struct net_frontend * frontend = NULL; + + frontend = (struct net_frontend *)v3_htable_search(vm->dev_mgr.net_table, + (addr_t)frontend_name); + + if (frontend == NULL) { + PrintError("Could not find frontend net device %s\n", frontend_name); + return 0; + } + + if (frontend->connect(vm, frontend->priv_data, ops, cfg, private_data) == -1) { + PrintError("Error connecting to net frontend %s\n", frontend_name); + return -1; + } + + return 0; +} + + +struct char_frontend { + int (*connect)(struct v3_vm_info * vm, + void * frontend_data, + struct v3_dev_char_ops * ops, + v3_cfg_tree_t * cfg, + void * priv_data, + void ** push_fn_arg); + + + struct list_head char_node; + + void * priv_data; +}; + + + +int v3_dev_add_char_frontend(struct v3_vm_info * vm, + char * name, + int (*connect)(struct v3_vm_info * vm, + void * frontend_data, + struct v3_dev_char_ops * ops, + v3_cfg_tree_t * cfg, + void * private_data, + void ** push_fn_arg), + void * priv_data) +{ + struct char_frontend * frontend = NULL; + + frontend = (struct char_frontend *)V3_Malloc(sizeof(struct char_frontend)); + memset(frontend, 0, sizeof(struct char_frontend)); + + frontend->connect = connect; + frontend->priv_data = priv_data; + + list_add(&(frontend->char_node), &(vm->dev_mgr.char_list)); + v3_htable_insert(vm->dev_mgr.char_table, (addr_t)(name), (addr_t)frontend); + + return 0; +} + + +int v3_dev_connect_char(struct v3_vm_info * vm, + char * frontend_name, + struct v3_dev_char_ops * ops, + v3_cfg_tree_t * cfg, + void * private_data, + void ** push_fn_arg) +{ + struct char_frontend * frontend = NULL; + + frontend = (struct char_frontend *)v3_htable_search(vm->dev_mgr.char_table, + (addr_t)frontend_name); + + if (frontend == NULL) { + PrintError("Could not find frontend char device %s\n", frontend_name); + return 0; + } + + if (frontend->connect(vm, frontend->priv_data, ops, cfg, private_data, push_fn_arg) == -1) { + PrintError("Error connecting to char frontend %s\n", frontend_name); + return -1; + } + + return 0; +} +