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.


added memory conversions and copies for the guest/host contexts
[palacios.git] / palacios / src / geekos / vmm_mem.c
index bba8333..0551675 100644 (file)
@@ -5,18 +5,42 @@
 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_region(shadow_region_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 init_shadow_region_physical(shadow_region_t * entry,
+                                addr_t               guest_addr_start,
+                                addr_t               guest_addr_end,
+                                guest_region_type_t  guest_region_type,
+                                addr_t               host_addr_start,
+                                host_region_type_t   host_region_type)
+{
+  init_shadow_region(entry, guest_addr_start, guest_addr_end, guest_region_type, host_region_type);
+  entry->host_addr.phys_addr.host_start = host_addr_start;
+
+}
+                   
+
+void init_shadow_map(shadow_map_t * map) {
+  map->num_regions = 0;
+
+  map->head = NULL;
 }
 
 
-void free_mem_list(vmm_mem_list_t * list) {
-  mem_region_t * cursor = list->head;
-  mem_region_t * tmp = NULL;
+void free_shadow_map(shadow_map_t * map) {
+  shadow_region_t * cursor = map->head;
+  shadow_region_t * tmp = NULL;
 
   while(cursor) {
     tmp = cursor;
@@ -24,330 +48,174 @@ void free_mem_list(vmm_mem_list_t * list) {
     VMMFree(tmp);
   }
 
-  VMMFree(list);
+  VMMFree(map);
 }
 
-/*** 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, ullong_t addr, uint_t num_pages) {
 
-  uint_t num_new_pages = num_pages;
-  ullong_t new_end = addr + (num_pages * PAGE_SIZE);
-
-  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 {
-    ullong_t cursor_end = cursor->addr + (cursor->num_pages * PAGE_SIZE);
-
-    if (addr > cursor_end) {
-      // 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)) {
-      // 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;
+/* 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_shadow_region(shadow_map_t * map,
+                     shadow_region_t * region) 
+{
+  shadow_region_t * cursor = map->head;
 
-    }
+  if ((!cursor) || (cursor->guest_start >= region->guest_end)) {
+    region->prev = NULL;
+    region->next = cursor;
+    map->num_regions++;
+    map->head = region;
+    return 0;
   }
-    
-  // Clean up any overlaps that follow
-  while ((cursor->next) && (cursor->next->addr <= new_end)) {
-    mem_region_t * overlap = cursor->next;
-    ullong_t overlap_end = overlap->addr + (overlap->num_pages * PAGE_SIZE);
-    
-    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;
+  while (cursor) {
+    // Check if it overlaps with the current cursor
+    if ((cursor->guest_end > region->guest_start) && (cursor->guest_start < region->guest_start)) {
+      // overlaps not allowed
+      return -1;
     }
     
-    VMMFree(overlap);
-    
-    list->num_regions--;
-  }
-
-
-  list->num_pages += num_new_pages;
-
-  return 0;
-}
-
+    if (!(cursor->next)) {
+      // add to the end of the list
+      cursor->next = region;
+      region->prev = cursor;
+      region->next = NULL;
+      map->num_regions++;
+      return 0;
+    } 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;
 
-/* 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, ullong_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))) ) {
-      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;
-      }
+      map->num_regions++;
+      
+      return 0;
+    } else if (cursor->next->guest_end < region->guest_start) {
+      cursor = cursor->next;
+    } else {
+      // This cannot happen!
+      // we should panic here
+      return -1;
     }
   }
-
-  return prev_region;
+  
+  // This cannot happen
+  // We should panic here
+  return -1;
 }
 
 
-
-void init_mem_layout(vmm_mem_layout_t * layout) {
-  layout->num_pages = 0;
-  layout->num_regions = 0;
-
-  layout->head = NULL;
+int delete_shadow_region(shadow_map_t * map,
+                        addr_t guest_start,
+                        addr_t guest_end) {
+  return -1;
 }
 
 
-void free_mem_layout(vmm_mem_layout_t * layout) {
-  layout_region_t * cursor = layout->head;
-  layout_region_t * tmp = NULL;
-
-  while(cursor) {
-    tmp = cursor;
-    cursor = cursor->next;
-    VMMFree(tmp);
-  }
 
-  VMMFree(layout);
+shadow_region_t *get_shadow_region_by_index(shadow_map_t *  map,
+                                              uint_t index) {
+  shadow_region_t * reg = map->head;
+  uint_t i = 0;
 
-}
-
-
-/* this function returns a pointer to the location in the layout 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
- */
-layout_region_t * get_layout_cursor(vmm_mem_layout_t * layout, ullong_t addr) {
-  layout_region_t * prev_region = layout->head;
-
-
-  while (prev_region != NULL) {
-    if ( (addr >= prev_region->addr) && 
-        (addr <= (prev_region->addr + (prev_region->num_pages * PAGE_SIZE))) ) {
-      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;
-      }
+  while (reg) { 
+    if (i == index) { 
+      return reg;
     }
+    reg = reg->next;
+    i++;
   }
-
-  return prev_region;
+  return NULL;
 }
 
 
-/* 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 = get_layout_cursor(layout, region->addr);
-
-  if (cursor == NULL) {
-    if (layout->head) {
-      if (layout->head->addr < region->addr + (region->num_pages * PAGE_SIZE)) {
-       // overlaps not allowed
-       return -1;
-      }
-      layout->head->prev = region;
-    }
+shadow_region_t * get_shadow_region_by_addr(shadow_map_t * map,
+                                              addr_t addr) {
+  shadow_region_t * reg = map->head;
 
-    region->prev = NULL;
-    region->next = layout->head;
-    layout->head = region;
-    
-    layout->num_regions++;
-    layout->num_pages += region->num_pages;
-  } else if ((region->addr >= cursor->addr) && 
-            (region->addr <= cursor->addr + (cursor->num_pages * PAGE_SIZE))) {
-    // overlaps not allowed
-    return -1;
-  } else if (region->addr > cursor->addr + (cursor->num_pages * PAGE_SIZE)) {
-    // add region to layout
-    region->next = cursor->next;
-    region->prev = cursor;
-    
-    if (region->next) {
-      region->next->prev = region;
+  while (reg) {
+    if ((reg->guest_start <= addr) && (reg->guest_end > addr)) {
+      return reg;
+    } else if (reg->guest_start > addr) {
+      return NULL;
+    } else {
+      reg = reg->next;
     }
-    cursor->next = region;
-
-    layout->num_regions++;
-    layout->num_pages += region->num_pages;
-  } else {
-    return -1;
   }
-
-
-  return 0;
-}
-
-
-
-
-
-int add_shared_mem_range(vmm_mem_layout_t * layout, ullong_t addr, uint_t num_pages, ullong_t host_addr) {
-  layout_region_t * shared_region = os_hooks->malloc(sizeof(layout_region_t));
-
-  shared_region->next = NULL;
-  shared_region->prev = NULL;
-  shared_region->addr = addr;
-  shared_region->num_pages = num_pages;
-  shared_region->type = SHARED;
-  shared_region->host_addr = host_addr;
-
-  return add_mem_range(layout, shared_region);
+  return NULL;
 }
 
-int add_unmapped_mem_range(vmm_mem_layout_t * layout, ullong_t addr, uint_t num_pages) {
-  layout_region_t * unmapped_region = os_hooks->malloc(sizeof(layout_region_t));
-  
-  unmapped_region->next = NULL;
-  unmapped_region->prev = NULL;
-  unmapped_region->addr = addr;
-  unmapped_region->num_pages = num_pages;
-  unmapped_region->type = UNMAPPED;
-  unmapped_region->host_addr = 0;
-
-  return add_mem_range(layout, unmapped_region);
-}
 
-int add_guest_mem_range(vmm_mem_layout_t * layout, ullong_t addr, uint_t num_pages) {
-  layout_region_t * guest_region = os_hooks->malloc(sizeof(layout_region_t));
 
-  guest_region->next = NULL;
-  guest_region->prev = NULL;
-  guest_region->addr = addr;
-  guest_region->num_pages = num_pages;
-  guest_region->type = GUEST;
-  guest_region->host_addr = 0;
+host_region_type_t lookup_shadow_map_addr(shadow_map_t * map, addr_t guest_addr, addr_t * host_addr) {
+  shadow_region_t * reg = get_shadow_region_by_addr(map, guest_addr);
 
-  return add_mem_range(layout, guest_region);
+  if (!reg) {
+    // No mapping exists
+    return HOST_REGION_INVALID;
+  } else {
+    switch (reg->host_type) {
+    case HOST_REGION_PHYSICAL_MEMORY:
+     *host_addr = (guest_addr - reg->guest_start) + reg->host_addr.phys_addr.host_start;
+     return reg->host_type;
+    case HOST_REGION_MEMORY_MAPPED_DEVICE:
+    case HOST_REGION_UNALLOCATED:
+      // ... 
+    default:
+      *host_addr = 0;
+      return reg->host_type;
+    }
+  }
 }
 
 
-
-
-
-void print_mem_list(vmm_mem_list_t * list) {
-  mem_region_t * cur = list->head;
+void print_shadow_map(shadow_map_t * map) {
+  shadow_region_t * cur = map->head;
   int i = 0;
 
-  PrintDebug("Memory Region List (regions: %d) (pages: %d)\n", list->num_regions, list->num_pages);
+  PrintDebug("Memory Layout (regions: %d) \n", map->num_regions);
 
   while (cur) {
-    PrintDebug("%d: 0x%x - 0x%x\n", i, cur->addr, cur->addr + (cur->num_pages * PAGE_SIZE));
+    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", cur->host_addr.phys_addr.host_start);
+    }
+    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");
 }
 
 
 
-void print_mem_layout(vmm_mem_layout_t * layout) {
-  layout_region_t * cur = layout->head;
-  int i = 0;
 
-  PrintDebug("Memory Layout (regions: %d) (pages: %d)\n", layout->num_regions, layout->num_pages);
 
-  while (cur) {
-    PrintDebug("%d: 0x%x - 0x%x\n", i, cur->addr, cur->addr + (cur->num_pages * PAGE_SIZE));
-    cur = cur->next;
-    i++;
-  }
-  PrintDebug("\n");
-}
+
+
 
 
 
 #ifdef VMM_MEM_TEST
+
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
@@ -355,12 +223,18 @@ void print_mem_layout(vmm_mem_layout_t * layout) {
 
 
 
+
 struct vmm_os_hooks * os_hooks;
 
 void * TestMalloc(uint_t size) {
   return malloc(size);
 }
 
+void * TestAllocatePages(int size) {
+  return malloc(4096 * size);
+}
+
+
 void TestPrint(const char * fmt, ...) {
   va_list args;
 
@@ -369,65 +243,97 @@ void TestPrint(const char * fmt, ...) {
   va_end(args);
 }
 
-int mem_list_add_test_1() {
-  vmm_mem_list_t list;
+int mem_list_add_test_1(  vmm_mem_list_t * list) {
+
   uint_t offset = 0;
 
-  init_mem_list(&list);
+  PrintDebug("\n\nTesting Memory List\n");
+
+  init_mem_list(list);
 
   offset = PAGE_SIZE * 6;
   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 10));
-  add_mem_list_pages(&list, PAGE_SIZE * 6, 10);
-  print_mem_list(&list);
+  add_mem_list_pages(list, offset, 10);
+  print_mem_list(list);
 
 
   offset = 0;
   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + PAGE_SIZE * 4);
-  add_mem_list_pages(&list, 0, 4);
-  print_mem_list(&list);
+  add_mem_list_pages(list, offset, 4);
+  print_mem_list(list);
 
   offset = PAGE_SIZE * 20;
   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1));
-  add_mem_list_pages(&list, PAGE_SIZE * 20, 1);
-  print_mem_list(&list);
+  add_mem_list_pages(list, offset, 1);
+  print_mem_list(list);
+
+  offset = PAGE_SIZE * 21;
+  PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 3));
+  add_mem_list_pages(list, offset, 3);
+  print_mem_list(list);
 
 
   offset = PAGE_SIZE * 10;
   PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 30));
-  add_mem_list_pages(&list, PAGE_SIZE * 10, 30);
-  print_mem_list(&list);
+  add_mem_list_pages(list, offset, 30);
+  print_mem_list(list);
+
+
+  offset = PAGE_SIZE * 5;
+  PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1));
+  add_mem_list_pages(list, offset, 1);
+  print_mem_list(list);
+
 
   return 0;
 }
 
 
-int mem_layout_add_test_1() {
-  vmm_mem_layout_t layout;
-  uint_t offset = 0;
+int mem_layout_add_test_1(vmm_mem_layout_t * layout) {
 
-  init_mem_layout(&layout);
+  
+  uint_t start = 0;
+  uint_t end = 0;
 
-  offset = PAGE_SIZE * 6;
-  PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 10));
-  add_guest_mem_range(&layout, PAGE_SIZE * 6, 10);
-  print_mem_layout(&layout);
+  PrintDebug("\n\nTesting Memory Layout\n");
 
+  init_mem_layout(layout);
 
-  offset = 0;
-  PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + PAGE_SIZE * 4);
-  add_guest_mem_range(&layout, 0, 4);
-  print_mem_layout(&layout);
+  start = 0x6000;
+  end = 0x10000;;
+  PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+  add_guest_mem_range(layout, start, end);
+  print_mem_layout(layout);
+
+
+  start = 0x1000;
+  end = 0x3000;
+  PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+  add_guest_mem_range(layout, start, end);
+  print_mem_layout(layout);
+
+  start = 0x2000;
+  end = 0x6000;
+  PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+  add_guest_mem_range(layout, start, end);
+  print_mem_layout(layout);
+
+  start = 0x4000;
+  end = 0x5000;
+  PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+  add_guest_mem_range(layout, start, end);
+  print_mem_layout(layout);
+
+
+  start = 0x5000;
+  end = 0x7000;
+  PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+  add_guest_mem_range(layout, start, end);
+  print_mem_layout(layout);
 
-  offset = PAGE_SIZE * 20;
-  PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1));
-  add_guest_mem_range(&layout, PAGE_SIZE * 20, 1);
-  print_mem_layout(&layout);
 
 
-  offset = PAGE_SIZE * 10;
-  PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 30));
-  add_guest_mem_range(&layout, PAGE_SIZE * 10, 30);
-  print_mem_layout(&layout);
 
   return 0;
 }
@@ -438,14 +344,25 @@ int main(int argc, char ** argv) {
   struct vmm_os_hooks dummy_hooks;
   os_hooks = &dummy_hooks;
 
+  vmm_mem_layout_t layout;
+  vmm_mem_list_t list;
+
   os_hooks->malloc = &TestMalloc;
   os_hooks->free = &free;
   os_hooks->print_debug = &TestPrint;
+  os_hooks->allocate_pages = &TestAllocatePages;
+
 
 
-  printf("mem_list_add_test_1: %d\n", mem_list_add_test_1());
-  printf("layout_add_test_t: %d\n", mem_layout_add_test_1());
+  printf("mem_list_add_test_1: %d\n", mem_list_add_test_1(&list));
+  printf("layout_add_test_1: %d\n", mem_layout_add_test_1(&layout));
 
   return 0;
 }
 #endif
+
+
+
+
+
+