X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_dev_mgr.c;h=615c8ecbc12c44d34a866a5ec111d1c807064980;hb=570ad6257ed18fbbc840c17a600f12f2dc44b010;hp=81f053c3b0e0d3a54cbe6b848728d8105084f541;hpb=7841dc573457c334a0f3b6e9186d26b1776c400f;p=palacios.git diff --git a/palacios/src/palacios/vmm_dev_mgr.c b/palacios/src/palacios/vmm_dev_mgr.c index 81f053c..615c8ec 100644 --- a/palacios/src/palacios/vmm_dev_mgr.c +++ b/palacios/src/palacios/vmm_dev_mgr.c @@ -1,219 +1,242 @@ - -#include +#include #include #include #include + extern struct vmm_os_hooks *os_hooks; #ifndef NULL #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) { + mgr->dev_list.head = NULL; + mgr->dev_list.num_devs = 0; return 0; } -int dev_mgr_deinit(struct vmm_dev_mgr *mgr) +int dev_mgr_deinit(struct vmm_dev_mgr * mgr) { - int rc; + struct vm_device * dev = mgr->dev_list.head; - while (mgr->dev_list) { - rc=dev_mgr_detach_device(mgr->vm,mgr->dev_list); - if (rc) { - // Bad bad bad - } + while (dev) { + unattach_device(dev); + free_device(dev); + dev = dev->next; } 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; + + + +int dev_mgr_add_device(struct vmm_dev_mgr * mgr, struct vm_device * dev) { + dev->next = mgr->dev_list.head; + dev->prev = 0; + if (dev->next) { + dev->next->prev = dev; } + mgr->dev_list.head = dev; + + mgr->dev_list.num_devs++; + + return 0; +} - device->next = mgr->dev_list; - device->prev = 0; - if (device->next) { - device->next->prev = device; +int dev_mgr_remove_device(struct vmm_dev_mgr * mgr, struct vm_device * dev) { + if (mgr->dev_list.head == dev) { + mgr->dev_list.head = dev->next; + } else { + dev->prev->next = dev->next; + } + if (dev->next) { + dev->next->prev = dev->prev; } - mgr->dev_list = device; - device->vm=vm; + mgr->dev_list.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; + +int dev_mgr_add_io_hook(struct vmm_dev_mgr * mgr, struct dev_io_hook * hook) { + hook->mgr_next = mgr->io_hooks.head; + hook->mgr_prev = NULL; + if (hook->mgr_next) { + hook->mgr_next->mgr_prev = hook; + } + mgr->io_hooks.head = hook; + + mgr->io_hooks.num_hooks++; + + return 0; +} + + +int dev_mgr_remove_io_hook(struct vmm_dev_mgr * mgr, struct dev_io_hook * hook) { + if (mgr->io_hooks.head == hook) { + mgr->io_hooks.head = hook->mgr_next; } else { - device->prev->next = device->next; + hook->mgr_prev->mgr_next = hook->mgr_next; } - if (device->next) { - device->next->prev=device->prev; + + if (hook->mgr_next) { + hook->mgr_next->mgr_prev = hook->mgr_prev; } - // avoid interrupts here - - device->deinit_device(device); + mgr->io_hooks.num_hooks--; - device->vm=NULL; 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_add_io_hook(struct vm_device * dev, struct dev_io_hook * hook) { + hook->dev_next = dev->io_hooks.head; + hook->dev_prev = NULL; + if (hook->dev_next) { + hook->dev_next->dev_prev = hook; + } + dev->io_hooks.head = hook; - + dev->io_hooks.num_hooks++; -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)); - - if (!hook) { - return -1; + return 0; +} + + +int dev_remove_io_hook(struct vm_device * dev, struct dev_io_hook * hook) { + if (dev->io_hooks.head == hook) { + dev->io_hooks.head = hook->dev_next; + } else { + hook->dev_prev->dev_next = hook->dev_next; } - int (*read)(ushort_t, void *, uint_t, void *) = NULL; - int (*write)(ushort_t, void *, uint_t, void *) = NULL; + if (hook->dev_next) { + hook->dev_next->dev_prev = hook->dev_prev; + } + + dev->io_hooks.num_hooks--; - 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); + return 0; +} + + +struct dev_io_hook * dev_mgr_find_io_hook(struct vmm_dev_mgr * mgr, ushort_t port) { + struct dev_io_hook * tmp = mgr->io_hooks.head; + + while (tmp) { + if (tmp->port == 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); + } + tmp = tmp->mgr_next; + } + + return tmp; +} + +struct dev_io_hook * dev_find_io_hook(struct vm_device * dev, ushort_t port) { + struct dev_io_hook * tmp = dev->io_hooks.head; + + while (tmp) { + if (tmp->port == port) { break; } - break; - case DEVICE_PASSTHROUGH: - read=write=NULL; - break; + tmp = tmp->dev_next; } - - 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); + + return tmp; +} + + + + +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); -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; + dev->ops->deinit(dev); + dev_mgr_remove_device(mgr, dev); + dev->vm = NULL; - while (hook) { - if (hook->guest_port==portno) { - DELETE(device->io_hooks,hook); - break; - } + return 0; +} + + + +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; + } + + + 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; + + dev_mgr_add_io_hook(&(dev->vm->dev_mgr), hook); + dev_add_io_hook(dev, hook); + } else { + return -1; } + return 0; +} + + +int dev_unhook_io(struct vm_device *dev, + ushort_t port) { + + 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 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 = os_hooks->malloc(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 @@ -228,13 +251,9 @@ 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; @@ -243,15 +262,13 @@ int dev_mgr_hook_mem(struct guest_info *vm, int dev_mgr_unhook_mem(struct guest_info *vm, struct vm_device *device, - void *guest_physical_start, - void *guest_physical_end) + void *start, + void *end) { - struct vm_device_mem_hook *hook = device->mem_hooks; + struct dev_mem_hook *hook = device->mem_hooks.head; while (hook) { - if (hook->guest_physical_start==guest_physical_start && - hook->guest_physical_end==guest_physical_end) { - DELETE(device->mem_hooks,hook); + if (((hook->addr_start) == start) && (hook->addr_end == end)) { break; } } @@ -272,24 +289,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 = mgr->dev_list.head; + + while (dev) { + PrintDebugDev(dev); + dev = dev->next; } - 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 = dev->io_hooks.head; + + PrintDebug("IO Hooks (%d) for Device: %s\n", dev->io_hooks.num_hooks, dev->name); + + while (hook) { + PrintDebug("\tPort: 0x%x (read=0x%x), (write=0x%x)\n", hook->port, hook->read, hook->write); + hook = hook->dev_next; + } + + return; +}