From 1b65136a11453fe7e89320dfe6170a0cd75e60dd Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 24 Jul 2025 16:33:10 +0000 Subject: x86_64: clean up hw details --- arch/x86_64/CMakeLists.txt | 4 ++ arch/x86_64/include/arch/boot/pointers.hpp | 15 ----- .../include/arch/kernel/cpu/control_register.hpp | 71 --------------------- arch/x86_64/include/arch/kernel/cpu/tlb.hpp | 27 -------- arch/x86_64/include/x86_64/cpu/registers.hpp | 72 ++++++++++++++++++++++ arch/x86_64/include/x86_64/memory/mmu.hpp | 27 ++++++++ arch/x86_64/src/cpu/registers.cpp | 64 +++++++++++++++++++ arch/x86_64/src/kernel/cpu/control_register.cpp | 66 -------------------- arch/x86_64/src/kernel/cpu/tlb.cpp | 16 ----- arch/x86_64/src/memory/mmu.cpp | 17 +++++ 10 files changed, 184 insertions(+), 195 deletions(-) delete mode 100644 arch/x86_64/include/arch/boot/pointers.hpp delete mode 100644 arch/x86_64/include/arch/kernel/cpu/control_register.hpp delete mode 100644 arch/x86_64/include/arch/kernel/cpu/tlb.hpp create mode 100644 arch/x86_64/include/x86_64/cpu/registers.hpp create mode 100644 arch/x86_64/include/x86_64/memory/mmu.hpp create mode 100644 arch/x86_64/src/cpu/registers.cpp delete mode 100644 arch/x86_64/src/kernel/cpu/control_register.cpp delete mode 100644 arch/x86_64/src/kernel/cpu/tlb.cpp create mode 100644 arch/x86_64/src/memory/mmu.cpp diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index ddc2d46..c585cbf 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -22,7 +22,11 @@ target_sources("x86_64" PRIVATE "src/boot/initialize_runtime.cpp" "src/boot/multiboot.s" + # CPU intrinsics + "src/cpu/registers.cpp" + # Memory management + "src/memory/mmu.cpp" "src/memory/region_allocator.cpp" # VGA text mode diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp deleted file mode 100644 index fe9c657..0000000 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP -#define TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP - -#include - -namespace teachos::arch::boot -{ - /** - * @brief Address pointing to the start of the multiboot information structure. - */ - extern "C" size_t const multiboot_information_pointer; - -} // namespace teachos::arch::boot - -#endif // TEACHOS_ARCH_X86_64_BOOT_POINTERS_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/control_register.hpp b/arch/x86_64/include/arch/kernel/cpu/control_register.hpp deleted file mode 100644 index dcaf02d..0000000 --- a/arch/x86_64/include/arch/kernel/cpu/control_register.hpp +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_CR3_HPP -#define TEACHOS_ARCH_X86_64_KERNEL_CPU_CR3_HPP - -#include - -namespace teachos::arch::kernel::cpu -{ - /** - * @brief Control registers that can be read and written to. - * - * @note CR1 and CR5 - 7 are reserved and will throw an exception if they are accessed, therefore they are not defined - * in the enum. See https://en.wikipedia.org/wiki/Control_register#Control_registers_in_Intel_x86_series for more - * information. - */ - enum struct control_register : uint8_t - { - CR0, ///< Contains various control flags that modify basic operation of the processor, Machine Status World (MSW) - ///< register. - CR2 = 2U, ///< Contains Page Fault Linear Address (PFLA), when page fault occurs address program attended to accces - ///< is stored here. - CR3, ///< Enables process to translate linear addresses into physical addresses using paging, CR0 bit 32 Paging - ///< (PG) needs to be enabled simply contains the register value that represents the physical address of the - ///< level 4 page table used for paging in the system. Therefore reading this value allows to access the level - ///< 4 page table directly. Instead of over the virtual address 0xffffffff'fffff000, which then has to be - ///< first translated into a physical address. - CR4 ///< Used in protected mode to control operations. - }; - - /** - * @brief Control register 0 flags that can be set. - * - * @note Modifies the basic operation of the processor. Only the most important extensions are listed below, the rest - * are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#CR0 for more information. - */ - enum struct cr0_flags : uint64_t - { - PROTECTED_MODE_ENABLED = 1U << 0U, ///< System is in protected or system is in real mode. - TASK_SWITCHED = 1U << 3U, ///< Allows saving x87 task context upon a task switch only after x87 instruction used. - WRITE_PROTECT = 1U << 16U, ///< When set, the CPU cannot write to read-only pages when privilege level is 0. - PAGING = 1U << 31U, // Enable paging using the CR3 register. - }; - - /** - * @brief Reads the value of the given control register. - * - * @param cr Control register that should be read. - * @return Value of the control register. - */ - auto read_control_register(control_register cr) -> uint64_t; - - /** - * @brief Sets a specific bit in the Extended Feature Enable Register (EFER) Model-Specific Register (MSR) register. - * - * @param cr Control register that should be written. - * @param new_value New value that should be written. - */ - auto write_control_register(control_register cr, uint64_t new_value) -> void; - - /** - * @brief Sets a specific bit in the CR0. - * - * @note This function reads the current value of the CR0 register, ORs the specified - * bit with the current value, and writes the updated value back to the CR0. - * - * @param flag he flag to set in the CR0. - */ - auto set_cr0_bit(cr0_flags flag) -> void; - -} // namespace teachos::arch::kernel::cpu - -#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_CR3_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/tlb.hpp b/arch/x86_64/include/arch/kernel/cpu/tlb.hpp deleted file mode 100644 index f3e58a6..0000000 --- a/arch/x86_64/include/arch/kernel/cpu/tlb.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_TLB_HPP -#define TEACHOS_ARCH_X86_64_KERNEL_CPU_TLB_HPP - -#include "arch/memory/paging/virtual_page.hpp" - -namespace teachos::arch::kernel::cpu -{ - /** - * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained - * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. - * - * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for - * that page. - */ - auto tlb_flush(memory::paging::virtual_address address) -> void; - - /** - * @brief Invalidates the translation lookaside buffer (TLB) entry for all page tables. - * - * @note Simply reassigns the CR3 register the value of the CR3 register, causing a flush of the TLB buffer, because - * the system has to assume that the location of the level 4 page table moved. - */ - auto tlb_flush_all() -> void; - -} // namespace teachos::arch::kernel::cpu - -#endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_TLB_HPP diff --git a/arch/x86_64/include/x86_64/cpu/registers.hpp b/arch/x86_64/include/x86_64/cpu/registers.hpp new file mode 100644 index 0000000..607d559 --- /dev/null +++ b/arch/x86_64/include/x86_64/cpu/registers.hpp @@ -0,0 +1,72 @@ +#ifndef TEACHOS_X86_64_CPU_REGISTERS_HPP +#define TEACHOS_X86_64_CPU_REGISTERS_HPP + +#include + +namespace teachos::x86_64::cpu +{ + + /** + * @brief Control registers that can be read and written to. + * + * @note CR1 and CR5 - 7 are reserved and will throw an exception if they are accessed, therefore they are not defined + * in the enum. See https://en.wikipedia.org/wiki/Control_register#Control_registers_in_Intel_x86_series for more + * information. + */ + enum struct control_register : uint8_t + { + cr0, ///< Contains various control flags that modify basic operation of the processor, Machine Status World (MSW) + ///< register. + cr2 = 2U, ///< Contains Page Fault Linear Address (PFLA), when page fault occurs address program attended to accces + ///< is stored here. + cr3, ///< Enables process to translate linear addresses into physical addresses using paging, CR0 bit 32 Paging + ///< (PG) needs to be enabled simply contains the register value that represents the physical address of the + ///< level 4 page table used for paging in the system. Therefore reading this value allows to access the level + ///< 4 page table directly. Instead of over the virtual address 0xffffffff'fffff000, which then has to be + ///< first translated into a physical address. + cr4 ///< Used in protected mode to control operations. + }; + + /** + * @brief Control register 0 flags that can be set. + * + * @note Modifies the basic operation of the processor. Only the most important extensions are listed below, the rest + * are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#CR0 for more information. + */ + enum struct cr0_flags : uint64_t + { + PROTECTED_MODE_ENABLED = 1U << 0U, ///< System is in protected or system is in real mode. + TASK_SWITCHED = 1U << 3U, ///< Allows saving x87 task context upon a task switch only after x87 instruction used. + WRITE_PROTECT = 1U << 16U, ///< When set, the CPU cannot write to read-only pages when privilege level is 0. + PAGING = 1U << 31U, // Enable paging using the CR3 register. + }; + + /** + * @brief Reads the value of the given control register. + * + * @param cr Control register that should be read. + * @return Value of the control register. + */ + auto read_control_register(control_register cr) -> uint64_t; + + /** + * @brief Sets a specific bit in the Extended Feature Enable Register (EFER) Model-Specific Register (MSR) register. + * + * @param cr Control register that should be written. + * @param new_value New value that should be written. + */ + auto write_control_register(control_register cr, uint64_t new_value) -> void; + + /** + * @brief Sets a specific bit in the CR0. + * + * @note This function reads the current value of the CR0 register, ORs the specified + * bit with the current value, and writes the updated value back to the CR0. + * + * @param flag he flag to set in the CR0. + */ + auto set_cr0_bit(cr0_flags flag) -> void; + +} // namespace teachos::x86_64::cpu + +#endif \ No newline at end of file diff --git a/arch/x86_64/include/x86_64/memory/mmu.hpp b/arch/x86_64/include/x86_64/memory/mmu.hpp new file mode 100644 index 0000000..b03ffa2 --- /dev/null +++ b/arch/x86_64/include/x86_64/memory/mmu.hpp @@ -0,0 +1,27 @@ +#ifndef TEACHOS_X86_64_MEMORY_MMU_HPP +#define TEACHOS_X86_64_MEMORY_MMU_HPP + +#include "x86_64/memory/address.hpp" + +namespace teachos::x86_64::memory +{ + /** + * @brief Invalidates any translation lookaside buffer (TLB) entry for the page table the given address is cotained + * in. See https://www.felixcloutier.com/x86/invlpg for more information on the used x86 instruction. + * + * @param address Memory address, which will be used to determine the contained page and flush the TLB entry for + * that page. + */ + auto tlb_flush(linear_address address) -> void; + + /** + * @brief Invalidates the translation lookaside buffer (TLB) entry for all page tables. + * + * @note Simply reassigns the CR3 register the value of the CR3 register, causing a flush of the TLB buffer, because + * the system has to assume that the location of the level 4 page table moved. + */ + auto tlb_flush_all() -> void; + +} // namespace teachos::x86_64::memory + +#endif \ No newline at end of file diff --git a/arch/x86_64/src/cpu/registers.cpp b/arch/x86_64/src/cpu/registers.cpp new file mode 100644 index 0000000..7ade98d --- /dev/null +++ b/arch/x86_64/src/cpu/registers.cpp @@ -0,0 +1,64 @@ +#include "x86_64/cpu/registers.hpp" + +#include + +namespace teachos::x86_64::cpu +{ + auto read_control_register(control_register cr) -> uint64_t + { + uint64_t current_value; + switch (cr) + { + case control_register::cr0: + asm volatile("mov %%cr0, %[output]" : [output] "=r"(current_value)); + break; + case control_register::cr2: + asm volatile("mov %%cr2, %[output]" : [output] "=r"(current_value)); + break; + case control_register::cr3: + asm volatile("mov %%cr3, %[output]" : [output] "=r"(current_value)); + break; + case control_register::cr4: + asm volatile("mov %%cr4, %[output]" : [output] "=r"(current_value)); + break; + } + return current_value; + } + + auto write_control_register(control_register cr, uint64_t new_value) -> void + { + switch (cr) + { + case control_register::cr0: + asm volatile("mov %[input], %%cr0" + : /* no output from call */ + : [input] "r"(new_value) + : "memory"); + break; + case control_register::cr2: + asm volatile("mov %[input], %%cr2" + : /* no output from call */ + : [input] "r"(new_value) + : "memory"); + break; + case control_register::cr3: + asm volatile("mov %[input], %%cr3" + : /* no output from call */ + : [input] "r"(new_value) + : "memory"); + break; + case control_register::cr4: + asm volatile("mov %[input], %%cr4" + : /* no output from call */ + : [input] "r"(new_value) + : "memory"); + break; + } + } + + auto set_cr0_bit(cr0_flags flag) -> void + { + auto const cr0 = read_control_register(control_register::cr0); + write_control_register(control_register::cr0, static_cast::type>(flag) | cr0); + } +} // namespace teachos::x86_64::cpu diff --git a/arch/x86_64/src/kernel/cpu/control_register.cpp b/arch/x86_64/src/kernel/cpu/control_register.cpp deleted file mode 100644 index 41b8cd7..0000000 --- a/arch/x86_64/src/kernel/cpu/control_register.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "arch/kernel/cpu/control_register.hpp" - -#include "arch/exception_handling/panic.hpp" - -#include - -namespace teachos::arch::kernel::cpu -{ - auto read_control_register(control_register cr) -> uint64_t - { - uint64_t current_value; - switch (cr) - { - case control_register::CR0: - asm volatile("mov %%cr0, %[output]" : [output] "=r"(current_value)); - break; - case control_register::CR2: - asm volatile("mov %%cr2, %[output]" : [output] "=r"(current_value)); - break; - case control_register::CR3: - asm volatile("mov %%cr3, %[output]" : [output] "=r"(current_value)); - break; - case control_register::CR4: - asm volatile("mov %%cr4, %[output]" : [output] "=r"(current_value)); - break; - } - return current_value; - } - - auto write_control_register(control_register cr, uint64_t new_value) -> void - { - switch (cr) - { - case control_register::CR0: - asm volatile("mov %[input], %%cr0" - : /* no output from call */ - : [input] "r"(new_value) - : "memory"); - break; - case control_register::CR2: - asm volatile("mov %[input], %%cr2" - : /* no output from call */ - : [input] "r"(new_value) - : "memory"); - break; - case control_register::CR3: - asm volatile("mov %[input], %%cr3" - : /* no output from call */ - : [input] "r"(new_value) - : "memory"); - break; - case control_register::CR4: - asm volatile("mov %[input], %%cr4" - : /* no output from call */ - : [input] "r"(new_value) - : "memory"); - break; - } - } - - auto set_cr0_bit(cr0_flags flag) -> void - { - auto const cr0 = read_control_register(control_register::CR0); - write_control_register(control_register::CR0, static_cast::type>(flag) | cr0); - } -} // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/src/kernel/cpu/tlb.cpp b/arch/x86_64/src/kernel/cpu/tlb.cpp deleted file mode 100644 index a09001c..0000000 --- a/arch/x86_64/src/kernel/cpu/tlb.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "arch/kernel/cpu/tlb.hpp" - -#include "arch/kernel/cpu/control_register.hpp" - -namespace teachos::arch::kernel::cpu -{ - auto tlb_flush(memory::paging::virtual_address address) -> void - { - asm volatile("invlpg (%[input])" : /* no output from call */ : [input] "r"(address) : "memory"); - } - - auto tlb_flush_all() -> void - { - write_control_register(cpu::control_register::CR3, read_control_register(cpu::control_register::CR3)); - } -} // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/src/memory/mmu.cpp b/arch/x86_64/src/memory/mmu.cpp new file mode 100644 index 0000000..31783fe --- /dev/null +++ b/arch/x86_64/src/memory/mmu.cpp @@ -0,0 +1,17 @@ +#include "x86_64/memory/mmu.hpp" + +#include "x86_64/cpu/registers.hpp" + +namespace teachos::x86_64::memory +{ + auto tlb_flush(linear_address address) -> void + { + asm volatile("invlpg (%[input])" : /* no output from call */ : [input] "r"(address) : "memory"); + } + + auto tlb_flush_all() -> void + { + auto current_value = cpu::read_control_register(cpu::control_register::cr3); + cpu::write_control_register(cpu::control_register::cr3, current_value); + } +} // namespace teachos::x86_64::memory -- cgit v1.2.3