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 shadow memory map to use Red Black Tree
Jack Lange [Wed, 28 Jan 2009 23:37:08 +0000 (17:37 -0600)]
cleaned up shadow memory map interface

palacios/include/palacios/vm_guest.h
palacios/include/palacios/vmm_mem.h
palacios/src/palacios/svm.c
palacios/src/palacios/vm_guest_mem.c
palacios/src/palacios/vmm_config.c
palacios/src/palacios/vmm_io.c
palacios/src/palacios/vmm_mem.c
palacios/src/palacios/vmm_paging.c
palacios/src/palacios/vmm_shadow_paging.c

index 29ea0c5..271bbb9 100644 (file)
@@ -112,7 +112,8 @@ struct guest_info {
   uint_t cpl;
 
   addr_t mem_size; // Probably in bytes for now....
-  struct shadow_map mem_map;
+  v3_shdw_map_t mem_map;
+
 
   struct vm_time time_state;
 
index 3616bc7..ae4ca05 100644 (file)
@@ -28,6 +28,8 @@
 #include <palacios/vmm_types.h>
 
 #include <palacios/vmm_paging.h>
+#include <palacios/vmm_rbtree.h>
+
 
 struct guest_info;
 
@@ -40,18 +42,17 @@ typedef enum shdw_region_type {
   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
-  SHDW_REGION_UNALLOCATED,                // Region is mapped on demand
-} shdw_region_type_t;
+} v3_shdw_region_type_t;
 
 
+typedef struct rb_root v3_shdw_map_t;
 
-struct vmm_mem_hook;
 
-struct shadow_region {
+struct v3_shadow_region {
   addr_t                  guest_start; 
   addr_t                  guest_end; 
 
-  shdw_region_type_t      host_type;
+  v3_shdw_region_type_t   host_type;
   
   addr_t                  host_addr; // This either points to a host address mapping
 
@@ -63,83 +64,61 @@ struct shadow_region {
 
   void * priv_data;
 
-  struct shadow_region *next, *prev;
+  struct rb_node tree_node;
 };
 
 
 
-struct shadow_map {
-  uint_t num_regions;
-
-  struct shadow_region * head;
-};
+void v3_init_shadow_map(struct guest_info * info);
+void v3_delete_shadow_map(struct guest_info * info);
 
 
+int v3_add_shadow_mem(struct guest_info * guest_info, 
+                     addr_t guest_addr_start,
+                     addr_t guest_addr_end,
+                     addr_t host_addr);
 
-void init_shadow_region(struct shadow_region * entry,
-                       addr_t               guest_addr_start,
-                       addr_t               guest_addr_end,
-                       shdw_region_type_t   shdw_region_type);
-
+int v3_hook_full_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
+                    int (*read)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
+                    int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
+                    void * priv_data);
 
-int add_shadow_region_passthrough(struct guest_info * guest_info, 
-                                 addr_t guest_addr_start,
-                                 addr_t guest_addr_end,
-                                 addr_t host_addr);
+int v3_hook_write_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
+                     addr_t host_addr,
+                     int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
+                     void * priv_data);
 
-void init_shadow_map(struct guest_info * info);
-void free_shadow_map(struct shadow_map * map);
 
-struct shadow_region * get_shadow_region_by_addr(struct shadow_map * map, addr_t guest_addr);
 
-struct shadow_region * get_shadow_region_by_index(struct shadow_map * map, uint_t index);
 
-shdw_region_type_t lookup_shadow_map_addr(struct shadow_map * map, addr_t guest_addr, addr_t * host_addr);
 
-shdw_region_type_t get_shadow_addr_type(struct guest_info * info, addr_t guest_addr);
-addr_t get_shadow_addr(struct guest_info * info, addr_t guest_addr);
 
-// Semantics:
-// Adding a region that overlaps with an existing region results is undefined
-// and will probably fail
-int add_shadow_region(struct shadow_map * map, struct shadow_region * entry);
+void v3_delete_shadow_region(struct guest_info * info, struct v3_shadow_region * reg);
 
-// Semantics:
-// Deletions result in splitting
-int delete_shadow_region(struct shadow_map * map,
-                        addr_t guest_start, 
-                        addr_t guest_end);
 
+struct v3_shadow_region * v3_get_shadow_region(struct guest_info * info, addr_t guest_addr);
+addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, addr_t guest_addr);
 
-void print_shadow_map(struct shadow_map * map);
 
 
 
-struct shadow_region * v3_get_shadow_region(struct guest_info * info, addr_t addr);
 
-int v3_hook_full_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
-                    int (*read)(addr_t guest_addr, void * dst, uint_t length, void * priv_data),
-                    int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
-                    void * priv_data);
+void print_shadow_map(struct guest_info * info);
 
-int v3_hook_write_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
-                     addr_t host_addr,
-                     int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
-                     void * priv_data);
 
 
 
 
+const uchar_t * v3_shdw_region_type_to_str(v3_shdw_region_type_t type);
 
