X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fgeekos%2Fvmm_mem.c;h=4b2d6d9eb9300be1ef946b95a75436a1bb6789d0;hb=3f025fd4e0e535801836faa4259b94b18b94f231;hp=bba83330f102486db2dad9243469eaca870425e9;hpb=701de97007c8b6776998eeab78469a4304f6b871;p=palacios-OLD.git diff --git a/palacios/src/geekos/vmm_mem.c b/palacios/src/geekos/vmm_mem.c index bba8333..4b2d6d9 100644 --- a/palacios/src/geekos/vmm_mem.c +++ b/palacios/src/geekos/vmm_mem.c @@ -5,18 +5,42 @@ 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_region(shadow_region_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_region_physical(shadow_region_t * entry, + addr_t guest_addr_start, + addr_t guest_addr_end, + guest_region_type_t guest_region_type, + addr_t host_addr_start, + host_region_type_t host_region_type) +{ + init_shadow_region(entry, guest_addr_start, guest_addr_end, guest_region_type, host_region_type); + entry->host_addr.phys_addr.host_start = host_addr_start; + +} + + +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_region_t * cursor = map->head; + shadow_region_t * tmp = NULL; while(cursor) { tmp = cursor; @@ -24,330 +48,175 @@ void free_mem_list(vmm_mem_list_t * list) { VMMFree(tmp); } - VMMFree(list); + VMMFree(map); } -/*** 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; - - 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_region(shadow_map_t * map, + shadow_region_t * region) +{ + shadow_region_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; - } - - if (overlap_end > new_end) { - uint_t extension = (overlap_end - new_end) / PAGE_SIZE; - cursor->num_pages += extension; - num_new_pages -= (overlap->num_pages - extension); - } else { - num_new_pages -= overlap->num_pages; + 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; } - VMMFree(overlap); - - list->num_regions--; - } - - - list->num_pages += num_new_pages; - - return 0; -} - + 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; -/* 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; - } + map->num_regions++; + + return 0; + } else if (cursor->next->guest_end < region->guest_start) { + cursor = cursor->next; + } else { + // This cannot happen! + // we should panic here + return -1; } } - - return prev_region; + + // This cannot happen + // We should panic here + return -1; } - -void init_mem_layout(vmm_mem_layout_t * layout) { - layout->num_pages = 0; - layout->num_regions = 0; - - layout->head = NULL; +int delete_shadow_region(shadow_map_t * map, + addr_t guest_start, + addr_t guest_end) { + return -1; } -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); - } - - VMMFree(layout); - -} +shadow_region_t *get_shadow_region_by_index(shadow_map_t * map, + uint_t index) { + shadow_region_t * reg = map->head; + uint_t i = 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; - } + while (reg) { + if (i == index) { + return reg; } + reg = reg->next; + i++; } - - 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; - } +shadow_region_t * get_shadow_region_by_addr(shadow_map_t * map, + addr_t addr) { + shadow_region_t * reg = map->head; - 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 - 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; + 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; } - cursor->next = region; - - layout->num_regions++; - layout->num_pages += region->num_pages; - } else { - return -1; } - - - return 0; + return NULL; } +int guest_paddr_to_host_paddr(shadow_region_t * entry, + addr_t guest_addr, + addr_t * host_addr) { + if (!((guest_addr >= entry->guest_start) && + (guest_addr < entry->guest_end))) { + return -1; + } -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); + 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; + } } - - - -void print_mem_list(vmm_mem_list_t * list) { - mem_region_t * cur = list->head; +void print_shadow_map(shadow_map_t * map) { + shadow_region_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", cur->host_addr.phys_addr.host_start); + } + 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 #include #include @@ -355,12 +224,18 @@ void print_mem_layout(vmm_mem_layout_t * layout) { + 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; @@ -369,65 +244,97 @@ void TestPrint(const char * fmt, ...) { 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; } @@ -438,14 +345,25 @@ int main(int argc, char ** argv) { 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 + + + + + +