aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAqua-sama <aqua@iserlohn-fortress.net>2021-03-11 22:48:10 +0200
committerAqua-sama <aqua@iserlohn-fortress.net>2021-03-11 22:48:10 +0200
commit79e11fedd97325ba3dc7546373817b021edd89c7 (patch)
treeb291adc6891b8f51feb28db79c7c94acbee3d35a
parentMap kernel to 0xc000 rather than 0xc010 (diff)
downloadkernel.cpp-79e11fedd97325ba3dc7546373817b021edd89c7.tar.xz
vmm: map multiboot structs
-rw-r--r--src/boot.S24
-rw-r--r--src/kernel.cc9
-rw-r--r--src/kernel/dump_multiboot.cc2
-rw-r--r--src/vmm.cc50
-rw-r--r--src/vmm.h28
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<uint32_t*>(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 <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;
+}
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 <stdlib.h>
+
#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<size_t>(offset);
+ }
+ constexpr static size_t page_id(uint32_t offset) { return static_cast<size_t>(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);