mp = palacios_alloc_extended(sizeof(struct buddy_mempool), GFP_KERNEL, zone->node_id);
- if (IS_ERR(mp)) {
+ if (!mp) {
ERROR("Could not allocate mempool\n");
return -1;
}
BITS_TO_LONGS(mp->num_blocks) * sizeof(long), GFP_KERNEL, zone->node_id
);
+ if (!(mp->tag_bits)) {
+ ERROR("Could not allocate tag_bits\n");
+ palacios_free(mp);
+ return -1;
+ }
+
+
/* Initially mark all minimum-sized blocks as allocated */
bitmap_zero(mp->tag_bits, mp->num_blocks);
* 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;
}
+
}
}
/**
* Returns a block of memory to the buddy system memory allocator.
*/
-void
+int
buddy_free(
//! Buddy system memory allocator object.
struct buddy_memzone * zone,
pool = find_mempool(zone, addr);
if ((pool == NULL) || (order > pool->pool_order)) {
- WARNING("Attempted to free an invalid page address (%p) - pool=%p order=%lu\n", (void *)addr,pool,order);
- palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
- return;
+ WARNING("Attempted to free an invalid page address (%p) - pool=%p order=%lu\n", (void *)addr,pool,order);
+ palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
+ return -1;
}
if (is_available(pool, block)) {
ERROR("Error: Freeing an available block\n");
palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
- return;
+ return -1;
}
pool->num_free_blocks += (1UL << (order - zone->min_order));
list_add(&(block->link), &(zone->avail[order]));
palacios_spinlock_unlock_irqrestore(&(zone->lock), flags);
+
+ return 0;
}
char proc_file_name[128];
memset(proc_file_name, 0, 128);
- snprintf(proc_file_name, 128, "v3-mem%d", zone->node_id);
+ snprintf(proc_file_name, 128, "v3-mem%u", zone->node_id);
remove_proc_entry(proc_file_name, palacios_get_procdir());
}