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.


changed memory map to be layered on top of a single contiguous allocation
Jack Lange [Fri, 17 Apr 2009 22:06:47 +0000 (17:06 -0500)]
added hypercall to retrieve offset

palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm_mem.h
palacios/src/palacios/vm_guest_mem.c
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_direct_paging_32.h
palacios/src/palacios/vmm_direct_paging_32pae.h
palacios/src/palacios/vmm_direct_paging_64.h
palacios/src/palacios/vmm_mem.c
palacios/src/palacios/vmm_shadow_paging_32.h
palacios/src/palacios/vmm_shadow_paging_64.h

index 005d32b..d23c823 100644 (file)
@@ -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
index 3408525..f87c8d0 100644 (file)
@@ -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);
index c88ecd2..ca040f7 100644 (file)
@@ -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;
index eb03b0e..8531d58 100644 (file)
@@ -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    
 
index 6645f86..42da5b1 100644 (file)
@@ -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;
index 27cc9b3..d681969 100644 (file)
@@ -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;
index ab82c9a..c42499d 100644 (file)
@@ -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;
index c244793..d37b3da 100644 (file)
 #include <palacios/vmm_mem.h>
 #include <palacios/vmm.h>
 #include <palacios/vmm_util.h>
-//#include <palacios/vmm_decoder.h>
 #include <palacios/vmm_emulator.h>
 
 
-
+#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";
     }
 }
 
index d9d54f4..755c9a6 100644 (file)
@@ -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);
index db252d3..5bcf9c9 100644 (file)
@@ -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);