-const uchar_t * shdw_region_type_to_str(shdw_region_type_t type);
 
 
 int handle_special_page_fault(struct guest_info * info, addr_t fault_addr, addr_t gp_addr, pf_error_t access_info);
 
 int v3_handle_mem_wr_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa, 
-                         struct shadow_region * reg, pf_error_t access_info);
+                         struct v3_shadow_region * reg, pf_error_t access_info);
 int v3_handle_mem_full_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa, 
-                           struct shadow_region * reg, pf_error_t access_info);
+                           struct v3_shadow_region * reg, pf_error_t access_info);
 
 #endif // ! __V3VEE__
 
index b052eee..f5489c3 100644 (file)
@@ -196,7 +196,8 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) {
     struct v3_io_hook * iter;
     struct rb_node * io_node = v3_rb_first(&(vm_info->io_map));
     addr_t io_port_bitmap;
-    
+    int i = 0;
+
     io_port_bitmap = (addr_t)V3_VAddr(V3_AllocPages(3));
     memset((uchar_t*)io_port_bitmap, 0, PAGE_SIZE * 3);
     
@@ -209,10 +210,13 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info *vm_info) {
 
       ushort_t port = iter->port;
       uchar_t * bitmap = (uchar_t *)io_port_bitmap;
+      PrintDebug("%d: Hooking Port %d\n", i, port);
 
       bitmap += (port / 8);
       //      PrintDebug("Setting Bit for port 0x%x\n", port);
       *bitmap |= 1 << (port % 8);
+
+      i++;
     } while ((io_node = v3_rb_next(io_node)));
 
 
