diff options
Diffstat (limited to 'kernel/paging.cpp')
-rw-r--r-- | kernel/paging.cpp | 72 |
1 files changed, 56 insertions, 16 deletions
diff --git a/kernel/paging.cpp b/kernel/paging.cpp index 8c27abc..17b61f4 100644 --- a/kernel/paging.cpp +++ b/kernel/paging.cpp @@ -10,9 +10,13 @@ extern "C" { namespace mercury::kernel::paging { static constexpr uint64_t kernel_vram_start = 0xffffffffc0000000; - static constexpr uint64_t kernel_vram_pages = 261888; - static constexpr uint64_t kernel_stack_bottom = 0xfffffffffff01000; - static constexpr uint64_t kernel_stack_top = 0xfffffffffffff000; + static constexpr uint64_t kernel_vram_end = 0xffffffffffe00000; + static constexpr uint64_t kernel_vram_pages = + (kernel_vram_end - kernel_vram_start) / 4096; + static constexpr uint64_t syscall_stack_bottom = 0xfffffffffff01000; + static constexpr uint64_t syscall_stack_top = 0xfffffffffffff000; + static constexpr uint64_t interrupt_stack_bottom = 0xffffffffffe01000; + static constexpr uint64_t interrupt_stack_top = 0xffffffffffeff000; static constexpr uint64_t pram_pages = 1 << 23; static uint64_t pram_usage_bitmap[pram_pages / 64]; @@ -32,25 +36,29 @@ namespace mercury::kernel::paging { [[gnu::aligned(4096)]] uint64_t kernel_p2[512]; [[gnu::aligned(4096)]] uint64_t kernel_p1s[512 * 512]; - static uint64_t encode_pte( - uint64_t addr, bool user, bool write, bool execute) { + uint64_t kernel_p4e; + + uint64_t encode_pte( + uint64_t addr, bool user, bool write, bool execute, bool ps + ) { return (addr & 0x0000ffffffffffff) | (execute ? 0 : (1ULL << 63)) - | (user << 2) | (write << 1) | 1; + | (ps << 7) | (user << 2) | (write << 1) | 1; } void init_kernel_page_tables(uint64_t kernel_offset) { __kernel_p4_paddr = (uint64_t)kernel_p4 - kernel_offset; for (int i = 0; i < 511; ++i) kernel_p4[i] = 0; - kernel_p4[511] = encode_pte( - (uint64_t)kernel_p3 - kernel_offset, false, true, true); + kernel_p4e = encode_pte( + (uint64_t)kernel_p3 - kernel_offset, false, true, true, false); + kernel_p4[511] = kernel_p4e; for (int i = 0; i < 511; ++i) kernel_p3[i] = 0; kernel_p3[511] = encode_pte( - (uint64_t)kernel_p2 - kernel_offset, false, true, true); + (uint64_t)kernel_p2 - kernel_offset, false, true, true, false); for (int i = 0; i < 512; ++i) kernel_p2[i] = encode_pte( - (uint64_t)kernel_p1s + 4096 * i - kernel_offset, false, true, true); + (uint64_t)kernel_p1s + 4096 * i - kernel_offset, false, true, true, false); for (int i = 0; i < 512 * 512; ++i) kernel_p1s[i] = 0; } @@ -58,14 +66,22 @@ namespace mercury::kernel::paging { void map_kernel_page( uint64_t paddr, uint64_t vaddr, bool write, bool execute) { uint64_t i = (vaddr - kernel_vram_start) / 4096; - kernel_p1s[i] = encode_pte(paddr, false, write, execute); + kernel_p1s[i] = encode_pte(paddr, false, write, execute, false); + } + + void unmap_kernel_page(uint64_t vaddr) { + uint64_t i = (vaddr - kernel_vram_start) / 4096; + kernel_p1s[i] = 0; + asm volatile ( + "mov %%cr3, %%rax\nmov %%rax, %%cr3" ::: "%rax" + ); } static uint64_t take_pram_page() { for (uint64_t i = 0; i < pram_pages / 64; ++i) - if (pram_usage_bitmap[i] != 0xffffffffffffffff) + if (~pram_usage_bitmap[i] != 0) for (int j = 0; j < 64; ++j) - if (!(pram_usage_bitmap[i] & (1ULL << j))) { + if (~pram_usage_bitmap[i] & (1ULL << j)) { pram_usage_bitmap[i] |= (1ULL << j); return 4096 * (i * 64 + j); } @@ -73,9 +89,27 @@ namespace mercury::kernel::paging { return 0; } - void map_kernel_stack() { - for (uint64_t vaddr = kernel_stack_bottom; - vaddr < kernel_stack_top; vaddr += 4096) + uint64_t take_2mib_pram_page() { + for (uint64_t i = 0; i < pram_pages / 512; ++i) { + for (int j = 0; j < 8; ++j) + if (pram_usage_bitmap[i * 8 + j] != 0) + goto next_i; + for (int j = 0; j < 8; ++j) + pram_usage_bitmap[i * 8 + j] = ~0ULL; + return 0x200000 * i; + next_i: + ; + } + //TODO: handle error + return 0; + } + + void map_kernel_stacks() { + for (uint64_t vaddr = syscall_stack_bottom; + vaddr < syscall_stack_top; vaddr += 4096) + map_kernel_page(take_pram_page(), vaddr, true, false); + for (uint64_t vaddr = interrupt_stack_bottom; + vaddr < interrupt_stack_top; vaddr += 4096) map_kernel_page(take_pram_page(), vaddr, true, false); } @@ -103,6 +137,12 @@ namespace mercury::kernel::paging { return (void *)vaddr; } + void map_new_kernel_page(uint64_t &vaddr_out, uint64_t &paddr_out) { + vaddr_out = find_unmapped_vram_region(1); + paddr_out = take_pram_page(); + map_kernel_page(paddr_out, vaddr_out, true, false); + } + uint64_t get_used_vram_page_count() { uint64_t count = 0; for (uint64_t i = 0; i < kernel_vram_pages; ++i) |