From 4440cd93ee5526ea09e501b073639d8eee8f1ccf Mon Sep 17 00:00:00 2001 From: "iliya.saroukha" <iliya.saroukhanian@etu.hesge.ch> Date: Tue, 22 Oct 2024 19:05:12 +0200 Subject: [PATCH] feat: paging seemingly fully working now --- kernel/mem/paging.c | 121 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 3 deletions(-) diff --git a/kernel/mem/paging.c b/kernel/mem/paging.c index c1ff3c5..5d0ac1d 100644 --- a/kernel/mem/paging.c +++ b/kernel/mem/paging.c @@ -1,7 +1,15 @@ #include "paging.h" +#include "boot/multiboot.h" +#include "boot/multiboot_structs.h" +#include "common/mem.h" +#include "common/types.h" +#include "drivers/display.h" #include "frame.h" #include "x86.h" +extern void ld_stack_start(); +uint_t stack_start = (uint_t)&ld_stack_start; + static PDE_t kernel_pagedir[PAGETABLES_IN_PD] __attribute__((aligned(PAGE_SIZE))); @@ -12,21 +20,128 @@ static PDE_t kernel_pagedir[PAGETABLES_IN_PD] // table if one was just allocated, otherwise returns 0. static PTE_t *mmap_page(PDE_t *pagedir, uint32_t virt_addr, uint32_t phys_addr, enum privilege_t privilege, enum access_t access) { - // TODO + uint_t pde_idx = ADDR_TO_PDE(virt_addr); + PTE_t *page_table = NULL; + + if (!pagedir[pde_idx].present) { + page_table = frame_alloc(); + + if (page_table == FRAME_ALLOC_ERR) { + return FRAME_ALLOC_ERR; + } + + pagedir[pde_idx].present = 1; + pagedir[pde_idx].rw = access; + pagedir[pde_idx].user = privilege; + pagedir[pde_idx].page_sz = 0; + pagedir[pde_idx].pagetable_frame_number = ADDR_TO_FRAME_NB(page_table); + + uint_t pte_idx = (virt_addr >> 12) & 0x3FF; + + page_table[pte_idx].present = 1; + page_table[pte_idx].user = privilege; + page_table[pte_idx].rw = access; + page_table[pte_idx].frame_number = ADDR_TO_FRAME_NB(phys_addr); + + return page_table; + } + + page_table = + (PTE_t *)FRAME_NB_TO_ADDR(pagedir[pde_idx].pagetable_frame_number); + + uint_t pte_idx = (virt_addr >> 12) & 0x3FF; + + page_table[pte_idx].present = 1; + page_table[pte_idx].user = privilege; + page_table[pte_idx].rw = access; + page_table[pte_idx].frame_number = ADDR_TO_FRAME_NB(phys_addr); + + return 0; } void paging_mmap(PDE_t *pagedir, uint32_t virt_addr, uint32_t phys_addr, uint32_t size, enum privilege_t privilege, enum access_t access) { - // TODO + struct terminal_t term; + + if (term_init(&term) != 0) { + return; + } + + uint_t va_aligned = ALIGN_TO_PAGE_SIZE(virt_addr); + uint_t pa_aligned = ALIGN_TO_PAGE_SIZE(phys_addr); + + uint_t end_addr = va_aligned + size; + // i actually hate myself for this `if` block, ugliest stuff ever + uint_t to_mmap; + if (end_addr < PAGE_SIZE) { + to_mmap = PAGE_SIZE; + } else { + to_mmap = ALIGN_TO_PAGE_SIZE(end_addr); + } + /*uint_t to_mmap = ALIGN_TO_PAGE_SIZE(va_aligned + size);*/ + + for (uint_t i = va_aligned, j = pa_aligned; i < to_mmap; + i += PAGE_SIZE, j += FRAME_SIZE) { + PTE_t *pt = mmap_page(pagedir, i, j, privilege, access); + + if (pt == FRAME_ALLOC_ERR) { + /*kprintf(&term,*/ + /* "New page table allocated at 0x%x pointing to 0x%x\n", + * pt,*/ + /* FRAME_NB_TO_ADDR(pt->frame_number));*/ + kprintf(&term, "Shit happened\n"); + } + } } static void unmap_page(PDE_t *pagedir, uint32_t virt_addr) { // TODO + uint_t pde_idx = ADDR_TO_PDE(virt_addr); + PDE_t *dir_entry = &pagedir[pde_idx]; + + PTE_t *page_table = + (PTE_t *)FRAME_NB_TO_ADDR(dir_entry->pagetable_frame_number); + + uint_t pte_idx = (virt_addr >> 12) & 0x3FF; + + frame_free((void *)FRAME_NB_TO_ADDR(page_table[pte_idx].frame_number)); + memset(&page_table[pte_idx], 0, sizeof(PTE_t)); + + for (uint_t i = 0; i < PAGES_IN_PT; i++) { + if (!is_frame_free(page_table[i].frame_number)) { + return; + } + } + + frame_free((void *)FRAME_NB_TO_ADDR(dir_entry->pagetable_frame_number)); + memset(dir_entry, 0, sizeof(PDE_t)); } void paging_init(uint_t RAM_in_KB) { - // TODO + if (!RAM_in_KB) { + return; + } + + paging_mmap(kernel_pagedir, 0, 0, RAM_in_KB * 1024, PRIVILEGE_KERNEL, + ACCESS_READWRITE); + + multiboot_info_t *mbi = multiboot_get_info(); + uint_t fb_size = mbi->framebuffer_pitch * + (mbi->framebuffer_height * (mbi->framebuffer_bpp / 8)); + + // Identity mapping of the framebuffer + paging_mmap(kernel_pagedir, mbi->framebuffer_addr, mbi->framebuffer_addr, + fb_size, PRIVILEGE_KERNEL, ACCESS_READWRITE); + + // Second mapping of the VBE framebuffer to VA 3GB (3 * (1 << 30)) + uint_t va_framebuffer = 3 * (1UL << 30); + paging_mmap(kernel_pagedir, va_framebuffer, mbi->framebuffer_addr, fb_size, + PRIVILEGE_KERNEL, ACCESS_READWRITE); + + unmap_page(kernel_pagedir, 0); + // unmapping the stack guard page + unmap_page(kernel_pagedir, stack_start); paging_load_pagedir(kernel_pagedir); paging_enable(); -- GitLab