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.


*** empty log message ***
[palacios.git] / palacios / src / geekos / vmm_mem.c
index 1071b74..20899b0 100644 (file)
 extern struct vmm_os_hooks * os_hooks;
 
 
-void init_mem_list(vmm_mem_list_t * list) {
-  list->num_pages = 0;
-  list->long_mode = false;
-  
-  list->num_regions = 0;
-  list->head = NULL;
+void init_shadow_map_entry(shadow_map_entry_t *entry,
+                          addr_t              guest_addr_start,
+                          addr_t              guest_addr_end,
+                          guest_region_type_t guest_region_type,
+                          host_region_type_t  host_region_type)
+{
+  entry->guest_type=guest_region_type;
+  entry->guest_start=guest_addr_start;
+  entry->guest_end=guest_addr_end;
+  entry->host_type=host_region_type;
+  entry->next=entry->prev=NULL;
 }
 
-
-void free_mem_list(vmm_mem_list_t * list) {
-  mem_region_t * cursor = list->head;
-  mem_region_t * tmp = NULL;
-
-  while(cursor) {
-    tmp = cursor;
-    cursor = cursor->next;
-    VMMFree(tmp);
-  }
-
-  VMMFree(list);
-}
-
-/*** FOR THE LOVE OF GOD WRITE SOME UNIT TESTS FOR THIS THING ***/
-
-
-
-// Scan the current list, and extend an existing region if one exists
-// Otherwise create a new region and merge it into the correct location in the list
-//
-// We scan to find the position at which to add the new region and insert it
-// Then we clean up any region following the new region that overlaps
-// 
-// JRL: This is pretty hairy...
-int add_mem_list_pages(vmm_mem_list_t * list, addr_t addr, uint_t num_pages) {
-
-  uint_t num_new_pages = num_pages;
-  addr_t new_end = addr + (num_pages * PAGE_SIZE) - 1;
-
-  mem_region_t * cursor = get_mem_list_cursor(list, addr);
-
-
-  // PrintDebug("Adding: 0x%x - 0x%x\n", addr, num_pages * PAGE_SIZE);
-
-
-  // Make a new region at the head of the list
-  if (cursor == NULL) {
-    cursor = os_hooks->malloc(sizeof(mem_region_t));
-
-    cursor->prev = NULL;
-    cursor->addr = addr;
-    cursor->num_pages = num_pages;
-
-    cursor->next = list->head;
-    list->head = cursor;
-
-    if (cursor->next) {
-      cursor->next->prev = cursor;
-    }
-
-    list->num_regions++;
-  } else {
-    addr_t cursor_end = cursor->addr + (cursor->num_pages * PAGE_SIZE) - 1;
-
-    if (addr > cursor_end + 1) {
-      // address falls after cursor region
-      
-      mem_region_t * new_region = os_hooks->malloc(sizeof(mem_region_t));
-
-      new_region->prev = cursor;
-      new_region->next = cursor->next;
-
-      if (cursor->next) {
-       cursor->next->prev = new_region;
-      }
-      cursor->next = new_region;
-
-      new_region->addr = addr;
-      new_region->num_pages = num_pages;
-
-      list->num_regions++;
-
-      cursor = new_region;
-    } else if ((addr >= cursor->addr) && 
-              (addr <= cursor_end + 1)) {
-      // address falls inside the cursor region
-
-
-      // The region has already been added
-      if (new_end <= cursor_end) {
-       return -1;
-      }
-
-      // We need to extend the old region
-      num_new_pages = (new_end - cursor_end) / PAGE_SIZE;
-      cursor->num_pages += num_new_pages;
-
-    }
-  }
-
-    
-  // Clean up any overlaps that follow
-  while ((cursor->next) && (cursor->next->addr <= new_end + 1)) {
-    mem_region_t * overlap = cursor->next;
-    addr_t overlap_end = overlap->addr + (overlap->num_pages * PAGE_SIZE) - 1;
-    
-    cursor->next = overlap->next;
-    if (overlap->next) {
-      overlap->next->prev = cursor;
-    }
-    
-    if (overlap_end > new_end) {
-      uint_t extension = (overlap_end - new_end) / PAGE_SIZE;
-
-      cursor->num_pages += extension;
-      num_new_pages -= (overlap->num_pages - extension);
-    } else {
-      num_new_pages -= overlap->num_pages;
-    }
-    
-    VMMFree(overlap);
-    
-    list->num_regions--;
-  }
-
-
-  list->num_pages += num_new_pages;
-
-  return 0;
-}
-
-
-/* this function returns a pointer to the location in the memory list that 
- * corresponds to addr.
- * Rules: 
- *     IF addr is in a region, a ptr to that region is returned
- *     IF addr is not in a region, a ptr to the previous region is returned
- *     IF addr is before all regions, returns NULL
- *     IF list is empty, returns NULL
- */
-mem_region_t * get_mem_list_cursor(vmm_mem_list_t * list, addr_t addr) {
-  mem_region_t * prev_region = list->head;
-
-  while (prev_region != NULL) {
-    if ( (addr >= prev_region->addr) && 
-        (addr < (prev_region->addr + (prev_region->num_pages * PAGE_SIZE) - 1)) ) {
-      return prev_region;
-    } else if (addr < prev_region->addr) {
-      // If this region is the current head, then this should return NULL
-      return prev_region->prev;
-    } else if (addr >= (prev_region->addr + (prev_region->num_pages * PAGE_SIZE))) {
-      if (prev_region->next) {
-       prev_region = prev_region->next;
-      } else {
-       return prev_region;
-      }
-    }
-  }
-
-  return prev_region;
-}
-
-
-
-/* Returns the page address of page number 'index' in the memory list
- * If index is out of bounds... returns -1 (an invalid page address)
- */
-addr_t get_mem_list_addr(vmm_mem_list_t * list, uint_t index) {
-  mem_region_t * reg = list->head;
-  uint_t i = index;
-
-  // Memory List overrun
-  if (index > list->num_pages - 1) {
-    return -1;
-  }
-
-  while (i >= 0) {
-    if (reg->num_pages <= index) {
-      i -= reg->num_pages;
-      reg = reg->next;
-    } else {
-      return reg->addr + (i * PAGE_SIZE);
-    }
-  }
-
-  return -1;
+void init_shadow_map_entry_physical(shadow_map_entry_t *entry,
+                                   addr_t              guest_addr_start,
+                                   addr_t              guest_addr_end,
+                                   guest_region_type_t guest_region_type,
+                                   addr_t              host_addr_start,
+                                   addr_t              host_addr_end,
+                                   host_region_type_t  host_region_type)
+{
+  init_shadow_map_entry(entry,guest_addr_start,guest_addr_end,guest_region_type,host_region_type);
+  entry->host_addr.phys_addr.host_start=host_addr_start;
+  entry->host_addr.phys_addr.host_end=host_addr_end;
 }
+                   
 
+void init_shadow_map(shadow_map_t * map) 
+{
+  map->num_regions = 0;
 
-void init_mem_layout(vmm_mem_layout_t * layout) {
-  layout->num_pages = 0;
-  layout->num_regions = 0;
-
-  layout->head = NULL;
+  map->head = NULL;
 }
 
 
-void free_mem_layout(vmm_mem_layout_t * layout) {
-  layout_region_t * cursor = layout->head;
-  layout_region_t * tmp = NULL;
+void free_shadow_map(shadow_map_t * map) {
+  shadow_map_entry_t * cursor = map->head;
+  shadow_map_entry_t * tmp = NULL;
 
   while(cursor) {
     tmp = cursor;
@@ -211,208 +50,165 @@ void free_mem_layout(vmm_mem_layout_t * layout) {
     VMMFree(tmp);
   }
 
-  VMMFree(layout);
+  VMMFree(map);
 
 }
 
 
 
-/* This is slightly different semantically from the mem list, in that we don't allow overlaps
- * we could probably allow overlappig regions of the same type... but I'll let someone else deal with that
+/* This is slightly different semantically from the mem list, in that
+ * we don't allow overlaps we could probably allow overlappig regions
+ * of the same type... but I'll let someone else deal with that
  */
-int add_mem_range(vmm_mem_layout_t * layout, layout_region_t * region) {
-  layout_region_t * cursor = layout->head;
+int add_shadow_map_region(shadow_map_t * map,
+                         shadow_map_entry_t * region) 
+{
+  shadow_map_entry_t * cursor = map->head;
 
-  if ((!cursor) || (cursor->start >= region->end)) {
+  if ((!cursor) || (cursor->guest_start >= region->guest_end)) {
     region->prev = NULL;
     region->next = cursor;
-    layout->num_pages += (region->end - region->start) / PAGE_SIZE;
-    layout->num_regions++;
-    layout->head = region;
-
+    map->num_regions++;
+    map->head = region;
     return 0;
   }
 
   while (cursor) {
     // Check if it overlaps with the current cursor
-    if ((cursor->end > region->start) && (cursor->start < region->start)) {
+    if ((cursor->guest_end > region->guest_start) && (cursor->guest_start < region->guest_start)) {
       // overlaps not allowed
       return -1;
     }
     
-    // add to the end of the list
     if (!(cursor->next)) {
+      // add to the end of the list
       cursor->next = region;
       region->prev = cursor;
-      layout->num_regions++;
-      layout->num_pages += (region->end - region->start) / PAGE_SIZE;
+      region->next = NULL;
+      map->num_regions++;
       return 0;
-    } else if (cursor->next->start >= region->end) {
+    } else if (cursor->next->guest_start >= region->guest_end) {
       // add here
       region->next = cursor->next;
       region->prev = cursor;
-
+      
       cursor->next->prev = region;
       cursor->next = region;
 
-      layout->num_regions++;
-      layout->num_pages += (region->end - region->start) / PAGE_SIZE;
+      map->num_regions++;
       
       return 0;
-    } else if (cursor->next->end < region->start) {
+    } else if (cursor->next->guest_end < region->guest_start) {
       cursor = cursor->next;
     } else {
+      // This cannot happen!
+      // we should panic here
       return -1;
     }
   }
-
+  
+  // This cannot happen
+  // We should panic here
   return -1;
 }
 
 
-
-
-
-int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end, addr_t host_addr) {
-  layout_region_t * shared_region = os_hooks->malloc(sizeof(layout_region_t));
-  int ret;
-
-  shared_region->next = NULL;
-  shared_region->prev = NULL;
-  shared_region->start = start;
-  shared_region->end = end;
-  shared_region->type = SHARED;
-  shared_region->host_addr = host_addr;
-
-  ret = add_mem_range(layout, shared_region);
-
-  if (ret != 0) {
-    VMMFree(shared_region);
-  }
-
-  return ret;
-}
-
-int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end) {
-  layout_region_t * unmapped_region = os_hooks->malloc(sizeof(layout_region_t));
-  int ret;  
-
-  unmapped_region->next = NULL;
-  unmapped_region->prev = NULL;
-  unmapped_region->start = start;
-  unmapped_region->end = end;
-  unmapped_region->type = UNMAPPED;
-  unmapped_region->host_addr = 0;
-
-  ret = add_mem_range(layout, unmapped_region);
-
-  if (ret != 0) {
-    VMMFree(unmapped_region);
-  }
-
-  return ret;
-}
-
-int add_guest_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end) {
-  layout_region_t * guest_region = os_hooks->malloc(sizeof(layout_region_t));
-  int ret;
-
-  guest_region->next = NULL;
-  guest_region->prev = NULL;
-  guest_region->start = start;
-  guest_region->end = end;
-  guest_region->type = GUEST;
-  guest_region->host_addr = 0;
-
-  ret = add_mem_range(layout, guest_region);
-  
-  if (ret != 0) {
-    VMMFree(guest_region);
-  }
-
-  return ret;
+int delete_shadow_map_region(shadow_map_t *map,
+                            addr_t guest_start,
+                            addr_t guest_end)
+{
+  return -1;
 }
 
 
 
-/* Returns the page address of page number 'index' in the memory list
- * If index is out of bounds... returns -1 (an invalid page address)
- */
-addr_t get_mem_layout_addr(vmm_mem_layout_t * layout, uint_t index) {
-  layout_region_t * reg = layout->head;
-  uint_t i = index;
+shadow_map_entry_t *get_shadow_map_region_by_index(shadow_map_t * map,
+                                                  uint_t index) 
+{
+  shadow_map_entry_t * reg = map->head;
+  uint_t i = 0;
 
-  // Memory List overrun
-  if (index > layout->num_pages - 1) {
-    return -1;
-  }
-
-  while (i >= 0) {
-    if (!reg) {
-      return -1;
-    }
-
-    int num_reg_pages = reg->end - reg->start;
-
-    if (num_reg_pages <= index) {
-      i -= num_reg_pages;
-      reg = reg->next;
-    } else {
-      return reg->start + (i * PAGE_SIZE);
+  while (reg) { 
+    if (i==index) { 
+      return reg;
     }
+    reg=reg->next;
+    i++;
   }
-
-  return -1;
+  return NULL;
 }
 
-layout_region_t * get_mem_layout_region(vmm_mem_layout_t * layout, addr_t addr) {
-  layout_region_t * tmp_reg = layout->head;
 
+shadow_map_entry_t * get_shadow_map_region_by_addr(shadow_map_t *map,
+                                                  addr_t addr) 
+{
+  shadow_map_entry_t * reg = map->head;
 
-  while (tmp_reg) {
-    if ((tmp_reg->start <= addr) && (tmp_reg->end > addr)) {
-      return tmp_reg;
-    } else if (tmp_reg->start > addr) {
+
+  while (reg) {
+    if ((reg->guest_start <= addr) && (reg->guest_end > addr)) {
+      return reg;
+    } else if (reg->guest_start > addr) {
       return NULL;
     } else {
-      tmp_reg = tmp_reg->next;
+      reg = reg->next;
     }
   }
-
   return NULL;
 }
 
 
 
+int map_guest_physical_to_host_physical(shadow_map_entry_t *entry, 
+                                       addr_t guest_addr,
+                                       addr_t *host_addr)
+{
+  if (!(guest_addr>=entry->guest_start && guest_addr<entry->guest_end)) { 
+    return -1;
+  }
 
-void print_mem_list(vmm_mem_list_t * list) {
-  mem_region_t * cur = list->head;
-  int i = 0;
-
-  PrintDebug("Memory Region List (regions: %d) (pages: %d)\n", list->num_regions, list->num_pages);
-
-  while (cur) {
-    PrintDebug("%d: 0x%x - 0x%x\n", i, cur->addr, cur->addr + (cur->num_pages * PAGE_SIZE) - 1);
-    cur = cur->next;
-    i++;
+  switch (entry->host_type) { 
+  case HOST_REGION_PHYSICAL_MEMORY:
+  case HOST_REGION_MEMORY_MAPPED_DEVICE:
+  case HOST_REGION_UNALLOCATED:
+    *host_addr=(guest_addr-entry->guest_start) + entry->host_addr.phys_addr.host_start;
+    return 0;
+    break;
+  default:
+    return -1;
+    break;
   }
-  PrintDebug("\n");
 }
 
 
-
-void print_mem_layout(vmm_mem_layout_t * layout) {
-  layout_region_t * cur = layout->head;
+void print_shadow_map(shadow_map_t *map) {
+  shadow_map_entry_t * cur = map->head;
   int i = 0;
 
-  PrintDebug("Memory Layout (regions: %d) (pages: %d)\n", layout->num_regions, layout->num_pages);
+  PrintDebug("Memory Layout (regions: %d) \n", map->num_regions);
 
   while (cur) {
-    PrintDebug("%d: 0x%x - 0x%x\n", i, cur->start, cur->end -1);
+    PrintDebug("%d:  0x%x - 0x%x (%s) -> ", i, cur->guest_start, cur->guest_end -1,
+              cur->guest_type == GUEST_REGION_PHYSICAL_MEMORY ? "GUEST_REGION_PHYSICAL_MEMORY" :
+              cur->guest_type == GUEST_REGION_NOTHING ? "GUEST_REGION_NOTHING" :
+              cur->guest_type == GUEST_REGION_MEMORY_MAPPED_DEVICE ? "GUEST_REGION_MEMORY_MAPPED_DEVICE" :
+              "UNKNOWN");            
+    if (cur->host_type==HOST_REGION_PHYSICAL_MEMORY || 
+       cur->host_type==HOST_REGION_UNALLOCATED ||
+       cur->host_type==HOST_REGION_MEMORY_MAPPED_DEVICE) { 
+      PrintDebug("0x%x - 0x%x ", cur->host_addr.phys_addr.host_start, cur->host_addr.phys_addr.host_end);
+    }
+    PrintDebug("(%s)\n",
+              cur->host_type == HOST_REGION_PHYSICAL_MEMORY ? "HOST_REGION_PHYSICAL_MEMORY" :
+              cur->host_type == HOST_REGION_UNALLOCATED ? "HOST_REGION_UNALLOACTED" :
+              cur->host_type == HOST_REGION_NOTHING ? "HOST_REGION_NOTHING" :
+              cur->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE ? "HOST_REGION_MEMORY_MAPPED_DEVICE" :
+              cur->host_type == HOST_REGION_REMOTE ? "HOST_REGION_REMOTE" : 
+              cur->host_type == HOST_REGION_SWAPPED ? "HOST_REGION_SWAPPED" :
+              "UNKNOWN");
     cur = cur->next;
     i++;
   }
-  PrintDebug("\n");
 }
 
 
@@ -424,7 +220,6 @@ void print_mem_layout(vmm_mem_layout_t * layout) {
 
 
 
-
 #ifdef VMM_MEM_TEST