#include "vmm.h" typedef void (*constructor)(); extern "C" { /* .text */ uint32_t begin_text; uint32_t end_text; /* .rodata */ uint32_t begin_rodata; uint32_t end_rodata; /* .data */ uint32_t begin_constinit; uint32_t end_constinit; constructor begin_ctors; constructor end_ctors; uint32_t begin_data; uint32_t end_data; /* .bss */ uint32_t begin_bss; uint32_t end_bss; void kernel_constructors() { for (constructor* i = &begin_ctors; i != &end_ctors; ++i) (*i)(); } void dump_address() { printk("text begin: ", uhex{reinterpret_cast(&begin_text)}, " end: ", uhex{reinterpret_cast(&end_text)}, '\n'); printk("rodata begin: ", uhex{reinterpret_cast(&begin_rodata)}, " end: ", uhex{reinterpret_cast(&end_rodata)}, '\n'); printk("constinit begin: ", uhex{reinterpret_cast(&begin_constinit)}, " end: ", uhex{reinterpret_cast(&end_constinit)}, '\n'); printk("ctors begin: ", uhex{reinterpret_cast(&begin_ctors)}, " end: ", uhex{reinterpret_cast(&end_ctors)}, '\n'); printk("data begin: ", uhex{reinterpret_cast(&begin_data)}, " end: ", uhex{reinterpret_cast(&end_data)}, '\n'); printk("bss begin: ", uhex{reinterpret_cast(&begin_bss)}, " end: ", uhex{reinterpret_cast(&end_bss)}, '\n'); } } // extern "C" /* boot.S externs */ extern uint32_t kernel_pagedir; extern uint32_t kernel_ptable0; extern uint32_t VADDR_OFFSET; /* vmm */ static_assert(sizeof(vmm::address) == 4); static_assert(vmm::address(0xc03ff000) == 0xc03ff000); static_assert(vmm::address(0xc03ff000).table_idx == 768); static_assert(vmm::address(0xc03ff000).page_idx == 1023); static_assert(vmm::address(0xc03ff000).offset == 0); vmm::vmm(uint32_t* addr) : directory{(addr == nullptr) ? &kernel_pagedir : addr} {} Result vmm::map(uint32_t addr, const vmm::address dest) { const auto phys_offset = addr % 4096; const auto phys_paddr = addr & 0xfffff000; // TODO allocate page table if (directory[dest.table_idx] == 0) return Result{vmm::TableNotAllocated}; page_table table{directory[dest.table_idx]}; if (table.set(dest.page_idx, phys_paddr)) { vmm::reload(); return Result{dest + phys_offset}; } else return Result{vmm::AddressAlreadyMapped}; } void vmm::unmap(const address d) { if (directory[d.table_idx] == 0) return; page_table table{directory[d.table_idx]}; table.set(d.page_idx, 0); vmm::reload(); } vmm::page_table::page_table(uint32_t from) { // TODO get flags // convert physical address to a virtual address so we can read it from &= 0xfffff000; // discard flags from += reinterpret_cast(&VADDR_OFFSET); pages = reinterpret_cast(from); }