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.


Generalization of constraints on page allocation and implementation/use
Peter Dinda [Fri, 17 Apr 2015 17:11:43 +0000 (12:11 -0500)]
The idea here is to allow Palacios code to request pages that satisfy some
filter function.  For example, a filter function might reject allocations
above the 4GB line, or it might reject allocations that map to undesirable
cache lines.

- it removes the notion of a constraint mask in page allocation
- eliminates the < 4GB flag
- adds the notion of constraints in page allocation as filter
  functions
- modifies the implementation and uses to match

linux_module/buddy.c
linux_module/buddy.h
linux_module/mm.c
linux_module/mm.h
linux_module/palacios-stubs.c
linux_module/palacios.h
palacios/include/palacios/vmm.h
palacios/src/palacios/mmu/vmm_shdw_pg_tlb.c
palacios/src/palacios/vmm.c
palacios/src/palacios/vmm_direct_paging.c
palacios/src/palacios/vmm_mem.c

index 26a7021..f21c95d 100644 (file)
@@ -285,13 +285,14 @@ int buddy_remove_pool(struct buddy_memzone * zone,
  * Arguments:
  *       [IN] mp:    Buddy system memory allocator object.
  *       [IN] order: Block size to allocate (2^order bytes).
- *       [IN] constraints: bitmmask showing restrictions for scan. currently: 0=none, or LWK_BUDDY_CONSTRAINT_4GB
+ *       [IN] filter_func: returns nonzero if given paddr is OK to use
+ *       [IN] filter_state: opaque argument to filter_func
  * Returns:
  *       Success: Pointer to the start of the allocated memory block.
  *       Failure: NULL
  */
 uintptr_t
-buddy_alloc(struct buddy_memzone *zone, unsigned long order, int constraints)
+buddy_alloc(struct buddy_memzone *zone, unsigned long order, int (*filter_func)(void *paddr, void *filter_state), void *filter_state)
 {
     unsigned long j;
     struct buddy_mempool * mp = NULL;
@@ -301,11 +302,6 @@ buddy_alloc(struct buddy_memzone *zone, unsigned long order, int constraints)
     struct block * buddy_block = NULL;
     unsigned long flags = 0;
 
-    if (constraints && constraints!=LWK_BUDDY_CONSTRAINT_4GB) { 
-       ERROR("Do not know how to satisfy constraint mask 0x%x\n", constraints);
-       return (uintptr_t) NULL;
-    }
-
     BUG_ON(zone == NULL);
     BUG_ON(order > zone->max_order);
 
@@ -333,23 +329,22 @@ buddy_alloc(struct buddy_memzone *zone, unsigned long order, int constraints)
        list_for_each(cur, list) {
            block = list_entry(cur, struct block, link);
 
-           if (!constraints) {
-               // without a constraint, we just want the first one
+           if (!filter_func) {
+               // without a filter, we just want the first one
                break;
-           }
-           
-           if (constraints & LWK_BUDDY_CONSTRAINT_4GB) {
-               // under this constraint, we will only use if the entirity
-               // of the allocation within the block will be below 4 GB
+           } else {
+
                void *block_pa = (void*)__pa(block);
-               if ((block_pa + (1ULL<<order)) <= (void*)(0x100000000ULL)) {
+
+               if (filter_func(block_pa,filter_state)) { 
                    // this block will work
                    break;
                } else {
-                   // look for the next block
+                   // this block won't work
                    block=NULL;
                    continue;
                }
+
            }
        }
        
index e0ef86d..163c5a8 100644 (file)
@@ -92,14 +92,13 @@ buddy_remove_pool(struct buddy_memzone * zone,
                  void          **user_metadata);
 
 
-// constraint=0 => no constraints, otherwise bitmask of:
-#define LWK_BUDDY_CONSTRAINT_4GB 0x1
 
 /* Allocate pages, returns physical address */
 extern uintptr_t 
 buddy_alloc(struct buddy_memzone * zone,
            unsigned long order,
-           int constraints);
+           int (*filter_func)(void *paddr, void *filter_state),
+           void *filter_state);
 
 
 /* Free a physical address */
index 1b70b74..e4c374a 100644 (file)
@@ -21,20 +21,9 @@ static uintptr_t * seed_addrs = NULL;
 
 
 // alignment is in bytes
-uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id, int constraints) {
+uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id, int (*filter_func)(void *paddr, void *filter_state), void *filter_state) {
     uintptr_t addr = 0; 
     int any = node_id==-1; // can allocate on any
-    int buddy_constraints=0;
-
-    if (constraints && constraints!=V3_ALLOC_PAGES_CONSTRAINT_4GB) { 
-       ERROR("Unknown constraint mask 0x%x\n",constraints);
-       return 0;
-    }
-    
-    if (constraints & V3_ALLOC_PAGES_CONSTRAINT_4GB) { 
-       buddy_constraints |= LWK_BUDDY_CONSTRAINT_4GB;
-    }
-
 
     if (node_id == -1) {
        int cpu_id = get_cpu();
@@ -50,14 +39,14 @@ uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id, int cons
        return 0;
     }
 
-    addr = buddy_alloc(memzones[node_id], get_order(num_pages * PAGE_SIZE) + PAGE_SHIFT, buddy_constraints);
+    addr = buddy_alloc(memzones[node_id], get_order(num_pages * PAGE_SIZE) + PAGE_SHIFT, filter_func, filter_state);
 
     if (!addr && any) { 
        int i;
        // do a scan to see if we can satisfy request on any node
        for (i=0; i< numa_num_nodes(); i++) { 
            if (i!=node_id) { 
-               addr = buddy_alloc(memzones[i], get_order(num_pages * PAGE_SIZE) + PAGE_SHIFT, buddy_constraints);
+               addr = buddy_alloc(memzones[i], get_order(num_pages * PAGE_SIZE) + PAGE_SHIFT, filter_func, filter_state);
                if (addr) {
                    break;
                }
@@ -313,7 +302,7 @@ int palacios_init_mm( void ) {
                pgs = alloc_pages_node(node_id, GFP_KERNEL, MAX_ORDER - 1);
 
                if (!pgs) {
-                   INFO("Could not allocate initial memory block for node %d beloew 4GB\n", node_id);
+                   INFO("Could not allocate initial memory block for node %d below 4GB\n", node_id);
                    if (!pgs) {
                        ERROR("Could not allocate initial memory block for node %d without restrictions\n", node_id);
                        BUG_ON(!pgs);
index b758b72..29c0738 100644 (file)
@@ -7,7 +7,7 @@
 
 
 
-uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id, int constraints);
+uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id, int (*filter_func)(void *paddr, void *filter_state), void *filter_state);
 void free_palacios_pg(uintptr_t base_addr);
 void free_palacios_pgs(uintptr_t base_addr, u64 num_pages);
 
index 54b2ad1..10d2fde 100644 (file)
@@ -175,18 +175,18 @@ void palacios_print_scoped(void * vm, int vcore, const char *fmt, ...) {
  * Allocates a contiguous region of pages of the requested size.
  * Returns the physical address of the first page in the region.
  */
-void *palacios_allocate_pages(int num_pages, unsigned int alignment, int node_id, int constraints) {
+void *palacios_allocate_pages(int num_pages, unsigned int alignment, int node_id, int (*filter_func)(void *paddr, void *filter_state), void *filter_state) {
     void * pg_addr = NULL;
 
     if (num_pages<=0) { 
-       ERROR("ALERT ALERT Attempt to allocate zero or fewer pages (%d pages, alignment %d, node %d, constraints 0x%x)\n",num_pages, alignment, node_id, constraints);
+       ERROR("ALERT ALERT Attempt to allocate zero or fewer pages (%d pages, alignment %d, node %d, filter_func %p, filter_state %p)\n",num_pages, alignment, node_id, filter_func, filter_state);
       return NULL;
     }
 
-    pg_addr = (void *)alloc_palacios_pgs(num_pages, alignment, node_id, constraints);
+    pg_addr = (void *)alloc_palacios_pgs(num_pages, alignment, node_id, filter_func, filter_state);
 
     if (!pg_addr) { 
-       ERROR("ALERT ALERT  Page allocation has FAILED Warning (%d pages, alignment %d, node %d, constraints 0x%x)\n",num_pages, alignment, node_id, constraints);
+       ERROR("ALERT ALERT  Page allocation has FAILED Warning (%d pages, alignment %d, node %d, filter_func %p, filter_state %p)\n",num_pages, alignment, node_id, filter_func, filter_state);
        return NULL;
     }
 
index 1b5cf44..4c8cf62 100644 (file)
@@ -62,10 +62,9 @@ struct v3_guest_img {
     char name[128];
 } __attribute__((packed));
 
-typedef enum { PREALLOCATED=0,          // user space-allocated (e.g. hot remove)
+typedef enum { PREALLOCATED=0,         // user space-allocated (e.g. hot remove)
              REQUESTED,               // kernel will attempt allocation (anywhere)
              REQUESTED32,             // kernel will attempt allocation (<4GB)
-
 } v3_mem_region_type_t;
 
 struct v3_mem_region {
@@ -156,7 +155,7 @@ struct proc_dir_entry *palacios_get_procdir(void);
 void  palacios_print_scoped(void *vm, int vcore, const char *fmt, ...);
 #define palacios_print(...) palacios_print_scoped(0,-1, __VA_ARGS__)
 // node_id=-1 => no node constraint
-void *palacios_allocate_pages(int num_pages, unsigned int alignment, int node_id, int constraints);
+void *palacios_allocate_pages(int num_pages, unsigned int alignment, int node_id, int (*filter_func)(void *paddr, void *filter_state), void *filter_state);
 void  palacios_free_pages(void *page_addr, int num_pages);
 void *palacios_alloc(unsigned int size);
 // node_id=-1 => no node constraint
index 14bbb2b..c00e10f 100644 (file)
@@ -59,7 +59,7 @@ int      v3_get_vcore(struct guest_info *);
        extern struct v3_os_hooks * os_hooks;                           \
        void * ptr = 0;                                                 \
        if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
-           ptr = (os_hooks)->allocate_pages(num_pages,PAGE_SIZE_4KB,-1,0); \
+           ptr = (os_hooks)->allocate_pages(num_pages,PAGE_SIZE_4KB,-1,0,0); \
        }                                                               \
        ptr;                                                            \
     })
@@ -70,7 +70,7 @@ int      v3_get_vcore(struct guest_info *);
        extern struct v3_os_hooks * os_hooks;                           \
        void * ptr = 0;                                                 \
        if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
-           ptr = (os_hooks)->allocate_pages(num_pages,align,-1,0);     \
+           ptr = (os_hooks)->allocate_pages(num_pages,align,-1,0,0);   \
        }                                                               \
        ptr;                                                            \
     })
@@ -81,17 +81,17 @@ int      v3_get_vcore(struct guest_info *);
         extern struct v3_os_hooks * os_hooks;                           \
         void * ptr = 0;                                                 \
         if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
-            ptr = (os_hooks)->allocate_pages(num_pages, PAGE_SIZE_4KB, node_id,0); \
+            ptr = (os_hooks)->allocate_pages(num_pages, PAGE_SIZE_4KB, node_id,0,0); \
         }                                                               \
         ptr;                                                            \
     })
 
-#define V3_AllocPagesExtended(num_pages, align, node_id, constraints)                  \
+#define V3_AllocPagesExtended(num_pages, align, node_id, filter_func, filter_state) \
     ({                                                                  \
         extern struct v3_os_hooks * os_hooks;                           \
         void * ptr = 0;                                                 \
         if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
-            ptr = (os_hooks)->allocate_pages(num_pages, align, node_id,constraints); \
+            ptr = (os_hooks)->allocate_pages(num_pages, align, node_id, filter_func, filter_state); \
         }                                                               \
         ptr;                                                            \
     })
@@ -357,8 +357,9 @@ struct v3_os_hooks {
     //   - node_id -1 => any node, otherwise the numa node we want to alloc from
     //   - constraint = 0 => no constraints, otherwise a bitwise-or of the following flags
     // Allocates physically contiguous pages
-#define V3_ALLOC_PAGES_CONSTRAINT_4GB  1
-    void *(*allocate_pages)(int num_pages, unsigned int alignment, int node_id, int constraint);
+    //   - with desired alignment
+    //   - that the filter_func returns nonzero on (if filter_func is given)
+    void *(*allocate_pages)(int num_pages, unsigned int alignment, int node_id, int (*filter_func)(void *paddr, void *filter_state), void *filter_state);
     void (*free_pages)(void * page, int num_pages);
 
     // Allocates virtually contiguous memory
index 9c5545c..d6f77d8 100644 (file)
@@ -54,13 +54,6 @@ static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core);
 #include "vmm_shdw_pg_tlb_32pae.h"
 #include "vmm_shdw_pg_tlb_64.h"
 
-static inline int get_constraints(struct guest_info *core) 
-{
-  // the current version of VTLB does not require any constraints
-  // on where page tables are allocated since it will use
-  // 32PAE page tables on a 64 bit machine even in 32 bit mode and below
-  return 0;  
-}
 
 
 static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core) {
@@ -98,7 +91,7 @@ static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core)
        return NULL;
     }
 
