Commit 94bbac3f authored by Charles Jacobsen's avatar Charles Jacobsen Committed by Vikram Narayanan

test-v2: Fix more allocator bugs.

I needed to re-think the free lists initialization.
Also bug in demand paging.

Heap and kmalloc now initialize, but I still crash afterward.
parent 3710d903
...@@ -52,8 +52,10 @@ static int pb_backing(struct lcd_page_allocator *pa, ...@@ -52,8 +52,10 @@ static int pb_backing(struct lcd_page_allocator *pa,
if (!pa->cbs->alloc_map_regular_mem_chunk) /* no demand paging */ if (!pa->cbs->alloc_map_regular_mem_chunk) /* no demand paging */
return 0; return 0;
offset = lcd_page_block_to_offset(pa, pb); offset = lcd_page_block_to_offset(pa, pb);
if (offset & ((1UL << pa->max_order) - 1)) /* not on boundary */ if (offset & ((1UL << (pa->max_order + PAGE_SHIFT)) - 1)) {
/* not on boundary */
return 0; return 0;
}
if (pb->n) /* already backed */ if (pb->n) /* already backed */
return 0; return 0;
...@@ -216,7 +218,7 @@ static void do_free(struct lcd_page_allocator *pa, ...@@ -216,7 +218,7 @@ static void do_free(struct lcd_page_allocator *pa,
* Calculate index of page block in giant array. Should * Calculate index of page block in giant array. Should
* be a multiple of 2^order. * be a multiple of 2^order.
*/ */
pb_idx = (pb - pa->pb_array) / sizeof(struct lcd_page_block); pb_idx = pb - pa->pb_array;
BUG_ON(pb_idx & ((1 << block_order) - 1)); BUG_ON(pb_idx & ((1 << block_order) - 1));
/* /*
* Coalesce * Coalesce
...@@ -234,7 +236,7 @@ static void do_free(struct lcd_page_allocator *pa, ...@@ -234,7 +236,7 @@ static void do_free(struct lcd_page_allocator *pa,
* *
* 1 - Remove from its current free list * 1 - Remove from its current free list
*/ */
list_del(&buddy->buddy_list); list_del_init(&buddy->buddy_list);
/* /*
* 2 - Dec the total number of free page blocks as we * 2 - Dec the total number of free page blocks as we
* are removing it from its current free list. (We will * are removing it from its current free list. (We will
...@@ -284,6 +286,39 @@ static void do_free(struct lcd_page_allocator *pa, ...@@ -284,6 +286,39 @@ static void do_free(struct lcd_page_allocator *pa,
/* ALLOCATOR INIT -------------------------------------------------- */ /* ALLOCATOR INIT -------------------------------------------------- */
#if 0
static void check_free_lists(struct lcd_page_allocator *pa)
{
unsigned idx;
struct list_head *cursor;
struct lcd_page_block *pb;
for (idx = pa->min_order; idx <= pa->max_order; idx++) {
if (list_empty(&pa->free_lists[idx])){
LIBLCD_ERR("LIST order=%d EMPTY", idx);
continue;
}
LIBLCD_ERR("LIST order=%d NOT EMPTY", idx);
if (idx >= pa->max_order - 2) {
list_for_each(cursor, &pa->free_lists[idx - pa->min_order]) {
pb = list_entry(cursor, struct lcd_page_block,
buddy_list);
LIBLCD_ERR("head pb idx 0x%lx, group order %d",
pb - pa->pb_array,
pb->block_order);
}
}
}
LIBLCD_ERR("DONE");
}
#endif
static struct lcd_page_allocator* static struct lcd_page_allocator*
init_struct_pa(void *metadata_addr, init_struct_pa(void *metadata_addr,
unsigned long metadata_sz, unsigned long metadata_sz,
...@@ -344,22 +379,17 @@ void init_page_blocks(struct lcd_page_allocator *pa) ...@@ -344,22 +379,17 @@ void init_page_blocks(struct lcd_page_allocator *pa)
pa_nr_page_blocks(pa) * sizeof(struct lcd_page_block)); pa_nr_page_blocks(pa) * sizeof(struct lcd_page_block));
pa->pb_array = cursor; pa->pb_array = cursor;
/* /*
* Initialize each one's buddy list head, and add it to the * Initialize each one's buddy list head, and put the
* min order free list. (We have to add it to the min free * max_order page block boundaries in the largest-sized
* list because the allocator won't consider a page block * free list.
* free if its buddy list is empty.) Then free each one to trigger full
* coalescing. (Freeing just the first page block won't trigger
* full coalescing, because the buddy allocator assumes that
* maximal coalescing has been done when free is called.)
*/ */
for (i = 0; i < pa_nr_page_blocks(pa); i++) { for (i = 0; i < pa_nr_page_blocks(pa); i++)
INIT_LIST_HEAD(&cursor[i].buddy_list); INIT_LIST_HEAD(&cursor[i].buddy_list);
list_add(&cursor[i].buddy_list, &pa->free_lists[0]);
} for (i = 0; i < pa_nr_page_blocks(pa); i += (1UL << (pa->max_order))) {
for (i = 0; i < pa_nr_page_blocks(pa); i++) { cursor[i].block_order = pa->max_order;
lcd_page_allocator_free(pa, list_add_tail(&cursor[i].buddy_list,
&cursor[i], &pa->free_lists[pa->max_order]);
0);
} }
} }
...@@ -381,7 +411,7 @@ static int alloc_metadata_page_blocks(struct lcd_page_allocator *pa, ...@@ -381,7 +411,7 @@ static int alloc_metadata_page_blocks(struct lcd_page_allocator *pa,
* pa points to beginning of metadata. Remember, * pa points to beginning of metadata. Remember,
* guest virtual == guest physical inside an LCD. * guest virtual == guest physical inside an LCD.
*/ */
metadata_base = __gpa((unsigned long)pa); metadata_base = lcd_gva2gpa(__gva((unsigned long)pa));
/* /*
* Allocate the big chunks first * Allocate the big chunks first
*/ */
...@@ -419,10 +449,9 @@ static int alloc_metadata_page_blocks(struct lcd_page_allocator *pa, ...@@ -419,10 +449,9 @@ static int alloc_metadata_page_blocks(struct lcd_page_allocator *pa,
* page blocks. (This means the remaining page blocks will be used * page blocks. (This means the remaining page blocks will be used
* for real allocs.) * for real allocs.)
*/ */
tail_order = 0; metadata_sz = ALIGN(metadata_sz,
metadata_sz >>= PAGE_SHIFT; (1UL << (pa->min_order + PAGE_SHIFT)));
while (metadata_sz >>= 1) tail_order = ilog2(metadata_sz >> (pa->min_order + PAGE_SHIFT));
tail_order++;
pb = alloc_page_blocks(pa, tail_order); pb = alloc_page_blocks(pa, tail_order);
if (!pb) { if (!pb) {
LIBLCD_ERR("error allocating page blocks for metadata"); LIBLCD_ERR("error allocating page blocks for metadata");
...@@ -444,12 +473,12 @@ static int alloc_metadata_page_blocks(struct lcd_page_allocator *pa, ...@@ -444,12 +473,12 @@ static int alloc_metadata_page_blocks(struct lcd_page_allocator *pa,
* Remember offset to first non-metadata page block * Remember offset to first non-metadata page block
*/ */
pa->first_non_metadata_pb_idx = pa->first_non_metadata_pb_idx =
(pb + (1UL << tail_order) - pa->pb_array) / pb + (1UL << tail_order) - pa->pb_array;
sizeof(struct lcd_page_block);
/* /*
* All page blocks that contain metadata have been allocated, * All page blocks that contain metadata have been allocated,
* and resource nodes have been installed. * and resource nodes have been installed.
*/ */
return 0; return 0;
} }
...@@ -733,15 +762,15 @@ unsigned long lcd_page_block_to_offset(struct lcd_page_allocator *pa, ...@@ -733,15 +762,15 @@ unsigned long lcd_page_block_to_offset(struct lcd_page_allocator *pa,
{ {
unsigned long offset; unsigned long offset;
offset = (pb - pa->pb_array) / sizeof(struct lcd_page_block); offset = pb - pa->pb_array;
/* Each page block is 2^min_order bytes of mem */ /* Each page block is 2^(min_order + PAGE_SHIFT) bytes of mem */
return offset << pa->min_order; return offset << (pa->min_order + PAGE_SHIFT);
} }
struct lcd_page_block* struct lcd_page_block*
lcd_offset_to_page_block(struct lcd_page_allocator *pa, lcd_offset_to_page_block(struct lcd_page_allocator *pa,
unsigned long offset) unsigned long offset)
{ {
return &pa->pb_array[offset >> pa->min_order]; return &pa->pb_array[offset >> (pa->min_order + PAGE_SHIFT)];
} }
...@@ -196,7 +196,6 @@ heap_alloc_map_metadata_memory(const struct lcd_page_allocator_cbs *cbs, ...@@ -196,7 +196,6 @@ heap_alloc_map_metadata_memory(const struct lcd_page_allocator_cbs *cbs,
* Since we are embedding, we need to allocate in 2^alloc_order * Since we are embedding, we need to allocate in 2^alloc_order
* chunks of pages. * chunks of pages.
*/ */
total = ALIGN(metadata_sz, (1UL << (alloc_order + PAGE_SHIFT))); total = ALIGN(metadata_sz, (1UL << (alloc_order + PAGE_SHIFT)));
nr_allocs = total >> (alloc_order + PAGE_SHIFT); /* > 0 */ nr_allocs = total >> (alloc_order + PAGE_SHIFT); /* > 0 */
......
...@@ -173,11 +173,6 @@ static int handle_syscall_pages_alloc(struct lcd *lcd) ...@@ -173,11 +173,6 @@ static int handle_syscall_pages_alloc(struct lcd *lcd)
* Get slot where to store alloc'd pages, flags, * Get slot where to store alloc'd pages, flags,
* and order * and order
*/ */
LCD_ERR("syscall args: %lx, %lx, %lx",
lcd_arch_get_syscall_arg0(lcd->lcd_arch),
lcd_arch_get_syscall_arg1(lcd->lcd_arch),
lcd_arch_get_syscall_arg2(lcd->lcd_arch));
slot = __cptr(lcd_arch_get_syscall_arg0(lcd->lcd_arch)); slot = __cptr(lcd_arch_get_syscall_arg0(lcd->lcd_arch));
flags = (unsigned int)lcd_arch_get_syscall_arg1(lcd->lcd_arch); flags = (unsigned int)lcd_arch_get_syscall_arg1(lcd->lcd_arch);
order = (unsigned int)lcd_arch_get_syscall_arg2(lcd->lcd_arch); order = (unsigned int)lcd_arch_get_syscall_arg2(lcd->lcd_arch);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment