diff options
Diffstat (limited to 'src/vmm.cc')
-rw-r--r-- | src/vmm.cc | 50 |
1 files changed, 50 insertions, 0 deletions
@@ -1,3 +1,4 @@ +#include "vmm.h" #include <stdlib.h> typedef void (*constructor)(); @@ -47,3 +48,52 @@ void dump_address() { " end: ", uhex{reinterpret_cast<uint32_t>(&end_bss)}, '\n'); } } // extern "C" + +/* boot.S page directory and kernel page table */ +extern uint32_t kernel_pagedir; +extern uint32_t kernel_ptable0; + +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'); + } +} + +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; + + const auto table = table_id(dest); + const auto page = page_id(dest - table * 4 * 1024 * 1024); + + printk("phys_addr page: ", uhex{phys_page}, '\n'); + printk(" offset: ", uhex{phys_offset}, '\n'); + printk(" table: ", table, '\n'); + printk(" page: ", page, '\n'); + + if (directory[table] == 0) return 0; + + 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; + + uint32_t cr0; + asm volatile("mov %%cr0, %0" : "=r"(cr0)); + asm volatile("mov %0, %%cr0" : : "r"(cr0)); + + return table * 4 * 1024 * 1024 + page * 4 * 1024 + phys_offset; +} |