* 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;
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);
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;
}
+
}
}
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 */
// 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();
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;
}
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);
-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);
* 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;
}
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 {
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
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; \
})
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; \
})
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; \
})
// - 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
#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) {
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");
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");
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");
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");