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.


this is a fix for the get_next_region function.
Alex Merritt [Tue, 10 Aug 2010 20:28:13 +0000 (15:28 -0500)]
palacios/src/palacios/vmm_direct_paging_64.h
palacios/src/palacios/vmm_mem.c

index 80dce91..9a4a1fc 100644 (file)
@@ -82,7 +82,7 @@ static int get_page_size() {
            return -1;
        }
 
-       if (pg_next_reg->base == 1) { // next region == base region
+       if (pg_next_reg->base == 1) {
            use_large_page = 1; // State A
        } else {
 #if 0       // State B/C and D optimization
@@ -121,6 +121,10 @@ static inline int handle_passthrough_pagefault_64(struct guest_info * core, addr
     struct v3_mem_region * region =  v3_get_mem_region(core->vm_info, core->cpu_id, fault_addr);
     int page_size = PAGE_SIZE_4KB;
 
+    if (region == NULL) {
+       PrintError("%s: invalid region, addr=%p\n", __FUNCTION__, (void *)fault_addr);
+       return -1;
+    }
 
     /*  Check if:
      *  1. the guest is configured to use large pages and 
index 6a7b154..3ebb041 100644 (file)
@@ -311,30 +311,38 @@ struct v3_mem_region * v3_get_mem_region(struct v3_vm_info * vm, uint16_t core_i
 
 
 
-/* Search the "hooked" memory regions for a region that ends after the given address.  If the
- * address is invalid, return NULL. Else, return the first region found or the base region if no
- * region ends after the given address.
+/* Given an address, find the successor region. If the address is within a region, return that
+ * region. Input is an address, because the address may not have a region associated with it.
+ *
+ * Returns a region following or touching the given address. If address is invalid, NULL is
+ * returned, else the base region is returned if no region exists at or after the given address.
  */
 struct v3_mem_region * v3_get_next_mem_region( struct v3_vm_info * vm, uint16_t core_id, addr_t guest_addr) {
-    struct rb_node * n = vm->mem_map.mem_regions.rb_node;
-    struct v3_mem_region * reg = NULL;
-
-    // Keep going to the right in the tree while the address is greater than the current region's
-    // end address.
-    while (n) {
-        reg = rb_entry(n, struct v3_mem_region, tree_node);
-        if (guest_addr >= reg->guest_end) { // reg is [start,end)
-            n = n->rb_right;
-        } else {
-           if ((core_id == reg->core_id) || (reg->core_id == V3_MEM_CORE_ANY)) {
-               return reg;
-           } else {
-               n = n->rb_right;
+    struct rb_node * current_n         = vm->mem_map.mem_regions.rb_node;
+    struct rb_node * successor_n       = NULL; /* left-most node greater than guest_addr */
+    struct v3_mem_region * current_r   = NULL;
+
+    /* current_n tries to find the region containing guest_addr, going right when smaller and left when
+     * greater. Each time current_n becomes greater than guest_addr, update successor <- current_n.
+     * current_n becomes successively closer to guest_addr than the previous time it was greater
+     * than guest_addr.
+     */
+
+    /* | is address, ---- is region, + is intersection */
+    while (current_n) {
+        current_r = rb_entry(current_n, struct v3_mem_region, tree_node);
+       if (current_r->guest_start > guest_addr) { /* | ---- */
+           successor_n = current_n;
+           current_n = current_n->rb_left;
+       } else {
+           if (current_r->guest_end > guest_addr) {
+               return current_r; /* +--- or --+- */
            }
-        }
+           current_n = current_n->rb_right; /* ---- | */
+       }
     }
 
-    // There is no registered region, so we check if it's a valid address in the base region
+    /* Address does not have its own region. Check if it's a valid address in the base region */
 
     if (guest_addr >= vm->mem_map.base_region.guest_end) {
        PrintError("%s: Guest Address Exceeds Base Memory Size (ga=%p), (limit=%p)\n",