-    page_tail->page_pa = (addr_t)V3_AllocPagesExtended(1,PAGE_SIZE_4KB,-1,get_constraints(core));
+    page_tail->page_pa = (addr_t)V3_AllocPagesExtended(1,PAGE_SIZE_4KB,-1,0,0);
 
     if (!page_tail->page_pa) {
        PrintError(core->vm_info, core, "Cannot allocate page\n");
index f9e07df..b7f45cd 100644 (file)
@@ -616,7 +616,7 @@ int v3_move_vm_mem(struct v3_vm_info * vm, void *gpa, int target_cpu) {
     new_hpa = V3_AllocPagesExtended(num_pages,
                                    PAGE_SIZE_4KB,
                                    new_node,
-                                   0);  // no constraints given new shadow pager impl
+                                   0, 0);  // no constraints given new shadow pager impl
 
     if (!new_hpa) { 
        PrintError(vm, VCORE_NONE, "Cannot allocate memory for new base region...\n");
index 0458155..1175b25 100644 (file)
@@ -161,7 +161,7 @@ static addr_t create_generic_pt_page(struct guest_info *core) {
     void * page = 0;
     void *temp;
 
-    temp = V3_AllocPagesExtended(1, PAGE_SIZE_4KB, -1, 0); // no constraints
+    temp = V3_AllocPagesExtended(1, PAGE_SIZE_4KB, -1, 0, 0); // no constraints
 
     if (!temp) {  
        PrintError(VM_NONE, VCORE_NONE,"Cannot allocate page\n");
index aa71a8b..9cf6ea1 100644 (file)
@@ -221,7 +221,7 @@ int v3_init_mem_map(struct v3_vm_info * vm) {
            region->host_addr = (addr_t)V3_AllocPagesExtended(block_pages,
                                                              PAGE_SIZE_4KB,
                                                              node_id,
-                                                             0); // no constraints 
+                                                             0, 0); // no constraints 
            
            if ((void *)region->host_addr == NULL) { 
                PrintError(vm, VCORE_NONE, "Could not allocate guest memory\n");