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.


Constraints in page allocation, and code changes to use them; shadow paging allocati...
Peter Dinda [Sun, 18 Aug 2013 21:01:07 +0000 (16:01 -0500)]
This updates the page allocation os hook to take a "constraints" parameter.  Currently,
there only one constraint, allocation below 4 GB.   The buddy allocator and other elements
of the support code now obey this constraint.   I have vetted page allocations in Palacios
so that with a guest using shadow paging, any allocation that could become part of the
guest memory map, and any allocation done in 32 bit shadow paging (page tables) is done
with this constraint.  THis includes direct paging.  Nested paging should be unaffected.

36 files changed:
linux_module/buddy.c
linux_module/buddy.h
linux_module/linux-exts.c
linux_module/main.c
linux_module/mm.c
linux_module/mm.h
linux_module/palacios-stubs.c
linux_module/palacios.h
palacios/include/palacios/vmm.h
palacios/include/vnet/vnet_host.h
palacios/src/devices/cga.c
palacios/src/devices/cirrus_gfx_card.c
palacios/src/devices/paragraph.c
palacios/src/devices/swapbypass_cache.c
palacios/src/devices/swapbypass_cache2.c
palacios/src/devices/tmpdisk.c
palacios/src/devices/vga.c
palacios/src/palacios/mmu/vmm_shdw_pg_cache.c
palacios/src/palacios/mmu/vmm_shdw_pg_kvm.c
palacios/src/palacios/mmu/vmm_shdw_pg_swapbypass.c
palacios/src/palacios/mmu/vmm_shdw_pg_tlb.c
palacios/src/palacios/svm.c
palacios/src/palacios/svm_io.c
palacios/src/palacios/svm_msr.c
palacios/src/palacios/vmm_dev_mgr.c
palacios/src/palacios/vmm_direct_paging.c
palacios/src/palacios/vmm_direct_paging_32.h
palacios/src/palacios/vmm_direct_paging_32pae.h
palacios/src/palacios/vmm_direct_paging_64.h
palacios/src/palacios/vmm_mem.c
palacios/src/palacios/vmm_mem_hook.c
palacios/src/palacios/vmm_symspy.c
palacios/src/palacios/vmx.c
palacios/src/palacios/vmx_ept.c
palacios/src/palacios/vmx_io.c
palacios/src/palacios/vmx_msr.c

index b4f2b81..f7c91cb 100644 (file)
@@ -153,7 +153,7 @@ int buddy_add_pool(struct buddy_memzone * zone,
        return -1;
     }
 
