X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fgeekos%2Fvmm_mem.c;h=05516758a21ff76b226726ee957851333067152e;hb=b85f79b8030114370851ed3422c078debe630570;hp=b2721ebab54748483f4a964c4f124fc477183853;hpb=190b2ef9470c23c275754b74745933d973f8c439;p=palacios.releases.git diff --git a/palacios/src/geekos/vmm_mem.c b/palacios/src/geekos/vmm_mem.c index b2721eb..0551675 100644 --- a/palacios/src/geekos/vmm_mem.c +++ b/palacios/src/geekos/vmm_mem.c @@ -5,205 +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 free_mem_list(vmm_mem_list_t * list) { - mem_region_t * cursor = list->head; - mem_region_t * tmp = NULL; - - while(cursor) { - tmp = cursor; - cursor = cursor->next; - 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, addr_t addr, uint_t num_pages) { - - uint_t num_new_pages = num_pages; - 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)); - - 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 { - addr_t cursor_end = cursor->addr + (cursor->num_pages * PAGE_SIZE) - 1; - - if (addr > cursor_end + 1) { - // 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 + 1)) { - // 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; - - } - } - - - // Clean up any overlaps that follow - while ((cursor->next) && (cursor->next->addr <= new_end + 1)) { - mem_region_t * overlap = cursor->next; - addr_t overlap_end = overlap->addr + (overlap->num_pages * PAGE_SIZE) - 1; - - 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; - } - - VMMFree(overlap); - - list->num_regions--; - } - - - list->num_pages += num_new_pages; - - return 0; -} - - -/* 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, 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) - 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))) { - if (prev_region->next) { - prev_region = prev_region->next; - } else { - return prev_region; - } - } - } - - return prev_region; +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; - -/* 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_shadow_map(shadow_map_t * map) { + map->num_regions = 0; -void init_mem_layout(vmm_mem_layout_t * layout) { - layout->num_pages = 0; - layout->num_regions = 0; - - layout->head = NULL; + map->head = NULL; } -void free_mem_layout(vmm_mem_layout_t * layout) { - layout_region_t * cursor = layout->head; - layout_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; @@ -211,216 +48,160 @@ void free_mem_layout(vmm_mem_layout_t * layout) { VMMFree(tmp); } - VMMFree(layout); - + VMMFree(map); } -/* 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, addr_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 +/* 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) - 1) { - // overlaps not allowed - return -1; - } - layout->head->prev = region; - } +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 = 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) - 1)) { - // overlaps not allowed - return -1; - } else if (region->addr > cursor->addr + (cursor->num_pages * PAGE_SIZE) - 1) { - // 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 { - return -1; + region->next = cursor; + map->num_regions++; + map->head = region; + return 0; } + 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 (!(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; - return 0; -} - - - - - -int add_shared_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages, 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->type = SHARED; - shared_region->host_addr = host_addr; - - ret = add_mem_range(layout, shared_region); - - if (ret != 0) { - VMMFree(shared_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 ret; + + // This cannot happen + // We should panic here + return -1; } -int add_unmapped_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages) { - 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->type = UNMAPPED; - unmapped_region->host_addr = 0; - - ret = add_mem_range(layout, unmapped_region); - - if (ret != 0) { - VMMFree(unmapped_region); - } - - return ret; +int delete_shadow_region(shadow_map_t * map, + addr_t guest_start, + addr_t guest_end) { + return -1; } -int add_guest_mem_range(vmm_mem_layout_t * layout, addr_t addr, uint_t num_pages) { - 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->type = GUEST; - guest_region->host_addr = 0; - ret = add_mem_range(layout, guest_region); - - if (ret == 0) { - layout->num_guest_pages += num_pages; - } else { - VMMFree(guest_region); - } +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; - return ret; + while (reg) { + if (i == index) { + return reg; + } + reg = reg->next; + i++; + } + return NULL; } +shadow_region_t * get_shadow_region_by_addr(shadow_map_t * map, + addr_t addr) { + shadow_region_t * reg = map->head; -/* 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; - } - - if (reg->num_pages <= index) { - i -= reg->num_pages; - reg = reg->next; + while (reg) { + if ((reg->guest_start <= addr) && (reg->guest_end > addr)) { + return reg; + } else if (reg->guest_start > addr) { + return NULL; } else { - return reg->addr + (i * PAGE_SIZE); + reg = reg->next; } } - - return -1; + return NULL; } +host_region_type_t lookup_shadow_map_addr(shadow_map_t * map, addr_t guest_addr, addr_t * host_addr) { + shadow_region_t * reg = get_shadow_region_by_addr(map, guest_addr); -void print_mem_list(vmm_mem_list_t * list) { - mem_region_t * cur = list->head; - int i = 0; - - 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) - 1); - cur = cur->next; - i++; + if (!reg) { + // No mapping exists + return HOST_REGION_INVALID; + } else { + switch (reg->host_type) { + case HOST_REGION_PHYSICAL_MEMORY: + *host_addr = (guest_addr - reg->guest_start) + reg->host_addr.phys_addr.host_start; + return reg->host_type; + case HOST_REGION_MEMORY_MAPPED_DEVICE: + case HOST_REGION_UNALLOCATED: + // ... + default: + *host_addr = 0; + return reg->host_type; + } } - PrintDebug("\n"); } - -void print_mem_layout(vmm_mem_layout_t * layout) { - layout_region_t * cur = layout->head; +void print_shadow_map(shadow_map_t * map) { + shadow_region_t * cur = map->head; int i = 0; - PrintDebug("Memory Layout (regions: %d) (pages: %d)\n", layout->num_regions, layout->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) - 1); + 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"); } @@ -432,8 +213,6 @@ void print_mem_layout(vmm_mem_layout_t * layout) { - - #ifdef VMM_MEM_TEST @@ -441,7 +220,7 @@ void print_mem_layout(vmm_mem_layout_t * layout) { #include #include -#include + @@ -511,41 +290,46 @@ int mem_list_add_test_1( vmm_mem_list_t * list) { } -int mem_layout_add_test_1(vmm_mem_layout_t *layout) { +int mem_layout_add_test_1(vmm_mem_layout_t * layout) { - uint_t offset = 0; + + uint_t start = 0; + uint_t end = 0; PrintDebug("\n\nTesting Memory Layout\n"); init_mem_layout(layout); - offset = PAGE_SIZE * 6; - PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 10)); - add_guest_mem_range(layout, offset, 10); + start = 0x6000; + end = 0x10000;; + 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, offset, 1); + start = 0x1000; + end = 0x3000; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); print_mem_layout(layout); - - offset = PAGE_SIZE * 16; - PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + PAGE_SIZE * 4); - add_guest_mem_range(layout, offset, 4); + start = 0x2000; + end = 0x6000; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); 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, offset, 30); + start = 0x4000; + end = 0x5000; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); print_mem_layout(layout); - offset = 0; - PrintDebug("Adding 0x%x - 0x%x\n", offset, offset + (PAGE_SIZE * 1)); - add_guest_mem_range(layout, offset, 1); + start = 0x5000; + end = 0x7000; + PrintDebug("Adding 0x%x - 0x%x\n", start, end); + add_guest_mem_range(layout, start, end); print_mem_layout(layout); @@ -573,10 +357,6 @@ int main(int argc, char ** argv) { 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)); - - pde_t * pde = generate_guest_page_tables(&layout, &list); - PrintDebugPageTables(pde); - return 0; } #endif