@@ -353,7 +357,11 @@ static int start_svm_guest(struct guest_info *info) {
     v3_clgi();
 
 
-    //PrintDebug("SVM Entry to rip=%p...\n", (void *)info->rip);
+    /*
+    PrintDebug("SVM Entry to CS=%p  rip=%p...\n", 
+              (void *)(addr_t)info->segments.cs.base, 
+              (void *)(addr_t)info->rip);
+    */
 
     v3_get_msr(0xc0000101, &vm_cr_high, &vm_cr_low);
 
index 78b4b7e..b8db954 100644 (file)
@@ -66,14 +66,15 @@ int host_pa_to_host_va(addr_t host_pa, addr_t * host_va) {
 
 
 int guest_pa_to_host_pa(struct guest_info * guest_info, addr_t guest_pa, addr_t * host_pa) {
-  // we use the shadow map here...
-  shdw_region_type_t reg_type = lookup_shadow_map_addr(&(guest_info->mem_map), guest_pa, host_pa);
-
-  if ((reg_type == SHDW_REGION_INVALID) ||
-      (reg_type == SHDW_REGION_UNALLOCATED) ||
-      (reg_type == SHDW_REGION_FULL_HOOK)){
-    PrintError("In GPA->HPA: Could not find address in shadow map (addr=%p) (reg_type=%d)\n", 
-               (void *)guest_pa, reg_type);
+  struct v3_shadow_region * shdw_reg = v3_get_shadow_region(guest_info, guest_pa);
+
+  *host_pa = v3_get_shadow_addr(shdw_reg, guest_pa);
+
+  if ((shdw_reg == NULL) ||
+      (shdw_reg->host_type == SHDW_REGION_INVALID) ||
+      (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 99033e5..82f34e2 100644 (file)
@@ -76,7 +76,7 @@ int v3_config_guest(struct guest_info * info, struct v3_vm_config * config_ptr)
 
   v3_init_decoder(info);
 
-  init_shadow_map(info);
+  v3_init_shadow_map(info);
   
   if (v3_cpu_type == V3_SVM_REV3_CPU) {
     info->shdw_pg_mode = NESTED_PAGING;
@@ -124,7 +124,7 @@ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * conf
     PrintDebug("Layout Region %d bytes\n", config_ptr->rombios_size);
     memcpy(V3_VAddr(guest_mem), config_ptr->rombios, config_ptr->rombios_size);
 
-    add_shadow_region_passthrough(info, ROMBIOS_START, ROMBIOS_START + (num_pages * PAGE_SIZE), (addr_t)guest_mem);
+    v3_add_shadow_mem(info, ROMBIOS_START, ROMBIOS_START + (num_pages * PAGE_SIZE) - 1, (addr_t)guest_mem);
     
     PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n", 
               (void *)ROMBIOS_START, 
@@ -141,7 +141,7 @@ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * conf
     PrintDebug("Layout Region %d bytes\n", config_ptr->vgabios_size);
     memcpy(V3_VAddr(guest_mem), config_ptr->vgabios, config_ptr->vgabios_size);
 
-    add_shadow_region_passthrough(info, VGABIOS_START, VGABIOS_START + (num_pages * PAGE_SIZE), (addr_t)guest_mem);
+    v3_add_shadow_mem(info, VGABIOS_START, VGABIOS_START + (num_pages * PAGE_SIZE) - 1, (addr_t)guest_mem);
     
     PrintDebug("Adding Shadow Region (0x%p-0x%p) -> 0x%p\n", 
               (void *)VGABIOS_START, 
@@ -150,44 +150,44 @@ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * conf
   }
 
       //     
-  add_shadow_region_passthrough(info, 0x0, 0xa0000, (addr_t)V3_AllocPages(160));
+  v3_add_shadow_mem(info, 0x0, 0x9ffff, (addr_t)V3_AllocPages(160));
   
   if (0) {
-    add_shadow_region_passthrough(info, 0xa0000, 0xc0000, 0xa0000); 
+    v3_add_shadow_mem(info, 0xa0000, 0xbffff, 0xa0000); 
   } else {
-    v3_hook_write_mem(info, 0xa0000, 0xc0000, 0xa0000,  passthrough_mem_write, NULL);
+    v3_hook_write_mem(info, 0xa0000, 0xbffff, 0xa0000,  passthrough_mem_write, NULL);
   }  
   
   // TEMP
   //add_shadow_region_passthrough(info, 0xc0000, 0xc8000, 0xc0000);
   
   if (1) {
-    add_shadow_region_passthrough(info, 0xc7000, 0xc8000, (addr_t)V3_AllocPages(1));
-    if (add_shadow_region_passthrough(info, 0xc8000, 0xf0000, (addr_t)V3_AllocPages(40)) == -1) {
+    v3_add_shadow_mem(info, 0xc7000, 0xc8000, (addr_t)V3_AllocPages(1));
+    if (v3_add_shadow_mem(info, 0xc8000, 0xf0000, (addr_t)V3_AllocPages(40)) == -1) {
       PrintDebug("Error adding shadow region\n");
     }
   } else {
-    add_shadow_region_passthrough(info, 0xc0000, 0xc8000, 0xc0000);
-    add_shadow_region_passthrough(info, 0xc8000, 0xf0000, 0xc8000);
+    v3_add_shadow_mem(info, 0xc0000, 0xc8000, 0xc0000);
+    v3_add_shadow_mem(info, 0xc8000, 0xf0000, 0xc8000);
   }
   
   
   if (1) {
-  add_shadow_region_passthrough(info, 0x100000, 0x1000000, (addr_t)V3_AllocPages(4096));
+    v3_add_shadow_mem(info, 0x100000, 0x1000000, (addr_t)V3_AllocPages(4096));
   } else {
     /* MEMORY HOOK TEST */
-    add_shadow_region_passthrough(info, 0x100000, 0xa00000, (addr_t)V3_AllocPages(2304));
+    v3_add_shadow_mem(info, 0x100000, 0xa00000, (addr_t)V3_AllocPages(2304));
     v3_hook_write_mem(info, 0xa00000, 0xa01000, (addr_t)V3_AllocPages(1), passthrough_mem_write, NULL); 
-    add_shadow_region_passthrough(info, 0xa01000, 0x1000000, (addr_t)V3_AllocPages(1791));
+    v3_add_shadow_mem(info, 0xa01000, 0x1000000, (addr_t)V3_AllocPages(1791));
   }
 
-    add_shadow_region_passthrough(info, 0x1000000, 0x8000000, (addr_t)V3_AllocPages(32768));
+  v3_add_shadow_mem(info, 0x1000000, 0x8000000, (addr_t)V3_AllocPages(32768));
  
   // test - give linux accesss to PCI space - PAD
-  add_shadow_region_passthrough(info, 0xc0000000,0xffffffff,0xc0000000);
+  v3_add_shadow_mem(info, 0xc0000000,0xffffffff,0xc0000000);
   
   
-  print_shadow_map(&(info->mem_map));
+  print_shadow_map(info);
 
   return 0;
 }
index e3820b9..f7bea5a 100644 (file)
@@ -142,6 +142,8 @@ int v3_unhook_io_port(struct guest_info * info, uint_t port) {
 
   v3_rb_erase(&(hook->tree_node), &(info->io_map));
 
+  V3_Free(hook);
+
   return 0;
 }
 
index fa17e97..62bca66 100644 (file)
 
 
 
-void init_shadow_region(struct shadow_region * entry,
-                       addr_t               guest_addr_start,
-                       addr_t               guest_addr_end,
-                       shdw_region_type_t   shdw_region_type)
-{
-  entry->guest_start = guest_addr_start;
-  entry->guest_end = guest_addr_end;
-  entry->host_type = shdw_region_type;
-  entry->host_addr = 0;
-  entry->next = entry->prev = NULL;
+
+
+
+
+static inline
+struct v3_shadow_region * insert_shadow_region(struct guest_info * info, 
+                                              struct v3_shadow_region * region);
+
+
+
+void v3_init_shadow_map(struct guest_info * info) {
+  info->mem_map.rb_node = NULL;
+}
+
+void v3_delete_shadow_map(struct guest_info * info) {
+  struct rb_node * node = v3_rb_first(&(info->mem_map));
+  struct v3_shadow_region * reg;
+  struct rb_node * tmp_node = NULL;
+  
+   while (node) {
+    reg = rb_entry(node, struct v3_shadow_region, tree_node);
+    tmp_node = node;
+    node = v3_rb_next(node);
+
+    v3_delete_shadow_region(info, reg);
+  }
 }
 
-int add_shadow_region_passthrough( struct guest_info *  guest_info,
-                                  addr_t               guest_addr_start,
-                                  addr_t               guest_addr_end,
-                                  addr_t               host_addr)
+
+
+
+int v3_add_shadow_mem( struct guest_info *  info,
+                      addr_t               guest_addr_start,
+                      addr_t               guest_addr_end,
+                      addr_t               host_addr)
 {
-  struct shadow_region * entry = (struct shadow_region *)V3_Malloc(sizeof(struct shadow_region));
+  struct v3_shadow_region * entry = (struct v3_shadow_region *)V3_Malloc(sizeof(struct v3_shadow_region));
 
-  init_shadow_region(entry, guest_addr_start, guest_addr_end, 
-                    SHDW_REGION_ALLOCATED);
+  entry->guest_start = guest_addr_start;
+  entry->guest_end = guest_addr_end;
+  entry->host_type = SHDW_REGION_ALLOCATED;
   entry->host_addr = host_addr;
+  entry->write_hook = NULL;
+  entry->read_hook = NULL;
+  entry->priv_data = NULL;
+
+  if (insert_shadow_region(info, entry)) {
+    V3_Free(entry);
+    return -1;
+  }
 
-  return add_shadow_region(&(guest_info->mem_map), entry);
+  return 0;
 }
 
+
+
 int v3_hook_write_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end, 
                      addr_t host_addr,
                      int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
                      void * priv_data) {
 
-  struct shadow_region * entry = (struct shadow_region *)V3_Malloc(sizeof(struct shadow_region));
+  struct v3_shadow_region * entry = (struct v3_shadow_region *)V3_Malloc(sizeof(struct v3_shadow_region));
 
-  init_shadow_region(entry, guest_addr_start, guest_addr_end, 
-                    SHDW_REGION_WRITE_HOOK);
 
+  entry->guest_start = guest_addr_start;
+  entry->guest_end = guest_addr_end;
+  entry->host_type = SHDW_REGION_WRITE_HOOK;
+  entry->host_addr = host_addr;
   entry->write_hook = write;
   entry->read_hook = NULL;
-  entry->host_addr = host_addr;
   entry->priv_data = priv_data;
 
-  return add_shadow_region(&(info->mem_map), entry);  
+  if (insert_shadow_region(info, entry)) {
+    V3_Free(entry);
+    return -1;
+  }
+
+  return 0;  
 }
 
 int v3_hook_full_mem(struct guest_info * info, addr_t guest_addr_start, addr_t guest_addr_end,
@@ -73,28 +109,79 @@ int v3_hook_full_mem(struct guest_info * info, addr_t guest_addr_start, addr_t g
                     int (*write)(addr_t guest_addr, void * src, uint_t length, void * priv_data),
                     void * priv_data) {
   
-  struct shadow_region * entry = (struct shadow_region *)V3_Malloc(sizeof(struct shadow_region));
-
-  init_shadow_region(entry, guest_addr_start, guest_addr_end, 
-                    SHDW_REGION_FULL_HOOK);
+  struct v3_shadow_region * entry = (struct v3_shadow_region *)V3_Malloc(sizeof(struct v3_shadow_region));
 
+  entry->guest_start = guest_addr_start;
+  entry->guest_end = guest_addr_end;
+  entry->host_type = SHDW_REGION_FULL_HOOK;
+  entry->host_addr = (addr_t)NULL;
   entry->write_hook = write;
   entry->read_hook = read;
   entry->priv_data = priv_data;
+  
+  if (insert_shadow_region(info, entry)) {
+    V3_Free(entry);
+    return -1;
+  }
+
+  return 0;
+}
+
+
+
 
-  entry->host_addr = 0;
+static inline 
+struct v3_shadow_region * __insert_shadow_region(struct guest_info * info, 
+                                                struct v3_shadow_region * region) {
+  struct rb_node ** p = &(info->mem_map.rb_node);
+  struct rb_node * parent = NULL;
+  struct v3_shadow_region * tmp_region;
 
-  return add_shadow_region(&(info->mem_map), entry);
+  while (*p) {
+    parent = *p;
+    tmp_region = rb_entry(parent, struct v3_shadow_region, tree_node);
+
+    if (region->guest_end <= tmp_region->guest_start) {
+      p = &(*p)->rb_left;
+    } else if (region->guest_start >= tmp_region->guest_end) {
+      p = &(*p)->rb_right;
+    } else {
+      return tmp_region;
+    }
+  }
+
+  rb_link_node(&(region->tree_node), parent, p);
+  
+  return NULL;
 }
 
 
+static inline
+struct v3_shadow_region * insert_shadow_region(struct guest_info * info, 
+                                              struct v3_shadow_region * region) {
+  struct v3_shadow_region * ret;
+
+  if ((ret = __insert_shadow_region(info, region))) {
+    return ret;
+  }
+  
+  v3_rb_insert_color(&(region->tree_node), &(info->mem_map));
+
+  return NULL;
+}
+                                                
+
+
+
+
+
 
 
 int handle_special_page_fault(struct guest_info * info, 
                              addr_t fault_gva, addr_t fault_gpa, 
                              pf_error_t access_info) 
 {
- struct shadow_region * reg = get_shadow_region_by_addr(&(info->mem_map), fault_gpa);
+ struct v3_shadow_region * reg = v3_get_shadow_region(info, fault_gpa);
 
   PrintDebug("Handling Special Page Fault\n");
 
@@ -112,7 +199,7 @@ int handle_special_page_fault(struct guest_info * info,
 }
 
 int v3_handle_mem_wr_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa, 
-                         struct shadow_region * reg, pf_error_t access_info) {
+                         struct v3_shadow_region * reg, pf_error_t access_info) {
 
   addr_t write_src_addr = 0;
 
@@ -133,211 +220,79 @@ int v3_handle_mem_wr_hook(struct guest_info * info, addr_t guest_va, addr_t gues
 }
 
 int v3_handle_mem_full_hook(struct guest_info * info, addr_t guest_va, addr_t guest_pa, 
-                           struct shadow_region * reg, pf_error_t access_info) {
+                           struct v3_shadow_region * reg, pf_error_t access_info) {
   return -1;
 }
 
 
 
-struct shadow_region * v3_get_shadow_region(struct guest_info * info, addr_t addr) {
-  struct shadow_region * reg = info->mem_map.head;
-
-  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;
-    }
-  }
-  return NULL;
-}
-
-
-void init_shadow_map(struct guest_info * info) {
-  struct shadow_map * map = &(info->mem_map);
-
-  map->num_regions = 0;
-
-  map->head = NULL;
-}
-
+struct v3_shadow_region * v3_get_shadow_region(struct guest_info * info, addr_t guest_addr) {
+  struct rb_node * n = info->mem_map.rb_node;
+  struct v3_shadow_region * reg = NULL;
 
-void free_shadow_map(struct shadow_map * map) {
-  struct shadow_region * cursor = map->head;
-  struct shadow_region * tmp = NULL;
+  while (n) {
+    reg = rb_entry(n, struct v3_shadow_region, tree_node);
 
-  while(cursor) {
-    tmp = cursor;
-    cursor = cursor->next;
-    V3_Free(tmp);
-  }
-
-  V3_Free(map);
-}
-
-
-
-
-int add_shadow_region(struct shadow_map * map,
-                     struct shadow_region * region) 
-{
-  struct shadow_region * cursor = map->head;
-
-  PrintDebug("Adding Shadow Region: (0x%p-0x%p)\n", 
-            (void *)region->guest_start, (void *)region->guest_end);
-
-  if ((!cursor) || (cursor->guest_start >= region->guest_end)) {
-    region->prev = NULL;
-    region->next = cursor;
-    map->num_regions++;
-    map->head = region;
-    return 0;
-  }
-
-  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;
-    }
-    
-    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;
-
-      map->num_regions++;
-      
-      return 0;
-    } else if (cursor->next->guest_end <= region->guest_start) {
-      cursor = cursor->next;
+    if (guest_addr < reg->guest_start) {
+      n = n->rb_left;
+    } else if (guest_addr >= reg->guest_end) {
+      n = n->rb_right;
     } else {
-      // This cannot happen!
-      // we should panic here
-      return -1;
-    }
-  }
-  
-  // This cannot happen
-  // We should panic here
-  return -1;
-}
-
-
-int delete_shadow_region(struct shadow_map * map,
-                        addr_t guest_start,
-                        addr_t guest_end) {
-  return -1;
-}
-
-
-
-struct shadow_region *get_shadow_region_by_index(struct shadow_map *  map,
-                                                uint_t index) {
-  struct shadow_region * reg = map->head;
-  uint_t i = 0;
-
-  while (reg) { 
-    if (i == index) { 
       return reg;
     }
-    reg = reg->next;
-    i++;
   }
-  return NULL;
-}
-
-
-struct shadow_region * get_shadow_region_by_addr(struct shadow_map * map,
-                                                addr_t addr) {
-  struct shadow_region * reg = map->head;
 
-  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;
-    }
-  }
   return NULL;
 }
 
 
-shdw_region_type_t get_shadow_addr_type(struct guest_info * info, addr_t guest_addr) {
-  struct shadow_region * reg = get_shadow_region_by_addr(&(info->mem_map), guest_addr);
 
-  if (!reg) {
-    return SHDW_REGION_INVALID;
+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 {
-    return reg->host_type;
-  }
-}
-
-addr_t get_shadow_addr(struct guest_info * info, addr_t guest_addr) {
-  struct shadow_region * reg = get_shadow_region_by_addr(&(info->mem_map), guest_addr);
-
-  if (!reg) {
+    PrintError("MEM Region Invalid\n");
     return 0;
-  } else {
-    return (guest_addr - reg->guest_start) + reg->host_addr;
   }
 }
 
 
-shdw_region_type_t lookup_shadow_map_addr(struct shadow_map * map, addr_t guest_addr, addr_t * host_addr) {
-  struct shadow_region * reg = get_shadow_region_by_addr(map, guest_addr);
 
-  if (!reg) {
-    // No mapping exists
-    return SHDW_REGION_INVALID;
-  } else {
-    switch (reg->host_type) {
-    case SHDW_REGION_ALLOCATED:
-    case SHDW_REGION_WRITE_HOOK:
-     *host_addr = (guest_addr - reg->guest_start) + reg->host_addr;
-     return reg->host_type;
-    case SHDW_REGION_UNALLOCATED:
-    case SHDW_REGION_FULL_HOOK:
-      // ... 
-    default:
-      *host_addr = 0;
-      return reg->host_type;
-    }
+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));
+
+    V3_Free(reg);
   }
 }
 
 
-void print_shadow_map(struct shadow_map * map) {
-  struct shadow_region * cur = map->head;
+
+
+void print_shadow_map(struct guest_info * info) {
+  struct rb_node * node = v3_rb_first(&(info->mem_map));
+  struct v3_shadow_region * reg;
   int i = 0;
 
-  PrintDebug("Memory Layout (regions: %d) \n", map->num_regions);
+  PrintDebug("Memory Layout:\n");
 
-  while (cur) {
-    PrintDebug("%d:  0x%p - 0x%p -> ", i, 
-              (void *)cur->guest_start, (void *)(cur->guest_end - 1));
-    if (cur->host_type == SHDW_REGION_ALLOCATED || 
-       cur->host_type == SHDW_REGION_UNALLOCATED) {
-      PrintDebug("0x%p", (void *)(cur->host_addr));
-    }
-    PrintDebug("(%s)\n", shdw_region_type_to_str(cur->host_type));
-    cur = cur->next;
+  do {
+    reg = rb_entry(node, struct v3_shadow_region, tree_node);
+
+    PrintDebug("%d:  0x%p - 0x%p -> 0x%p\n", i, 
+              (void *)(reg->guest_start), 
+              (void *)(reg->guest_end - 1), 
+              (void *)(reg->host_addr));
+
+    PrintDebug("\t(%s) (WriteHook = 0x%p) (ReadHook = 0x%p)\n", 
+              v3_shdw_region_type_to_str(reg->host_type),
+              (void *)(reg->write_hook), 
+              (void *)(reg->read_hook));
+    
     i++;
-  }
+  } while ((node = v3_rb_next(node)));
 }
 
 
@@ -345,183 +300,19 @@ 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";
-static const uchar_t  SHDW_REGION_UNALLOCATED_STR[] = "SHDW_REGION_UNALLOCATED";
 
 
 
-const uchar_t * shdw_region_type_to_str(shdw_region_type_t type) {
+const uchar_t * v3_shdw_region_type_to_str(v3_shdw_region_type_t type) {
   switch (type) {
-  case SHDW_REGION_INVALID: 
-    return SHDW_REGION_INVALID_STR;
   case SHDW_REGION_WRITE_HOOK:
     return SHDW_REGION_WRITE_HOOK_STR;
   case SHDW_REGION_FULL_HOOK:
     return SHDW_REGION_FULL_HOOK_STR;
   case SHDW_REGION_ALLOCATED:
     return SHDW_REGION_ALLOCATED_STR;
-  case SHDW_REGION_UNALLOCATED:
-    return SHDW_REGION_UNALLOCATED_STR;
   default:
     return SHDW_REGION_INVALID_STR;
   }
 }
 
-
-
-
-
-
-
-#ifdef VMM_MEM_TEST
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-
-
-
-
-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;
-
-  va_start(args, fmt);
-  vprintf(fmt, args);
-  va_end(args);
-}
-
-int mem_list_add_test_1(  vmm_mem_list_t * list) {
-
-  uint_t offset = 0;
-
-  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, 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, 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, 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, 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 start = 0;
-  uint_t end = 0;
-
-  PrintDebug("\n\nTesting Memory Layout\n");
-
-  init_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);
-
-
-
-
-  return 0;
-}
-
-
-
-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(&list));
-  printf("layout_add_test_1: %d\n", mem_layout_add_test_1(&layout));
-
-  return 0;
-}
-#endif
-
-
-
-
-
-
index 271ee3f..1a7dc7b 100644 (file)
@@ -669,7 +669,6 @@ pt_access_status_t inline v3_can_access_pte64(pte64_t * pte, addr_t addr, pf_err
 pde32_t * create_passthrough_pts_32(struct guest_info * guest_info) {
   addr_t current_page_addr = 0;
   int i, j;
-  struct shadow_map * map = &(guest_info->mem_map);
 
   pde32_t * pde = V3_VAddr(V3_AllocPages(1));
 
@@ -679,11 +678,10 @@ pde32_t * create_passthrough_pts_32(struct guest_info * guest_info) {
     
 
     for (j = 0; j < MAX_PTE32_ENTRIES; j++) {
-      struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
+      struct v3_shadow_region * region =  v3_get_shadow_region(guest_info, current_page_addr);
 
       if (!region || 
-         (region->host_type == SHDW_REGION_FULL_HOOK) || 
-         (region->host_type == SHDW_REGION_UNALLOCATED)) {
+         (region->host_type == SHDW_REGION_FULL_HOOK)) {
        pte[j].present = 0;
        pte[j].writable = 0;
        pte[j].user_page = 0;
@@ -770,7 +768,6 @@ pde32_t * create_passthrough_pts_32(struct guest_info * guest_info) {
 pdpe32pae_t * create_passthrough_pts_32PAE(struct guest_info * guest_info) {
   addr_t current_page_addr = 0;
   int i, j, k;
-  struct shadow_map * map = &(guest_info->mem_map);
 
   pdpe32pae_t * pdpe = V3_VAddr(V3_AllocPages(1));
   memset(pdpe, 0, PAGE_SIZE);
@@ -787,11 +784,10 @@ pdpe32pae_t * create_passthrough_pts_32PAE(struct guest_info * guest_info) {
       
       
       for (k = 0; k < MAX_PTE32PAE_ENTRIES; k++) {
-       struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
+       struct v3_shadow_region * region = v3_get_shadow_region(guest_info, current_page_addr);
        
        if (!region || 
-           (region->host_type == SHDW_REGION_FULL_HOOK) || 
-           (region->host_type == SHDW_REGION_UNALLOCATED)) {
+           (region->host_type == SHDW_REGION_FULL_HOOK)) {
          pte[k].present = 0;
          pte[k].writable = 0;
          pte[k].user_page = 0;
@@ -912,7 +908,6 @@ pdpe32pae_t * create_passthrough_pts_32PAE(struct guest_info * guest_info) {
 pml4e64_t * create_passthrough_pts_64(struct guest_info * info) {
   addr_t current_page_addr = 0;
   int i, j, k, m;
-  struct shadow_map * map = &(info->mem_map);
   
   pml4e64_t * pml = V3_VAddr(V3_AllocPages(1));
 
@@ -930,13 +925,12 @@ pml4e64_t * create_passthrough_pts_64(struct guest_info * info) {
 
 
        for (m = 0; m < MAX_PTE64_ENTRIES; m++) {
-         struct shadow_region * region = get_shadow_region_by_addr(map, current_page_addr);
+         struct v3_shadow_region * region = v3_get_shadow_region(info, current_page_addr);
          
 
          
          if (!region || 
-             (region->host_type == SHDW_REGION_FULL_HOOK) || 
-             (region->host_type == SHDW_REGION_UNALLOCATED)) {
+             (region->host_type == SHDW_REGION_FULL_HOOK)) {
            pte[m].present = 0;
            pte[m].writable = 0;
            pte[m].user_page = 0;
index 0690f66..198d17e 100644 (file)
@@ -625,6 +625,17 @@ static int handle_large_pagefault_32(struct guest_info * info,
   pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
   addr_t guest_fault_pa = BASE_TO_PAGE_ADDR_4MB(large_guest_pde->page_base_addr) + PAGE_OFFSET_4MB(fault_addr);  
 
+  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)) {
+    // 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);
+    return -1;
+  }
+
   if (shadow_pte_access == PT_ACCESS_OK) {
     // Inconsistent state...
     // Guest Re-Entry will flush tables and everything should now workd
@@ -635,20 +646,11 @@ static int handle_large_pagefault_32(struct guest_info * info,
   
   if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
     // Get the guest physical address of the fault
-    shdw_region_type_t host_page_type = get_shadow_addr_type(info, guest_fault_pa);
 
-    if (host_page_type == SHDW_REGION_INVALID) {
-      // 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);
-      return 0;
-    }
-
-    if ((host_page_type == SHDW_REGION_ALLOCATED) || 
-       (host_page_type == SHDW_REGION_WRITE_HOOK)) {
+    if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) || 
+       (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) {
       struct shadow_page_state * state = &(info->shdw_pg_state);
-      addr_t shadow_pa = get_shadow_addr(info, guest_fault_pa);
+      addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, guest_fault_pa);
 
       shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
 
@@ -666,7 +668,7 @@ static int handle_large_pagefault_32(struct guest_info * info,
        PrintDebug("Marking page as Guest Page Table (large page)\n");
        shadow_pte->vmm_info = PT32_GUEST_PT;
        shadow_pte->writable = 0;
-      } else if (host_page_type == SHDW_REGION_WRITE_HOOK) {
+      } else if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) {
        shadow_pte->writable = 0;
       } else {
        shadow_pte->writable = 1;
@@ -681,20 +683,17 @@ static int handle_large_pagefault_32(struct guest_info * info,
     } else {
       // Handle hooked pages as well as other special pages
       //      if (handle_special_page_fault(info, fault_addr, guest_fault_pa, error_code) == -1) {
-      struct shadow_region * reg = v3_get_shadow_region(info, guest_fault_pa);
 
-      if (v3_handle_mem_full_hook(info, fault_addr, guest_fault_pa, reg, error_code) == -1) {
+      if (v3_handle_mem_full_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
        PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
        return -1;
       }
     }
   } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
-    shdw_region_type_t host_page_type = get_shadow_addr_type(info, guest_fault_pa);
 
-    if (host_page_type == SHDW_REGION_WRITE_HOOK) {
-      struct shadow_region * reg = v3_get_shadow_region(info, guest_fault_pa);
+    if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) {
 
-      if (v3_handle_mem_wr_hook(info, fault_addr, guest_fault_pa, reg, error_code) == -1) {
+      if (v3_handle_mem_wr_hook(info, fault_addr, guest_fault_pa, shdw_reg, error_code) == -1) {
        PrintError("Special Page Fault handler returned error for address: %p\n", (void *)fault_addr);
        return -1;
       }
@@ -733,6 +732,15 @@ static int handle_shadow_pte32_fault(struct guest_info * info,
   pte32_t * shadow_pte = (pte32_t *)&(shadow_pt[PTE32_INDEX(fault_addr)]);
   addr_t guest_pa = BASE_TO_PAGE_ADDR((addr_t)(guest_pte->page_base_addr)) +  PAGE_OFFSET(fault_addr);
 
+  struct v3_shadow_region * shdw_reg =  v3_get_shadow_region(info, guest_pa);
+
+  if ((shdw_reg == NULL) || 
+      (shdw_reg->host_type == SHDW_REGION_INVALID)) {
+    // 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);
+    return 0;
+  }
 
   // Check the guest page permissions
   guest_pte_access = v3_can_access_pte32(guest_pt, fault_addr, error_code);
@@ -765,26 +773,13 @@ static int handle_shadow_pte32_fault(struct guest_info * info,
 
 
   if (shadow_pte_access == PT_ACCESS_NOT_PRESENT) {
-
-
     // Page Table Entry Not Present
     PrintDebug("guest_pa =%p\n", (void *)guest_pa);
 
-    shdw_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa);
-
-    if (host_page_type == SHDW_REGION_INVALID) {
-      // 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);
-      return 0;
-    }
-
-    // else...
-
-    if ((host_page_type == SHDW_REGION_ALLOCATED) ||
-       (host_page_type == SHDW_REGION_WRITE_HOOK)) {
+    if ((shdw_reg->host_type == SHDW_REGION_ALLOCATED) ||
+       (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK)) {
       struct shadow_page_state * state = &(info->shdw_pg_state);
-      addr_t shadow_pa = get_shadow_addr(info, guest_pa);
+      addr_t shadow_pa = v3_get_shadow_addr(shdw_reg, guest_pa);
       
       shadow_pte->page_base_addr = PAGE_BASE_ADDR(shadow_pa);
       
@@ -805,7 +800,7 @@ static int handle_shadow_pte32_fault(struct guest_info * info,
        shadow_pte->vmm_info = PT32_GUEST_PT;
       }
 
-      if (host_page_type == SHDW_REGION_WRITE_HOOK) {
+      if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) {
        shadow_pte->writable = 0;
       } else if (guest_pte->dirty == 1) {
        shadow_pte->writable = guest_pte->writable;
@@ -826,9 +821,8 @@ static int handle_shadow_pte32_fault(struct guest_info * info,
 
     } else {
       // Page fault handled by hook functions
-      struct shadow_region * reg = v3_get_shadow_region(info, guest_pa);
 
-      if (v3_handle_mem_full_hook(info, fault_addr, guest_pa, reg, error_code) == -1) {
+      if (v3_handle_mem_full_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) {
        PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
        return -1;
       }
@@ -840,12 +834,8 @@ static int handle_shadow_pte32_fault(struct guest_info * info,
   } else if (shadow_pte_access == PT_ACCESS_WRITE_ERROR) {
     guest_pte->dirty = 1;
 
-    shdw_region_type_t host_page_type = get_shadow_addr_type(info, guest_pa);
-
-    if (host_page_type == SHDW_REGION_WRITE_HOOK) {
-      struct shadow_region * reg = v3_get_shadow_region(info, guest_pa);
-
-      if (v3_handle_mem_wr_hook(info, fault_addr, guest_pa, reg, error_code) == -1) {
+    if (shdw_reg->host_type == SHDW_REGION_WRITE_HOOK) {
+      if (v3_handle_mem_wr_hook(info, fault_addr, guest_pa, shdw_reg, error_code) == -1) {
        PrintError("Special Page fault handler returned error for address: %p\n",  (void *)fault_addr);
        return -1;
       }