From: Peter Dinda Date: Sun, 4 Aug 2013 22:31:02 +0000 (-0500) Subject: Add load-time configurable memory block size X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=c17cafcb6db943bd5bbb31d86f0392c113b2d668;hp=6b964ba81db60030c37b66da2c2b4a38f4ef8d96;p=palacios.git Add load-time configurable memory block size --- diff --git a/Kconfig b/Kconfig index eebccc4..9c9dfe2 100644 --- a/Kconfig +++ b/Kconfig @@ -121,8 +121,10 @@ config MEM_BLOCK_SIZE int "Allocation size for underlying VM memory" default 134217728 help - This is the size in bytes of the underlying memory allocations used for the base memory regions. - A good default value is 128MB (134217728 or 0x8000000 bytes) + This is the default size in bytes of the underlying memory allocations used for the base memory regions. + A good default value is 128MB (134217728 or 0x8000000 bytes). Note that the host interface must be able + to provide contiguous memory of at least this size in order for VMs to typically work. This + value can be overriden via a load-time option, provided the host supports this. config ALIGNED_PG_ALLOC bool "Host support for aligned page allocations" diff --git a/palacios/include/palacios/vmm_mem.h b/palacios/include/palacios/vmm_mem.h index e4505db..ff20faf 100644 --- a/palacios/include/palacios/vmm_mem.h +++ b/palacios/include/palacios/vmm_mem.h @@ -119,6 +119,9 @@ uint32_t v3_get_max_page_size(struct guest_info * core, addr_t fault_addr, v3_cp void v3_print_mem_map(struct v3_vm_info * vm); +void v3_init_mem(); +void v3_deinit_mem(); + #endif /* ! __V3VEE__ */ diff --git a/palacios/src/palacios/vmm.c b/palacios/src/palacios/vmm.c index f28266c..b49b75e 100644 --- a/palacios/src/palacios/vmm.c +++ b/palacios/src/palacios/vmm.c @@ -50,7 +50,6 @@ int v3_dbg_enable = 0; - static void init_cpu(void * arg) { uint32_t cpu_id = (uint32_t)(addr_t)arg; @@ -121,6 +120,9 @@ void Init_V3(struct v3_os_hooks * hooks, char * cpu_mask, int num_cpus, char *op // Parse host-os defined options into an easily-accessed format. v3_parse_options(options); + // Memory manager initialization + v3_init_mem(); + // Register all the possible device types V3_init_devices(); @@ -197,6 +199,8 @@ void Shutdown_V3() { } } + v3_deinit_mem(); + } @@ -278,6 +282,7 @@ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) { uint8_t * core_mask = (uint8_t *)&cpu_mask; // This is to make future expansion easier uint32_t avail_cores = 0; int vcore_id = 0; + extern uint64_t v3_mem_block_size; if (vm->run_state != VM_STOPPED) { @@ -290,7 +295,7 @@ int v3_start_vm(struct v3_vm_info * vm, unsigned int cpu_mask) { for (i=0;inum_cores;i++) { if (vm->cores[i].shdw_pg_mode == SHADOW_PAGING) { for (j=0;jmem_map.num_base_regions;j++) { - if ((vm->mem_map.base_regions[i].host_addr + V3_CONFIG_MEM_BLOCK_SIZE) >= 0x100000000ULL) { + if ((vm->mem_map.base_regions[i].host_addr + v3_mem_block_size) >= 0x100000000ULL) { PrintError(vm, VCORE_NONE, "Base memory region %d exceeds 4 GB boundary with shadow paging enabled on core %d.\n",j, i); PrintError(vm, VCORE_NONE, "Any use of non-64 bit mode in the guest is likely to fail in this configuration.\n"); PrintError(vm, VCORE_NONE, "If you would like to proceed anyway, remove this check and recompile Palacios.\n"); @@ -644,7 +649,7 @@ int v3_get_state_vm(struct v3_vm_info *vm, uint32_t i; uint32_t numcores = core->num_vcores > vm->num_cores ? vm->num_cores : core->num_vcores; uint32_t numregions = mem->num_regions > vm->mem_map.num_base_regions ? vm->mem_map.num_base_regions : mem->num_regions; - + extern uint64_t v3_mem_block_size; switch (vm->run_state) { case VM_INVALID: base->state = V3_VM_INVALID; break; @@ -692,7 +697,7 @@ int v3_get_state_vm(struct v3_vm_info *vm, for (i=0;imem_map.num_base_regions;i++) { mem->region[i].host_paddr = (void*)(vm->mem_map.base_regions[i].host_addr); - mem->region[i].size = V3_CONFIG_MEM_BLOCK_SIZE; + mem->region[i].size = v3_mem_block_size; } mem->num_regions=numregions; diff --git a/palacios/src/palacios/vmm_checkpoint.c b/palacios/src/palacios/vmm_checkpoint.c index 049e05e..3872abb 100644 --- a/palacios/src/palacios/vmm_checkpoint.c +++ b/palacios/src/palacios/vmm_checkpoint.c @@ -316,6 +316,7 @@ static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { void * ctx = NULL; uint64_t ret = 0; int i; + extern uint64_t v3_mem_block_size; ctx = v3_chkpt_open_ctx(chkpt, "memory_img"); @@ -327,7 +328,7 @@ static int load_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { for (i=0;imem_map.num_base_regions;i++) { guest_mem_base = V3_VAddr((void *)vm->mem_map.base_regions[i].host_addr); - if (v3_chkpt_load(ctx, "memory_img", V3_CONFIG_MEM_BLOCK_SIZE, guest_mem_base)) { + if (v3_chkpt_load(ctx, "memory_img", v3_mem_block_size, guest_mem_base)) { PrintError(vm, VCORE_NONE, "Unable to load all of memory (region %d) (requested=%llu bytes, result=%llu bytes\n",i,(uint64_t)(vm->mem_size),ret); v3_chkpt_close_ctx(ctx); return -1; @@ -344,6 +345,7 @@ static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { void * guest_mem_base = NULL; void * ctx = NULL; uint64_t ret = 0; + extern uint64_t v3_mem_block_size; int i; @@ -356,7 +358,7 @@ static int save_memory(struct v3_vm_info * vm, struct v3_chkpt * chkpt) { for (i=0;imem_map.num_base_regions;i++) { guest_mem_base = V3_VAddr((void *)vm->mem_map.base_regions[i].host_addr); - if (v3_chkpt_save(ctx, "memory_img", V3_CONFIG_MEM_BLOCK_SIZE, guest_mem_base)) { + if (v3_chkpt_save(ctx, "memory_img", v3_mem_block_size, guest_mem_base)) { PrintError(vm, VCORE_NONE, "Unable to save all of memory (region %d) (requested=%llu, received=%llu)\n",i,(uint64_t)(vm->mem_size),ret); v3_chkpt_close_ctx(ctx); return -1; diff --git a/palacios/src/palacios/vmm_mem.c b/palacios/src/palacios/vmm_mem.c index d1d2b43..d934398 100644 --- a/palacios/src/palacios/vmm_mem.c +++ b/palacios/src/palacios/vmm_mem.c @@ -28,12 +28,14 @@ #include +uint64_t v3_mem_block_size = V3_CONFIG_MEM_BLOCK_SIZE; + struct v3_mem_region * v3_get_base_region(struct v3_vm_info * vm, addr_t gpa) { struct v3_mem_map * map = &(vm->mem_map); - uint32_t block_index = gpa / V3_CONFIG_MEM_BLOCK_SIZE; + uint32_t block_index = gpa / v3_mem_block_size; - if (gpa > (map->num_base_regions * V3_CONFIG_MEM_BLOCK_SIZE) || + if (gpa > (map->num_base_regions * v3_mem_block_size) || (block_index >= map->num_base_regions)) { PrintError(vm, VCORE_NONE, "Guest Address Exceeds Base Memory Size (ga=0x%p), (limit=0x%p)\n", (void *)gpa, (void *)vm->mem_size); @@ -106,11 +108,11 @@ static int gpa_to_node_from_cfg(struct v3_vm_info * vm, addr_t gpa) { int v3_init_mem_map(struct v3_vm_info * vm) { struct v3_mem_map * map = &(vm->mem_map); - addr_t block_pages = V3_CONFIG_MEM_BLOCK_SIZE >> 12; + addr_t block_pages = v3_mem_block_size >> 12; int i = 0; - map->num_base_regions = (vm->mem_size / V3_CONFIG_MEM_BLOCK_SIZE) + \ - ((vm->mem_size % V3_CONFIG_MEM_BLOCK_SIZE) > 0); + map->num_base_regions = (vm->mem_size / v3_mem_block_size) + \ + ((vm->mem_size % v3_mem_block_size) > 0); map->mem_regions.rb_node = NULL; @@ -128,10 +130,10 @@ int v3_init_mem_map(struct v3_vm_info * vm) { for (i = 0; i < map->num_base_regions; i++) { struct v3_mem_region * region = &(map->base_regions[i]); int node_id = -1; - + // 2MB page alignment needed for 2MB hardware nested paging - region->guest_start = V3_CONFIG_MEM_BLOCK_SIZE * i; - region->guest_end = region->guest_start + V3_CONFIG_MEM_BLOCK_SIZE; + region->guest_start = v3_mem_block_size * i; + region->guest_end = region->guest_start + v3_mem_block_size; // We assume that the xml config was smart enough to align the layout to the block size // If they didn't we're going to ignore their settings @@ -152,7 +154,7 @@ int v3_init_mem_map(struct v3_vm_info * vm) { } // Clear the memory... - memset(V3_VAddr((void *)region->host_addr), 0, V3_CONFIG_MEM_BLOCK_SIZE); + memset(V3_VAddr((void *)region->host_addr), 0, v3_mem_block_size); region->flags.read = 1; region->flags.write = 1; @@ -174,7 +176,7 @@ void v3_delete_mem_map(struct v3_vm_info * vm) { struct rb_node * node = v3_rb_first(&(map->mem_regions)); struct v3_mem_region * reg; struct rb_node * tmp_node = NULL; - addr_t block_pages = V3_CONFIG_MEM_BLOCK_SIZE >> 12; + addr_t block_pages = v3_mem_block_size >> 12; int i = 0; while (node) { @@ -650,3 +652,20 @@ void v3_print_mem_map(struct v3_vm_info * vm) { } while ((node = v3_rb_next(node))); } + +void v3_init_mem() +{ + char *arg = v3_lookup_option("mem_block_size"); + + if (arg) { + v3_mem_block_size = atoi(arg); + V3_Print(VM_NONE,VCORE_NONE,"memory block size set to %llu bytes\n",v3_mem_block_size); + } else { + V3_Print(VM_NONE,VCORE_NONE,"default memory block size of %llu bytes is in use\n",v3_mem_block_size); + } +} + +void v3_deinit_mem() +{ + // currently nothing +}