From 961139df9ed8720087fab3b90993d523dafaf0ea Mon Sep 17 00:00:00 2001 From: ngiddings Date: Sat, 17 Apr 2021 03:45:45 -0500 Subject: [PATCH] Improved kernel memory usage Moved base linear address to 0xFF800000 Kernel only reserves the page frames it actually needs Memory for multiboot2 headers is freed Video memory and APIC registers are dynamically mapped into linear addresses --- include/pageallocator.h | 2 +- include/stdio.h | 2 ++ src/pageallocator.c | 17 +++++++++++++++- src/x86/apic.c | 5 +++-- src/x86/entry.S | 28 ++++++++++++--------------- src/x86/linker.ld | 9 ++++----- src/x86/mmgr.c | 28 +++++++++++++++++++++++++++ src/x86/multiboot2.c | 4 ---- src/x86/putc.c | 10 +++++++++- src/x86/quark_x86.c | 43 +++++++++++++++-------------------------- 10 files changed, 91 insertions(+), 57 deletions(-) diff --git a/include/pageallocator.h b/include/pageallocator.h index 5b52d54..3bb71d3 100644 --- a/include/pageallocator.h +++ b/include/pageallocator.h @@ -72,4 +72,4 @@ size_t free_page_count(struct page_stack_t *stack); * @param stack * @param map */ -int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map, size_t page_size); +int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map); diff --git a/include/stdio.h b/include/stdio.h index 3c086ee..e669124 100644 --- a/include/stdio.h +++ b/include/stdio.h @@ -2,6 +2,8 @@ #include +int initialize_screen(); + int putchar(int c); int puts(const char *str); diff --git a/src/pageallocator.c b/src/pageallocator.c index 6289809..51135bf 100644 --- a/src/pageallocator.c +++ b/src/pageallocator.c @@ -1,4 +1,6 @@ #include "pageallocator.h" +#include "mmgr.h" +#include "allocator.h" #include "types/status.h" physaddr_t reserve_page(struct page_stack_t *stack) @@ -15,12 +17,25 @@ physaddr_t reserve_page(struct page_stack_t *stack) int free_page(struct page_stack_t *stack, physaddr_t location) { + void *new_limit; if(stack->stack_pointer > stack->limit_pointer) { stack->stack_pointer--; *stack->stack_pointer = location; return S_OK; } + else if((new_limit = allocate_from_top(page_size)) != NULL) + { + switch(map_page(stack, new_limit, location, PAGE_RW)) + { + case S_OUT_OF_MEMORY: + return S_OUT_OF_MEMORY; + case S_OUT_OF_BOUNDS: + return S_OUT_OF_BOUNDS; + case S_OK: + stack->limit_pointer = new_limit; + } + } return S_OUT_OF_MEMORY; } @@ -29,7 +44,7 @@ size_t free_page_count(struct page_stack_t *stack) return stack->base_pointer - stack->stack_pointer; } -int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map, size_t page_size) +int initialize_page_stack(struct page_stack_t *stack, struct memory_map_t *map) { stack->total_pages = 0; for(int i = 0; i < map->size; i++) diff --git a/src/x86/apic.c b/src/x86/apic.c index 32d6b84..9698e55 100644 --- a/src/x86/apic.c +++ b/src/x86/apic.c @@ -1,4 +1,5 @@ #include "mmgr.h" +#include "allocator.h" #include "apic.h" #include "msr.h" #include "stdio.h" @@ -33,9 +34,9 @@ void apic_enable(struct page_stact_t *page_stack) ); struct msr_apic_base_t msr; read_msr(MSR_APIC_BASE, (uint64_t*)&msr); - map_page(page_stack, &_kernel_end, msr.apic_base << 12, PAGE_RW); + apic_registers = (struct apic_registers_t*)allocate_from_bottom(page_size); + map_page(page_stack, apic_registers, msr.apic_base << 12, PAGE_RW); printf("MSR_APIC_BASE: %016x\n", *((uint32_t*)&msr)); - apic_registers = (struct apic_registers_t*)&_kernel_end; apic_registers->spurious_iv.value = apic_registers->spurious_iv.value | 0x100; } diff --git a/src/x86/entry.S b/src/x86/entry.S index bb4a2ed..24aad6a 100755 --- a/src/x86/entry.S +++ b/src/x86/entry.S @@ -30,7 +30,7 @@ .set tagEntryType, 3 .set tagEntrySize, 12 -.set tagEntryAddress, _start - (0xFF900000 - 0x100000) +.set tagEntryAddress, _start - (0xFF800000 - 0x100000) .set tagModuleAlignType, 6 .set tagModuleAlignSize, 8 @@ -108,19 +108,6 @@ _tempIdentityMap: .skip 4096 _tempPgTable: .skip 4096 - -_bootCmdLine: -.skip 64 - -.align 64 -.global system_info -system_info: -.skip 16 - -.align 64 -.global memory_map -memory_map: -.skip 16 * 16 .section .text .global _start @@ -152,13 +139,22 @@ _start: sub $BASE_DIFF, %eax push %eax + # Push ending physical address to map + mov (%ebx), %eax + add %ebx, %eax + push %eax + + # Push starting physical address to map + mov $PHYSICAL_BASE, %eax + push %eax + # Load physical address of startPaging() mov $start_paging, %eax sub $BASE_DIFF, %eax # Initialize paging call *%eax - + # Jump into mapped kernel binary lea 1f, %eax jmp *%eax @@ -173,7 +169,7 @@ _start: # Change EBX to point to the virtual address of the multiboot info # If the new pointer is out-of-bounds, error - add $0xFF800000, %ebx + add $0xFF700000, %ebx cmp $0xFF800000, %ebx jl .err cmp $0xFFC00000, %ebx diff --git a/src/x86/linker.ld b/src/x86/linker.ld index bf01f37..f13451d 100755 --- a/src/x86/linker.ld +++ b/src/x86/linker.ld @@ -2,7 +2,7 @@ ENTRY(_start) SECTIONS { - . = 0xFF900000; + . = 0xFF800000; VIRTUAL_BASE = .; PHYSICAL_BASE = 0x100000; BASE_DIFF = VIRTUAL_BASE - PHYSICAL_BASE; @@ -34,9 +34,8 @@ SECTIONS BSS_END = ADDR(.bss) + SIZEOF(.bss) - (VIRTUAL_BASE - PHYSICAL_BASE); IMAGE_SIZE = ((BSS_END - LOAD_START) + (4096 - ((BSS_END - LOAD_START) % 4096))) / 4096; - _pageMapLocation = 0xFF800000; - _heapLocation = 0xFFB00000; - _heapSize = 0x100000; - _kernelStart = VIRTUAL_BASE; + _kernel_pstart = PHYSICAL_BASE; + _kernel_pend = PHYSICAL_BASE + (4096 * IMAGE_SIZE); + _kernel_start = VIRTUAL_BASE; _kernel_end = VIRTUAL_BASE + (4096 * IMAGE_SIZE); } diff --git a/src/x86/mmgr.c b/src/x86/mmgr.c index c4edb6a..572abc2 100644 --- a/src/x86/mmgr.c +++ b/src/x86/mmgr.c @@ -28,6 +28,34 @@ struct page_table_entry_t *page_tables = (struct page_table_entry_t *)0xFFC00000 struct page_table_entry_t *page_directory = (struct page_table_entry_t *)0xFFFFF000; +int start_paging(physaddr_t start, physaddr_t end, uint32_t *directory, uint32_t *table, uint32_t *identity_table) +{ + physaddr_t p = start; + size_t count = 0; + while(p < end) + { + uint32_t table_entry = p + 3; + int index = p / page_size; + table[index - start / page_size] = table_entry; + identity_table[index] = table_entry; + p += page_size; + count++; + } + directory[0] = ((uint32_t)identity_table) + 3; + directory[1022] = ((uint32_t)table) + 3; + directory[1023] = ((uint32_t)directory) + 3; + asm("mov %0, %%cr3" + : + : "r"(directory)); + asm("mov %%cr0, %%eax \n" + "or $0x80010000, %%eax \n" + "mov %%eax, %%cr0" + : + : + : "eax"); + return count; +} + physaddr_t create_address_space(struct page_stack_t *page_stack) { physaddr_t table = reserve_page(page_stack); diff --git a/src/x86/multiboot2.c b/src/x86/multiboot2.c index c692b5f..c8fff69 100644 --- a/src/x86/multiboot2.c +++ b/src/x86/multiboot2.c @@ -36,10 +36,6 @@ void *read_multiboot_table(struct boot_info_t *boot_info, void *table) M_UNAVAILABLE); boot_info->module_count++; } - else - { - printf("WARNING: Too many modules, must skip one.\n"); - } break; case MB_BOOT_COMMAND: strcpy(boot_info->parameters, &((struct multiboot2_string_t*) table)->str); diff --git a/src/x86/putc.c b/src/x86/putc.c index 854751f..fad6f72 100644 --- a/src/x86/putc.c +++ b/src/x86/putc.c @@ -1,4 +1,6 @@ #include "stdio.h" +#include "mmgr.h" +#include "allocator.h" #include enum vga_color_t { @@ -28,12 +30,18 @@ struct cell_t char bg : 4; }; -struct cell_t *screen = (struct cell_t*)0xFF8B8000; +struct cell_t *screen = (struct cell_t*)NULL; size_t cursor = 0; const size_t tab_width = 4; const size_t line_width = 80; +int initialize_screen() +{ + screen = allocate_from_bottom(page_size); + map_page(NULL, screen, 0x000B8000, PAGE_RW); +} + int putchar(int c) { switch(c) diff --git a/src/x86/quark_x86.c b/src/x86/quark_x86.c index 31fb801..7f8d281 100644 --- a/src/x86/quark_x86.c +++ b/src/x86/quark_x86.c @@ -1,5 +1,7 @@ #include "kernel.h" #include "pageallocator.h" +#include "allocator.h" +#include "mmgr.h" #include "multiboot2.h" #include "memorymap.h" #include "apic.h" @@ -11,38 +13,18 @@ #include #include +extern int _kernel_pstart; +extern int _kernel_pend; +extern int _kernel_start; extern int _kernel_end; struct kernel_t kernel_state; -int start_paging(uint32_t *directory, uint32_t *table, uint32_t *identityTable) -{ - for (int i = 0; i < 1024; i++) - { - uint32_t pte = i * 4096 + 3; - table[i] = pte; - identityTable[i] = pte; - } - directory[0] = ((uint32_t)identityTable) + 3; - directory[1022] = ((uint32_t)table) + 3; - directory[1023] = ((uint32_t)directory) + 3; - asm("mov %0, %%cr3" - : - : "r"(directory)); - asm("mov %%cr0, %%eax \n" - "or $0x80010000, %%eax \n" - "mov %%eax, %%cr0" - : - : - : "eax"); - return 0; -} - int initialize(void *multiboot_info) { initialize_gdt(); initialize_idt(); - printf("***%s***\n", PACKAGE_STRING); + initialize_allocator(&_kernel_end, (void*)0xFFC00000); static struct page_stack_t page_stack; struct memory_region_t map_array[16]; char bootloader_name[64]; @@ -55,12 +37,19 @@ int initialize(void *multiboot_info) .array = map_array, .size = 0, .capacity = 16}}; + void *multiboot_end = multiboot_info + *(uint32_t*)multiboot_info; multiboot_info += 8; while (multiboot_info != NULL) { multiboot_info = read_multiboot_table(&boot_info, multiboot_info); } - insert_region(&boot_info.map, 0, 1 << 22, M_UNAVAILABLE); + insert_region(&boot_info.map, (physaddr_t)&_kernel_pstart, (physaddr_t)&_kernel_pend, M_UNAVAILABLE); + for(void *p = (void*)&_kernel_end; p < multiboot_end; p += page_size) + { + unmap_page(p); + } + initialize_screen(); + printf("***%s***\n", PACKAGE_STRING); printf("Type\t\tLocation\t\tSize\n"); for (size_t i = 0; i < boot_info.map.size && boot_info.map.array[i].size > 0; i++) { @@ -68,8 +57,8 @@ int initialize(void *multiboot_info) } page_stack.base_pointer = (physaddr_t*)0xFFC00000; page_stack.stack_pointer = (physaddr_t*)0xFFC00000; - page_stack.limit_pointer = (physaddr_t*)0xFF900000; - initialize_page_stack(&page_stack, &boot_info.map, 4096); + page_stack.limit_pointer = (physaddr_t*)0xFFC00000; + initialize_page_stack(&page_stack, &boot_info.map); apic_enable(page_stack); apic_registers->divide_config.value = APIC_DIVIDE_128; apic_registers->lvt_timer.vector = ISR_APIC_TIMER;