X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_dev_mgr.c;h=8f9b3a25f4733ca78ec82295a64eb3577b6aa077;hp=81f053c3b0e0d3a54cbe6b848728d8105084f541;hb=f7cc83b3bae64c853f5b7b63e2830b1ea92dfed9;hpb=7841dc573457c334a0f3b6e9186d26b1776c400f diff --git a/palacios/src/palacios/vmm_dev_mgr.c b/palacios/src/palacios/vmm_dev_mgr.c index 81f053c..8f9b3a2 100644 --- a/palacios/src/palacios/vmm_dev_mgr.c +++ b/palacios/src/palacios/vmm_dev_mgr.c @@ -1,8 +1,9 @@ - -#include +#include #include #include #include +#include + extern struct vmm_os_hooks *os_hooks; @@ -10,212 +11,194 @@ extern struct vmm_os_hooks *os_hooks; #define NULL 0 #endif -int dev_mgr_init(struct vmm_dev_mgr *mgr, struct guest_info *vm) -{ - mgr->vm=vm; - mgr->dev_list=NULL; - mgr->num_devices=0; +int dev_mgr_init(struct vmm_dev_mgr * mgr) { + + INIT_LIST_HEAD(&(mgr->dev_list)); + mgr->num_devs = 0; + + INIT_LIST_HEAD(&(mgr->io_hooks)); + mgr->num_io_hooks = 0; + return 0; } -int dev_mgr_deinit(struct vmm_dev_mgr *mgr) -{ - int rc; +int dev_mgr_deinit(struct vmm_dev_mgr * mgr) { + struct vm_device * dev; - while (mgr->dev_list) { - rc=dev_mgr_detach_device(mgr->vm,mgr->dev_list); - if (rc) { - // Bad bad bad - } + list_for_each_entry(dev, &(mgr->dev_list), dev_link) { + unattach_device(dev); + free_device(dev); } + return 0; } -int dev_mgr_attach_device(struct guest_info *vm, struct vm_device *device) -{ - struct vmm_dev_mgr *mgr= &(vm->dev_mgr); - - if (device->io_hooks || device->mem_hooks) { - return -1; - } - device->next = mgr->dev_list; - device->prev = 0; - if (device->next) { - device->next->prev = device; - } - mgr->dev_list = device; - - device->vm=vm; + + +int dev_mgr_add_device(struct vmm_dev_mgr * mgr, struct vm_device * dev) { + list_add(&(dev->dev_link), &(mgr->dev_list)); + mgr->num_devs++; return 0; } -int dev_mgr_detach_device(struct guest_info *vm, struct vm_device *device) -{ - if (device->prev==0) { - vm->dev_mgr.dev_list = device->next; - } else { - device->prev->next = device->next; - } - if (device->next) { - device->next->prev=device->prev; - } - - // avoid interrupts here +int dev_mgr_remove_device(struct vmm_dev_mgr * mgr, struct vm_device * dev) { + list_del(&(dev->dev_link)); + mgr->num_devs--; + + return 0; +} - device->deinit_device(device); - device->vm=NULL; + +/* IO HOOKS */ +int dev_mgr_add_io_hook(struct vmm_dev_mgr * mgr, struct dev_io_hook * hook) { + list_add(&(hook->mgr_list), &(mgr->io_hooks)); + mgr->num_io_hooks++; return 0; } -#define INSERT_FRONT(listhead,item) \ - do { \ - if (!(listhead)) { \ - (listhead)=(item); \ - (item)->prev=NULL; \ - (item)->next=NULL; \ - } else { \ - (item)->prev=NULL; \ - (item)->next=(listhead); \ - if ((listhead)->next) { \ - (listhead)->next->prev=(item); \ - } \ - (listhead)=(item); \ - } \ - } while (0) - -#define DELETE(listhead,item) \ - do { \ - if ((item)->prev) { \ - (item)->prev->next=(item)->next; \ - } else { \ - (listhead)=(item)->next; \ - } \ - if ((item)->next) { \ - (item)->next->prev=(item)->prev; \ - } \ - } while (0) - +int dev_mgr_remove_io_hook(struct vmm_dev_mgr * mgr, struct dev_io_hook * hook) { + list_del(&(hook->mgr_list)); + mgr->num_io_hooks--; - + return 0; +} -int dev_mgr_hook_io(struct guest_info *vm, - struct vm_device *device, - ushort_t portno, - enum access_control control, - enum access_type atype) -{ - struct vm_device_io_hook *hook = os_hooks->malloc(sizeof(struct vm_device_io_hook)); + +int dev_add_io_hook(struct vm_device * dev, struct dev_io_hook * hook) { + list_add(&(hook->dev_list), &(dev->io_hooks)); + dev->num_io_hooks++; + return 0; +} + + +int dev_remove_io_hook(struct vm_device * dev, struct dev_io_hook * hook) { + list_del(&(hook->dev_list)); + dev->num_io_hooks--; + + return 0; +} + + + + + +struct dev_io_hook * dev_mgr_find_io_hook(struct vmm_dev_mgr * mgr, ushort_t port) { + struct dev_io_hook * tmp; + + list_for_each_entry(tmp, &(mgr->io_hooks), mgr_list) { + if (tmp->port == port) { + return tmp; + } + } + return NULL; +} + +struct dev_io_hook * dev_find_io_hook(struct vm_device * dev, ushort_t port) { + struct dev_io_hook * tmp; + + list_for_each_entry(tmp, &(dev->io_hooks), dev_list) { + if (tmp->port == port) { + return tmp; + } + } + return NULL; +} + + + + +int dev_hook_io(struct vm_device *dev, + ushort_t port, + int (*read)(ushort_t port, void * dst, uint_t length, struct vm_device * dev), + int (*write)(ushort_t port, void * src, uint_t length, struct vm_device * dev)) { + + struct dev_io_hook *hook = os_hooks->malloc(sizeof(struct dev_io_hook)); if (!hook) { return -1; } - int (*read)(ushort_t, void *, uint_t, void *) = NULL; - int (*write)(ushort_t, void *, uint_t, void *) = NULL; - - switch (control) { - case DEVICE_EMULATED: - switch (atype) { - case DEVICE_READ: - read = (int (*)(ushort_t, void *,uint_t, void *)) (device->read_io_port); - break; - case DEVICE_WRITE: - write = (int (*)(ushort_t, void *, uint_t, void *)) (device->write_io_port); - break; - case DEVICE_READWRITE: - read = (int (*)(ushort_t, void *, uint_t, void *)) (device->read_io_port); - write = (int (*)(ushort_t, void *, uint_t, void *)) (device->write_io_port); - break; - } - break; - case DEVICE_PASSTHROUGH: - read=write=NULL; - break; - } + + if (hook_io_port(&(dev->vm->io_map), port, + (int (*)(ushort_t, void *, uint_t, void *))read, + (int (*)(ushort_t, void *, uint_t, void *))write, + (void *)dev) == 0) { + + hook->dev = dev; + hook->port = port; + hook->read = read; + hook->write = write; - hook_io_port(&(vm->io_map), - portno, - read, - write, - device); - - hook->control=control; - hook->atype=atype; - hook->guest_port = portno; - - INSERT_FRONT(device->io_hooks,hook); - + dev_mgr_add_io_hook(&(dev->vm->dev_mgr), hook); + dev_add_io_hook(dev, hook); + } else { + + return -1; + } + return 0; } -int dev_mgr_unhook_io(struct guest_info *vm, - struct vm_device *device, - ushort_t portno) -{ - struct vm_device_io_hook *hook = device->io_hooks; +int dev_unhook_io(struct vm_device *dev, + ushort_t port) { - while (hook) { - if (hook->guest_port==portno) { - DELETE(device->io_hooks,hook); - break; - } - } + struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr); + struct dev_io_hook * hook = dev_mgr_find_io_hook(mgr, port); if (!hook) { - // Very bad - unhooking something that doesn't exist! return -1; } - return unhook_io_port(&(vm->io_map), - portno); + dev_mgr_remove_io_hook(mgr, hook); + dev_remove_io_hook(dev, hook); + + return unhook_io_port(&(dev->vm->io_map), port); +} + + +int attach_device(struct guest_info * vm, struct vm_device * dev) { + struct vmm_dev_mgr *mgr= &(vm->dev_mgr); + + dev->vm = vm; + dev_mgr_add_device(mgr, dev); + dev->ops->init(dev); + + return 0; } +int unattach_device(struct vm_device * dev) { + struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr); + + dev->ops->deinit(dev); + dev_mgr_remove_device(mgr, dev); + dev->vm = NULL; + + return 0; +} + + + int dev_mgr_hook_mem(struct guest_info *vm, struct vm_device *device, - void *guest_physical_address_start, - void *guest_physical_address_end, - enum access_control control, - enum access_type atype) + void *start, + void *end) { - struct vm_device_mem_hook *hook = os_hooks->malloc(sizeof(struct vm_device_mem_hook)); - + struct dev_mem_hook * hook = (struct dev_mem_hook*)V3_Malloc(sizeof(struct dev_mem_hook)); + // V3_Malloc(struct dev_mem_hook *, hook,sizeof(struct dev_mem_hook)); + if (!hook) { return -1; } - int (*read)(ushort_t, void *, uint_t, void *) = NULL; - int (*write)(ushort_t, void *, uint_t, void *) = NULL; - - switch (control) { - case DEVICE_EMULATED: - switch (atype) { - case DEVICE_READ: - read = (int (*)(ushort_t, void *, uint_t, void *))(device->read_mapped_memory); - break; - case DEVICE_WRITE: - write = (int (*)(ushort_t, void *, uint_t, void *))(device->write_mapped_memory); - break; - case DEVICE_READWRITE: - read = (int (*)(ushort_t, void *, uint_t, void *))(device->read_mapped_memory); - write = (int (*)(ushort_t, void *, uint_t, void *))(device->write_mapped_memory); - break; - } - break; - case DEVICE_PASSTHROUGH: - read=write=NULL; - break; - } - - /* not implemented yet hook_memory(vm->mem_map, guest_physical_address_start, @@ -228,39 +211,27 @@ int dev_mgr_hook_mem(struct guest_info *vm, return -1; // remove when hook_memory works - hook->control=control; - hook->atype=atype; - hook->guest_physical_start = guest_physical_address_start; - hook->guest_physical_end = guest_physical_address_end; - - INSERT_FRONT(device->mem_hooks,hook); + hook->addr_start = start; + hook->addr_end = end; return 0; } -int dev_mgr_unhook_mem(struct guest_info *vm, - struct vm_device *device, - void *guest_physical_start, - void *guest_physical_end) -{ - struct vm_device_mem_hook *hook = device->mem_hooks; - - while (hook) { - if (hook->guest_physical_start==guest_physical_start && - hook->guest_physical_end==guest_physical_end) { - DELETE(device->mem_hooks,hook); - break; - } - } - +int dev_mgr_unhook_mem(struct vm_device *dev, + addr_t start, + addr_t end) { + /* + struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr); + struct dev_mem_hook *hook = dev_mgr_find_mem_hook(mgr, start, end); + if (!hook) { // Very bad - unhooking something that doesn't exist! return -1; } - + */ /* not implemented yet return unhook_mem_port(vm->mem_map, @@ -272,24 +243,39 @@ int dev_mgr_unhook_mem(struct guest_info *vm, } -int dev_mgr_unhook_device(struct guest_info *vm, - struct vm_device *device) -{ - struct vm_device_io_hook *iohook=device->io_hooks; - struct vm_device_mem_hook *memhook=device->mem_hooks; - while (iohook) { - if (dev_mgr_unhook_io(vm,device,iohook->guest_port)) { - return -1; - } - } - while (memhook) { - if (dev_mgr_unhook_mem(vm,device,memhook->guest_physical_start, memhook->guest_physical_end)) { - return -1; - } +void PrintDebugDevMgr(struct vmm_dev_mgr * mgr) { + struct vm_device * dev; + PrintDebug("%d devices registered with manager\n", mgr->num_devs); + + list_for_each_entry(dev, &(mgr->dev_list), dev_link) { + PrintDebugDev(dev); + PrintDebug("next..\n"); } - return 0; + return; +} + + +void PrintDebugDev(struct vm_device * dev) { + + PrintDebug("Device: %s\n", dev->name); + PrintDebugDevIO(dev); } +void PrintDebugDevMgrIO(struct vmm_dev_mgr * mgr) { + +} + +void PrintDebugDevIO(struct vm_device * dev) { + struct dev_io_hook * hook; + + PrintDebug("IO Hooks(%d) for Device: %s\n", dev->num_io_hooks, dev->name); + + list_for_each_entry(hook, &(dev->io_hooks), dev_list) { + PrintDebug("\tPort: 0x%x (read=0x%x), (write=0x%x)\n", hook->port, hook->read, hook->write); + } + + return; +}