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);
}
+// 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);
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));
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;
return -1;
}
+ list_add(&(hook->hook_node), &(hooks->hook_list));
+
return 0;
}
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;
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
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;
}
+