diff --git a/vm/sparse.c b/vm/sparse.c index 1944a95..43ae313 100644 --- a/vm/sparse.c +++ b/vm/sparse.c @@ -24,6 +24,7 @@ */ #include #include +#include #include #include #include @@ -63,6 +64,10 @@ static struct vm_page *get_or_create_page(phys_addr_t addr) size_t nr_pages = vm_page_order_to_pages(sector->s_size); sector->s_pages = kzalloc(nr_pages * sizeof(struct vm_page), 0); + if (!sector->s_pages) { + panic("out of memory!"); + } + for (size_t i = 0; i < nr_pages; i++) { sector->s_pages[i].p_flags = VM_PAGE_RESERVED; } @@ -73,17 +78,16 @@ static struct vm_page *get_or_create_page(phys_addr_t addr) return §or->s_pages[page_number]; } -static enum vm_page_order find_minimum_sector_size(size_t pmem_size) +static enum vm_page_order find_minimum_sector_size(phys_addr_t pmem_end) { for (enum vm_page_order i = VM_PAGE_4K; i < VM_PAGE_64G; i++) { size_t order_bytes = vm_page_order_to_bytes(i); - if (order_bytes * VM_MAX_SECTORS >= pmem_size) { + if (order_bytes * VM_MAX_SECTORS >= pmem_end) { return i; } } - /* TODO panic here, once panic() is implemented. */ - return VM_PAGE_64G; + panic("cannot find suitable sector size for memory map."); } /* this function is called to calculate the optimal sector size for the system, @@ -93,12 +97,14 @@ static enum vm_page_order find_minimum_sector_size(size_t pmem_size) this function uses some heuristics and thresholds that are untested and are in need of improvement to ensure that sparse works well on a wide range of systems. */ -static void calculate_sector_size_and_count(size_t pmem_size, size_t reserved_size, unsigned int *out_sector_count, enum vm_page_order *out_sector_size) +static void calculate_sector_size_and_count( + phys_addr_t pmem_end, size_t reserved_size, size_t free_size, + unsigned int *out_sector_count, enum vm_page_order *out_sector_size) { /* we can support up to VM_MAX_SECTORS memory sectors. the minimum sector size is what ever is required to cover all of physical memory in the maximum number of sectors */ - enum vm_page_order sector_size = find_minimum_sector_size(pmem_size); + enum vm_page_order sector_size = find_minimum_sector_size(pmem_end); if (sector_size <= VM_PAGE_2M) { /* override really small sector sizes with something @@ -107,7 +113,6 @@ static void calculate_sector_size_and_count(size_t pmem_size, size_t reserved_si sector_size = VM_PAGE_2M; } - size_t free_size = pmem_size - reserved_size; /* the absolute difference between the amount of free memory and the amount of reserved memory. */ size_t memdiff = absdiff64(free_size, reserved_size); @@ -133,12 +138,12 @@ static void calculate_sector_size_and_count(size_t pmem_size, size_t reserved_si power of 2. */ size_t sector_bytes = vm_page_order_to_bytes(sector_size); - if (pmem_size & (sector_bytes - 1)) { - pmem_size &= ~(sector_bytes - 1); - pmem_size += sector_bytes; + if (pmem_end & (sector_bytes - 1)) { + pmem_end &= ~(sector_bytes - 1); + pmem_end += sector_bytes; } - size_t sector_count = div64_pow2(pmem_size, sector_bytes); + size_t sector_count = div64_pow2(pmem_end, sector_bytes); *out_sector_count = sector_count; *out_sector_size = sector_size; @@ -146,15 +151,19 @@ static void calculate_sector_size_and_count(size_t pmem_size, size_t reserved_si void vm_sparse_init(void) { - size_t pmem_size = 0, reserved_size = 0; + size_t pmem_limit = 0, reserved_size = 0, free_size = 0; struct memblock_iter it; for_each_mem_range (&it, 0x0, UINTPTR_MAX) { - if (pmem_size < it.it_limit + 1) { - pmem_size = it.it_limit + 1; + if (pmem_limit < it.it_limit + 1) { + pmem_limit = it.it_limit + 1; } } + for_each_free_mem_range (&it, 0x0, UINTPTR_MAX) { + free_size += it.it_limit - it.it_base + 1; + } + for_each_reserved_mem_range (&it, 0x0, UINTPTR_MAX) { reserved_size += it.it_limit - it.it_base + 1; } @@ -162,7 +171,9 @@ void vm_sparse_init(void) enum vm_page_order sector_size; size_t sector_bytes = 0; unsigned int nr_sectors = 0; - calculate_sector_size_and_count(pmem_size, reserved_size, &nr_sectors, §or_size); + calculate_sector_size_and_count( + pmem_limit, reserved_size, free_size, + &nr_sectors, §or_size); sector_bytes = vm_page_order_to_bytes(sector_size); char sector_size_str[64];