// Then we clean up any region following the new region that overlaps
//
// JRL: This is pretty hairy...
-int add_mem_list_pages(vmm_mem_list_t * list, ullong_t addr, uint_t num_pages) {
+int add_mem_list_pages(vmm_mem_list_t * list, addr_t addr, uint_t num_pages) {
uint_t num_new_pages = num_pages;
- ullong_t new_end = addr + (num_pages * PAGE_SIZE);
+ addr_t new_end = addr + (num_pages * PAGE_SIZE) - 1;
mem_region_t * cursor = get_mem_list_cursor(list, addr);
-
// PrintDebug("Adding: 0x%x - 0x%x\n", addr, num_pages * PAGE_SIZE);
+
// Make a new region at the head of the list
if (cursor == NULL) {
cursor = os_hooks->malloc(sizeof(mem_region_t));
list->num_regions++;
} else {
- ullong_t cursor_end = cursor->addr + (cursor->num_pages * PAGE_SIZE);
+ addr_t cursor_end = cursor->addr + (cursor->num_pages * PAGE_SIZE) - 1;
- if (addr > cursor_end) {
+ if (addr > cursor_end + 1) {
// address falls after cursor region
mem_region_t * new_region = os_hooks->malloc(sizeof(mem_region_t));
cursor = new_region;
} else if ((addr >= cursor->addr) &&
- (addr <= cursor_end)) {
+ (addr <= cursor_end + 1)) {
// address falls inside the cursor region
}
}
+
// Clean up any overlaps that follow
- while ((cursor->next) && (cursor->next->addr <= new_end)) {
+ while ((cursor->next) && (cursor->next->addr <= new_end + 1)) {
mem_region_t * overlap = cursor->next;
- ullong_t overlap_end = overlap->addr + (overlap->num_pages * PAGE_SIZE);
+ addr_t overlap_end = overlap->addr + (overlap->num_pages * PAGE_SIZE) - 1;
cursor->next = overlap->next;
if (overlap->next) {
* IF addr is before all regions, returns NULL
* IF list is empty, returns NULL
*/
-mem_region_t * get_mem_list_cursor(vmm_mem_list_t * list, ullong_t addr) {
+mem_region_t * get_mem_list_cursor(vmm_mem_list_t * list, addr_t addr) {
mem_region_t * prev_region = list->head;
while (prev_region != NULL) {
if ( (addr >= prev_region->addr) &&
- (addr <= (prev_region->addr + (prev_region->num_pages * PAGE_SIZE))) ) {
+ (addr < (prev_region->addr + (prev_region->num_pages * PAGE_SIZE) - 1)) ) {
return prev_region;
} else if (addr < prev_region->addr) {
// If this region is the current head, then this should return NULL
return prev_region->prev;
- } else if (addr > (prev_region->addr + (prev_region->num_pages * PAGE_SIZE))) {
+ } else if (addr >= (prev_region->addr + (prev_region->num_pages * PAGE_SIZE))) {
if (prev_region->next) {
prev_region = prev_region->next;
} else {
+/* Returns the page address of page number 'index' in the memory list
+ * If index is out of bounds... returns -1 (an invalid page address)
+ */
+addr_t get_mem_list_addr(vmm_mem_list_t * list, uint_t index) {
+ mem_region_t * reg = list->head;
+ uint_t i = index;
+
+ // Memory List overrun
+ if (index > list->num_pages - 1) {
+ return -1;
+ }
+
+ while (i >= 0) {
+ if (reg->num_pages <= index) {
+ i -= reg->num_pages;
+ reg = reg->next;
+ } else {
+ return reg->addr + (i * PAGE_SIZE);
+ }
+ }
+
+ return -1;
+}
+
+
void init_mem_layout(vmm_mem_layout_t * layout) {
layout->num_pages = 0;
layout->num_regions = 0;
}
-/* this function returns a pointer to the location in the layout list that
- * corresponds to addr.
- * Rules:
- * IF addr is in a region, a ptr to that region is returned
- * IF addr is not in a region, a ptr to the previous region is returned
- * IF addr is before all regions, returns NULL
- * IF list is empty, returns NULL
- */
-layout_region_t * get_layout_cursor(vmm_mem_layout_t * layout, ullong_t addr) {
- layout_region_t * prev_region = layout->head;
-
-
- while (prev_region != NULL) {
- if ( (addr >= prev_region->addr) &&
- (addr <= (prev_region->addr + (prev_region->num_pages * PAGE_SIZE))) ) {
- return prev_region;
- } else if (addr < prev_region->addr) {
- // If this region is the current head, then this should return NULL
- return prev_region->prev;
- } else if (addr > (prev_region->addr + (prev_region->num_pages * PAGE_SIZE))) {
- if (prev_region->next) {
- prev_region = prev_region->next;
- } else {
- return prev_region;
- }
- }
- }
-
- return prev_region;
-}
-
/* This is slightly different semantically from the mem list, in that we don't allow overlaps
* we could probably allow overlappig regions of the same type... but I'll let someone else deal with that
*/
int add_mem_range(vmm_mem_layout_t * layout, layout_region_t * region) {
-
- layout_region_t * cursor = get_layout_cursor(layout, region->addr);
-
- if (cursor == NULL) {
- if (layout->head) {
- if (layout->head->addr < region->addr + (region->num_pages * PAGE_SIZE)) {
- // overlaps not allowed
- return -1;
- }
- layout->head->prev = region;
- }
+ layout_region_t * cursor = layout->head;
+ if ((!cursor) || (cursor->start >= region->end)) {
region->prev = NULL;
- region->next = layout->head;
- layout->head = region;
-
+ region->next = cursor;
+ layout->num_pages += (region->end - region->start) / PAGE_SIZE;
layout->num_regions++;
- layout->num_pages += region->num_pages;
- } else if ((region->addr >= cursor->addr) &&
- (region->addr <= cursor->addr + (cursor->num_pages * PAGE_SIZE))) {
- // overlaps not allowed
- return -1;
- } else if (region->addr > cursor->addr + (cursor->num_pages * PAGE_SIZE)) {
- // add region to layout
- region->next = cursor->next;
- region->prev = cursor;
-
- if (region->next) {
- region->next->prev = region;
- }
- cursor->next = region;
+ layout->head = region;
- layout->num_regions++;
- layout->num_pages += region->num_pages;
- } else {
- return -1;
+ return 0;
}
+ while (cursor) {
+ // Check if it overlaps with the current cursor
+ if ((cursor->end > region->start) && (cursor->start < region->start)) {
+ // overlaps not allowed
+ return -1;
+ }
+
+ // add to the end of the list
+ if (!(cursor->next)) {
+ cursor->next = region;
+ region->prev = cursor;
+ layout->num_regions++;
+ layout->num_pages += (region->end - region->start) / PAGE_SIZE;
+ return 0;
+ } else if (cursor->next->start >= region->end) {
+ // add here
+ region->next = cursor->next;
+ region->prev = cursor;
+
+ cursor->next->prev = region;
+ cursor->next = region;
+
+ layout->num_regions++;
+ layout->num_pages += (region->end - region->start) / PAGE_SIZE;
+
+ return 0;
+ } else if (cursor->next->end < region->start) {
+ cursor = cursor->next;
+ } else {
+ return -1;
+ }
+ }
- return 0;
+ return -1;
}
-int add_shared_mem_range(vmm_mem_layout_t * layout, ullong_t addr, uint_t num_pages, ullong_t host_addr) {
+int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end, addr_t host_addr) {
layout_region_t * shared_region = os_hooks->malloc(sizeof(layout_region_t));
+ int ret;
shared_region->next = NULL;
shared_region->prev = NULL;
- shared_region->addr = addr;
- shared_region->num_pages = num_pages;
+ shared_region->start = start;
+ shared_region->end = end;
shared_region->type = SHARED;
shared_region->host_addr = host_addr;
- return add_mem_range(layout, shared_region);
+ ret = add_mem_range(layout, shared_region);
+
+ if (ret != 0) {
+ VMMFree(shared_region);
+ }
+
+ return ret;
}
-int add_unmapped_mem_range(vmm_mem_layout_t * layout, ullong_t addr, uint_t num_pages) {
+int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end) {
layout_region_t * unmapped_region = os_hooks->malloc(sizeof(layout_region_t));
-
+ int ret;
+
unmapped_region->next = NULL;
unmapped_region->prev = NULL;
- unmapped_region->addr = addr;
- unmapped_region->num_pages = num_pages;
+ unmapped_region->start = start;
+ unmapped_region->end = end;
unmapped_region->type = UNMAPPED;
unmapped_region->host_addr = 0;
- return add_mem_range(layout, unmapped_region);
+ ret = add_mem_range(layout, unmapped_region);
+
+ if (ret != 0) {
+ VMMFree(unmapped_region);
+ }
+
+ return ret;
}
-int add_guest_mem_range(vmm_mem_layout_t * layout, ullong_t addr, uint_t num_pages) {
+int add_guest_mem_range(vmm_mem_layout_t * layout, addr_t start, addr_t end) {
layout_region_t * guest_region = os_hooks->malloc(sizeof(layout_region_t));
+ int ret;
guest_region->next = NULL;
guest_region->prev = NULL;
- guest_region->addr = addr;
- guest_region->num_pages = num_pages;
+ guest_region->start = start;
+ guest_region->end = end;
guest_region->type = GUEST;
guest_region->host_addr = 0;
- return add_mem_range(layout, guest_region);
+ ret = add_mem_range(layout, guest_region);
+
+ if (ret != 0) {
+ VMMFree(guest_region);
+ }
+
+ return ret;
}
+/* Returns the page address of page number 'index' in the memory list
+ * If index is out of bounds... returns -1 (an invalid page address)
+ */
+addr_t get_mem_layout_addr(vmm_mem_layout_t * layout, uint_t index) {
+ layout_region_t * reg = layout->head;
+ uint_t i = index;
+
+ // Memory List overrun
+ if (index > layout->num_pages - 1) {
+ return -1;
+ }
+
+ while (i >= 0) {
+ if (!reg) {
+ return -1;
+ }
+
+ int num_reg_pages = reg->end - reg->start;
+
+ if (num_reg_pages <= index) {
+ i -= num_reg_pages;
+ reg = reg->next;
+ } else {
+ return reg->start + (i * PAGE_SIZE);
+ }
+ }
+
+ return -1;
+}
+
+layout_region_t * get_mem_layout_region(vmm_mem_layout_t * layout, addr_t addr) {
+ layout_region_t * tmp_reg = layout->head;
+
+
+ while (tmp_reg) {
+ if ((tmp_reg->start <= addr) && (tmp_reg->end > addr)) {
+ return tmp_reg;
+ } else if (tmp_reg->start > addr) {
+ return NULL;
+ } else {
+ tmp_reg = tmp_reg->next;
+ }
+ }
+
+ return NULL;
+}
+
+
void print_mem_list(vmm_mem_list_t * list) {
PrintDebug("Memory Region List (regions: %d) (pages: %d)\n", list->num_regions, list->num_pages);
while (cur) {
- PrintDebug("%d: 0x%x - 0x%x\n", i, cur->addr, cur->addr + (cur->num_pages * PAGE_SIZE));
+ PrintDebug("%d: 0x%x - 0x%x\n", i, cur->addr, cur->addr + (cur->num_pages * PAGE_SIZE) - 1);
cur = cur->next;
i++;
}
PrintDebug("Memory Layout (regions: %d) (pages: %d)\n", layout->num_regions, layout->num_pages);
while (cur) {
- PrintDebug("%d: 0x%x - 0x%x\n", i, cur->addr, cur->addr + (cur->num_pages * PAGE_SIZE));
+ PrintDebug("%d: 0x%x - 0x%x\n", i, cur->start, cur->end -1);
cur = cur->next;
i++;
}
+
+
+
+
+
+
+
+
#ifdef VMM_MEM_TEST
+
+
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
+
struct vmm_os_hooks * os_hooks;
void * TestMalloc(uint_t size) {
return malloc(size);
}
+void * TestAllocatePages(int size) {
+ return malloc(4096 * size);
+}
+
+
void TestPrint(const char * fmt, ...) {
va_list args;
va_end(args);
}
-int mem_list_add_test_1() {
- vmm_mem_list_t list;
+int mem_list_add_test_1( vmm_mem_list_t * list) {
+
uint_t offset = 0;
- init_mem_list(&list);
+ PrintDebug("\n\nTesting Memory List\n");
+
+ init_mem_list(list);
offset = PAGE_SIZE * 6;
PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 10));
- add_mem_list_pages(&list, PAGE_SIZE * 6, 10);
- print_mem_list(&list);
+ add_mem_list_pages(list, offset, 10);
+ print_mem_list(list);
offset = 0;
PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + PAGE_SIZE * 4);
- add_mem_list_pages(&list, 0, 4);
- print_mem_list(&list);
+ add_mem_list_pages(list, offset, 4);
+ print_mem_list(list);
offset = PAGE_SIZE * 20;
PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1));
- add_mem_list_pages(&list, PAGE_SIZE * 20, 1);
- print_mem_list(&list);
+ add_mem_list_pages(list, offset, 1);
+ print_mem_list(list);
+
+ offset = PAGE_SIZE * 21;
+ PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 3));
+ add_mem_list_pages(list, offset, 3);
+ print_mem_list(list);
offset = PAGE_SIZE * 10;
PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 30));
- add_mem_list_pages(&list, PAGE_SIZE * 10, 30);
- print_mem_list(&list);
+ add_mem_list_pages(list, offset, 30);
+ print_mem_list(list);
+
+
+ offset = PAGE_SIZE * 5;
+ PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1));
+ add_mem_list_pages(list, offset, 1);
+ print_mem_list(list);
+
+
return 0;
}
-int mem_layout_add_test_1() {
- vmm_mem_layout_t layout;
- uint_t offset = 0;
+int mem_layout_add_test_1(vmm_mem_layout_t *layout) {
- init_mem_layout(&layout);
+
+ uint_t start = 0;
+ uint_t end = 0;
- offset = PAGE_SIZE * 6;
- PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 10));
- add_guest_mem_range(&layout, PAGE_SIZE * 6, 10);
- print_mem_layout(&layout);
+ PrintDebug("\n\nTesting Memory Layout\n");
+ init_mem_layout(layout);
- offset = 0;
- PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + PAGE_SIZE * 4);
- add_guest_mem_range(&layout, 0, 4);
- print_mem_layout(&layout);
+ start = 0x6000;
+ end = 0x10000;;
+ PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+ add_guest_mem_range(layout, start, end);
+ print_mem_layout(layout);
+
+
+ start = 0x1000;
+ end = 0x3000;
+ PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+ add_guest_mem_range(layout, start, end);
+ print_mem_layout(layout);
+
+ start = 0x2000;
+ end = 0x6000;
+ PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+ add_guest_mem_range(layout, start, end);
+ print_mem_layout(layout);
+
+ start = 0x4000;
+ end = 0x5000;
+ PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+ add_guest_mem_range(layout, start, end);
+ print_mem_layout(layout);
+
+
+ start = 0x5000;
+ end = 0x7000;
+ PrintDebug("Adding 0x%x - 0x%x\n", start, end);
+ add_guest_mem_range(layout, start, end);
+ print_mem_layout(layout);
- offset = PAGE_SIZE * 20;
- PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1));
- add_guest_mem_range(&layout, PAGE_SIZE * 20, 1);
- print_mem_layout(&layout);
- offset = PAGE_SIZE * 10;
- PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 30));
- add_guest_mem_range(&layout, PAGE_SIZE * 10, 30);
- print_mem_layout(&layout);
return 0;
}
struct vmm_os_hooks dummy_hooks;
os_hooks = &dummy_hooks;
+ vmm_mem_layout_t layout;
+ vmm_mem_list_t list;
+
os_hooks->malloc = &TestMalloc;
os_hooks->free = &free;
os_hooks->print_debug = &TestPrint;
+ os_hooks->allocate_pages = &TestAllocatePages;
+
- printf("mem_list_add_test_1: %d\n", mem_list_add_test_1());
- printf("layout_add_test_t: %d\n", mem_layout_add_test_1());
+ printf("mem_list_add_test_1: %d\n", mem_list_add_test_1(&list));
+ printf("layout_add_test_1: %d\n", mem_layout_add_test_1(&layout));
return 0;
}
#endif
+
+
+
+
+
+