X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fpalacios%2Fvmm_mem_hook.c;h=46c84ccee031be7b0b177b0e0876f726e7f08f56;hb=b3e5aa263c35961c74e0b7ed96b8510e8c6d7d0d;hp=8ee243aa9c907989a6bd19cb741d216a38b1435d;hpb=0c31bb41ac41d04a891a6eeff5bae398fa89b419;p=palacios.git diff --git a/palacios/src/palacios/vmm_mem_hook.c b/palacios/src/palacios/vmm_mem_hook.c index 8ee243a..46c84cc 100644 --- a/palacios/src/palacios/vmm_mem_hook.c +++ b/palacios/src/palacios/vmm_mem_hook.c @@ -32,12 +32,16 @@ struct mem_hook { void * priv_data; addr_t hook_hva; - + struct v3_mem_region * region; + struct list_head hook_node; }; +static int free_hook(struct v3_vm_info * vm, struct mem_hook * hook); + + int v3_init_mem_hooks(struct v3_vm_info * vm) { struct v3_mem_hooks * hooks = &(vm->mem_hooks); @@ -49,15 +53,43 @@ int v3_init_mem_hooks(struct v3_vm_info * vm) { } +// We'll assume the actual hooks were either already cleared, +// or will be cleared by the memory map +int v3_deinit_mem_hooks(struct v3_vm_info * vm) { + struct v3_mem_hooks * hooks = &(vm->mem_hooks); + struct mem_hook * hook = NULL; + struct mem_hook * tmp = NULL; + + + // This is nasty... + // We delete the hook info but leave its memory region intact + // We rely on the memory map to clean up any orphaned regions as a result of this + // This needs to be fixed at some point... + list_for_each_entry_safe(hook, tmp, &(hooks->hook_list), hook_node) { + free_hook(vm, hook); + } + + + V3_FreePages(V3_PAddr(hooks->hook_hvas), vm->num_cores); + + return 0; +} + + static int handle_mem_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa, struct v3_mem_region * reg, pf_error_t access_info) { struct mem_hook * hook = reg->priv_data; + struct v3_mem_hooks * hooks = &(info->vm_info->mem_hooks); addr_t op_addr = 0; if (reg->flags.alloced == 0) { - op_addr = hook->hook_hva; + if (hook->hook_hva & 0xfff) { + op_addr = (addr_t)(hooks->hook_hvas + (PAGE_SIZE * info->cpu_id)); + } else { + op_addr = hook->hook_hva; + } } else { if (v3_gpa_to_hva(info, guest_pa, &op_addr) == -1) { PrintError("Could not translate hook address (%p)\n", (void *)guest_pa); @@ -103,7 +135,7 @@ int v3_hook_write_mem(struct v3_vm_info * vm, uint16_t core_id, void * priv_data) { struct v3_mem_region * entry = NULL; struct mem_hook * hook = V3_Malloc(sizeof(struct mem_hook)); - // struct v3_mem_hooks * hooks = &(vm->mem_hooks); + struct v3_mem_hooks * hooks = &(vm->mem_hooks); memset(hook, 0, sizeof(struct mem_hook)); @@ -114,6 +146,8 @@ int v3_hook_write_mem(struct v3_vm_info * vm, uint16_t core_id, entry = v3_create_mem_region(vm, core_id, guest_addr_start, guest_addr_end); + hook->region = entry; + entry->host_addr = host_addr; entry->unhandled = handle_mem_hook; entry->priv_data = hook; @@ -128,6 +162,8 @@ int v3_hook_write_mem(struct v3_vm_info * vm, uint16_t core_id, return -1; } + list_add(&(hook->hook_node), &(hooks->hook_list)); + return 0; } @@ -148,9 +184,10 @@ int v3_hook_full_mem(struct v3_vm_info * vm, uint16_t core_id, hook->write = write; hook->read = read; hook->priv_data = priv_data; - hook->hook_hva = (addr_t)hooks->hook_hvas + (PAGE_SIZE_4KB * core_id); + hook->hook_hva = (addr_t)0xfff; entry = v3_create_mem_region(vm, core_id, guest_addr_start, guest_addr_end); + hook->region = entry; entry->unhandled = handle_mem_hook; entry->priv_data = hook; @@ -161,10 +198,22 @@ int v3_hook_full_mem(struct v3_vm_info * vm, uint16_t core_id, return -1; } + list_add(&(hook->hook_node), &(hooks->hook_list)); + + return 0; } +static int free_hook(struct v3_vm_info * vm, struct mem_hook * hook) { + v3_delete_mem_region(vm, hook->region); + list_del(&(hook->hook_node)); + + V3_Free(hook); + + return 0; +} + // This will unhook the memory hook registered at start address // We do not support unhooking subregions @@ -172,11 +221,10 @@ int v3_unhook_mem(struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr_st struct v3_mem_region * reg = v3_get_mem_region(vm, core_id, guest_addr_start); struct mem_hook * hook = reg->priv_data; - V3_Free(hook); - - v3_delete_mem_region(vm, reg); + free_hook(vm, hook); return 0; } +