-    mp = palacios_alloc_node_extended(sizeof(struct buddy_mempool), GFP_KERNEL, zone->node_id);
+    mp = palacios_alloc_extended(sizeof(struct buddy_mempool), GFP_KERNEL, zone->node_id);
 
     if (IS_ERR(mp)) {
        ERROR("Could not allocate mempool\n");
@@ -170,7 +170,7 @@ int buddy_add_pool(struct buddy_memzone * zone,
     /* Allocate a bitmap with 1 bit per minimum-sized block */
     mp->num_blocks = (1UL << pool_order) / (1UL << zone->min_order);
 
-    mp->tag_bits   = palacios_alloc_node_extended(
+    mp->tag_bits   = palacios_alloc_extended(
                                  BITS_TO_LONGS(mp->num_blocks) * sizeof(long), GFP_KERNEL, zone->node_id
                                  );
 
@@ -261,21 +261,27 @@ 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
  * Returns:
  *       Success: Pointer to the start of the allocated memory block.
  *       Failure: NULL
  */
 uintptr_t
-buddy_alloc(struct buddy_memzone *zone, unsigned long order)
+buddy_alloc(struct buddy_memzone *zone, unsigned long order, int constraints)
 {
     unsigned long j;
     struct buddy_mempool * mp = NULL;
     struct list_head * list = NULL;
+    struct list_head * cur = NULL;
     struct block * block = NULL;
     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);
 
@@ -292,13 +298,44 @@ buddy_alloc(struct buddy_memzone *zone, unsigned long order)
 
        INFO("Order iter=%lu\n", j);
 
-       /* Try to allocate the first block in the order j list */
-       list = &zone->avail[j];
+       block=NULL;
+
+       list = &(zone->avail[j]);
+       
+       if (list_empty(list)) {
+           continue;
+       }
+
+       list_for_each(cur, list) {
+           block = list_entry(cur, struct block, link);
 
-       if (list_empty(list)) 
+           if (!constraints) {
+               // without a constraint, 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
+               void *block_pa = (void*)__pa(block);
+               if ((block_pa + (1ULL<<order)) <= (void*)(0x100000000ULL)) {
+                   // this block will work
+                   break;
+               } else {
+                   // look for the next block
+                   block=NULL;
+                   continue;
+               }
+           }
+       }
+       
+       if (!block) { 
+           // uh oh, no block, look to next order
            continue;
+       }
+
+       // have appropriate block, will allocate
 
-       block = list_entry(list->next, struct block, link);
        list_del(&(block->link));
 
        mp = block->mp;
@@ -307,11 +344,6 @@ buddy_alloc(struct buddy_memzone *zone, unsigned long order)
 
        INFO("pool=%p, block=%p, order=%lu, j=%lu\n", mp, block, order, j);
 
-       /*
-       palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
-       return 0;
-       */
-
        /* Trim if a higher order block than necessary was allocated */
        while (j > order) {
            --j;
@@ -563,11 +595,11 @@ buddy_init(
     if (min_order > max_order)
        return NULL;
 
-    zone = palacios_alloc_node_extended(sizeof(struct buddy_memzone), GFP_KERNEL, node_id);
+    zone = palacios_alloc_extended(sizeof(struct buddy_memzone), GFP_KERNEL, node_id);
        
     INFO("Allocated zone at %p\n", zone);
 
-    if (IS_ERR(zone)) {
+    if (!zone) {
        ERROR("Could not allocate memzone\n");
        return NULL;
     }
@@ -579,7 +611,13 @@ buddy_init(
     zone->node_id = node_id;
 
     /* Allocate a list for every order up to the maximum allowed order */
-    zone->avail = palacios_alloc_node_extended((max_order + 1) * sizeof(struct list_head), GFP_KERNEL, zone->node_id);
+    zone->avail = palacios_alloc_extended((max_order + 1) * sizeof(struct list_head), GFP_KERNEL, zone->node_id);
+
+    if (!(zone->avail)) { 
+       ERROR("Unable to allocate space for zone list\n");
+       palacios_free(zone);
+       return NULL;
+    }
 
     INFO("Allocated free lists at %p\n", zone->avail);
 
index 34742e1..4781cfc 100644 (file)
@@ -91,10 +91,14 @@ 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);
+           unsigned long order,
+           int constraints);
 
 
 /* Free a physical address */
index f393edc..7b09021 100644 (file)
@@ -43,7 +43,7 @@ static inline struct global_ctrl * __insert_global_ctrl(struct global_ctrl * ctr
 
 int add_global_ctrl(unsigned int cmd, 
                    int (*handler)(unsigned int cmd, unsigned long arg)) {
-    struct global_ctrl * ctrl = palacios_alloc_extended(sizeof(struct global_ctrl), GFP_KERNEL);
+    struct global_ctrl * ctrl = palacios_alloc_extended(sizeof(struct global_ctrl), GFP_KERNEL,-1);
 
     if (ctrl == NULL) {
         printk("Error: Could not allocate global ctrl %d\n", cmd);
index 79b6280..228a1d3 100644 (file)
@@ -449,7 +449,7 @@ static int __init v3_init(void) {
     {
        struct proc_dir_entry *entry;
 
-       INFO("palacios_proc_dir=%p before v3-guests\n",palacios_proc_dir);
+       //INFO("palacios_proc_dir=%p before v3-guests\n",palacios_proc_dir);
        entry = create_proc_read_entry("v3-guests", 0444, palacios_proc_dir, read_guests, NULL);
         if (entry) {
            INFO("/proc/v3vee/v3-guests successfully created\n");
@@ -554,7 +554,7 @@ void * trace_malloc(size_t size, gfp_t flags) {
     void * addr = NULL;
 
     mod_allocs++;
-    addr = palacios_alloc_extended(size, flags);
+    addr = palacios_alloc_extended(size, flags, -1);
 
     return addr;
 }
index 01d4b75..5e98f79 100644 (file)
@@ -13,6 +13,7 @@
 #include "mm.h"
 #include "buddy.h"
 #include "numa.h"
+#include "palacios/vmm.h"
 
 
 static struct buddy_memzone ** memzones = NULL;
@@ -20,9 +21,20 @@ static uintptr_t * seed_addrs = NULL;
 
 
 // alignment is in bytes
-uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id) {
+uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id, int constraints) {
     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();
@@ -38,14 +50,14 @@ uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id) {
        return 0;
     }
 
-    addr = buddy_alloc(memzones[node_id], get_order(num_pages * PAGE_SIZE) + PAGE_SHIFT);
+    addr = buddy_alloc(memzones[node_id], get_order(num_pages * PAGE_SIZE) + PAGE_SHIFT, buddy_constraints);
 
     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);
+               addr = buddy_alloc(memzones[i], get_order(num_pages * PAGE_SIZE) + PAGE_SHIFT, buddy_constraints);
                if (addr) {
                    break;
                }
@@ -132,6 +144,10 @@ int add_palacios_memory(struct v3_mem_region *r) {
        return -1;
     }
 
+    if ((node_id != r->node) && (r->node!=-1)) { 
+       INFO("Memory add request is for node %d, but memory is in node %d\n",r->node,node_id);
+    }
+
     pool_order = get_order(r->num_pages * PAGE_SIZE) + PAGE_SHIFT;
 
     if (buddy_add_pool(memzones[node_id], r->base_addr, pool_order, keep)) {
@@ -203,7 +219,7 @@ int palacios_init_mm( void ) {
 
     INFO("memory manager init: MAX_ORDER=%d (%llu bytes)\n",MAX_ORDER, PAGE_SIZE*pow2(MAX_ORDER));
 
-    memzones = palacios_alloc_extended(sizeof(struct buddy_memzone *) * num_nodes, GFP_KERNEL);
+    memzones = palacios_alloc_extended(sizeof(struct buddy_memzone *) * num_nodes, GFP_KERNEL,-1);
 
     if (!memzones) { 
        ERROR("Cannot allocate space for memory zones\n");
@@ -213,7 +229,7 @@ int palacios_init_mm( void ) {
 
     memset(memzones, 0, sizeof(struct buddy_memzone *) * num_nodes);
 
-    seed_addrs = palacios_alloc_extended(sizeof(uintptr_t) * num_nodes, GFP_KERNEL);
+    seed_addrs = palacios_alloc_extended(sizeof(uintptr_t) * num_nodes, GFP_KERNEL,-1);
 
     if (!seed_addrs) { 
        ERROR("Cannot allocate space for seed addrs\n");
index 744c567..9452ddd 100644 (file)
@@ -7,7 +7,7 @@
 
 
 
-uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id);
+uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id, int constraints);
 void free_palacios_pg(uintptr_t base_addr);
 void free_palacios_pgs(uintptr_t base_addr, u64 num_pages);
 
index 7ad4ad8..08021e4 100644 (file)
@@ -165,7 +165,7 @@ 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) {
+void *palacios_allocate_pages(int num_pages, unsigned int alignment, int node_id, int constraints) {
     void * pg_addr = NULL;
 
     if (num_pages<=0) { 
@@ -173,7 +173,7 @@ void *palacios_allocate_pages(int num_pages, unsigned int alignment, int node_id
       return NULL;
     }
 
-    pg_addr = (void *)alloc_palacios_pgs(num_pages, alignment, node_id);
+    pg_addr = (void *)alloc_palacios_pgs(num_pages, alignment, node_id, constraints);
 
     if (!pg_addr) { 
        ERROR("ALERT ALERT  Page allocation has FAILED Warning\n");
@@ -203,7 +203,7 @@ void palacios_free_pages(void * page_paddr, int num_pages) {
 
 
 void *
-palacios_alloc_extended(unsigned int size, unsigned int flags) {
+palacios_alloc_extended(unsigned int size, unsigned int flags, int node) {
     void * addr = NULL;
 
     if (size==0) { 
@@ -214,7 +214,11 @@ palacios_alloc_extended(unsigned int size, unsigned int flags) {
       return NULL;
     }
 
-    addr = kmalloc(size+2*ALLOC_PAD, flags);
+    if (node==-1) { 
+       addr = kmalloc(size+2*ALLOC_PAD, flags);
+    } else {
+       addr = kmalloc_node(size+2*ALLOC_PAD, flags, node);
+    }
 
     if (!addr) { 
        ERROR("ALERT ALERT  kmalloc has FAILED FAILED FAILED\n");
@@ -275,9 +279,9 @@ palacios_alloc(unsigned int size) {
     // module, both in places where interrupts are off and where they are on
     // a GFP_KERNEL call, when done with interrupts off can lead to DEADLOCK
     if (irqs_disabled()) {
-       return palacios_alloc_extended(size,GFP_ATOMIC);
+       return palacios_alloc_extended(size,GFP_ATOMIC,-1);
     } else {
-       return palacios_alloc_extended(size,GFP_KERNEL);
+       return palacios_alloc_extended(size,GFP_KERNEL,-1);
     }
 
 }
index f9927c2..977d617 100644 (file)
@@ -140,14 +140,12 @@ struct proc_dir_entry *palacios_get_procdir(void);
 // The idea is that everything uses the same stubs
 void  palacios_print_scoped(void *vm, int vcore, const char *fmt, ...);
 #define palacios_print(...) palacios_print_scoped(0,-1, __VA_ARGS__)
-void *palacios_allocate_pages(int num_pages, unsigned int alignment, int node_id);
+// node_id=-1 => no node constraint
+void *palacios_allocate_pages(int num_pages, unsigned int alignment, int node_id, int constraints);
 void  palacios_free_pages(void *page_addr, int num_pages);
 void *palacios_alloc(unsigned int size);
-void *palacios_alloc_extended(unsigned int size, unsigned int flags);
-// FIX
-// NEED A palacios_alloc_node wrapper
-//
-#define palacios_alloc_node_extended(size, flags, node) kmalloc_node(size,flags,node)
+// node_id=-1 => no node constraint
+void *palacios_alloc_extended(unsigned int size, unsigned int flags, int node_id);
 void  palacios_free(void *);
 void *palacios_valloc(unsigned int size); // use instead of vmalloc
 void  palacios_vfree(void *);             // use instead of vfree
index a8f321c..d53af85 100644 (file)
@@ -22,7 +22,6 @@
 
 
 
-
 #ifdef __V3VEE__
 #include <palacios/vmm_mem.h>
 #include <palacios/vmm_types.h>
@@ -60,18 +59,36 @@ 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);       \
+           ptr = (os_hooks)->allocate_pages(num_pages,PAGE_SIZE_4KB,-1,0); \
        }                                                               \
        ptr;                                                            \
     })
 
 
+// Use 32 bit constraints if the vm uses 32bit shadow paging at any point
+// Should be used for shadow page tables and any physical memory
+// mapped into the vm
+#define V3_AllocShadowSafePages(vm,num_pages)                          \
+    ({                                                                 \
+       extern struct v3_os_hooks * os_hooks;                           \
+       void * ptr = 0;                                                 \
+       int c; int shadow=0;                                            \
+        for (c=0;c<(vm)->num_cores && !shadow;c++) {                    \
+            shadow|=vm->cores[c].shdw_pg_mode==SHADOW_PAGING;           \
+        }                                                               \
+       if ((os_hooks) && (os_hooks)->allocate_pages) {                 \
+           ptr = (os_hooks)->allocate_pages(num_pages,PAGE_SIZE_4KB,-1,\
+                    shadow ? V3_ALLOC_PAGES_CONSTRAINT_4GB : 0);        \
+       }                                                               \
+       ptr;                                                            \
+    })
+
 #define V3_AllocAlignedPages(num_pages, align)                         \
     ({                                                                 \
        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);       \
+           ptr = (os_hooks)->allocate_pages(num_pages,align,-1,0);     \
        }                                                               \
        ptr;                                                            \
     })
@@ -82,7 +99,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); \
+            ptr = (os_hooks)->allocate_pages(num_pages, PAGE_SIZE_4KB, node_id,0); \
+        }                                                               \
+        ptr;                                                            \
+    })
+
+#define V3_AllocPagesExtended(num_pages, align, node_id, constraints)                  \
+    ({                                                                  \
+        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;                                                            \
     })
@@ -304,14 +331,18 @@ struct v3_vm_info;
 
 /* This will contain function pointers that provide OS services */
 struct v3_os_hooks {
-  // the vm pointer is the host os's "priv_data" from v3_create_vm
-  // if vm is null, this is a general palacios printout
-  // if vm is not null, and vcore is negative, this is a general print form the vm
-  // if vm is not null, and vcore is non-negative, this is a print from a specific vcore
+    // the vm pointer is the host os's "priv_data" from v3_create_vm
+    // if vm is null, this is a general palacios printout
+    // if vm is not null, and vcore is negative, this is a general print form the vm
+    // if vm is not null, and vcore is non-negative, this is a print from a specific vcore
     void (*print)(void *vm, int vcore, const char * format, ...)
        __attribute__ ((format (printf, 3, 4)));
-  
-    void *(*allocate_pages)(int num_pages, unsigned int alignment, int node_id);
+
+    // For page allocation:
+    //   - 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
+#define V3_ALLOC_PAGES_CONSTRAINT_4GB  1
+    void *(*allocate_pages)(int num_pages, unsigned int alignment, int node_id, int constraint);
     void (*free_pages)(void * page, int num_pages);
 
     void *(*malloc)(unsigned int size);
index 6347fed..9ab151d 100644 (file)
@@ -92,7 +92,7 @@ extern struct vnet_host_hooks * host_hooks;
 /* 4KB-aligned */
 static inline void * Vnet_AllocPages(int num_pages){
     if ((host_hooks) && host_hooks->allocate_pages) {
-       return host_hooks->allocate_pages(num_pages, PAGE_SIZE_4KB);
+       return host_hooks->allocate_pages(num_pages, PAGE_SIZE_4KB,-1,0); // any zone, no constraints
     }
 
     return NULL;
index d79e577..1d23a20 100644 (file)
@@ -1252,7 +1252,7 @@ static int cga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
   
     video_state->dev = dev;
 
-    video_state->framebuf_pa = (addr_t)V3_AllocPages(FRAMEBUF_SIZE / 4096);
+    video_state->framebuf_pa = (addr_t)V3_AllocShadowSafePages(vm,FRAMEBUF_SIZE / 4096);
 
     if (!video_state->framebuf_pa) { 
        PrintError(vm, VCORE_NONE, "Cannot allocate frame buffer\n");
index c6b7a43..66f75b4 100644 (file)
@@ -442,7 +442,7 @@ static int cirrus_gfx_card_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg){
     PrintDebug(info->vm_info, info, "video: init_device\n");
     PrintDebug(info->vm_info, info, "Num Pages=%d\n", SIZE_OF_REGION / 4096);
 
-    video_state->video_memory_pa = (addr_t)V3_AllocPages(SIZE_OF_REGION / 4096);
+    video_state->video_memory_pa = (addr_t)V3_AllocShadowSafePages(vm, SIZE_OF_REGION / 4096);
     if (!video_state->video_memory_pa) { 
        PrintError(info->vm_info, info, "Cannot allocate video memory\n");
        V3_Free(video_state);
index 36e44d8..32f07f1 100644 (file)
@@ -452,7 +452,7 @@ static int paragraph_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg)
   if (state->mode==MEM || state->mode==GCONS_MEM) { 
     state->mem_size=MAXX*MAXY*MAXBPP;
     PrintDebug(vm, VCORE_NONE, "paragraph: allocating %llu bytes for local framebuffer\n", state->mem_size);
-    state->mem_paddr = V3_AllocPages(ceil_pages(state->mem_size));
+    state->mem_paddr = V3_AllocShadowSafePages(vm,ceil_pages(state->mem_size));
     if (!state->mem_paddr) { 
       PrintError(state->vm, VCORE_NONE, "paragraph: Cannot allocate memory for framebuffer\n");
       paragraph_free_internal(state);
index 23e7d41..882d55f 100644 (file)
@@ -296,7 +296,7 @@ static int swap_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     swap->active = 0;
     swap->hdr = (union swap_header *)swap;
 
-    swap->swap_base_addr = (addr_t)V3_AllocPages(swap->capacity / 4096);
+    swap->swap_base_addr = (addr_t)V3_AllocShadowSafePages(swap->capacity / 4096); 
 
     if (!swap->swap_base_addr) { 
        PrintError(vm, VCORE_NONE, "Cannot allocate swap space\n");
index 09d090b..408d2b8 100644 (file)
@@ -578,7 +578,7 @@ static int connect_fn(struct v3_vm_info * vm,
 
        swap->active = 0;
 
-       swap->cache_base_addr = (addr_t)V3_AllocPages(swap->cache_size / 4096);
+       swap->cache_base_addr = (addr_t)V3_AllocShadowSafePages(vm,swap->cache_size / 4096);
 
        if (!swap->cache_base_addr) { 
            PrintError(vm, VCORE_NONE, "Cannot allocate cache space\n");
index 0b5fb1f..1046b9b 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <palacios/vmm.h>
 #include <palacios/vmm_dev_mgr.h>
-
+#include <palacios/vm_guest.h>
 
 struct blk_state {
     uint64_t capacity;
@@ -120,7 +120,7 @@ static int blk_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
 
     blk->capacity = capacity;
     
-    blk->blk_base_addr = (addr_t)V3_AllocPages(blk->capacity / 4096);
+    blk->blk_base_addr = (addr_t)V3_AllocShadowSafePages(vm,blk->capacity / 4096);
 
     if (!blk->blk_base_addr) { 
        PrintError(vm, VCORE_NONE, "Cannot allocate block space\n");
index db11ea4..16e4583 100644 (file)
@@ -2847,7 +2847,7 @@ static int vga_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
     for (i=0;i<MAP_NUM;i++) { 
        void *temp;
 
-       temp = (void*)V3_AllocPages(MAP_SIZE/4096);
+       temp = (void*)V3_AllocShadowSafePages(vm,MAP_SIZE/4096);
        if (!temp) { 
            PrintError(vm, VCORE_NONE, "vga: cannot allocate maps\n");
            free_vga(vga);
index a3bc512..cf60c86 100644 (file)
@@ -391,7 +391,9 @@ static struct shdw_pg_data * create_shdw_pt(struct v3_vm_info * vm, addr_t gpa,
            return NULL;
        }
 
-       pg_data->hpa = (addr_t)V3_AllocPages(1);
+       pg_data->hpa = (addr_t)V3_AllocPagesExtended(1,PAGE_SIZE_4KB,-1,
+                                                    V3_ALLOC_PAGES_CONSTRAINT_4GB);
+
 
        if (!pg_data->hpa) {
            PrintError(vm, VCORE_NONE,  "Cannot allocate page for shadow page table\n");
index 074e2ab..53cd9d9 100644 (file)
@@ -112,12 +112,16 @@ static void shadow_free_pde_chain(struct guest_info *core, struct pde_chain *pc)
 }
 
 
+
 static void shadow_free_page (struct guest_info * core, struct shadow_page_cache_data * page) 
 {
     list_del(&page->link);
 
     V3_FreePages((void *)page->page_pa, 1);
-    page->page_pa=(addr_t)V3_AllocPages(1);
+    
+    // presumably the same page could be used for 32 or 64 bit tables, so, we'll make it 
+    // uniformly compatible
+    page->page_pa=(addr_t)V3_AllocPagesExtended(1,PAGE_SIZE_4KB,-1,V3_ALLOC_PAGES_CONSTRAINT_4GB);
 
     if (!page->page_pa) { 
        PrintError(info->vm_info, info, "Freeing shadow page failed on allocation\n");
@@ -182,7 +186,11 @@ static int alloc_shadow_pages(struct guest_info * core)
        page_header = &core->page_header_buf[i];
 
        INIT_LIST_HEAD(&page_header->link);
-       if (!(page_header->page_pa = (addr_t)V3_AllocPages(1))) {
+       // presumably the same page could be used for 32 or 64 bit tables, so, we'll make it 
+       // uniformly compatible
+       page_headeer->page_pa=(addr_t)V3_AllocPagesExtended(1,PAGE_SIZE_4KB,-1,
+                                                           V3_ALLOC_PAGES_CONSTRAINT_4GB);
+       if (!(page_header->page_pa)) {
            PrintError(info->vm_info, info, "Allocation failed in allocating shadow page\n");
            goto error_1;
        }
index a5c77a4..06c5a40 100644 (file)
@@ -248,6 +248,25 @@ static addr_t map_swp_page(struct v3_vm_info * vm, pte32_t * shadow_pte, pte32_t
 #include "vmm_shdw_pg_swapbypass_32pae.h"
 #include "vmm_shdw_pg_swapbypass_64.h"
 
+static inline int get_constraints(struct guest_info *core) 
+{
+    switch (v3_get_vm_cpu_mode(core)) {
+       case PROTECTED:
+       case PROTECTED_PAE:
+           return V3_ALLOC_PAGES_CONSTRAINT_4GB;
+           break;
+       case LONG:
+       case LONG_32_COMPAT:
+       case LONG_16_COMPAT:
+           return 0;
+           break;
+       default:
+           return V3_ALLOC_PAGES_CONSTRAINT_4GB;
+           break;
+    }
+    return V3_ALLOC_PAGES_CONSTRAINT_4GB;
+}
+
 
 static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core) {
     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
@@ -284,7 +303,7 @@ static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core)
        return NULL;
     }
 
-    page_tail->page_pa = (addr_t)V3_AllocPages(1);
+    page_tail->page_pa = (addr_t)V3_AllocPagesExtended(1,PAGE_SIZE_4KB,-1,get_constraints(core));
 
     if (!page_tail->page_pa) {
        PrintError(core->vm_info, core, "Cannot allocate page\n");
index 02be430..51e88e8 100644 (file)
@@ -53,6 +53,26 @@ static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core);
 #include "vmm_shdw_pg_tlb_64.h"
 
 
+static inline int get_constraints(struct guest_info *core) 
+{
+    switch (v3_get_vm_cpu_mode(core)) {
+       case PROTECTED:
+       case PROTECTED_PAE:
+           return V3_ALLOC_PAGES_CONSTRAINT_4GB;
+           break;
+       case LONG:
+       case LONG_32_COMPAT:
+       case LONG_16_COMPAT:
+           return 0;
+           break;
+       default:
+           return V3_ALLOC_PAGES_CONSTRAINT_4GB;
+           break;
+    }
+    return V3_ALLOC_PAGES_CONSTRAINT_4GB;
+}
+
+
 static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core) {
     struct v3_shdw_pg_state * state = &(core->shdw_pg_state);
     struct vtlb_local_state * impl_state = (struct vtlb_local_state *)(state->local_impl_data);
@@ -88,7 +108,7 @@ static struct shadow_page_data * create_new_shadow_pt(struct guest_info * core)
        return NULL;
     }
 
-    page_tail->page_pa = (addr_t)V3_AllocPages(1);
+    page_tail->page_pa = (addr_t)V3_AllocPagesExtended(1,PAGE_SIZE_4KB,-1,get_constraints(core));
 
     if (!page_tail->page_pa) {
        PrintError(core->vm_info, core, "Cannot allocate page\n");
@@ -167,15 +187,19 @@ static int vtlb_activate_shdw_pt(struct guest_info * core) {
 
        case PROTECTED:
            return activate_shadow_pt_32(core);
+           break;
        case PROTECTED_PAE:
            return activate_shadow_pt_32pae(core);
+           break;
        case LONG:
        case LONG_32_COMPAT:
        case LONG_16_COMPAT:
            return activate_shadow_pt_64(core);
+           break;
        default:
            PrintError(core->vm_info, core, "Invalid CPU mode: %s\n", v3_cpu_mode_to_str(v3_get_vm_cpu_mode(core)));
            return -1;
+           break;
     }
 
     return 0;
index c9ef918..71e62d6 100644 (file)
@@ -74,7 +74,7 @@ extern int v3_svm_launch(vmcb_t * vmcb, struct v3_gprs * vm_regs, vmcb_t * host_
 
 static vmcb_t * Allocate_VMCB() {
     vmcb_t * vmcb_page = NULL;
-    addr_t vmcb_pa = (addr_t)V3_AllocPages(1);
+    addr_t vmcb_pa = (addr_t)V3_AllocPages(1);   // need not be shadow safe, not exposed to guest
 
     if ((void *)vmcb_pa == NULL) {
       PrintError(VM_NONE, VCORE_NONE, "Error allocating VMCB\n");
@@ -1042,7 +1042,7 @@ void v3_init_svm_cpu(int cpu_id) {
     V3_Print(VM_NONE, VCORE_NONE,  "SVM Enabled\n");
 
     // Setup the host state save area
-    host_vmcbs[cpu_id] = (addr_t)V3_AllocPages(4);
+    host_vmcbs[cpu_id] = (addr_t)V3_AllocPages(4); // need not be shadow-safe, not exposed to guest
 
     if (!host_vmcbs[cpu_id]) {
        PrintError(VM_NONE, VCORE_NONE,  "Failed to allocate VMCB\n");
@@ -1287,7 +1287,7 @@ void Init_VMCB_pe(vmcb_t *vmcb, struct guest_info vm_info) {
   
 
   ctrl_area->instrs.IOIO_PROT = 1;
-  ctrl_area->IOPM_BASE_PA = (uint_t)V3_AllocPages(3);
+  ctrl_area->IOPM_BASE_PA = (uint_t)V3_AllocPages(3); // need not be shadow-safe, not exposed to guest
 
   if (!ctrl_area->IOPM_BASE_PA) { 
       PrintError(core->vm_info, core, "Cannot allocate IO bitmap\n");
index 95dc860..91ba659 100644 (file)
@@ -50,7 +50,7 @@ int v3_init_svm_io_map(struct v3_vm_info * vm) {
 
     vm->io_map.update_map = update_map;
 
-    temp = V3_AllocPages(3);
+    temp = V3_AllocPages(3); // need not be shadow-safe, not exposed to guest
     
     if (!temp) { 
        PrintError(vm, VCORE_NONE,  "Cannot allocate io bitmap\n");
index 5c39c6e..08b1569 100644 (file)
@@ -87,7 +87,7 @@ int v3_init_svm_msr_map(struct v3_vm_info * vm) {
   
     msr_map->update_map = update_map;
 
-    temp = V3_AllocPages(2);
+    temp = V3_AllocPages(2); // need not be shadow-safe, not exposed to guest
     
     if (!temp) { 
        PrintError(vm, VCORE_NONE,  "Cannot allocate msr bitmap\n");
index 3709ced..2c449bc 100644 (file)
@@ -94,7 +94,10 @@ int V3_init_devices() {
 
 
 int V3_deinit_devices() {    
-    v3_free_htable(master_dev_table, 0, 0);
+    if (master_dev_table) { 
+       v3_free_htable(master_dev_table, 0, 0);
+       master_dev_table=0;
+    }
     return 0;
 }
 
@@ -329,7 +332,10 @@ int v3_deinit_dev_mgr(struct v3_vm_info * vm) {
 
     free_frontends(vm, mgr);
 
-    v3_free_htable(mgr->dev_table, 0, 0);
+    if (mgr->dev_table) { 
+       v3_free_htable(mgr->dev_table, 0, 0);
+       mgr->dev_table=0;
+    }
 
     return 0;
 }
index 92601c4..5f5be4c 100644 (file)
 #endif
 
 
-static addr_t create_generic_pt_page() {
+static addr_t create_generic_pt_page(struct guest_info *core) {
     void * page = 0;
     void *temp;
 
-    temp = V3_AllocPages(1);
+    temp = V3_AllocPagesExtended(1, PAGE_SIZE_4KB, -1, 
+                                core->shdw_pg_mode==SHADOW_PAGING ? V3_ALLOC_PAGES_CONSTRAINT_4GB : 0);
     if (!temp) { 
        PrintError(VM_NONE, VCORE_NONE,"Cannot allocate page\n");
        return 0;
@@ -53,7 +54,7 @@ static addr_t create_generic_pt_page() {
 #include "vmm_direct_paging_64.h"
 
 int v3_init_passthrough_pts(struct guest_info * info) {
-    info->direct_map_pt = (addr_t)V3_PAddr((void *)create_generic_pt_page());
+    info->direct_map_pt = (addr_t)V3_PAddr((void *)create_generic_pt_page(info));
     return 0;
 }
 
index e0ac13b..9d3a5c9 100644 (file)
@@ -57,7 +57,7 @@ static inline int handle_passthrough_pagefault_32(struct guest_info * info,
 
     // Fix up the PDE entry
     if (pde[pde_index].present == 0) {
-       pte = (pte32_t *)create_generic_pt_page();
+       pte = (pte32_t *)create_generic_pt_page(info);
        
        pde[pde_index].present = 1;
        pde[pde_index].writable = 1;
index e1a84f0..9d07d39 100644 (file)
@@ -57,7 +57,7 @@ static inline int handle_passthrough_pagefault_32pae(struct guest_info * info,
 
     // Fix up the PDPE entry
     if (pdpe[pdpe_index].present == 0) {
-       pde = (pde32pae_t *)create_generic_pt_page();
+       pde = (pde32pae_t *)create_generic_pt_page(info);
    
        pdpe[pdpe_index].present = 1;
        // Set default PDPE Flags...
@@ -69,7 +69,7 @@ static inline int handle_passthrough_pagefault_32pae(struct guest_info * info,
 
     // Fix up the PDE entry
     if (pde[pde_index].present == 0) {
-       pte = (pte32pae_t *)create_generic_pt_page();
+       pte = (pte32pae_t *)create_generic_pt_page(info);
 
        pde[pde_index].present = 1;
        pde[pde_index].writable = 1;
index 004eceb..92af1f5 100644 (file)
@@ -70,7 +70,7 @@ static inline int handle_passthrough_pagefault_64(struct guest_info * core, addr
 
     //Fix up the PML entry
     if (pml[pml_index].present == 0) {
-       pdpe = (pdpe64_t *)create_generic_pt_page();
+       pdpe = (pdpe64_t *)create_generic_pt_page(core);
    
        // Set default PML Flags...
        pml[pml_index].present = 1;
@@ -84,7 +84,7 @@ static inline int handle_passthrough_pagefault_64(struct guest_info * core, addr
 
     // Fix up the PDPE entry
     if (pdpe[pdpe_index].present == 0) {
-       pde = (pde64_t *)create_generic_pt_page();
+       pde = (pde64_t *)create_generic_pt_page(core);
        
        // Set default PDPE Flags...
        pdpe[pdpe_index].present = 1;
@@ -139,7 +139,7 @@ static inline int handle_passthrough_pagefault_64(struct guest_info * core, addr
     
     // Fix up the PDE entry
     if (pde[pde_index].present == 0) {
-       pte = (pte64_t *)create_generic_pt_page();
+       pte = (pte64_t *)create_generic_pt_page(core);
        
        pde[pde_index].present = 1;
        pde[pde_index].writable = 1;
index d934398..bc9490f 100644 (file)
@@ -104,6 +104,36 @@ static int gpa_to_node_from_cfg(struct v3_vm_info * vm, addr_t gpa) {
     return -1;
 }
 
+//
+// This code parallels that in vmm_shadow_paging.c:v3_init_shdw_impl() 
+// and vmm_config.c:determine_paging_mode.   The determination of which
+// paging mode will be used is determined much later than the allocation of
+// the guest memory regions, so we need to do this here to decide if they
+// need to be below 4 GB or not.
+static int will_use_shadow_paging(struct v3_vm_info *vm)
+{
+    v3_cfg_tree_t * pg_cfg = v3_cfg_subtree(vm->cfg_data->cfg, "paging");
+    char * pg_mode = v3_cfg_val(pg_cfg, "mode");
+   
+    if (pg_mode == NULL) { 
+       return 1; // did not ask, get shadow
+    } else {
+       if (strcasecmp(pg_mode, "nested") == 0) {
+           extern v3_cpu_arch_t v3_mach_type;
+           if ((v3_mach_type == V3_SVM_REV3_CPU) || 
+               (v3_mach_type == V3_VMX_EPT_CPU) ||
+               (v3_mach_type == V3_VMX_EPT_UG_CPU)) {
+               return 0; // ask for nested, get nested
+           } else { 
+               return 1; // ask for nested, get shadow
+           }
+       } else if (strcasecmp(pg_mode, "shadow") != 0) { 
+           return 1;     // ask for shadow, get shadow
+       } else {
+           return 1;     // ask for something else, get shadow
+       }
+    }
+}
 
 
 int v3_init_mem_map(struct v3_vm_info * vm) {
@@ -141,13 +171,13 @@ int v3_init_mem_map(struct v3_vm_info * vm) {
         node_id = gpa_to_node_from_cfg(vm, region->guest_start);
         
         V3_Print(vm, VCORE_NONE, "Allocating block %d on node %d\n", i, node_id);
-        
-        if (node_id != -1) {
-            region->host_addr = (addr_t)V3_AllocPagesNode(block_pages, node_id);
-        } else {
-            region->host_addr = (addr_t)V3_AllocPages(block_pages);
-        }
 
+       region->host_addr = (addr_t)V3_AllocPagesExtended(block_pages,
+                                                         PAGE_SIZE_4KB,
+                                                         node_id,
+                                                         will_use_shadow_paging(vm) ? 
+                                                         V3_ALLOC_PAGES_CONSTRAINT_4GB : 0 ); 
+                                                            
         if ((void *)region->host_addr == NULL) { 
             PrintError(vm, VCORE_NONE, "Could not allocate guest memory\n");
             return -1;
index 1d49294..c30e51d 100644 (file)
@@ -58,7 +58,7 @@ int v3_init_mem_hooks(struct v3_vm_info * vm) {
 
     struct v3_mem_hooks * hooks = &(vm->mem_hooks);
 
-    temp = V3_AllocPages(vm->num_cores);
+    temp = V3_AllocShadowSafePages(vm,vm->num_cores);
 
     if (!temp) {
        PrintError(vm, VCORE_NONE, "Cannot allocate space for mem hooks\n");
@@ -67,7 +67,7 @@ int v3_init_mem_hooks(struct v3_vm_info * vm) {
 
     hooks->hook_hvas_1 = V3_VAddr(temp);
 
-    temp = V3_AllocPages(vm->num_cores);
+    temp = V3_AllocShadowSafePages(vm,vm->num_cores);
 
     if (!temp) {
        PrintError(vm, VCORE_NONE,"Cannot allocate space for mem hooks\n");
index 58f8aed..148cbcb 100644 (file)
@@ -117,7 +117,7 @@ static int symspy_msr_write(struct guest_info * core, uint_t msr, struct v3_msr
 
 int v3_init_symspy_vm(struct v3_vm_info * vm, struct v3_symspy_global_state * state) {
 
-    state->global_page_pa = (addr_t)V3_AllocPages(1);
+    state->global_page_pa = (addr_t)V3_AllocShadowSafePages(vm, 1);
     if (!state->global_page_pa) { 
        PrintError(vm, VCORE_NONE, "Cannot allocate page\n");
        return -1;
@@ -137,7 +137,7 @@ int v3_init_symspy_vm(struct v3_vm_info * vm, struct v3_symspy_global_state * st
 
 
 int v3_init_symspy_core(struct guest_info * core, struct v3_symspy_local_state * state) {
-    state->local_page_pa = (addr_t)V3_AllocPages(1);
+    state->local_page_pa = (addr_t)V3_AllocShadowSafePages(core->vm_info, 1);
 
     if (!state->local_page_pa) { 
        PrintError(core->vm_info, core, "Cannot allocate page\n");
index 3a64842..ae3fad4 100644 (file)
@@ -97,7 +97,7 @@ static addr_t allocate_vmcs() {
 
     PrintDebug(VM_NONE, VCORE_NONE, "Allocating page\n");
 
-    temp = V3_AllocPages(1);
+    temp = V3_AllocPages(1); // need not be shadow-safe, not exposed to guest
     if (!temp) { 
        PrintError(VM_NONE, VCORE_NONE, "Cannot allocate VMCS\n");
        return -1;
@@ -456,7 +456,7 @@ static int init_vmcs_bios(struct guest_info * core, struct vmx_data * vmx_state)
            return -1;
        }
 
-       vmx_state->msr_area_paddr = (addr_t)V3_AllocPages(1);
+       vmx_state->msr_area_paddr = (addr_t)V3_AllocPages(1); // need not be shadow-safe, not exposed to guest
        
        if (vmx_state->msr_area_paddr == (addr_t)NULL) {
            PrintError(core->vm_info, core, "could not allocate msr load/store area\n");
@@ -687,7 +687,7 @@ int v3_vmx_load_core(struct guest_info * core, void * ctx){
   struct cr0_32 * shadow_cr0;
   addr_t vmcs_page_paddr;  //HPA
   
-  vmcs_page_paddr = (addr_t) V3_AllocPages(1);
+  vmcs_page_paddr = (addr_t) V3_AllocPages(1); // need not be shadow-safe, not exposed to guest
   
   if (!vmcs_page_paddr) { 
     PrintError(core->vm_info, core, "Could not allocate space for a vmcs in VMX\n");
index 82f084a..08e6765 100644 (file)
@@ -30,7 +30,7 @@ static addr_t create_ept_page() {
     void * temp;
     void * page = 0;
     
-    temp = V3_AllocPages(1);
+    temp = V3_AllocPages(1);  // need not be shadow-safe, not exposed to guest
     if (!temp) {
        PrintError(VM_NONE, VCORE_NONE, "Cannot allocate EPT page\n");
        return 0;
index 1910f01..bed2980 100644 (file)
@@ -51,7 +51,7 @@ int v3_init_vmx_io_map(struct v3_vm_info * vm) {
 
     vm->io_map.update_map = update_map;
 
-    temp = V3_AllocPages(2);
+    temp = V3_AllocPages(2);  // need not be shadow-safe, not exposed to guest
     if (!temp) {
         PrintError(vm, VCORE_NONE, "Cannot allocate io bitmap\n");
        return -1;
index 9d6e42a..ea20374 100644 (file)
@@ -73,7 +73,7 @@ int v3_init_vmx_msr_map(struct v3_vm_info * vm) {
 
     msr_map->update_map = update_map;
     
-    temp = V3_AllocPages(1);
+    temp = V3_AllocPages(1); // need not be shadow-safe, not exposed to guest
     if (!temp) { 
         PrintError(vm, VCORE_NONE, "Cannot allocat MSR bitmap\n");
        return -1;