extern struct vmm_os_hooks * os_hooks;
-void init_mem_list(vmm_mem_list_t * list) {
- list->num_pages = 0;
- list->long_mode = false;
-
- list->num_regions = 0;
- list->head = NULL;
+void init_shadow_map_entry(shadow_map_entry_t *entry,
+ addr_t guest_addr_start,
+ addr_t guest_addr_end,
+ guest_region_type_t guest_region_type,
+ host_region_type_t host_region_type)
+{
+ entry->guest_type=guest_region_type;
+ entry->guest_start=guest_addr_start;
+ entry->guest_end=guest_addr_end;
+ entry->host_type=host_region_type;
+ entry->next=entry->prev=NULL;
+}
+
+void init_shadow_map_entry_physical(shadow_map_entry_t *entry,
+ addr_t guest_addr_start,
+ addr_t guest_addr_end,
+ guest_region_type_t guest_region_type,
+ addr_t host_addr_start,
+ addr_t host_addr_end,
+ host_region_type_t host_region_type)
+{
+ init_shadow_map_entry(entry,guest_addr_start,guest_addr_end,guest_region_type,host_region_type);
+ entry->host_addr.phys_addr.host_start=host_addr_start;
+ entry->host_addr.phys_addr.host_end=host_addr_end;
}
+
+void init_shadow_map(shadow_map_t * map)
+{
+ map->num_regions = 0;
+
+ map->head = NULL;
+}
-void free_mem_list(vmm_mem_list_t * list) {
- mem_region_t * cursor = list->head;
- mem_region_t * tmp = NULL;
+
+void free_shadow_map(shadow_map_t * map) {
+ shadow_map_entry_t * cursor = map->head;
+ shadow_map_entry_t * tmp = NULL;
while(cursor) {
tmp = cursor;
VMMFree(tmp);
}
- VMMFree(list);
-}
-
-/*** FOR THE LOVE OF GOD WRITE SOME UNIT TESTS FOR THIS THING ***/
-
-
-
-// Scan the current list, and extend an existing region if one exists
-// Otherwise create a new region and merge it into the correct location in the list
-//
-// We scan to find the position at which to add the new region and insert it
-// 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) {
-
- uint_t num_new_pages = num_pages;
- ullong_t new_end = addr + (num_pages * PAGE_SIZE);
-
- 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));
-
- cursor->prev = NULL;
- cursor->addr = addr;
- cursor->num_pages = num_pages;
+ VMMFree(map);
- cursor->next = list->head;
- list->head = cursor;
-
- if (cursor->next) {
- cursor->next->prev = cursor;
- }
-
- list->num_regions++;
- } else {
- ullong_t cursor_end = cursor->addr + (cursor->num_pages * PAGE_SIZE);
-
- if (addr > cursor_end) {
- // address falls after cursor region
-
- mem_region_t * new_region = os_hooks->malloc(sizeof(mem_region_t));
-
- new_region->prev = cursor;
- new_region->next = cursor->next;
-
- if (cursor->next) {
- cursor->next->prev = new_region;
- }
- cursor->next = new_region;
-
- new_region->addr = addr;
- new_region->num_pages = num_pages;
-
- list->num_regions++;
-
- cursor = new_region;
- } else if ((addr >= cursor->addr) &&
- (addr <= cursor_end)) {
- // address falls inside the cursor region
+}
- // The region has already been added
- if (new_end <= cursor_end) {
- return -1;
- }
- // We need to extend the old region
- num_new_pages = (new_end - cursor_end) / PAGE_SIZE;
- cursor->num_pages += num_new_pages;
+/* 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_shadow_map_region(shadow_map_t * map,
+ shadow_map_entry_t * region)
+{
+ shadow_map_entry_t * cursor = map->head;
- }
+ if ((!cursor) || (cursor->guest_start >= region->guest_end)) {
+ region->prev = NULL;
+ region->next = cursor;
+ map->num_regions++;
+ map->head = region;
+ return 0;
}
-
- // Clean up any overlaps that follow
- while ((cursor->next) && (cursor->next->addr <= new_end)) {
- mem_region_t * overlap = cursor->next;
- ullong_t overlap_end = overlap->addr + (overlap->num_pages * PAGE_SIZE);
-
- cursor->next = overlap->next;
- if (overlap->next) {
- overlap->next->prev = cursor;
+
+ while (cursor) {
+ // Check if it overlaps with the current cursor
+ if ((cursor->guest_end > region->guest_start) && (cursor->guest_start < region->guest_start)) {
+ // overlaps not allowed
+ return -1;
}
- if (overlap_end > new_end) {
- uint_t extension = (overlap_end - new_end) / PAGE_SIZE;
+ if (!(cursor->next)) {
+ // add to the end of the list
+ cursor->next = region;
+ region->prev = cursor;
+ region->next = NULL;
+ map->num_regions++;
+ return 0;
+ } else if (cursor->next->guest_start >= region->guest_end) {
+ // add here
+ region->next = cursor->next;
+ region->prev = cursor;
+
+ cursor->next->prev = region;
+ cursor->next = region;
- cursor->num_pages += extension;
- num_new_pages -= (overlap->num_pages - extension);
+ map->num_regions++;
+
+ return 0;
+ } else if (cursor->next->guest_end < region->guest_start) {
+ cursor = cursor->next;
} else {
- num_new_pages -= overlap->num_pages;
+ // This cannot happen!
+ // we should panic here
+ return -1;
}
-
- VMMFree(overlap);
-
- list->num_regions--;
}
-
-
- list->num_pages += num_new_pages;
-
- return 0;
+
+ // This cannot happen
+ // We should panic here
+ return -1;
}
-/* this function returns a pointer to the location in the memory 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
- */
-mem_region_t * get_mem_list_cursor(vmm_mem_list_t * list, ullong_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))) ) {
- 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;
+int delete_shadow_map_region(shadow_map_t *map,
+ addr_t guest_start,
+ addr_t guest_end)
+{
+ return -1;
}
-void init_mem_layout(vmm_mem_layout_t * layout) {
- layout->num_pages = 0;
- layout->num_regions = 0;
-
- layout->head = NULL;
-}
+shadow_map_entry_t *get_shadow_map_region_by_index(shadow_map_t * map,
+ uint_t index)
+{
+ shadow_map_entry_t * reg = map->head;
+ uint_t i = 0;
-
-void free_mem_layout(vmm_mem_layout_t * layout) {
- layout_region_t * cursor = layout->head;
- layout_region_t * tmp = NULL;
-
- while(cursor) {
- tmp = cursor;
- cursor = cursor->next;
- VMMFree(tmp);
+ while (reg) {
+ if (i==index) {
+ return reg;
+ }
+ reg=reg->next;
+ i++;
}
+ return NULL;
+}
- VMMFree(layout);
-}
+shadow_map_entry_t * get_shadow_map_region_by_addr(shadow_map_t *map,
+ addr_t addr)
+{
+ shadow_map_entry_t * reg = map->head;
-/* 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;
- }
+ while (reg) {
+ if ((reg->guest_start <= addr) && (reg->guest_end > addr)) {
+ return reg;
+ } else if (reg->guest_start > addr) {
+ return NULL;
+ } else {
+ reg = reg->next;
}
}
-
- return prev_region;
+ return NULL;
}
-/* 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;
- }
- region->prev = NULL;
- region->next = layout->head;
- layout->head = region;
-
- 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
+int map_guest_physical_to_host_physical(shadow_map_entry_t *entry,
+ addr_t guest_addr,
+ addr_t *host_addr)
+{
+ if (!(guest_addr>=entry->guest_start && guest_addr<entry->guest_end)) {
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->num_regions++;
- layout->num_pages += region->num_pages;
- } else {
+ switch (entry->host_type) {
+ case HOST_REGION_PHYSICAL_MEMORY:
+ case HOST_REGION_MEMORY_MAPPED_DEVICE:
+ case HOST_REGION_UNALLOCATED:
+ *host_addr=(guest_addr-entry->guest_start) + entry->host_addr.phys_addr.host_start;
+ return 0;
+ break;
+ default:
return -1;
+ break;
}
-
-
- return 0;
-}
-
-
-
-
-
-int add_shared_mem_range(vmm_mem_layout_t * layout, ullong_t addr, uint_t num_pages, ullong_t host_addr) {
- layout_region_t * shared_region = os_hooks->malloc(sizeof(layout_region_t));
-
- shared_region->next = NULL;
- shared_region->prev = NULL;
- shared_region->addr = addr;
- shared_region->num_pages = num_pages;
- shared_region->type = SHARED;
- shared_region->host_addr = host_addr;
-
- return add_mem_range(layout, shared_region);
}
-int add_unmapped_mem_range(vmm_mem_layout_t * layout, ullong_t addr, uint_t num_pages) {
- layout_region_t * unmapped_region = os_hooks->malloc(sizeof(layout_region_t));
-
- unmapped_region->next = NULL;
- unmapped_region->prev = NULL;
- unmapped_region->addr = addr;
- unmapped_region->num_pages = num_pages;
- unmapped_region->type = UNMAPPED;
- unmapped_region->host_addr = 0;
-
- return add_mem_range(layout, unmapped_region);
-}
-
-int add_guest_mem_range(vmm_mem_layout_t * layout, ullong_t addr, uint_t num_pages) {
- layout_region_t * guest_region = os_hooks->malloc(sizeof(layout_region_t));
-
- guest_region->next = NULL;
- guest_region->prev = NULL;
- guest_region->addr = addr;
- guest_region->num_pages = num_pages;
- guest_region->type = GUEST;
- guest_region->host_addr = 0;
-
- return add_mem_range(layout, guest_region);
-}
-
-
-
-
-void print_mem_list(vmm_mem_list_t * list) {
- mem_region_t * cur = list->head;
+void print_shadow_map(shadow_map_t *map) {
+ shadow_map_entry_t * cur = map->head;
int i = 0;
- PrintDebug("Memory Region List (regions: %d) (pages: %d)\n", list->num_regions, list->num_pages);
+ PrintDebug("Memory Layout (regions: %d) \n", map->num_regions);
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 (%s) -> ", i, cur->guest_start, cur->guest_end -1,
+ cur->guest_type == GUEST_REGION_PHYSICAL_MEMORY ? "GUEST_REGION_PHYSICAL_MEMORY" :
+ cur->guest_type == GUEST_REGION_NOTHING ? "GUEST_REGION_NOTHING" :
+ cur->guest_type == GUEST_REGION_MEMORY_MAPPED_DEVICE ? "GUEST_REGION_MEMORY_MAPPED_DEVICE" :
+ "UNKNOWN");
+ if (cur->host_type==HOST_REGION_PHYSICAL_MEMORY ||
+ cur->host_type==HOST_REGION_UNALLOCATED ||
+ cur->host_type==HOST_REGION_MEMORY_MAPPED_DEVICE) {
+ PrintDebug("0x%x - 0x%x ", cur->host_addr.phys_addr.host_start, cur->host_addr.phys_addr.host_end);
+ }
+ PrintDebug("(%s)\n",
+ cur->host_type == HOST_REGION_PHYSICAL_MEMORY ? "HOST_REGION_PHYSICAL_MEMORY" :
+ cur->host_type == HOST_REGION_UNALLOCATED ? "HOST_REGION_UNALLOACTED" :
+ cur->host_type == HOST_REGION_NOTHING ? "HOST_REGION_NOTHING" :
+ cur->host_type == HOST_REGION_MEMORY_MAPPED_DEVICE ? "HOST_REGION_MEMORY_MAPPED_DEVICE" :
+ cur->host_type == HOST_REGION_REMOTE ? "HOST_REGION_REMOTE" :
+ cur->host_type == HOST_REGION_SWAPPED ? "HOST_REGION_SWAPPED" :
+ "UNKNOWN");
cur = cur->next;
i++;
}
- PrintDebug("\n");
}
-void print_mem_layout(vmm_mem_layout_t * layout) {
- layout_region_t * cur = layout->head;
- int i = 0;
- 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));
- cur = cur->next;
- i++;
- }
- PrintDebug("\n");
-}
+
+
#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
+
+
+
+
+
+