--- /dev/null
+#include "palacios-nautilus-mm.h"
+#include "palacios-nautilus-mm-test.h"
+
+/*
+
+ Page-granularity memory management
+
+ This impedence-matches between Nautilus's singular allocator (malloc/free)
+ and page-level memory allocation needed in Palacios. It does so via
+ a last-fit-optimized bitmap allocator that operates over a large pool
+ allocated from Nautilus at startup.
+
+ Note that this allocation currently ignores NUMA and other constraints
+ as well as general filter expressions.
+
+*/
+
+static uint64_t get_order(uint64_t n)
+{
+ uint64_t top_bit_pos;
+
+ top_bit_pos = 63 - __builtin_clz(n);
+
+ return top_bit_pos + !!(n & ~(1<<top_bit_pos));
+
+}
+
+struct mempool {
+ u8 * bitmap;
+ u64 num_pages;
+ u64 num_free_pages;
+ u64 pool_start;
+ u64 base_addr;
+ u64 alloc_base_addr;
+};
+
+static struct mempool pool;
+
+
+static inline int get_page_bit(int index) {
+ int major = index / 8;
+ int minor = index % 8;
+ return pool.bitmap[major] & (0x1 << minor);
+}
+
+static inline void clear_page_bit(int index) {
+ int major = index / 8;
+ int minor = index % 8;
+ pool.bitmap[major] &= ~(0x1 << minor);
+ ++pool.num_free_pages;
+}
+
+static inline void set_page_bit(int index) {
+ int major = index / 8;
+ int minor = index % 8;
+ pool.bitmap[major] |= (0x1 << minor);
+ --pool.num_free_pages;
+}
+
+
+
+int init_palacios_nautilus_mm(uint64_t memsize) {
+
+ INFO("Palacios MM: init\n");
+ INFO("Palacios MM: Nautilus page size is %d\n", PAGE_SIZE);
+ unsigned num_nk_pages = memsize / PAGE_SIZE;
+ unsigned num_palacios_pages = memsize / PALACIOS_PAGE_SIZE;
+
+ INFO("Palacios MM: Initializing with %u 4K pages (%u pages on Nautilus)\n", num_palacios_pages, num_nk_pages);
+
+ unsigned bitmap_size = (num_palacios_pages / 8) + ((num_palacios_pages % 8) > 0);
+ pool.bitmap = palacios_alloc(bitmap_size);
+
+ if (!pool.bitmap) {
+ ERROR("Palacios MM: Failed to allocate bitmap\n");
+ return -1;
+ }
+ // note that this may not be aligned
+ pool.alloc_base_addr = (u64) palacios_alloc(PAGE_SIZE * num_nk_pages);
+
+ if (!pool.alloc_base_addr) {
+ ERROR("Palacios MM: FAILED TO ALLOCATE MEMORY\n");
+ return -1;
+ } else {
+ INFO("Palacios MM: success, alloc_base_addr=%p\n",pool.alloc_base_addr);
+ }
+
+ // Align our memory to a page boundary
+ pool.base_addr = (u64) (((uint64_t)pool.alloc_base_addr & (~0xfffULL)) + PALACIOS_PAGE_SIZE);
+
+ INFO("Palacios MM: success, cleaned up base_addr=%p\n",pool.base_addr);
+
+ // We have one fewer pages than requested due to the need to align
+ // the result of the malloc
+ pool.num_pages = num_palacios_pages - 1 ;
+ pool.num_free_pages = num_palacios_pages - 1;
+ pool.pool_start = 0;
+
+ // do unit test if desired
+ //test_palacios_mm(num_palacios_pages);
+
+ return 0;
+
+}
+
+
+int deinit_palacios_nautilus_mm(void) {
+ // free pages from nk
+ free((void*)pool.alloc_base_addr); pool.alloc_base_addr = 0;
+ free((void*)pool.bitmap); pool.bitmap = 0;
+
+ return 0;
+}
+
+static uintptr_t alloc_contig_pgs(u64 num_pages, u32 alignment)
+{
+
+ int step = 1;
+ int i = 0;
+ int j = 0;
+
+ if (num_pages > pool.num_free_pages) {
+ ERROR("ERROR(PALACIOS MM) : NOT ENOUGH MEMORY\n");
+ return 0;
+ }
+
+ //INFO("Allocating %llu pages (align=%lu)\n", num_pages, (unsigned long)alignment);
+
+ if (!pool.bitmap || !pool.base_addr) {
+ ERROR("ERROR: Attempting to allocate from uninitialized memory pool \n");
+ return 0;
+ }
+
+ if (alignment > 0) {
+ if (alignment != 4096) {
+ ERROR("ERROR: cannot handle alignment that is not 4KB\n");
+ return 0;
+ }
+ step = alignment / 4096;
+ }
+
+ // scan pages from last search forward
+ for (i = pool.pool_start; i < (pool.num_pages - num_pages + 1) ; ) {
+
+ for (j = i; j < (i+num_pages); j++) {
+ if (get_page_bit(j)) {
+ break;
+ }
+ }
+
+ if (j==(i+num_pages)) {
+ for (j = i; j<(i+num_pages); j++) {
+ set_page_bit(j);
+ }
+
+ pool.pool_start = j % pool.num_pages;
+
+ return (void*) (pool.base_addr + (i * 4096));
+
+ } else {
+ i = j+1;
+ }
+ }
+
+
+ // scan from front if we didn't find it
+ for (i = 0; i < (pool.num_pages - num_pages + 1) ; ) {
+
+ for (j = i; j < (i+num_pages); j++) {
+ if (get_page_bit(j)) {
+ break;
+ }
+ }
+
+ if (j==(i+num_pages)) {
+ for (j = i; j<(i+num_pages); j++) {
+ set_page_bit(j);
+ }
+
+ pool.pool_start = j % pool.num_pages;
+
+ return (void*)( pool.base_addr + (i * 4096));
+
+ } else {
+ i = j+1;
+ }
+ }
+
+
+ ERROR("Palacios MM: ERROR! Cannot allocate memory...\n");
+ ERROR("Palacios MM: Pool has %d pages, trying to allocate %d pages\n", pool.num_pages, num_pages);
+
+ return 0;
+}
+
+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;
+ addr = alloc_contig_pgs(num_pages, alignment);
+ return addr;
+}
+
+
+void free_palacios_pgs(uintptr_t pg_addr, u64 num_pages)
+{
+ int pg_idx = ((u64)pg_addr - pool.base_addr) / PALACIOS_PAGE_SIZE;
+ int i = 0;
+ for (i = pg_idx; i < pg_idx+num_pages; i++) {
+ clear_page_bit(i);
+ }
+}
+
+
+void free_palacios_pg(uintptr_t pg_addr)
+{
+ free_palacios_pgs(pg_addr, 1);
+}