From 774e3796b252383aafb8b3f30d51a19400c74516 Mon Sep 17 00:00:00 2001 From: Brett Weiland Date: Sun, 18 Apr 2021 16:00:17 -0500 Subject: modified: src/bootloader/bios_functions/bios_disk.asm modified: src/bootloader/bootloader.asm new file: src/include/kernel.h modified: src/include/libc.h modified: src/include/paging.h new file: src/include/panic.h modified: src/kernel/kernel.c modified: src/kernel/libc.c modified: src/kernel/page.c new file: src/kernel/panic.c modified: src/link.ld modified: src/makefile modified: tools/page/page.py --- src/kernel/page.c | 220 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 177 insertions(+), 43 deletions(-) (limited to 'src/kernel/page.c') diff --git a/src/kernel/page.c b/src/kernel/page.c index 6f1dd7c..de4f557 100644 --- a/src/kernel/page.c +++ b/src/kernel/page.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include void debug_print_memory() { struct memory_table *memtable = (struct memory_table *)&_meminfo_loc; @@ -14,62 +16,194 @@ void debug_print_memory() { printf("----------------------------------------------------------------------------\n"); } +void debug_pmap() { + struct phys_map* pmap; + int pmap_i = 0, order; + uint64_t buddy_size, blong_i, bbit_i, buddy_chunksize, omit_cnt; + printf("Maximum buddy order: %u (up to %#x sized chunks)\n", MAX_BUDDY_ORDER, (0x1000 << MAX_BUDDY_ORDER - 1)); + for(pmap = (struct phys_map*)&_stage2_pagetable; pmap != 0; pmap = pmap->next) { + printf("Table %u:\n" + "\tPhysical Start:\t%#p\n" + "\tTable location:\t%#p\n", pmap_i, pmap->zone_paddr, pmap); + for(order = 0; order <= MAX_BUDDY_ORDER - 1; order++) { + buddy_chunksize = (0x1000 << order); //TODO just put it in the for loop + buddy_size = (((order == MAX_BUDDY_ORDER - 1) + ? (uint64_t *)pmap->next : pmap->buddy[order + 1]) - pmap->buddy[order]); + printf("\tbuddy[%u]:\n" + "\t\tAddress:\t%#x\n" + "\t\tSize:\t\t%u\n" + "\t\tBuddies:\t\t\n", order, pmap->buddy[order], buddy_size); + + omit_cnt = 0; + + for(blong_i = 0; blong_i < buddy_size; blong_i++) { + for(bbit_i = 0; bbit_i < 64; bbit_i++) { + if(*(pmap->buddy[order] + blong_i) & ((uint64_t)1 << bbit_i)) { + if((omit_cnt < 20) || (blong_i == buddy_size - 1)) { + printf("address %#x\tbit %u: %p\t is free\n", + pmap->buddy[order] + blong_i, bbit_i, (uint64_t)pmap->zone_paddr + (((blong_i * 64) + bbit_i) * buddy_chunksize)); + } + omit_cnt++; + if(omit_cnt == 20) { + printf("\t\t\t[more entries ommited]\n"); + } + } + } + } + } + pmap_i++; + } +} + +void init_pmap() { + struct memory_table *zones = (struct memory_table *)&_meminfo_loc; + struct phys_map *pmap = (struct phys_map*)&_stage2_pagetable; + + unsigned int zone_i, pmap_i = 0; + int budorder; + + //we keep this info out of the struct because we won't need it after setting up + uint64_t zone_len[MAX_ZONE_CNT], buddy_bitlen[MAX_ZONE_CNT][MAX_BUDDY_ORDER], *buddy_end; + uint64_t pmap_size, pmap_bbitsize, pmap_blongsize, buddy_size, buddy_bit, pmap_bit; + uint64_t threshold_bitsize, threshold_longsize = 0; -//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; + void *paged_mem = (void *)&_stage2_pagetable + 0x200000; + map_page(&_stage2_pagetable, &_stage2_pagetable, PAGE_SIZE_2M); + for(zone_i = 0; zones[zone_i].length > 0; zone_i++) { - for(x = 0; x < 8; x++) { + if((zones[zone_i].type == MEM_AVAILABLE) && (zones[zone_i].ACPI & 1)) { - buddy_bitsize = memtable[i].length / (0x1000 * (1 << x)); - buddy_size = ceil(buddy_bitsize / (float)8); + //hopefully this should never happen... + //I should dig into the docs to check before removing this. + //We also could forget about MAX_ZONE_CNT if we did. - if((void *)buddy_ptr + buddy_size >= next_page) { - map_page(next_page, next_page, PAGE_SIZE_2M); - next_page += 0x200000; - } + if(zone_i >= MAX_ZONE_CNT) { + printf("Only %u zones can be used! Modify MAX_ZONE_CNT in paging.h to use all memory.\n", MAX_ZONE_CNT); + break; + } - 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)); - } + if((zones[zone_i].base <= (void*)&_stage2_pagetable) && + (zones[zone_i].base + zones[zone_i].length >= (void *)&_stage2_pagetable)) { + pmap->zone_paddr = &_stage2_pagetable; + zone_len[pmap_i] = zones[zone_i].length - (pmap->zone_paddr - zones[zone_i].base); + } + else { + pmap->zone_paddr = zones[zone_i].base; + zone_len[pmap_i] = zones[zone_i].length; + } - buddy_ptr += buddy_size; + pmap->buddy[0] = (void *)pmap + sizeof(*pmap); - prev_buddy_bsize = buddy_bitsize; + for(budorder = 1; budorder < MAX_BUDDY_ORDER; budorder++) { + buddy_bitlen[pmap_i][budorder - 1] = GET_BUDDY_BITLEN(zone_len[pmap_i], budorder - 1); + pmap->buddy[budorder] = (uint64_t *)pmap->buddy[budorder - 1] + + LSIZE_FROM_BITLEN(buddy_bitlen[pmap_i][budorder - 1]); + } - } - map->map_size = buddy_ptr - (uint64_t*)map; - map = (struct phys_map *)map + map->map_size; + buddy_bitlen[pmap_i][MAX_BUDDY_ORDER - 1] = GET_BUDDY_BITLEN(zone_len[pmap_i], MAX_BUDDY_ORDER - 1); + pmap->next = (void *)pmap->buddy[MAX_BUDDY_ORDER - 1] + + (LSIZE_FROM_BITLEN(buddy_bitlen[pmap_i][MAX_BUDDY_ORDER - 1]) * 8); + + pmap = pmap->next; + pmap_i++; - if((void *)map + 24 >= next_page) { - map_page(next_page, next_page, PAGE_SIZE_2M); - next_page += 0x200000; + //allocates by an extra sizeof(struct phys_map), + //but were about to discard anyway + while((void *)pmap + sizeof(*pmap) >= paged_mem) { + map_page(paged_mem, paged_mem, PAGE_SIZE_2M); + paged_mem += 0x200000; } - } + + } } -} + pmap_size = (void*)(pmap) - (void*)&_stage2_pagetable; + if(pmap_size >= zone_len[0]) panic(); //TODO debugging + + pmap_i = 0; + for(pmap = (struct phys_map*)&_stage2_pagetable; pmap->next != 0; pmap = pmap->next) { + for(budorder = MAX_BUDDY_ORDER - 1; budorder >= 0; budorder--) { + pmap_bbitsize = ceil((float)pmap_size / ((uint64_t)0x1000 << budorder)); + pmap_blongsize = pmap_bbitsize / 64; + + if(budorder == MAX_BUDDY_ORDER - 1) { + buddy_size = (uint64_t *)pmap->next - pmap->buddy[budorder]; + buddy_end = (uint64_t *)pmap->next - 1; + + threshold_bitsize = ((pmap_blongsize * 64) + pmap_bbitsize) * 2; + } + else { + buddy_size = pmap->buddy[budorder + 1] - pmap->buddy[budorder]; + buddy_end = pmap->buddy[budorder + 1] - 1; + + threshold_longsize = threshold_bitsize / 64; + } + pmap_bit = pmap_bbitsize & 63; + buddy_bit = buddy_bitlen[pmap_i][budorder] & 63; -//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) { + + if((pmap_bbitsize >= BITLEN_FROM_LSIZE(buddy_size)) && (pmap == (void *)&_stage2_pagetable)) { + bzero(pmap->buddy[budorder], buddy_size * 8); + } + else { + if(budorder == MAX_BUDDY_ORDER - 1) { + if(pmap == (void*)&_stage2_pagetable) { + if(pmap_blongsize) bzero(pmap->buddy[budorder], (pmap_blongsize - 1) * 8); + if(pmap_bit) { + *(pmap->buddy[budorder] + pmap_blongsize) = ~(((uint64_t)1 << pmap_bit) - 1); + } + else { + *(pmap->buddy[budorder] + pmap_blongsize) = UINT64_MAX; + } + if(pmap_blongsize + 1 == buddy_size) { + *buddy_end &= ((uint64_t)1 << buddy_bit) - 1; + } + else { + memset(pmap->buddy[budorder] + pmap_blongsize + 1, UINT8_MAX, (buddy_size - 1) * 8); + if(buddy_bit) { + *buddy_end = ((uint64_t)1 << buddy_bit) - 1; + } + else { + *buddy_end = UINT64_MAX; + } + } + threshold_bitsize = ((pmap_blongsize * 64) + pmap_bbitsize) * 2; + } + else { + memset(pmap->buddy[budorder], UINT8_MAX, (buddy_size - 1) * 8); + if(buddy_bit) { + *buddy_end = ((uint64_t)1 << buddy_bit) - 1; + } + else { + *buddy_end = UINT64_MAX; + } + } + } + else if(pmap == (void *)&_stage2_pagetable) { + if(threshold_longsize) bzero(pmap->buddy[budorder], (threshold_longsize - 1) * 8); + + if(threshold_bitsize > pmap_bbitsize) + *(pmap->buddy[budorder] + threshold_longsize) = ((uint64_t)1 << ((threshold_bitsize - 1) & 63)); + + if(buddy_size - threshold_longsize) + bzero(pmap->buddy[budorder] + threshold_longsize + 1, buddy_size - threshold_longsize); + if(buddy_bit & 1) { + *buddy_end = ((uint64_t)1 << (buddy_bit - 1)); + } + threshold_bitsize = ((pmap_blongsize * 64) + pmap_bbitsize) * 2; + } + else { + bzero(pmap->buddy[budorder], buddy_size); + if(buddy_bit & 1) { + *buddy_end = ((uint64_t)1 << ((buddy_bit) - 1)); + } + } + } + } + pmap_i++; + } } @@ -97,7 +231,7 @@ bool map_page(void *virtual_addr, void *physical_addr, uint8_t size) { 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) + if(table->pdpe[pdpe_i].base_ptr == ((uintptr_t)pa_ptr >> 30 & 0x1ff)) return true; goto error; } @@ -105,7 +239,7 @@ bool map_page(void *virtual_addr, void *physical_addr, uint8_t size) { if(table->pde[pde_i].present) { if(size == PAGE_SIZE_2M) { - if(table->pde[pde_i].base_ptr == (uintptr_t)pa_ptr >> 21 & 0x1ff) + if(table->pde[pde_i].base_ptr == ((uintptr_t)pa_ptr >> 21 & 0x1ff)) return true; goto error; } -- cgit v1.2.3