1 /* Palacios memory manager
5 #include <asm/page_64_types.h>
6 #include <linux/kernel.h>
7 #include <linux/list.h>
8 #include <linux/slab.h>
10 //static struct list_head pools;
21 static struct mempool pool;
23 static inline int get_page_bit(int index) {
24 int major = index / 8;
25 int minor = index % 8;
27 return (pool.bitmap[major] & (0x1 << minor));
30 static inline void set_page_bit(int index) {
31 int major = index / 8;
32 int minor = index % 8;
34 pool.bitmap[major] |= (0x1 << minor);
37 static inline void clear_page_bit(int index) {
38 int major = index / 8;
39 int minor = index % 8;
41 pool.bitmap[major] &= ~(0x1 << minor);
46 static uintptr_t alloc_contig_pgs(u64 num_pages, u32 alignment) {
51 printk("Allocating %llu pages (align=%lu)\n",
52 num_pages, (unsigned long)alignment);
54 if (pool.bitmap == NULL) {
55 printk("ERROR: Attempting to allocate from non initialized memory\n");
60 step = alignment / 4096;
63 // Start the search at the correct alignment
64 if (pool.base_addr % alignment) {
65 start = ((alignment - (pool.base_addr % alignment)) >> 12);
68 printk("\t Start idx %d (base_addr=%p)\n", start, (void *)(u64)pool.base_addr);
70 for (i = start; i < (pool.num_pages - num_pages); i += step) {
71 if (get_page_bit(i) == 0) {
75 for (j = i; (j - i) < num_pages; j++) {
76 if (get_page_bit(j) == 1) {
86 for (j = i; (j - i) < num_pages; j++) {
90 return pool.base_addr + (i * 4096);
94 /* printk("PALACIOS BAD: LARGE PAGE ALLOCATION FAILED\n"); */
100 // alignment is in bytes
101 uintptr_t alloc_palacios_pgs(u64 num_pages, u32 alignment) {
104 if ((num_pages < 12)) {
105 struct page * pgs = NULL;
106 int order = get_order(num_pages * PAGE_SIZE);
108 pgs = alloc_pages(GFP_DMA32, order);
110 WARN(!pgs, "Could not allocate pages\n");
112 /* if (!pgs) { printk("PALACIOS BAD: SMALL PAGE ALLOCATION FAILED\n"); } */
114 /* printk("%llu pages (order=%d) aquired from alloc_pages\n",
115 num_pages, order); */
117 addr = page_to_pfn(pgs) << PAGE_SHIFT;
119 //printk("Allocating %llu pages from bitmap allocator\n", num_pages);
120 //addr = pool.base_addr;
121 addr = alloc_contig_pgs(num_pages, alignment);
125 //printk("Returning from alloc addr=%p, vaddr=%p\n", (void *)addr, __va(addr));
131 void free_palacios_pgs(uintptr_t pg_addr, int num_pages) {
132 //printk("Freeing Memory page %p\n", (void *)pg_addr);
134 if ((pg_addr >= pool.base_addr) &&
135 (pg_addr < pool.base_addr + (4096 * pool.num_pages))) {
136 int pg_idx = (pg_addr - pool.base_addr) / 4096;
139 if ((pg_idx + num_pages) > pool.num_pages) {
140 printk("Freeing memory bounds exceeded\n");
144 for (i = 0; i < num_pages; i++) {
145 WARN(get_page_bit(pg_idx + i) == 0, "Trying to free unallocated page\n");
147 clear_page_bit(pg_idx + i);
150 __free_pages(pfn_to_page(pg_addr >> PAGE_SHIFT), get_order(num_pages * PAGE_SIZE));
155 int add_palacios_memory(uintptr_t base_addr, u64 num_pages) {
156 /* JRL: OK.... so this is horrible, terrible and if anyone else did it I would yell at them.
157 * But... the fact that you can do this in C is so ridiculous that I can't help myself.
158 * Note that we're repurposing "true" to be 1 here
161 int bitmap_size = (num_pages / 8) + ((num_pages % 8) > 0);
163 if (pool.num_pages != 0) {
164 printk("ERROR: Memory has already been added\n");
168 printk("Managing %dMB of memory starting at %llu (%lluMB)\n",
169 (unsigned int)(num_pages * 4096) / (1024 * 1024),
170 (unsigned long long)base_addr,
171 (unsigned long long)(base_addr / (1024 * 1024)));
174 pool.bitmap = kmalloc(bitmap_size, GFP_KERNEL);
176 if (IS_ERR(pool.bitmap)) {
177 printk("Error allocating Palacios MM bitmap\n");
181 memset(pool.bitmap, 0, bitmap_size);
183 pool.base_addr = base_addr;
184 pool.num_pages = num_pages;
191 int palacios_init_mm( void ) {
192 // INIT_LIST_HEAD(&(pools));
200 int palacios_deinit_mm( void ) {