Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Add load-time configurable memory block size
Peter Dinda [Sun, 4 Aug 2013 22:31:02 +0000 (17:31 -0500)]
Kconfig
palacios/include/palacios/vmm_mem.h
palacios/src/palacios/vmm.c
palacios/src/palacios/vmm_checkpoint.c
palacios/src/palacios/vmm_mem.c

diff --git a/Kconfig b/Kconfig
index eebccc4..9c9dfe2 100644 (file)
--- 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"
index e4505db..ff20faf 100644 (file)
@@ -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__ */
 
index f28266c..b49b75e 100644 (file)
@@ -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;i<vm->num_cores;i++) { 
        if (vm->cores[i].shdw_pg_mode == SHADOW_PAGING) {
            for (j=0;j<vm->mem_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;i<vm->mem_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;
index 049e05e..3872abb 100644 (file)
@@ -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;i<vm->mem_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;i<vm->mem_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;
index d1d2b43..d934398 100644 (file)
 #include <palacios/vmm_direct_paging.h>
 
 
+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
+}