From 79e11fedd97325ba3dc7546373817b021edd89c7 Mon Sep 17 00:00:00 2001 From: Aqua-sama Date: Thu, 11 Mar 2021 22:48:10 +0200 Subject: vmm: map multiboot structs --- src/boot.S | 24 +++++++++++---------- src/kernel.cc | 9 +++++++- src/kernel/dump_multiboot.cc | 2 -- src/vmm.cc | 50 ++++++++++++++++++++++++++++++++++++++++++++ src/vmm.h | 28 +++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 14 deletions(-) diff --git a/src/boot.S b/src/boot.S index 6588004..d1c4f9b 100644 --- a/src/boot.S +++ b/src/boot.S @@ -38,9 +38,11 @@ stack_top: .section .pages, "aw", @nobits .align 4096 -boot_page_directory: +.global kernel_pagedir +kernel_pagedir: .skip 1024 * 4 -boot_page_table1: +.global kernel_ptable0 +kernel_ptable0: .skip 1024 * 4 @@ -55,8 +57,8 @@ boot_page_table1: _start: cli - # Physical address of boot_page_table1. - movl $(boot_page_table1 - VADDR_OFFSET), %edi + # Physical address of kernel_ptable0. + movl $(kernel_ptable0 - VADDR_OFFSET), %edi # Only map the kernel. mov $_kernel_start - VADDR_OFFSET, %esi @@ -75,14 +77,14 @@ l_page_init: # Size of page is 4096 bytes. addl $4096, %esi - # Size of entries in boot_page_table1 is 4 bytes. + # Size of entries in kernel_ptable0 is 4 bytes. addl $4, %edi # Loop to the next entry if we haven't finished. loop l_page_init map_vga: # Map VGA video memory to 0xC03FF000 as "present, writable". - movl $(0x000B8000 | 0x003), boot_page_table1 - VADDR_OFFSET + 1023 * 4 + movl $(0x000B8000 | 0x003), kernel_ptable0 - VADDR_OFFSET + 1023 * 4 /* Enabling paging does not change the next instruction, which continues to be physical. Therefore, map the kernel @@ -91,11 +93,11 @@ map_vga: - entry 1 starts 0x0040 0000 ends 0x007f ffff - entry 768 starts 0xc000 0000 ends 0xc03f ffff */ - movl $(boot_page_table1 - VADDR_OFFSET + 0x003), boot_page_directory - VADDR_OFFSET + 1 * 4 - movl $(boot_page_table1 - VADDR_OFFSET + 0x003), boot_page_directory - VADDR_OFFSET + 768 * 4 + movl $(kernel_ptable0 - VADDR_OFFSET + 0x003), kernel_pagedir - VADDR_OFFSET + 1 * 4 + movl $(kernel_ptable0 - VADDR_OFFSET + 0x003), kernel_pagedir - VADDR_OFFSET + 768 * 4 - # Set cr3 to the address of the boot_page_directory. - movl $(boot_page_directory - VADDR_OFFSET), %ecx + # Set cr3 to the address of the kernel_pagedir. + movl $(kernel_pagedir - VADDR_OFFSET), %ecx movl %ecx, %cr3 # Enable paging and the write-protect bit. @@ -113,7 +115,7 @@ map_vga: kinit: # At this point, paging is fully set up and enabled. # Unmap the identity mapping as it is now unnecessary. - movl $0, boot_page_directory + 1 * 4 + movl $0, kernel_pagedir + 1 * 4 # Reload crc3 to force a TLB flush so the changes to take effect. movl %cr3, %ecx movl %ecx, %cr3 diff --git a/src/kernel.cc b/src/kernel.cc index b7aae2f..0915365 100644 --- a/src/kernel.cc +++ b/src/kernel.cc @@ -37,8 +37,15 @@ void kernel_main([[maybe_unused]] uint32_t mb_magic, [[maybe_unused]] uint32_t m printk("Hello, kernel World!\n"); dump_address(); - dump_multiboot(mb_magic, mb_addr); // dump_gdt(); + // + + vmm kvmm; + mb_addr = kvmm.map(mb_addr, 0xc03fe000); + + dump_multiboot(mb_magic, mb_addr); + // + // GDT gdt; IDT idt{gdt.descriptor(GDT::kcode)}; diff --git a/src/kernel/dump_multiboot.cc b/src/kernel/dump_multiboot.cc index 35c2874..f190cd3 100644 --- a/src/kernel/dump_multiboot.cc +++ b/src/kernel/dump_multiboot.cc @@ -5,8 +5,6 @@ extern "C" void dump_multiboot(uint32_t mb_magic, uint32_t mb_addr) { printk("multiboot magic: ", uhex{mb_magic}, mb_magic == MULTIBOOT2_BOOTLOADER_MAGIC ? " valid" : " invalid", '\n'); printk("multiboot addr: ", uhex{mb_addr}, !(mb_addr & 7) ? " is aligned" : " is not aligned", '\n'); - return; - struct multiboot_tag* tag; const uint32_t size = *reinterpret_cast(mb_addr); printk("Announced mbi size ", size, '\n'); diff --git a/src/vmm.cc b/src/vmm.cc index 346e6ab..483f02f 100644 --- a/src/vmm.cc +++ b/src/vmm.cc @@ -1,3 +1,4 @@ +#include "vmm.h" #include typedef void (*constructor)(); @@ -47,3 +48,52 @@ void dump_address() { " end: ", uhex{reinterpret_cast(&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(directory)}, '\n'); + printk("page table 768 ", uhex{reinterpret_cast(directory[768])}, '\n'); + printk("page table 768 vma ", uhex{to_vma(reinterpret_cast(directory[768]))}, '\n'); + printk("kernel_ptable0 is at ", uhex{reinterpret_cast(&kernel_ptable0)}, '\n'); + + uint32_t* page = reinterpret_cast(&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(to_vma(reinterpret_cast(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; +} diff --git a/src/vmm.h b/src/vmm.h index 45aa1e8..9de487b 100644 --- a/src/vmm.h +++ b/src/vmm.h @@ -1,3 +1,31 @@ +#include + #pragma once extern "C" void dump_address(); + +struct page_table { + uint32_t* addr; +}; + +class vmm { +public: + vmm(uint32_t* addr = nullptr); + + constexpr static size_t table_id(uint32_t offset) { + offset &= 0xfff00000; + offset /= (4 * 1024 * 1024); + return static_cast(offset); + } + constexpr static size_t page_id(uint32_t offset) { return static_cast(offset / 4096); } + + uint32_t map(uint32_t phys_addr, uint32_t offset); + +private: + uint32_t* directory; +}; + +static_assert(vmm::table_id(0x00001234) == 0); +static_assert(vmm::table_id(0x00400000) == 1); +static_assert(vmm::table_id(0xc0000000) == 768); +static_assert(vmm::table_id(0xc03ff000) == 768); -- cgit v1.2.1