#include #include #include #include void debug_print_memory() { struct memory_table *memtable = (struct memory_table *)&_meminfo_loc; printf(" __________________________________________________________________________\n"); printf("| type\tstart\t\t\tend\t\t\tsize\t\t |\n"); printf("|--------------------------------------------------------------------------|\n"); for(unsigned int i = 0; memtable[i].length > 0; i++) { printf("| %u %u\t0x%p\t0x%p\t0x%p |\n", memtable[i].type, memtable[i].ACPI, memtable[i].base, (memtable[i].base + memtable[i].length), memtable[i].length); } printf("----------------------------------------------------------------------------\n"); } //uses buddy system allocation void init_memory() { struct memory_table *memtable = (struct memory_table *)&_meminfo_loc; struct phys_map *map = (struct phys_map*)0x200000; uintptr_t onpage = 0x200000; unsigned int i, x, buddy_size, buddy_bitsize, prev_buddy_bsize; uint64_t *buddy_ptr; map_page((void*)0x200000, (void*)0x200000, PAGE_SIZE_2M); void *next_page = (void *)onpage + 0x200000; // at this point, we are declaring our header and kernel itself as free (so don't forget to fix that!) for(i = 0; memtable[i].length > 0; i++) { if((memtable[i].type == MEM_AVAILABLE) && (memtable[i].ACPI & 1)) { map->chunk_start = (void*)memtable[i].base; map->chunk_size = memtable[i].length; buddy_ptr = (void*)&map->buddies; for(x = 0; x < 8; x++) { buddy_bitsize = memtable[i].length / (0x1000 * (1 << x)); buddy_size = ceil(buddy_bitsize / (float)8); if((void *)buddy_ptr + buddy_size >= next_page) { map_page(next_page, next_page, PAGE_SIZE_2M); next_page += 0x200000; } bzero(buddy_ptr, buddy_size); //meant to be /8? if((buddy_bitsize * 2) != prev_buddy_bsize) { buddy_ptr[-1] |= (1 << ((prev_buddy_bsize % 8) - 1)); } buddy_ptr += buddy_size; prev_buddy_bsize = buddy_bitsize; } map->map_size = buddy_ptr - (uint64_t*)map; map = (struct phys_map *)map + map->map_size; if((void *)map + 24 >= next_page) { map_page(next_page, next_page, PAGE_SIZE_2M); next_page += 0x200000; } } } } //TODO this function was deleted due to it being wrong. //I'll create it once I have the physical paging prerequisite set up. void create_pagetable_stage2(uint64_t free_mem) { } /** * BIG TODO: * Paging turned out to be simpler then I thought. I've temporarily fixed the code, but needs to be rewritten/simplified. * Let's get rid of those nasty GOTOs if we can. * Also, once we get physical memory allocator up and running, impliment that in this function. **/ bool map_page(void *virtual_addr, void *physical_addr, uint8_t size) { //printf("map page called\n"); uintptr_t va_ptr = (uintptr_t)virtual_addr; uintptr_t pa_ptr = (uintptr_t)physical_addr; if((va_ptr % (1 << size)) || (pa_ptr % (1 << size))) { return 0; } page_table *table = (page_table *)PAGEMAP_LOCATION; int pte_i = (va_ptr >> 12) & 0x1ff; int pde_i = (va_ptr >> 21) & 0x1ff; int pdpe_i = (va_ptr >> 30) & 0x1ff; int pml4e_i = (va_ptr >> 39) & 0x1ff; if(table->pml4e[pml4e_i].present) { if(table->pml4e[pml4e_i].base_ptr != (uintptr_t)&table->pdpe[pdpe_i] >> 12) goto error; if(table->pdpe[pdpe_i].present) { if(size == PAGE_SIZE_1G) { if(table->pdpe[pdpe_i].base_ptr == (uintptr_t)pa_ptr >> 30 & 0x1ff) return true; goto error; } if(table->pdpe[pdpe_i].base_ptr != (uintptr_t)&table->pde[pde_i] >> 12) goto error; if(table->pde[pde_i].present) { if(size == PAGE_SIZE_2M) { if(table->pde[pde_i].base_ptr == (uintptr_t)pa_ptr >> 21 & 0x1ff) return true; goto error; } if(table->pde[pde_i].base_ptr != (uintptr_t)&table->pte[pte_i] >> 12) goto error; if(table->pte[pte_i].present) { if(table->pte[pte_i].base_ptr != ((pa_ptr >> 12) & 0x1ff)) goto error; return true; } else goto mod_page_pte; } else goto mod_page_pde; } else goto mod_page_pdpe; } else { table->pml4e[pml4e_i].base_ptr = (uintptr_t)&table->pdpe[pdpe_i] >> 12; table->pdpe[pml4e_i].read_write = 1; table->pml4e[pml4e_i].present = 1; mod_page_pdpe: table->pdpe[pdpe_i].read_write = 1; //TODO you just found out things are a lot more simple then you thought! if(size == PAGE_SIZE_1G) { table->pdpe[pdpe_i].size = 1; table->pdpe[pdpe_i].base_ptr = pa_ptr >> 12; table->pdpe[pdpe_i].present = 1; return true; } table->pdpe[pdpe_i].base_ptr = (uintptr_t)&table->pde[pde_i] >> 12; table->pdpe[pdpe_i].present = 1; mod_page_pde: table->pde[pde_i].read_write = 1; if(size == PAGE_SIZE_2M) { table->pde[pde_i].size = 1; table->pde[pde_i].base_ptr = pa_ptr >> 12; table->pde[pde_i].present = 1; return true; } table->pde[pde_i].base_ptr = (uintptr_t)&table->pte[pte_i] >> 12; table->pde[pde_i].present = 1; mod_page_pte: table->pte[pte_i].base_ptr = pa_ptr >> 12; table->pte[pte_i].read_write = 1; table->pte[pte_i].present = 1; return true; } error: printf("Page allocation error!\n"); return false; }