From: Jack Lange Date: Tue, 18 May 2010 03:34:33 +0000 (-0500) Subject: moved memory hooks out of core memory map implementation, X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=b93aeabee44c82139a9afd065dfcaca8ac6688ad;p=palacios.git moved memory hooks out of core memory map implementation, modified paging to implement unhandled callbacks --- diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index 041b755..f6bd9cb 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -118,6 +119,7 @@ struct v3_vm_info { addr_t mem_size; // In bytes for now struct v3_mem_map mem_map; + struct v3_mem_hooks mem_hooks; struct v3_shdw_impl_state shdw_impl; diff --git a/palacios/include/palacios/vmm_mem.h b/palacios/include/palacios/vmm_mem.h index 3cb091f..37f9320 100644 --- a/palacios/include/palacios/vmm_mem.h +++ b/palacios/include/palacios/vmm_mem.h @@ -47,7 +47,6 @@ typedef struct { uint8_t read : 1; uint8_t write : 1; uint8_t exec : 1; - uint8_t hook : 1; uint8_t base : 1; uint8_t alloced : 1; } __attribute__((packed)); @@ -64,10 +63,8 @@ struct v3_shadow_region { addr_t host_addr; // This either points to a host address mapping - // Called when data is read from a memory page - int (*read_hook)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data); - // Called when data is written to a memory page - int (*write_hook)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data); + int (*unhandled)(struct guest_info * info, addr_t guest_va, addr_t guest_pa, + struct v3_shadow_region * reg, pf_error_t access_info); void * priv_data; @@ -81,8 +78,6 @@ struct v3_mem_map { struct v3_shadow_region base_region; struct rb_root shdw_regions; - - void * hook_hvas; // this is an array of pages, equal to the number of cores }; @@ -92,30 +87,19 @@ void v3_delete_mem_map(struct v3_vm_info * vm); -int v3_add_shadow_mem(struct v3_vm_info * vm, uint16_t core_id, - addr_t guest_addr_start, addr_t guest_addr_end, addr_t host_addr); - -int v3_hook_full_mem(struct v3_vm_info * vm, uint16_t core_id, - addr_t guest_addr_start, addr_t guest_addr_end, - int (*read)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data), - int (*write)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), - void * priv_data); - -int v3_hook_write_mem(struct v3_vm_info * vm, uint16_t core_id, - addr_t guest_addr_start, addr_t guest_addr_end, addr_t host_addr, - int (*write)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), - void * priv_data); - - -int v3_unhook_mem(struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr_start); - - +struct v3_shadow_region * v3_create_mem_region(struct v3_vm_info * vm, uint16_t core_id, + addr_t guest_addr_start, addr_t guest_addr_end); +int v3_insert_shadow_region(struct v3_vm_info * vm, struct v3_shadow_region * reg); void v3_delete_shadow_region(struct v3_vm_info * vm, struct v3_shadow_region * reg); +/* This is a shortcut function for creating + inserting a memory region which redirects to host memory */ +int v3_add_shadow_mem(struct v3_vm_info * vm, uint16_t core_id, + addr_t guest_addr_start, addr_t guest_addr_end, addr_t host_addr); + struct v3_shadow_region * v3_get_shadow_region(struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr); @@ -131,8 +115,6 @@ void v3_print_mem_map(struct v3_vm_info * vm); -int v3_handle_mem_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa, - struct v3_shadow_region * reg, pf_error_t access_info); #endif // ! __V3VEE__ diff --git a/palacios/include/palacios/vmm_mem_hook.h b/palacios/include/palacios/vmm_mem_hook.h new file mode 100644 index 0000000..e30ecf7 --- /dev/null +++ b/palacios/include/palacios/vmm_mem_hook.h @@ -0,0 +1,60 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + + +#ifndef __VMM_MEM_HOOK_H +#define __VMM_MEM_HOOK_H + + +#ifdef __V3VEE__ + + +struct v3_mem_hooks { + + void * hook_hvas; // this is an array of pages, equal to the number of cores + + struct list_head hook_list; + +}; + + +int v3_init_mem_hooks(struct v3_vm_info * vm); + + +int v3_hook_full_mem(struct v3_vm_info * vm, uint16_t core_id, + addr_t guest_addr_start, addr_t guest_addr_end, + int (*read)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data), + int (*write)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), + void * priv_data); + +int v3_hook_write_mem(struct v3_vm_info * vm, uint16_t core_id, + addr_t guest_addr_start, addr_t guest_addr_end, addr_t host_addr, + int (*write)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), + void * priv_data); + + +int v3_unhook_mem(struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr_start); + + + + +#endif /* ! __V3VEE__ */ + + +#endif diff --git a/palacios/src/palacios/Makefile b/palacios/src/palacios/Makefile index 1aa182a..14001bb 100644 --- a/palacios/src/palacios/Makefile +++ b/palacios/src/palacios/Makefile @@ -32,7 +32,8 @@ obj-y := \ vmm_binaries.o \ vmm_cpuid.o \ vmm_xml.o \ - vmm_muxer.o + vmm_muxer.o \ + vmm_mem_hook.o \ obj-$(CONFIG_SVM) += svm.o \ svm_io.o \ diff --git a/palacios/src/palacios/mmu/vmm_shdw_pg_swapbypass_32.h b/palacios/src/palacios/mmu/vmm_shdw_pg_swapbypass_32.h index 6eca4d5..73347ab 100644 --- a/palacios/src/palacios/mmu/vmm_shdw_pg_swapbypass_32.h +++ b/palacios/src/palacios/mmu/vmm_shdw_pg_swapbypass_32.h @@ -367,16 +367,14 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault } - - // Write hooks trump all, and are set Read Only if (shdw_reg->flags.write == 0) { shadow_pte->writable = 0; } - } else if (shdw_reg->flags.hook == 1) { + } else { // Page fault handled by hook functions - if (v3_handle_mem_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { + if (shdw_reg->unhandled(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { PrintError("Special Page fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } @@ -384,15 +382,16 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) { guest_pte->dirty = 1; - if (shdw_reg->flags.hook == 1) { - if (v3_handle_mem_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { + + if (shdw_reg->flags.write == 1) { + PrintDebug("Shadow PTE Write Error\n"); + shadow_pte->writable = guest_pte->writable; + } else { + if (shdw_reg->unhandled(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { PrintError("Special Page fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } - } else if (shdw_reg->flags.write == 1) { - PrintDebug("Shadow PTE Write Error\n"); - shadow_pte->writable = guest_pte->writable; - } + } return 0; @@ -476,21 +475,17 @@ static int handle_4MB_shadow_pagefault_32(struct guest_info * info, shadow_pte->global_page = large_guest_pde->global_page; // - } else if (shdw_reg->flags.hook == 1) { - if (v3_handle_mem_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { + } else { + if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } } } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) { - - if (shdw_reg->flags.hook == 1) { - if (v3_handle_mem_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { - PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr); - return -1; - } - } - + if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { + PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr); + return -1; + } } else { PrintError("Error in large page fault handler...\n"); PrintError("This case should have been handled at the top level handler\n"); diff --git a/palacios/src/palacios/mmu/vmm_shdw_pg_swapbypass_64.h b/palacios/src/palacios/mmu/vmm_shdw_pg_swapbypass_64.h index 287b14c..ee9324c 100644 --- a/palacios/src/palacios/mmu/vmm_shdw_pg_swapbypass_64.h +++ b/palacios/src/palacios/mmu/vmm_shdw_pg_swapbypass_64.h @@ -452,7 +452,7 @@ static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault // Page Table Entry Not Present PrintDebug("guest_pa =%p\n", (void *)guest_pa); - if ((shdw_reg->flags.hook == 1) || + if ((shdw_reg->flags.alloced == 1) || (shdw_reg->flags.read == 1)) { addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, info->cpu_id, guest_pa); @@ -484,10 +484,10 @@ static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault shadow_pte->writable = 0; } - } else if (shdw_reg->flags.hook == 1) { + } else { // Page fault handled by hook functions - if (v3_handle_mem_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { + if (shdw_reg->unhandled(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { PrintError("Special Page fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } @@ -495,14 +495,16 @@ static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) { guest_pte->dirty = 1; - if (shdw_reg->flags.hook == 1) { - if (v3_handle_mem_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { + + + if (shdw_reg->flags.write == 1) { + PrintDebug("Shadow PTE Write Error\n"); + shadow_pte->writable = guest_pte->writable; + } else { + if (shdw_reg->unhandled(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { PrintError("Special Page fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } - } else if (shdw_reg->flags.write == 1) { - PrintDebug("Shadow PTE Write Error\n"); - shadow_pte->writable = guest_pte->writable; } @@ -585,20 +587,17 @@ static int handle_2MB_shadow_pagefault_64(struct guest_info * info, shadow_pte->global_page = large_guest_pde->global_page; // - } else if (shdw_reg->flags.hook == 1) { - if (v3_handle_mem_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { + } else { + if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } } } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) { - if (shdw_reg->flags.hook == 1) { - - if (v3_handle_mem_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { - PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr); - return -1; - } + if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { + PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr); + return -1; } } else { diff --git a/palacios/src/palacios/mmu/vmm_shdw_pg_tlb_32.h b/palacios/src/palacios/mmu/vmm_shdw_pg_tlb_32.h index 30acc7a..2832c5c 100644 --- a/palacios/src/palacios/mmu/vmm_shdw_pg_tlb_32.h +++ b/palacios/src/palacios/mmu/vmm_shdw_pg_tlb_32.h @@ -278,10 +278,10 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault shadow_pte->writable = 0; } - } else if (shdw_reg->flags.hook == 1) { - // Page fault handled by hook functions - - if (v3_handle_mem_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { + } else { + // Page fault on unhandled memory region + + if (shdw_reg->unhandled(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { PrintError("Special Page fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } @@ -289,14 +289,14 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) { guest_pte->dirty = 1; - if (shdw_reg->flags.hook == 1) { - if (v3_handle_mem_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { + if (shdw_reg->flags.write == 1) { + PrintDebug("Shadow PTE Write Error\n"); + shadow_pte->writable = guest_pte->writable; + } else { + if (shdw_reg->unhandled(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { PrintError("Special Page fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } - } else if (shdw_reg->flags.write == 1) { - PrintDebug("Shadow PTE Write Error\n"); - shadow_pte->writable = guest_pte->writable; } @@ -382,16 +382,16 @@ static int handle_4MB_shadow_pagefault_32(struct guest_info * info, shadow_pte->writable = 1; } - } else if (shdw_reg->flags.hook == 1) { - if (v3_handle_mem_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { + } else { + if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } } } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) { - if (shdw_reg->flags.hook == 1) { - if (v3_handle_mem_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { + if (shdw_reg->flags.write == 0) { + if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } diff --git a/palacios/src/palacios/mmu/vmm_shdw_pg_tlb_64.h b/palacios/src/palacios/mmu/vmm_shdw_pg_tlb_64.h index df44714..afa47cc 100644 --- a/palacios/src/palacios/mmu/vmm_shdw_pg_tlb_64.h +++ b/palacios/src/palacios/mmu/vmm_shdw_pg_tlb_64.h @@ -484,10 +484,10 @@ static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault shadow_pte->writable = 0; } - } else if (shdw_reg->flags.hook == 1) { - // Page fault handled by hook functions + } else { + // Pass to unhandled call back - if (v3_handle_mem_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { + if (shdw_reg->unhandled(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { PrintError("Special Page fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } @@ -495,17 +495,19 @@ static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) { guest_pte->dirty = 1; - if (shdw_reg->flags.hook == 1) { - if (v3_handle_mem_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { + + if (shdw_reg->flags.write == 1) { + PrintDebug("Shadow PTE Write Error\n"); + shadow_pte->writable = guest_pte->writable; + } else { + if (shdw_reg->unhandled(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) { PrintError("Special Page fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } - } else if (shdw_reg->flags.write == 1) { - PrintDebug("Shadow PTE Write Error\n"); - shadow_pte->writable = guest_pte->writable; } + return 0; } else { @@ -585,21 +587,17 @@ static int handle_2MB_shadow_pagefault_64(struct guest_info * info, shadow_pte->global_page = large_guest_pde->global_page; // - } else if (shdw_reg->flags.hook == 1) { - if (v3_handle_mem_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { + } else { + if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr); return -1; } } } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) { - - if (shdw_reg->flags.hook == 1) { - if (v3_handle_mem_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { - PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr); - return -1; - } + if (shdw_reg->unhandled(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) { + PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr); + return -1; } - } else { PrintError("Error in large page fault handler...\n"); PrintError("This case should have been handled at the top level handler\n"); diff --git a/palacios/src/palacios/vm_guest.c b/palacios/src/palacios/vm_guest.c index f7348ed..a7fe069 100644 --- a/palacios/src/palacios/vm_guest.c +++ b/palacios/src/palacios/vm_guest.c @@ -428,6 +428,7 @@ int v3_init_vm(struct v3_vm_info * vm) { return -1; } + v3_init_mem_hooks(vm); if (v3_init_shdw_impl(vm) == -1) { PrintError("VM initialization error in shadow implementaion\n"); diff --git a/palacios/src/palacios/vmm_direct_paging_32.h b/palacios/src/palacios/vmm_direct_paging_32.h index 047f2a6..0ca5287 100644 --- a/palacios/src/palacios/vmm_direct_paging_32.h +++ b/palacios/src/palacios/vmm_direct_paging_32.h @@ -73,11 +73,12 @@ static inline int handle_passthrough_pagefault_32(struct guest_info * info, // Fix up the PTE entry if (pte[pte_index].present == 0) { - pte[pte_index].user_page = 1; if ((region->flags.alloced == 1) && (region->flags.read == 1)) { + pte[pte_index].user_page = 1; + pte[pte_index].present = 1; if (region->flags.write == 1) { @@ -87,15 +88,15 @@ static inline int handle_passthrough_pagefault_32(struct guest_info * info, } pte[pte_index].page_base_addr = PAGE_BASE_ADDR(host_addr); + } else { + return region->unhandled(info, fault_addr, fault_addr, region, error_code); } + } else { + // We fix all permissions on the first pass, + // so we only get here if its an unhandled exception + return region->unhandled(info, fault_addr, fault_addr, region, error_code); } - if (region->flags.hook == 1) { - if ((error_code.write == 1) || (region->flags.read == 0)) { - return v3_handle_mem_hook(info, fault_addr, fault_addr, region, error_code); - } - } - return 0; } diff --git a/palacios/src/palacios/vmm_direct_paging_32pae.h b/palacios/src/palacios/vmm_direct_paging_32pae.h index 0c3381a..703b044 100644 --- a/palacios/src/palacios/vmm_direct_paging_32pae.h +++ b/palacios/src/palacios/vmm_direct_paging_32pae.h @@ -99,13 +99,11 @@ static inline int handle_passthrough_pagefault_32pae(struct guest_info * info, } pte[pte_index].page_base_addr = PAGE_BASE_ADDR(host_addr); + } else { + return region->unhandled(info, fault_addr, fault_addr, region, error_code); } - } - - if (region->flags.hook == 1) { - if ((error_code.write == 1) || (region->flags.read == 0)) { - return v3_handle_mem_hook(info, fault_addr, fault_addr, region, error_code); - } + } else { + return region->unhandled(info, fault_addr, fault_addr, region, error_code); } return 0; diff --git a/palacios/src/palacios/vmm_direct_paging_64.h b/palacios/src/palacios/vmm_direct_paging_64.h index 96b8f21..fc94d33 100644 --- a/palacios/src/palacios/vmm_direct_paging_64.h +++ b/palacios/src/palacios/vmm_direct_paging_64.h @@ -123,13 +123,14 @@ static inline int handle_passthrough_pagefault_64(struct guest_info * info, } pte[pte_index].page_base_addr = PAGE_BASE_ADDR(host_addr); + } else { + return region->unhandled(info, fault_addr, fault_addr, region, error_code); } - } - - if (region->flags.hook == 1) { - if ((error_code.write == 1) || (region->flags.read == 0)) { - return v3_handle_mem_hook(info, fault_addr, fault_addr, region, error_code); - } + } else { + // We fix all permissions on the first pass, + // so we only get here if its an unhandled exception + + return region->unhandled(info, fault_addr, fault_addr, region, error_code); } return 0; diff --git a/palacios/src/palacios/vmm_mem.c b/palacios/src/palacios/vmm_mem.c index c804970..019a1af 100644 --- a/palacios/src/palacios/vmm_mem.c +++ b/palacios/src/palacios/vmm_mem.c @@ -27,9 +27,6 @@ #include -static inline -struct v3_shadow_region * insert_shadow_region(struct v3_vm_info * vm, - struct v3_shadow_region * region); static int mem_offset_hypercall(struct guest_info * info, uint_t hcall_id, void * private_data) { @@ -41,6 +38,19 @@ static int mem_offset_hypercall(struct guest_info * info, uint_t hcall_id, void return 0; } +static int unhandled_err(struct guest_info * core, addr_t guest_va, addr_t guest_pa, + struct v3_shadow_region * reg, pf_error_t access_info) { + + PrintError("Unhandled memory access error\n"); + + v3_print_mem_map(core->vm_info); + + v3_print_guest_state(core); + + return -1; +} + + int v3_init_mem_map(struct v3_vm_info * vm) { struct v3_mem_map * map = &(vm->mem_map); @@ -51,9 +61,6 @@ int v3_init_mem_map(struct v3_vm_info * vm) { map->shdw_regions.rb_node = NULL; - map->hook_hvas = V3_VAddr(V3_AllocPages(vm->num_cores)); - - // There is an underlying region that contains all of the guest memory // PrintDebug("Mapping %d pages of memory (%u bytes)\n", (int)mem_pages, (uint_t)info->mem_size); @@ -66,6 +73,8 @@ int v3_init_mem_map(struct v3_vm_info * vm) { map->base_region.flags.exec = 1; map->base_region.flags.base = 1; map->base_region.flags.alloced = 1; + + map->base_region.unhandled = unhandled_err; if ((void *)map->base_region.host_addr == NULL) { PrintError("Could not allocate Guest memory\n"); @@ -80,11 +89,7 @@ int v3_init_mem_map(struct v3_vm_info * vm) { } -static inline addr_t get_hook_hva(struct guest_info * info) { - return (addr_t)(info->vm_info->mem_map.hook_hvas + (PAGE_SIZE_4KB * info->cpu_id)); -} - -void v3_delete_shadow_map(struct v3_vm_info * vm) { +void v3_delete_mem_map(struct v3_vm_info * vm) { struct rb_node * node = v3_rb_first(&(vm->mem_map.shdw_regions)); struct v3_shadow_region * reg; struct rb_node * tmp_node = NULL; @@ -98,93 +103,46 @@ void v3_delete_shadow_map(struct v3_vm_info * vm) { } V3_FreePage((void *)(vm->mem_map.base_region.host_addr)); - V3_FreePage(V3_PAddr((void *)(vm->mem_map.hook_hvas))); } - - -int v3_add_shadow_mem( struct v3_vm_info * vm, uint16_t core_id, - addr_t guest_addr_start, - addr_t guest_addr_end, - addr_t host_addr) -{ +struct v3_shadow_region * v3_create_mem_region(struct v3_vm_info * vm, uint16_t core_id, + addr_t guest_addr_start, addr_t guest_addr_end) { + struct v3_shadow_region * entry = (struct v3_shadow_region *)V3_Malloc(sizeof(struct v3_shadow_region)); memset(entry, 0, sizeof(struct v3_shadow_region)); entry->guest_start = guest_addr_start; entry->guest_end = guest_addr_end; - entry->host_addr = host_addr; - entry->write_hook = NULL; - entry->read_hook = NULL; - entry->priv_data = NULL; entry->core_id = core_id; + entry->unhandled = unhandled_err; - entry->flags.read = 1; - entry->flags.write = 1; - entry->flags.exec = 1; - entry->flags.alloced = 1; - - if (insert_shadow_region(vm, entry)) { - V3_Free(entry); - return -1; - } - - return 0; + return entry; } -int v3_hook_write_mem(struct v3_vm_info * vm, uint16_t core_id, - addr_t guest_addr_start, addr_t guest_addr_end, addr_t host_addr, - int (*write)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), - void * priv_data) { - struct v3_shadow_region * entry = (struct v3_shadow_region *)V3_Malloc(sizeof(struct v3_shadow_region)); - memset(entry, 0, sizeof(struct v3_shadow_region)); +int v3_add_shadow_mem( struct v3_vm_info * vm, uint16_t core_id, + addr_t guest_addr_start, + addr_t guest_addr_end, + addr_t host_addr) +{ + struct v3_shadow_region * entry = NULL; + + entry = v3_create_mem_region(vm, core_id, + guest_addr_start, + guest_addr_end); - entry->guest_start = guest_addr_start; - entry->guest_end = guest_addr_end; entry->host_addr = host_addr; - entry->write_hook = write; - entry->read_hook = NULL; - entry->priv_data = priv_data; - entry->core_id = core_id; - entry->flags.hook = 1; + entry->flags.read = 1; + entry->flags.write = 1; entry->flags.exec = 1; entry->flags.alloced = 1; - - if (insert_shadow_region(vm, entry)) { - V3_Free(entry); - return -1; - } - - return 0; -} - -int v3_hook_full_mem(struct v3_vm_info * vm, uint16_t core_id, - addr_t guest_addr_start, addr_t guest_addr_end, - int (*read)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data), - int (*write)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), - void * priv_data) { - - struct v3_shadow_region * entry = (struct v3_shadow_region *)V3_Malloc(sizeof(struct v3_shadow_region)); - memset(entry, 0, sizeof(struct v3_shadow_region)); - - entry->guest_start = guest_addr_start; - entry->guest_end = guest_addr_end; - entry->host_addr = (addr_t)NULL; - entry->write_hook = write; - entry->read_hook = read; - entry->priv_data = priv_data; - entry->core_id = core_id; - - entry->flags.hook = 1; - - if (insert_shadow_region(vm, entry)) { + if (v3_insert_shadow_region(vm, entry) == -1) { V3_Free(entry); return -1; } @@ -193,22 +151,6 @@ int v3_hook_full_mem(struct v3_vm_info * vm, uint16_t core_id, } -// This will unhook the memory hook registered at start address -// We do not support unhooking subregions -int v3_unhook_mem(struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr_start) { - struct v3_shadow_region * reg = v3_get_shadow_region(vm, core_id, guest_addr_start); - - if (!reg->flags.hook) { - PrintError("Trying to unhook a non hooked memory region (addr=%p)\n", (void *)guest_addr_start); - return -1; - } - - v3_delete_shadow_region(vm, reg); - - return 0; -} - - static inline struct v3_shadow_region * __insert_shadow_region(struct v3_vm_info * vm, @@ -246,14 +188,14 @@ struct v3_shadow_region * __insert_shadow_region(struct v3_vm_info * vm, } -static inline -struct v3_shadow_region * insert_shadow_region(struct v3_vm_info * vm, - struct v3_shadow_region * region) { + +int v3_insert_shadow_region(struct v3_vm_info * vm, + struct v3_shadow_region * region) { struct v3_shadow_region * ret; int i = 0; if ((ret = __insert_shadow_region(vm, region))) { - return ret; + return -1; } v3_rb_insert_color(&(region->tree_node), &(vm->mem_map.shdw_regions)); @@ -293,55 +235,9 @@ struct v3_shadow_region * insert_shadow_region(struct v3_vm_info * vm, } } - return NULL; -} - - - - - - -int v3_handle_mem_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa, - struct v3_shadow_region * reg, pf_error_t access_info) { - - addr_t op_addr = 0; - - if (reg->flags.alloced == 0) { - op_addr = get_hook_hva(info); - } else { - op_addr = (addr_t)V3_VAddr((void *)v3_get_shadow_addr(reg, info->cpu_id, guest_pa)); - } - - - if (access_info.write == 1) { - // Write Operation - - if (v3_emulate_write_op(info, guest_va, guest_pa, op_addr, - reg->write_hook, reg->priv_data) == -1) { - PrintError("Write Full Hook emulation failed\n"); - return -1; - } - } else { - // Read Operation - - if (reg->flags.read == 1) { - PrintError("Tried to emulate read for a guest Readable page\n"); - return -1; - } - - if (v3_emulate_read_op(info, guest_va, guest_pa, op_addr, - reg->read_hook, reg->write_hook, - reg->priv_data) == -1) { - PrintError("Read Full Hook emulation failed\n"); - return -1; - } - - } - - return 0; } - + @@ -474,10 +370,9 @@ void v3_print_mem_map(struct v3_vm_info * vm) { (void *)(reg->guest_end - 1), (void *)(reg->host_addr)); - V3_Print("\t(flags=%x) (WriteHook = 0x%p) (ReadHook = 0x%p)\n", + V3_Print("\t(flags=%x) (unhandled = 0x%p)\n", reg->flags.value, - (void *)(reg->write_hook), - (void *)(reg->read_hook)); + reg->unhandled); i++; } while ((node = v3_rb_next(node))); diff --git a/palacios/src/palacios/vmm_mem_hook.c b/palacios/src/palacios/vmm_mem_hook.c new file mode 100644 index 0000000..46203a4 --- /dev/null +++ b/palacios/src/palacios/vmm_mem_hook.c @@ -0,0 +1,179 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include +#include + +struct mem_hook { + + // Called when data is read from a memory page + int (*read)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data); + // Called when data is written to a memory page + int (*write)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data); + + void * priv_data; + addr_t hook_hva; + + +}; + + + +int v3_init_mem_hooks(struct v3_vm_info * vm) { + struct v3_mem_hooks * hooks = &(vm->mem_hooks); + + hooks->hook_hvas = V3_VAddr(V3_AllocPages(vm->num_cores)); + + INIT_LIST_HEAD(&(hooks->hook_list)); + + return 0; +} + + + + +static int handle_mem_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa, + struct v3_shadow_region * reg, pf_error_t access_info) { + struct mem_hook * hook = reg->priv_data; + addr_t op_addr = 0; + + if (reg->flags.alloced == 0) { + op_addr = hook->hook_hva; + } else { + op_addr = (addr_t)V3_VAddr((void *)v3_get_shadow_addr(reg, info->cpu_id, guest_pa)); + } + + + if (access_info.write == 1) { + // Write Operation + + if (v3_emulate_write_op(info, guest_va, guest_pa, op_addr, + hook->write, hook->priv_data) == -1) { + PrintError("Write Full Hook emulation failed\n"); + return -1; + } + } else { + // Read Operation + + if (reg->flags.read == 1) { + PrintError("Tried to emulate read for a guest Readable page\n"); + return -1; + } + + if (v3_emulate_read_op(info, guest_va, guest_pa, op_addr, + hook->read, hook->write, + hook->priv_data) == -1) { + PrintError("Read Full Hook emulation failed\n"); + return -1; + } + + } + + + return 0; +} + + + + +int v3_hook_write_mem(struct v3_vm_info * vm, uint16_t core_id, + addr_t guest_addr_start, addr_t guest_addr_end, addr_t host_addr, + int (*write)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), + void * priv_data) { + struct v3_shadow_region * entry = NULL; + struct mem_hook * hook = V3_Malloc(sizeof(struct mem_hook)); + // struct v3_mem_hooks * hooks = &(vm->mem_hooks); + + memset(hook, 0, sizeof(struct mem_hook)); + + hook->write = write; + hook->read = NULL; + hook->priv_data = priv_data; + hook->hook_hva = (addr_t)V3_VAddr((void *)host_addr); + + entry = v3_create_mem_region(vm, core_id, guest_addr_start, guest_addr_end); + + entry->host_addr = host_addr; + entry->unhandled = handle_mem_hook; + entry->priv_data = hook; + + entry->flags.read = 1; + entry->flags.exec = 1; + entry->flags.alloced = 1; + + if (v3_insert_shadow_region(vm, entry) == -1) { + V3_Free(entry); + V3_Free(hook); + return -1; + } + + return 0; +} + + + +int v3_hook_full_mem(struct v3_vm_info * vm, uint16_t core_id, + addr_t guest_addr_start, addr_t guest_addr_end, + int (*read)(struct guest_info * core, addr_t guest_addr, void * dst, uint_t length, void * priv_data), + int (*write)(struct guest_info * core, addr_t guest_addr, void * src, uint_t length, void * priv_data), + void * priv_data) { + + struct v3_shadow_region * entry = NULL; + struct mem_hook * hook = V3_Malloc(sizeof(struct mem_hook)); + struct v3_mem_hooks * hooks = &(vm->mem_hooks); + + memset(hook, 0, sizeof(struct mem_hook)); + + hook->write = write; + hook->read = read; + hook->priv_data = priv_data; + hook->hook_hva = (addr_t)hooks->hook_hvas + (PAGE_SIZE_4KB * core_id); + + entry = v3_create_mem_region(vm, core_id, guest_addr_start, guest_addr_end); + + entry->unhandled = handle_mem_hook; + entry->priv_data = hook; + + if (v3_insert_shadow_region(vm, entry)) { + V3_Free(entry); + V3_Free(hook); + return -1; + } + + return 0; +} + + + +// This will unhook the memory hook registered at start address +// We do not support unhooking subregions +int v3_unhook_mem(struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr_start) { + struct v3_shadow_region * reg = v3_get_shadow_region(vm, core_id, guest_addr_start); + struct mem_hook * hook = reg->priv_data; + + V3_Free(hook); + + v3_delete_shadow_region(vm, reg); + + return 0; +} + +