diff options
Diffstat (limited to 'src/vmm.cc')
-rw-r--r-- | src/vmm.cc | 65 |
1 files changed, 27 insertions, 38 deletions
@@ -1,5 +1,4 @@ #include "vmm.h" -#include <stdlib.h> typedef void (*constructor)(); @@ -49,51 +48,41 @@ void dump_address() { } } // extern "C" -/* boot.S page directory and kernel page table */ +/* boot.S externs */ extern uint32_t kernel_pagedir; extern uint32_t kernel_ptable0; +extern uint32_t VADDR_OFFSET; -constexpr uint32_t to_vma(uint32_t page_dir_address) { - page_dir_address &= 0xfffff000; - page_dir_address += 0xc0000000; - page_dir_address -= 0x00400000; - return page_dir_address; -} - -vmm::vmm(uint32_t* addr) : directory{(addr == nullptr) ? &kernel_pagedir : addr} { - printk("page directory is at ", uhex{reinterpret_cast<uint32_t>(directory)}, '\n'); - printk("page table 768 ", uhex{reinterpret_cast<uint32_t>(directory[768])}, '\n'); - printk("page table 768 vma ", uhex{to_vma(reinterpret_cast<uint32_t>(directory[768]))}, '\n'); - printk("kernel_ptable0 is at ", uhex{reinterpret_cast<uint32_t>(&kernel_ptable0)}, '\n'); - - uint32_t* page = reinterpret_cast<uint32_t*>(&kernel_ptable0); - for (size_t i = 0; i < 32; ++i) { - printk(uhex{page[i] & 0xfffff000}, ' '); - if (i % 4 == 3) printk('\n'); - } -} +/* 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); -uint32_t vmm::map(uint32_t phys_addr, uint32_t dest) { - const auto phys_offset = phys_addr % 4096; - const auto phys_page = phys_addr - phys_offset; +vmm::vmm(uint32_t* addr) : directory{(addr == nullptr) ? &kernel_pagedir : addr} {} - const auto table = table_id(dest); - const auto page = page_id(dest - table * 4 * 1024 * 1024); +Result<uint32_t, vmm::Error> vmm::map(uint32_t addr, const vmm::address dest) { + const auto phys_offset = addr % 4096; + const auto phys_paddr = addr & 0xfffff000; - printk("phys_addr page: ", uhex{phys_page}, '\n'); - printk(" offset: ", uhex{phys_offset}, '\n'); - printk(" table: ", table, '\n'); - printk(" page: ", page, '\n'); + // TODO allocate page table + if (directory[dest.table_idx] == 0) return Result<uint32_t, vmm::Error>{vmm::TableNotAllocated}; - if (directory[table] == 0) return 0; + page_table table{directory[dest.table_idx]}; - uint32_t* page_table = reinterpret_cast<uint32_t*>(to_vma(reinterpret_cast<uint32_t>(directory[table]))); - if (page_table[page] != 0) return 0; - page_table[page] = phys_page | 0x003; + if (table.set(dest.page_idx, phys_paddr)) { + vmm::reload(); + return Result<uint32_t, vmm::Error>{dest + phys_offset}; + } else + return Result<uint32_t, vmm::Error>{vmm::AddressAlreadyMapped}; +} - uint32_t cr0; - asm volatile("mov %%cr0, %0" : "=r"(cr0)); - asm volatile("mov %0, %%cr0" : : "r"(cr0)); +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<uint32_t>(&VADDR_OFFSET); - return table * 4 * 1024 * 1024 + page * 4 * 1024 + phys_offset; + pages = reinterpret_cast<uint32_t*>(from); } |