1 #include "palacios-nautilus-mm.h"
2 #include "palacios-nautilus-mm-test.h"
6 Page-granularity memory management
8 This impedence-matches between Nautilus's singular allocator (malloc/free)
9 and page-level memory allocation needed in Palacios. It does so via
10 a last-fit-optimized bitmap allocator that operates over a large pool
11 allocated from Nautilus at startup.
13 Note that this allocation currently ignores NUMA and other constraints
14 as well as general filter expressions.
18 static uint64_t get_order(uint64_t n)
22 top_bit_pos = 63 - __builtin_clz(n);
24 return top_bit_pos + !!(n & ~(1<<top_bit_pos));
37 static struct mempool pool;
40 static inline int get_page_bit(int index) {
41 int major = index / 8;
42 int minor = index % 8;
43 return pool.bitmap[major] & (0x1 << minor);
46 static inline void clear_page_bit(int index) {
47 int major = index / 8;
48 int minor = index % 8;
49 pool.bitmap[major] &= ~(0x1 << minor);
50 ++pool.num_free_pages;
53 static inline void set_page_bit(int index) {
54 int major = index / 8;
55 int minor = index % 8;
56 pool.bitmap[major] |= (0x1 << minor);
57 --pool.num_free_pages;
62 int init_palacios_nautilus_mm(uint64_t memsize) {
64 INFO("Palacios MM: init\n");
65 INFO("Palacios MM: Nautilus page size is %d\n", PAGE_SIZE);
66 unsigned num_nk_pages = memsize / PAGE_SIZE;
67 unsigned num_palacios_pages = memsize / PALACIOS_PAGE_SIZE;
69 INFO("Palacios MM: Initializing with %u 4K pages (%u pages on Nautilus)\n", num_palacios_pages, num_nk_pages);
71 unsigned bitmap_size = (num_palacios_pages / 8) + ((num_palacios_pages % 8) > 0);
72 pool.bitmap = palacios_alloc(bitmap_size);
75 ERROR("Palacios MM: Failed to allocate bitmap\n");
78 // note that this may not be aligned
79 pool.alloc_base_addr = (u64) palacios_alloc(PAGE_SIZE * num_nk_pages);
81 if (!pool.alloc_base_addr) {
82 ERROR("Palacios MM: FAILED TO ALLOCATE MEMORY\n");
85 INFO("Palacios MM: success, alloc_base_addr=%p\n",pool.alloc_base_addr);
88 // Align our memory to a page boundary
89 pool.base_addr = (u64) (((uint64_t)pool.alloc_base_addr & (~0xfffULL)) + PALACIOS_PAGE_SIZE);
91 INFO("Palacios MM: success, cleaned up base_addr=%p\n",pool.base_addr);
93 // We have one fewer pages than requested due to the need to align
94 // the result of the malloc
95 pool.num_pages = num_palacios_pages - 1 ;
96 pool.num_free_pages = num_palacios_pages - 1;
99 // do unit test if desired
100 //test_palacios_mm(num_palacios_pages);
107 int deinit_palacios_nautilus_mm(void) {
108 // free pages from nk
109 free((void*)pool.alloc_base_addr); pool.alloc_base_addr = 0;
110 free((void*)pool.bitmap); pool.bitmap = 0;
115 static uintptr_t alloc_contig_pgs(u64 num_pages, u32 alignment)
122 if (num_pages > pool.num_free_pages) {
123 ERROR("ERROR(PALACIOS MM) : NOT ENOUGH MEMORY\n");
127 //INFO("Allocating %llu pages (align=%lu)\n", num_pages, (unsigned long)alignment);
129 if (!pool.bitmap || !pool.base_addr) {
130 ERROR("ERROR: Attempting to allocate from uninitialized memory pool \n");
135 if (alignment != 4096) {
136 ERROR("ERROR: cannot handle alignment that is not 4KB\n");
139 step = alignment / 4096;
142 // scan pages from last search forward
143 for (i = pool.pool_start; i < (pool.num_pages - num_pages + 1) ; ) {
145 for (j = i; j < (i+num_pages); j++) {
146 if (get_page_bit(j)) {
151 if (j==(i+num_pages)) {
152 for (j = i; j<(i+num_pages); j++) {
156 pool.pool_start = j % pool.num_pages;
158 return (void*) (pool.base_addr + (i * 4096));
166 // scan from front if we didn't find it
167 for (i = 0; i < (pool.num_pages - num_pages + 1) ; ) {
169 for (j = i; j < (i+num_pages); j++) {
170 if (get_page_bit(j)) {
175 if (j==(i+num_pages)) {
176 for (j = i; j<(i+num_pages); j++) {
180 pool.pool_start = j % pool.num_pages;
182 return (void*)( pool.base_addr + (i * 4096));
190 ERROR("Palacios MM: ERROR! Cannot allocate memory...\n");
191 ERROR("Palacios MM: Pool has %d pages, trying to allocate %d pages\n", pool.num_pages, num_pages);
196 uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment, int node_id, int (*filter_func)(void *paddr, void *filter_state), void *filter_state)
199 addr = alloc_contig_pgs(num_pages, alignment);
204 void free_palacios_pgs(uintptr_t pg_addr, u64 num_pages)
206 int pg_idx = ((u64)pg_addr - pool.base_addr) / PALACIOS_PAGE_SIZE;
208 for (i = pg_idx; i < pg_idx+num_pages; i++) {
214 void free_palacios_pg(uintptr_t pg_addr)
216 free_palacios_pgs(pg_addr, 1);