From: Jack Lange Date: Fri, 17 Apr 2009 22:06:47 +0000 (-0500) Subject: changed memory map to be layered on top of a single contiguous allocation X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=058a3adde5893927ae056a1d8fbccd5191d2446f changed memory map to be layered on top of a single contiguous allocation added hypercall to retrieve offset --- diff --git a/palacios/include/palacios/vm_guest.h b/palacios/include/palacios/vm_guest.h index 005d32b..d23c823 100644 --- a/palacios/include/palacios/vm_guest.h +++ b/palacios/include/palacios/vm_guest.h @@ -130,7 +130,6 @@ struct guest_info { v3_paging_mode_t shdw_pg_mode; struct shadow_page_state shdw_pg_state; addr_t direct_map_pt; - // nested_paging_t nested_page_state; // This structure is how we get interrupts for the guest diff --git a/palacios/include/palacios/vmm_mem.h b/palacios/include/palacios/vmm_mem.h index 3408525..f87c8d0 100644 --- a/palacios/include/palacios/vmm_mem.h +++ b/palacios/include/palacios/vmm_mem.h @@ -38,18 +38,12 @@ struct guest_info; // These are the types of physical memory address regions // from the perspective of the HOST typedef enum shdw_region_type { - SHDW_REGION_INVALID, // This region is INVALID (this is a return type to denote errors) SHDW_REGION_WRITE_HOOK, // This region is mapped as read-only (page faults on write) SHDW_REGION_FULL_HOOK, // This region is mapped as not present (always generate page faults) SHDW_REGION_ALLOCATED, // Region is a section of host memory } v3_shdw_region_type_t; -typedef struct v3_shdw_map { - addr_t hook_hva; - - struct rb_root shdw_regions; -} v3_shdw_map_t; struct v3_shadow_region { @@ -72,6 +66,17 @@ struct v3_shadow_region { }; +typedef struct v3_shdw_map { + struct v3_shadow_region base_region; + + + addr_t hook_hva; + + struct rb_root shdw_regions; +} v3_shdw_map_t; + + + void v3_init_shadow_map(struct guest_info * info); void v3_delete_shadow_map(struct guest_info * info); diff --git a/palacios/src/palacios/vm_guest_mem.c b/palacios/src/palacios/vm_guest_mem.c index c88ecd2..ca040f7 100644 --- a/palacios/src/palacios/vm_guest_mem.c +++ b/palacios/src/palacios/vm_guest_mem.c @@ -74,8 +74,7 @@ int guest_pa_to_host_pa(struct guest_info * guest_info, addr_t guest_pa, addr_t return -1; } - if ((shdw_reg->host_type == SHDW_REGION_INVALID) || - (shdw_reg->host_type == SHDW_REGION_FULL_HOOK)) { + if (shdw_reg->host_type == SHDW_REGION_FULL_HOOK) { PrintError("In GPA->HPA: Could not find address in shadow map (addr=%p) (reg_type=%s)\n", (void *)guest_pa, v3_shdw_region_type_to_str(shdw_reg->host_type)); return -1; diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index eb03b0e..8531d58 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -76,6 +76,9 @@ static int passthrough_mem_write(addr_t guest_addr, void * src, uint_t length, v int v3_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) { extern v3_cpu_arch_t v3_cpu_type; + // Amount of ram the Guest will have, rounded to a 4K page boundary + info->mem_size = config_ptr->mem_size & ~(addr_t)0xfff; + // Initialize the subsystem data strutures v3_init_time(info); v3_init_io_map(info); @@ -86,9 +89,12 @@ int v3_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) v3_init_decoder(info); + v3_init_hypercall_map(info); + + + // Initialize the memory map v3_init_shadow_map(info); - v3_init_hypercall_map(info); if ((v3_cpu_type == V3_SVM_REV3_CPU) && (config_ptr->enable_nested_paging == 1)) { @@ -104,9 +110,6 @@ int v3_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) info->cpu_mode = REAL; info->mem_mode = PHYSICAL_MEM; - // Amount of ram the Guest will have, rounded to a 4K page boundary - info->mem_size = config_ptr->mem_size & ~(addr_t)0xfff; - // Configure the memory map for the guest if (setup_memory_map(info, config_ptr) == -1) { PrintError("Setting up guest memory map failed...\n"); @@ -116,8 +119,6 @@ int v3_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) // Configure the devices for the guest setup_devices(info, config_ptr); - - if (config_ptr->enable_profiling) { info->enable_profiler = 1; v3_init_profiler(info); @@ -141,28 +142,8 @@ int v3_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr) * We need to make sure the memory map extends to cover it */ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * config_ptr) { - addr_t mem_pages = info->mem_size >> 12; - PrintDebug("Setting up memory map (memory size=%dMB)\n", (uint_t)(info->mem_size / (1024 * 1024))); - // Fill up to the 640K hole - if (mem_pages >= 160) { - if (v3_add_shadow_mem(info, 0x0, 0xa0000, (addr_t)V3_AllocPages(160)) == -1) { - PrintError("Could not map full conventional memory\n"); - return -1; - } - } else { - // Less than 640k of memory - if (v3_add_shadow_mem(info, 0x0, (mem_pages * PAGE_SIZE), (addr_t)V3_AllocPages(mem_pages)) == -1) { - PrintError("Could not map subset of conventional memory\n"); - return -1; - }; - } - - -#define VGABIOS_START 0x000c0000 -#define ROMBIOS_START 0x000f0000 - // VGA frame buffer if (1) { if (v3_add_shadow_mem(info, 0xa0000, 0xc0000, 0xa0000) == -1) { @@ -172,104 +153,31 @@ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * conf } else { v3_hook_write_mem(info, 0xa0000, 0xc0000, 0xa0000, passthrough_mem_write, NULL); } - - + +#define VGABIOS_START 0x000c0000 +#define ROMBIOS_START 0x000f0000 + /* layout vgabios */ { - uint_t num_pages = (config_ptr->vgabios_size + PAGE_SIZE - 1) / PAGE_SIZE; - void * guest_mem = V3_AllocPages(num_pages); - addr_t vgabios_end = VGABIOS_START + (num_pages * PAGE_SIZE); - - PrintDebug("Layout Region %d bytes\n", config_ptr->vgabios_size); - memcpy(V3_VAddr(guest_mem), config_ptr->vgabios, config_ptr->vgabios_size); - - if (v3_add_shadow_mem(info, VGABIOS_START, vgabios_end, (addr_t)guest_mem) == -1) { - PrintError("Could not map VGABIOS\n"); - return -1; - } - - PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n", - (void *)VGABIOS_START, - (void *)vgabios_end, - (void *)guest_mem); - - - // Fill in the space between the VGABIOS and the ROMBIOS - // We'll just back this to shadow memory for now.... - if (v3_add_shadow_mem(info, vgabios_end, ROMBIOS_START, - (addr_t)V3_AllocPages((ROMBIOS_START - vgabios_end) / PAGE_SIZE)) == -1) { - PrintError("Could not map VGABIOS->ROMBIOS gap\n"); - return -1; - } + addr_t vgabios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), VGABIOS_START); + memcpy(V3_VAddr((void *)vgabios_dst), config_ptr->vgabios, config_ptr->vgabios_size); } /* layout rombios */ { - uint_t num_pages = (config_ptr->rombios_size + PAGE_SIZE - 1) / PAGE_SIZE; - void * guest_mem = V3_AllocPages(num_pages); - addr_t rombios_end = ROMBIOS_START + (num_pages * PAGE_SIZE); - - PrintDebug("Layout Region %d bytes\n", config_ptr->rombios_size); - memcpy(V3_VAddr(guest_mem), config_ptr->rombios, config_ptr->rombios_size); - - if (v3_add_shadow_mem(info, ROMBIOS_START, rombios_end, (addr_t)guest_mem) == -1) { - PrintError("Could not map ROMBIOS\n"); - return -1; - } - - PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n", - (void *)ROMBIOS_START, - (void *)rombios_end, - (void *)guest_mem); - - if (rombios_end != 0x100000) { - PrintError("ROMBIOS must reach the 1MB barrier....\n"); - return -1; - } + addr_t rombios_dst = v3_get_shadow_addr(&(info->mem_map.base_region), ROMBIOS_START); + memcpy(V3_VAddr((void *)rombios_dst), config_ptr->rombios, config_ptr->rombios_size); } #ifdef CRAY_XT { #define SEASTAR_START 0xffe00000 #define SEASTAR_END 0xffffffff - - // Fill in generic memory below the seastar - addr_t top_of_mem = (SEASTAR_START < info->mem_size) ? SEASTAR_START : info->mem_size; - int num_low_pages = (top_of_mem - 0x100000) / PAGE_SIZE; - - if (v3_add_shadow_mem(info, 0x100000, top_of_mem, (addr_t)V3_AllocPages(num_low_pages)) == -1) { - PrintError("Could not extended memory below 4G\n"); - return -1; - } - // Map the Seastar straight through if (v3_add_shadow_mem(info, SEASTAR_START, SEASTAR_END, SEASTAR_START) == -1) { PrintError("Could not map through the seastar\n"); return -1; } - - - // Add memory above the seastar - if (info->mem_size > SEASTAR_END) { - int num_high_pages = mem_pages - (SEASTAR_END / PAGE_SIZE); - - if (v3_add_shadow_mem(info, SEASTAR_END, info->mem_size, (addr_t)V3_AllocPages(num_high_pages)) == -1) { - PrintError("Could not map extended memory above 4G\n"); - return -1; - } - } - } -#else - // Fill in the extended memory map.... - { - int num_ext_pages = mem_pages - (0x100000 / PAGE_SIZE); - - if (num_ext_pages > 0) { - if (v3_add_shadow_mem(info, 0x100000, info->mem_size, (addr_t)V3_AllocPages(num_ext_pages)) == -1) { - PrintError("Could not allocate extended shadow memory\n"); - return -1; - } - } } #endif diff --git a/palacios/src/palacios/vmm_direct_paging_32.h b/palacios/src/palacios/vmm_direct_paging_32.h index 6645f86..42da5b1 100644 --- a/palacios/src/palacios/vmm_direct_paging_32.h +++ b/palacios/src/palacios/vmm_direct_paging_32.h @@ -42,8 +42,7 @@ static inline int handle_passthrough_pagefault_32(struct guest_info * info, struct v3_shadow_region * region = v3_get_shadow_region(info, fault_addr); - if ((region == NULL) || - (region->host_type == SHDW_REGION_INVALID)) { + if (region == NULL) { PrintError("Invalid region in passthrough page fault 32, addr=%p\n", (void *)fault_addr); return -1; diff --git a/palacios/src/palacios/vmm_direct_paging_32pae.h b/palacios/src/palacios/vmm_direct_paging_32pae.h index 27cc9b3..d681969 100644 --- a/palacios/src/palacios/vmm_direct_paging_32pae.h +++ b/palacios/src/palacios/vmm_direct_paging_32pae.h @@ -42,8 +42,7 @@ static inline int handle_passthrough_pagefault_32pae(struct guest_info * info, struct v3_shadow_region * region = v3_get_shadow_region(info, fault_addr); - if ((region == NULL) || - (region->host_type == SHDW_REGION_INVALID)) { + if (region == NULL) { PrintError("Invalid region in passthrough page fault 32PAE, addr=%p\n", (void *)fault_addr); return -1; diff --git a/palacios/src/palacios/vmm_direct_paging_64.h b/palacios/src/palacios/vmm_direct_paging_64.h index ab82c9a..c42499d 100644 --- a/palacios/src/palacios/vmm_direct_paging_64.h +++ b/palacios/src/palacios/vmm_direct_paging_64.h @@ -48,8 +48,7 @@ static inline int handle_passthrough_pagefault_64(struct guest_info * info, struct v3_shadow_region * region = v3_get_shadow_region(info, fault_addr); - if ((region == NULL) || - (region->host_type == SHDW_REGION_INVALID)) { + if (region == NULL) { PrintError("Invalid region in passthrough page fault 64, addr=%p\n", (void *)fault_addr); return -1; diff --git a/palacios/src/palacios/vmm_mem.c b/palacios/src/palacios/vmm_mem.c index c244793..d37b3da 100644 --- a/palacios/src/palacios/vmm_mem.c +++ b/palacios/src/palacios/vmm_mem.c @@ -20,11 +20,10 @@ #include #include #include -//#include #include - +#define MEM_OFFSET_HCALL 0x1000 @@ -33,13 +32,27 @@ struct v3_shadow_region * insert_shadow_region(struct guest_info * info, struct v3_shadow_region * region); +static int mem_offset_hypercall(struct guest_info * info, uint_t hcall_id, void * private_data) { + info->vm_regs.rbx = info->mem_map.base_region.host_addr; + + return 0; +} + void v3_init_shadow_map(struct guest_info * info) { v3_shdw_map_t * map = &(info->mem_map); + addr_t mem_pages = info->mem_size >> 12; map->shdw_regions.rb_node = NULL; map->hook_hva = (addr_t)V3_VAddr(V3_AllocPages(1)); + // There is an underlying region that contains all of the guest memory + map->base_region.guest_start = 0; + map->base_region.guest_end = info->mem_size; + map->base_region.host_type = SHDW_REGION_ALLOCATED; + map->base_region.host_addr = (addr_t)V3_AllocPages(mem_pages); + + v3_register_hypercall(info, MEM_OFFSET_HCALL, mem_offset_hypercall, NULL); } void v3_delete_shadow_map(struct guest_info * info) { @@ -177,10 +190,6 @@ struct v3_shadow_region * insert_shadow_region(struct guest_info * info, - - - - int handle_special_page_fault(struct guest_info * info, addr_t fault_gva, addr_t fault_gpa, pf_error_t access_info) @@ -253,24 +262,19 @@ struct v3_shadow_region * v3_get_shadow_region(struct guest_info * info, addr_t } } - return NULL; -} - + // There is not registered region, so we check if its a valid address in the base region -addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, addr_t guest_addr) { - if ( (reg) && - (reg->host_type != SHDW_REGION_FULL_HOOK) && - (reg->host_type != SHDW_REGION_INVALID) ) { - return (guest_addr - reg->guest_start) + reg->host_addr; - } else { - PrintDebug("MEM Region Invalid\n"); - return 0; + if (guest_addr > info->mem_map.base_region.guest_end) { + PrintError("Guest Address Exceeds Base Memory Size (ga=%p), (limit=%p)\n", + (void *)guest_addr, (void *)info->mem_map.base_region.guest_end); + return NULL; } + + return &(info->mem_map.base_region); } - void v3_delete_shadow_region(struct guest_info * info, struct v3_shadow_region * reg) { if (reg != NULL) { v3_rb_erase(&(reg->tree_node), &(info->mem_map.shdw_regions)); @@ -282,13 +286,32 @@ void v3_delete_shadow_region(struct guest_info * info, struct v3_shadow_region * +addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, addr_t guest_addr) { + if ( (reg) && + (reg->host_type != SHDW_REGION_FULL_HOOK)) { + return (guest_addr - reg->guest_start) + reg->host_addr; + } else { + PrintDebug("MEM Region Invalid\n"); + return 0; + } + +} + + + void print_shadow_map(struct guest_info * info) { struct rb_node * node = v3_rb_first(&(info->mem_map.shdw_regions)); - struct v3_shadow_region * reg; + struct v3_shadow_region * reg = &(info->mem_map.base_region); int i = 0; PrintDebug("Memory Layout:\n"); + + PrintDebug("Base Region: 0x%p - 0x%p -> 0x%p\n", + (void *)(reg->guest_start), + (void *)(reg->guest_end - 1), + (void *)(reg->host_addr)); + do { reg = rb_entry(node, struct v3_shadow_region, tree_node); @@ -307,13 +330,10 @@ void print_shadow_map(struct guest_info * info) { } -static const uchar_t SHDW_REGION_INVALID_STR[] = "SHDW_REGION_INVALID"; static const uchar_t SHDW_REGION_WRITE_HOOK_STR[] = "SHDW_REGION_WRITE_HOOK"; static const uchar_t SHDW_REGION_FULL_HOOK_STR[] = "SHDW_REGION_FULL_HOOK"; static const uchar_t SHDW_REGION_ALLOCATED_STR[] = "SHDW_REGION_ALLOCATED"; - - const uchar_t * v3_shdw_region_type_to_str(v3_shdw_region_type_t type) { switch (type) { case SHDW_REGION_WRITE_HOOK: @@ -323,7 +343,7 @@ const uchar_t * v3_shdw_region_type_to_str(v3_shdw_region_type_t type) { case SHDW_REGION_ALLOCATED: return SHDW_REGION_ALLOCATED_STR; default: - return SHDW_REGION_INVALID_STR; + return (uchar_t *)"SHDW_REGION_INVALID"; } } diff --git a/palacios/src/palacios/vmm_shadow_paging_32.h b/palacios/src/palacios/vmm_shadow_paging_32.h index d9d54f4..755c9a6 100644 --- a/palacios/src/palacios/vmm_shadow_paging_32.h +++ b/palacios/src/palacios/vmm_shadow_paging_32.h @@ -287,8 +287,7 @@ static int handle_large_pagefault_32(struct guest_info * info, struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info, guest_fault_pa); - if ((shdw_reg == NULL) || - (shdw_reg->host_type == SHDW_REGION_INVALID)) { + if (shdw_reg == NULL) { // Inject a machine check in the guest PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa); v3_raise_exception(info, MC_EXCEPTION); @@ -395,8 +394,7 @@ static int handle_shadow_pte32_fault(struct guest_info * info, struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info, guest_pa); - if ((shdw_reg == NULL) || - (shdw_reg->host_type == SHDW_REGION_INVALID)) { + if (shdw_reg == NULL) { // Inject a machine check in the guest PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa); v3_raise_exception(info, MC_EXCEPTION); diff --git a/palacios/src/palacios/vmm_shadow_paging_64.h b/palacios/src/palacios/vmm_shadow_paging_64.h index db252d3..5bcf9c9 100644 --- a/palacios/src/palacios/vmm_shadow_paging_64.h +++ b/palacios/src/palacios/vmm_shadow_paging_64.h @@ -385,8 +385,7 @@ static int handle_pte_shadow_pagefault_64(struct guest_info * info, addr_t fault - if ((shdw_reg == NULL) || - (shdw_reg->host_type == SHDW_REGION_INVALID)) { + if (shdw_reg == NULL) { // Inject a machine check in the guest PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_pa); v3_raise_exception(info, MC_EXCEPTION); @@ -518,8 +517,7 @@ static int handle_2MB_shadow_pagefault_64(struct guest_info * info, struct v3_shadow_region * shdw_reg = v3_get_shadow_region(info, guest_fault_pa); - if ((shdw_reg == NULL) || - (shdw_reg->host_type == SHDW_REGION_INVALID)) { + if (shdw_reg == NULL) { // Inject a machine check in the guest PrintDebug("Invalid Guest Address in page table (0x%p)\n", (void *)guest_fault_pa); v3_raise_exception(info, MC_EXCEPTION);