#include <linux/mm.h>
//static struct list_head pools;
+#include "palacios.h"
+
+#define OFFLINE_POOL_THRESHOLD 12
struct mempool {
uintptr_t base_addr;
}
+uintptr_t get_palacios_base_addr(void) {
+ return pool.base_addr;
+}
+
+u64 get_palacios_num_pages(void) {
+ return pool.num_pages;
+}
+
static uintptr_t alloc_contig_pgs(u64 num_pages, u32 alignment) {
int step = 1;
int i = 0;
int start = 0;
- printk("Allocating %llu pages (align=%lu)\n",
+ DEBUG("Allocating %llu pages (align=%lu)\n",
num_pages, (unsigned long)alignment);
if (pool.bitmap == NULL) {
- printk("ERROR: Attempting to allocate from non initialized memory\n");
+ ERROR("ERROR: Attempting to allocate from non initialized memory\n");
return 0;
}
if (alignment > 0) {
- step = alignment / 4096;
+ step = alignment / PAGE_SIZE;
}
// Start the search at the correct alignment
start = ((alignment - (pool.base_addr % alignment)) >> 12);
}
- printk("\t Start idx %d (base_addr=%llu)\n", start, (u64)pool.base_addr);
+ DEBUG("\t Start idx %d (base_addr=%p)\n", start, (void *)(u64)pool.base_addr);
for (i = start; i < (pool.num_pages - num_pages); i += step) {
if (get_page_bit(i) == 0) {
set_page_bit(j);
}
- return pool.base_addr + (i * 4096);
+ return pool.base_addr + (i * PAGE_SIZE);
}
}
+ ERROR("ALERT ALERT Allocation of Large Number of Contiguous Pages FAILED\n");
+
return 0;
}
uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment) {
uintptr_t addr = 0;
- if ((num_pages < 12)) {
+ if (num_pages < OFFLINE_POOL_THRESHOLD) {
struct page * pgs = NULL;
+ void *temp;
int order = get_order(num_pages * PAGE_SIZE);
- pgs = alloc_pages(GFP_DMA, order);
+ pgs = alloc_pages(GFP_DMA32, order);
- WARN(!pgs, "Could not allocate pages\n");
-
- printk("%llu pages (order=%d) aquired from alloc_pages\n",
- num_pages, order);
+ if (!pgs) {
+ ERROR("Could not allocate small number of contigious pages - retrying with internal allocation\n");
+ goto trybig;
+ }
+
+ /* DEBUG("%llu pages (order=%d) aquired from alloc_pages\n",
+ num_pages, order); */
addr = page_to_pfn(pgs) << PAGE_SHIFT;
+
+ temp = (void*)addr;
+
+ if ( (temp>=(void*)(pool.base_addr) &&
+ (temp<((void*)(pool.base_addr)+pool.num_pages*PAGE_SIZE)))
+ || ((temp+num_pages*PAGE_SIZE)>=(void*)(pool.base_addr) &&
+ ((temp+num_pages*PAGE_SIZE)<((void*)(pool.base_addr)+pool.num_pages*PAGE_SIZE))) ) {
+
+ ERROR("ALERT ALERT Allocation of small number of contiguous pages returned block that "
+ "OVERLAPS with the offline page pool addr=%p, addr+numpages=%p, "
+ "pool.base_addr=%p, pool.base_addr+pool.numpages=%p\n",
+ temp, temp+num_pages*PAGE_SIZE, (void*)(pool.base_addr),
+ (void*)(pool.base_addr)+pool.num_pages*PAGE_SIZE);
+ }
+
+
} else {
- printk("Allocating %llu pages from bitmap allocator\n", num_pages);
+ trybig:
+ //DEBUG("Allocating %llu pages from bitmap allocator\n", num_pages);
//addr = pool.base_addr;
addr = alloc_contig_pgs(num_pages, alignment);
+ if (!addr) {
+ ERROR("Could not allocate large number of contiguous pages\n");
+ }
}
- printk("Returning from alloc addr=%p, vaddr=%p\n", (void *)addr, __va(addr));
+ //DEBUG("Returning from alloc addr=%p, vaddr=%p\n", (void *)addr, __va(addr));
return addr;
}
void free_palacios_pgs(uintptr_t pg_addr, int num_pages) {
- printk("Freeing Memory page %p\n", (void *)pg_addr);
+ //DEBUG("Freeing Memory page %p\n", (void *)pg_addr);
if ((pg_addr >= pool.base_addr) &&
- (pg_addr < pool.base_addr + (4096 * pool.num_pages))) {
- int pg_idx = (pg_addr - pool.base_addr) / 4096;
+ (pg_addr < pool.base_addr + (PAGE_SIZE * pool.num_pages))) {
+ int pg_idx = (pg_addr - pool.base_addr) / PAGE_SIZE;
int i = 0;
+
+ if (num_pages<OFFLINE_POOL_THRESHOLD) {
+ ERROR("ALERT ALERT small page deallocation from offline pool\n");
+ return;
+ }
+
if ((pg_idx + num_pages) > pool.num_pages) {
- printk("Freeing memory bounds exceeded\n");
+ ERROR("Freeing memory bounds exceeded for offline pool\n");
return;
}
for (i = 0; i < num_pages; i++) {
- WARN(get_page_bit(pg_idx + i) == 0, "Trying to free unallocated page\n");
-
+ if (get_page_bit(pg_idx + i) == 0) {
+ ERROR("Trying to free unallocated page from offline pool\n");
+ }
clear_page_bit(pg_idx + i);
}
+
} else {
+ if (num_pages>=OFFLINE_POOL_THRESHOLD) {
+ ERROR("ALERT ALERT Large page deallocation from linux pool\n");
+ }
__free_pages(pfn_to_page(pg_addr >> PAGE_SHIFT), get_order(num_pages * PAGE_SIZE));
}
}
int bitmap_size = (num_pages / 8) + ((num_pages % 8) > 0);
if (pool.num_pages != 0) {
- printk("ERROR: Memory has already been added\n");
+ ERROR("ERROR: Memory has already been added\n");
return -1;
}
- printk("Managing %dMB of memory starting at %llu (%lluMB)\n",
- (unsigned int)(num_pages * 4096) / (1024 * 1024),
+ DEBUG("Managing %dMB of memory starting at %llu (%lluMB)\n",
+ (unsigned int)(num_pages * PAGE_SIZE) / (1024 * 1024),
(unsigned long long)base_addr,
(unsigned long long)(base_addr / (1024 * 1024)));
- pool.bitmap = kmalloc(bitmap_size, GFP_KERNEL);
+ pool.bitmap = palacios_alloc(bitmap_size);
if (IS_ERR(pool.bitmap)) {
- printk("Error allocating Palacios MM bitmap\n");
+ ERROR("Error allocating Palacios MM bitmap\n");
return -1;
}
int palacios_init_mm( void ) {
- // INIT_LIST_HEAD(&(pools));
+
pool.base_addr = 0;
pool.num_pages = 0;
pool.bitmap = NULL;
}
int palacios_deinit_mm( void ) {
- kfree(pool.bitmap);
+
+ palacios_free(pool.bitmap);
+
+ pool.bitmap=0;
+ pool.base_addr=0;
+ pool.num_pages=0;
+
+ // note that the memory is not onlined here - offlining and onlining
+ // is the resposibility of the caller
return 0;
}