From: Jack Lange Date: Fri, 15 Jan 2010 04:02:43 +0000 (-0600) Subject: added per core memory map support X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=36c1666cf64c49302d906a79d8cafbf760452d86;p=palacios.git added per core memory map support --- diff --git a/palacios/include/palacios/vmm_mem.h b/palacios/include/palacios/vmm_mem.h index f64f648..b318526 100644 --- a/palacios/include/palacios/vmm_mem.h +++ b/palacios/include/palacios/vmm_mem.h @@ -44,7 +44,7 @@ typedef enum shdw_region_type { SHDW_REGION_ALLOCATED, // Region is a section of host memory } v3_shdw_region_type_t; - +#define V3_MEM_CORE_ANY ((uint16_t)-1) struct v3_shadow_region { @@ -74,7 +74,7 @@ struct v3_mem_map { struct rb_root shdw_regions; void * hook_hvas; // this is an array of pages, equal to the number of cores -}; +}; int v3_init_mem_map(struct v3_vm_info * vm); @@ -83,23 +83,22 @@ void v3_delete_mem_map(struct v3_vm_info * vm); -int v3_add_shadow_mem(struct v3_vm_info * vm, - addr_t guest_addr_start, - addr_t guest_addr_end, - addr_t host_addr); +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, addr_t guest_addr_start, addr_t guest_addr_end, +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)(addr_t guest_addr, void * dst, uint_t length, void * priv_data), int (*write)(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, addr_t guest_addr_start, addr_t guest_addr_end, - addr_t host_addr, +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)(addr_t guest_addr, void * src, uint_t length, void * priv_data), void * priv_data); -int v3_unhook_mem(struct v3_vm_info * vm, addr_t guest_addr_start); +int v3_unhook_mem(struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr_start); @@ -110,8 +109,8 @@ void v3_delete_shadow_region(struct v3_vm_info * vm, struct v3_shadow_region * r -struct v3_shadow_region * v3_get_shadow_region(struct v3_vm_info * vm, addr_t guest_addr /*, int core_id */); -addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, addr_t guest_addr); +struct v3_shadow_region * v3_get_shadow_region(struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr); +addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, uint16_t core_id, addr_t guest_addr); diff --git a/palacios/src/devices/pci.c b/palacios/src/devices/pci.c index 042e9a8..8266167 100644 --- a/palacios/src/devices/pci.c +++ b/palacios/src/devices/pci.c @@ -437,10 +437,10 @@ static int bar_update(struct guest_info * info, struct pci_device * pci, int bar break; } case PCI_BAR_MEM32: { - v3_unhook_mem(info->vm_info, (addr_t)(bar->val)); + v3_unhook_mem(info->vm_info, V3_MEM_CORE_ANY, (addr_t)(bar->val)); if (bar->mem_read) { - v3_hook_full_mem(info->vm_info, PCI_MEM32_BASE(new_val), + v3_hook_full_mem(info->vm_info, V3_MEM_CORE_ANY, PCI_MEM32_BASE(new_val), PCI_MEM32_BASE(new_val) + (bar->num_pages * PAGE_SIZE_4KB), bar->mem_read, bar->mem_write, pci->priv_data); } else { @@ -731,7 +731,7 @@ static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev) // hook memory if (pci_dev->bar[i].mem_read) { // full hook - v3_hook_full_mem(vm, pci_dev->bar[i].default_base_addr, + v3_hook_full_mem(vm, V3_MEM_CORE_ANY, pci_dev->bar[i].default_base_addr, pci_dev->bar[i].default_base_addr + (pci_dev->bar[i].num_pages * PAGE_SIZE_4KB), pci_dev->bar[i].mem_read, pci_dev->bar[i].mem_write, pci_dev->priv_data); } else if (pci_dev->bar[i].mem_write) { diff --git a/palacios/src/palacios/vm_guest_mem.c b/palacios/src/palacios/vm_guest_mem.c index 85c7a46..3f6be1e 100644 --- a/palacios/src/palacios/vm_guest_mem.c +++ b/palacios/src/palacios/vm_guest_mem.c @@ -66,7 +66,7 @@ int host_pa_to_host_va(addr_t host_pa, addr_t * host_va) { int guest_pa_to_host_pa(struct guest_info * info, addr_t guest_pa, addr_t * host_pa) { - struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info->vm_info, guest_pa); + struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info->vm_info, info->cpu_id, guest_pa); if (shdw_reg == NULL) { PrintError("In GPA->HPA: Could not find address in shadow map (addr=%p) (NULL REGION)\n", @@ -80,7 +80,7 @@ int guest_pa_to_host_pa(struct guest_info * info, addr_t guest_pa, addr_t * host return -1; } - *host_pa = v3_get_shadow_addr(shdw_reg, guest_pa); + *host_pa = v3_get_shadow_addr(shdw_reg, info->cpu_id, guest_pa); return 0; } diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index e3bc57b..b05d637 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -544,7 +544,7 @@ static int setup_memory_map(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { addr_t host_addr = atox(v3_cfg_val(mem_region, "host_addr")); - if (v3_add_shadow_mem(vm, start_addr, end_addr, host_addr) == -1) { + if (v3_add_shadow_mem(vm, V3_MEM_CORE_ANY, start_addr, end_addr, host_addr) == -1) { PrintError("Could not map memory region: %p-%p => %p\n", (void *)start_addr, (void *)end_addr, (void *)host_addr); return -1; diff --git a/palacios/src/palacios/vmm_config_class.h b/palacios/src/palacios/vmm_config_class.h index 2160c6e..a0b2ba4 100644 --- a/palacios/src/palacios/vmm_config_class.h +++ b/palacios/src/palacios/vmm_config_class.h @@ -53,7 +53,7 @@ static int post_config_pc(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { extern uint8_t v3_vgabios_start[]; extern uint8_t v3_vgabios_end[]; - addr_t vgabios_dst = v3_get_shadow_addr(&(vm->mem_map.base_region), VGABIOS_START); + addr_t vgabios_dst = v3_get_shadow_addr(&(vm->mem_map.base_region), V3_MEM_CORE_ANY, VGABIOS_START); memcpy(V3_VAddr((void *)vgabios_dst), v3_vgabios_start, v3_vgabios_end - v3_vgabios_start); } @@ -62,7 +62,7 @@ static int post_config_pc(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { extern uint8_t v3_rombios_start[]; extern uint8_t v3_rombios_end[]; - addr_t rombios_dst = v3_get_shadow_addr(&(vm->mem_map.base_region), ROMBIOS_START); + addr_t rombios_dst = v3_get_shadow_addr(&(vm->mem_map.base_region), V3_MEM_CORE_ANY, ROMBIOS_START); memcpy(V3_VAddr((void *)rombios_dst), v3_rombios_start, v3_rombios_end - v3_rombios_start); } diff --git a/palacios/src/palacios/vmm_direct_paging_32.h b/palacios/src/palacios/vmm_direct_paging_32.h index f7f8a5a..bfbb4a3 100644 --- a/palacios/src/palacios/vmm_direct_paging_32.h +++ b/palacios/src/palacios/vmm_direct_paging_32.h @@ -39,7 +39,7 @@ static inline int handle_passthrough_pagefault_32(struct guest_info * info, int pde_index = PDE32_INDEX(fault_addr); int pte_index = PTE32_INDEX(fault_addr); - struct v3_shadow_region * region = v3_get_shadow_region(info->vm_info, fault_addr); + struct v3_shadow_region * region = v3_get_shadow_region(info->vm_info, info->cpu_id, fault_addr); if (region == NULL) { PrintError("Invalid region in passthrough page fault 32, addr=%p\n", @@ -47,7 +47,7 @@ static inline int handle_passthrough_pagefault_32(struct guest_info * info, return -1; } - host_addr = v3_get_shadow_addr(region, fault_addr); + host_addr = v3_get_shadow_addr(region, info->cpu_id, fault_addr); // Lookup the correct PDE address based on the PAGING MODE if (info->shdw_pg_mode == SHADOW_PAGING) { diff --git a/palacios/src/palacios/vmm_direct_paging_32pae.h b/palacios/src/palacios/vmm_direct_paging_32pae.h index 933b0fb..f7c1f76 100644 --- a/palacios/src/palacios/vmm_direct_paging_32pae.h +++ b/palacios/src/palacios/vmm_direct_paging_32pae.h @@ -40,7 +40,7 @@ static inline int handle_passthrough_pagefault_32pae(struct guest_info * info, int pde_index = PDE32PAE_INDEX(fault_addr); int pte_index = PTE32PAE_INDEX(fault_addr); - struct v3_shadow_region * region = v3_get_shadow_region(info->vm_info, fault_addr); + struct v3_shadow_region * region = v3_get_shadow_region(info->vm_info, info->cpu_id, fault_addr); if (region == NULL) { PrintError("Invalid region in passthrough page fault 32PAE, addr=%p\n", @@ -48,7 +48,7 @@ static inline int handle_passthrough_pagefault_32pae(struct guest_info * info, return -1; } - host_addr = v3_get_shadow_addr(region, fault_addr); + host_addr = v3_get_shadow_addr(region, info->cpu_id, fault_addr); // Lookup the correct PDPE address based on the PAGING MODE if (info->shdw_pg_mode == SHADOW_PAGING) { diff --git a/palacios/src/palacios/vmm_direct_paging_64.h b/palacios/src/palacios/vmm_direct_paging_64.h index 731c198..0511754 100644 --- a/palacios/src/palacios/vmm_direct_paging_64.h +++ b/palacios/src/palacios/vmm_direct_paging_64.h @@ -46,7 +46,7 @@ static inline int handle_passthrough_pagefault_64(struct guest_info * info, - struct v3_shadow_region * region = v3_get_shadow_region(info->vm_info, fault_addr); + struct v3_shadow_region * region = v3_get_shadow_region(info->vm_info, info->cpu_id, fault_addr); if (region == NULL) { PrintError("Invalid region in passthrough page fault 64, addr=%p\n", @@ -54,7 +54,7 @@ static inline int handle_passthrough_pagefault_64(struct guest_info * info, return -1; } - host_addr = v3_get_shadow_addr(region, fault_addr); + host_addr = v3_get_shadow_addr(region, info->cpu_id, fault_addr); // // Lookup the correct PML address based on the PAGING MODE diff --git a/palacios/src/palacios/vmm_mem.c b/palacios/src/palacios/vmm_mem.c index b59ace0..ea3dec6 100644 --- a/palacios/src/palacios/vmm_mem.c +++ b/palacios/src/palacios/vmm_mem.c @@ -100,7 +100,7 @@ void v3_delete_shadow_map(struct v3_vm_info * vm) { -int v3_add_shadow_mem( 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) @@ -114,6 +114,7 @@ int v3_add_shadow_mem( struct v3_vm_info * vm, entry->write_hook = NULL; entry->read_hook = NULL; entry->priv_data = NULL; + entry->core_id = core_id; if (insert_shadow_region(vm, entry)) { V3_Free(entry); @@ -125,8 +126,8 @@ int v3_add_shadow_mem( struct v3_vm_info * vm, -int v3_hook_write_mem(struct v3_vm_info * vm, addr_t guest_addr_start, addr_t guest_addr_end, - addr_t host_addr, +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)(addr_t guest_addr, void * src, uint_t length, void * priv_data), void * priv_data) { @@ -140,6 +141,7 @@ int v3_hook_write_mem(struct v3_vm_info * vm, addr_t guest_addr_start, addr_t gu entry->write_hook = write; entry->read_hook = NULL; entry->priv_data = priv_data; + entry->core_id = core_id; if (insert_shadow_region(vm, entry)) { V3_Free(entry); @@ -149,7 +151,8 @@ int v3_hook_write_mem(struct v3_vm_info * vm, addr_t guest_addr_start, addr_t gu return 0; } -int v3_hook_full_mem(struct v3_vm_info * vm, addr_t guest_addr_start, addr_t guest_addr_end, +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)(addr_t guest_addr, void * dst, uint_t length, void * priv_data), int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data), void * priv_data) { @@ -163,7 +166,8 @@ int v3_hook_full_mem(struct v3_vm_info * vm, addr_t guest_addr_start, addr_t gue entry->write_hook = write; entry->read_hook = read; entry->priv_data = priv_data; - + entry->core_id = core_id; + if (insert_shadow_region(vm, entry)) { V3_Free(entry); return -1; @@ -175,8 +179,8 @@ int v3_hook_full_mem(struct v3_vm_info * vm, addr_t guest_addr_start, addr_t gue // 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, addr_t guest_addr_start) { - struct v3_shadow_region * reg = v3_get_shadow_region(vm, guest_addr_start); +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->host_type != SHDW_REGION_FULL_HOOK) || (reg->host_type != SHDW_REGION_WRITE_HOOK)) { @@ -207,7 +211,17 @@ struct v3_shadow_region * __insert_shadow_region(struct v3_vm_info * vm, } else if (region->guest_start >= tmp_region->guest_end) { p = &(*p)->rb_right; } else { - return tmp_region; + if ((region->guest_end != tmp_region->guest_end) || + (region->guest_start != tmp_region->guest_start)) { + PrintError("Trying to map a partial overlapped core specific page...\n"); + return tmp_region; // This is ugly... + } else if (region->core_id == tmp_region->core_id) { + return tmp_region; + } else if (region->core_id < tmp_region->core_id) { + p = &(*p)->rb_left; + } else { + p = &(*p)->rb_right; + } } } @@ -270,11 +284,10 @@ struct v3_shadow_region * insert_shadow_region(struct v3_vm_info * vm, -int handle_special_page_fault(struct guest_info * info, - addr_t fault_gva, addr_t fault_gpa, - pf_error_t access_info) +int handle_special_page_fault(struct guest_info * info, + addr_t fault_gva, addr_t fault_gpa, pf_error_t access_info) { - struct v3_shadow_region * reg = v3_get_shadow_region(info->vm_info, fault_gpa); + struct v3_shadow_region * reg = v3_get_shadow_region(info->vm_info, info->cpu_id, fault_gpa); PrintDebug("Handling Special Page Fault\n"); @@ -294,7 +307,7 @@ int handle_special_page_fault(struct guest_info * info, int v3_handle_mem_wr_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 dst_addr = (addr_t)V3_VAddr((void *)v3_get_shadow_addr(reg, guest_pa)); + addr_t dst_addr = (addr_t)V3_VAddr((void *)v3_get_shadow_addr(reg, info->cpu_id, guest_pa)); if (v3_emulate_write_op(info, guest_va, guest_pa, dst_addr, reg->write_hook, reg->priv_data) == -1) { @@ -330,7 +343,7 @@ int v3_handle_mem_full_hook(struct guest_info * info, addr_t guest_va, addr_t gu -struct v3_shadow_region * v3_get_shadow_region(struct v3_vm_info * vm, addr_t guest_addr) { +struct v3_shadow_region * v3_get_shadow_region(struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr) { struct rb_node * n = vm->mem_map.shdw_regions.rb_node; struct v3_shadow_region * reg = NULL; @@ -342,7 +355,12 @@ struct v3_shadow_region * v3_get_shadow_region(struct v3_vm_info * vm, addr_t gu } else if (guest_addr >= reg->guest_end) { n = n->rb_right; } else { + if ((core_id == reg->core_id) || + (reg->core_id == V3_MEM_CORE_ANY)) { return reg; + } else { + n = n->rb_right; + } } } @@ -413,7 +431,7 @@ void v3_delete_shadow_region(struct v3_vm_info * vm, struct v3_shadow_region * r -addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, addr_t guest_addr) { +addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, uint16_t core_id, addr_t guest_addr) { if ( (reg) && (reg->host_type != SHDW_REGION_FULL_HOOK)) { return (guest_addr - reg->guest_start) + reg->host_addr; diff --git a/palacios/src/palacios/vmm_shadow_paging_32.h b/palacios/src/palacios/vmm_shadow_paging_32.h index ab1e291..5e1d9c9 100644 --- a/palacios/src/palacios/vmm_shadow_paging_32.h +++ b/palacios/src/palacios/vmm_shadow_paging_32.h @@ -206,7 +206,7 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]); addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) + PAGE_OFFSET(fault_addr); - struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info->vm_info, guest_pa); + struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info->vm_info, info->cpu_id, guest_pa); if (shdw_reg == NULL) { // Inject a machine check in the guest @@ -341,7 +341,7 @@ static int handle_pte_shadow_pagefault_32(struct guest_info * info, addr_t fault if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) || (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) { - addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, guest_pa); + addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, info->cpu_id, guest_pa); shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa); @@ -427,7 +427,7 @@ static int handle_4MB_shadow_pagefault_32(struct guest_info * info, PrintDebug("Handling 4MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code); PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde); - struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info->vm_info, guest_fault_pa); + struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info->vm_info, info->cpu_id, guest_fault_pa); if (shdw_reg == NULL) { @@ -450,7 +450,7 @@ static int handle_4MB_shadow_pagefault_32(struct guest_info * info, if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) || (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) { - addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, guest_fault_pa); + addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, info->cpu_id, guest_fault_pa); shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa); diff --git a/palacios/src/palacios/vmm_shadow_paging_64.h b/palacios/src/palacios/vmm_shadow_paging_64.h index 1da1f99..af149fd 100644 --- a/palacios/src/palacios/vmm_shadow_paging_64.h +++ b/palacios/src/palacios/vmm_shadow_paging_64.h @@ -408,7 +408,7 @@ static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault PrintDebug("Handling PTE fault\n"); - struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info->vm_info, guest_pa); + struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info->vm_info, info->cpu_id, guest_pa); @@ -454,7 +454,7 @@ static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) || (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) { - addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, guest_pa); + addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, info->cpu_id, guest_pa); shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa); @@ -536,7 +536,7 @@ static int handle_2MB_shadow_pagefault_64(struct guest_info * info, PrintDebug("Handling 2MB fault (guest_fault_pa=%p) (error_code=%x)\n", (void *)guest_fault_pa, *(uint_t*)&error_code); PrintDebug("ShadowPT=%p, LargeGuestPDE=%p\n", shadow_pt, large_guest_pde); - struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info->vm_info, guest_fault_pa); + struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info->vm_info, info->cpu_id, guest_fault_pa); if (shdw_reg == NULL) { @@ -560,7 +560,7 @@ static int handle_2MB_shadow_pagefault_64(struct guest_info * info, if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) || (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) { - addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, guest_fault_pa); + addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, info->cpu_id, guest_fault_pa); shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);