aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatteo Gmür <matteo.gmuer1@ost.ch>2024-11-10 11:45:26 +0000
committerMatteo Gmür <matteo.gmuer1@ost.ch>2024-11-10 11:45:26 +0000
commit45e7b24f19b3c4557f98996a44d8857d750ca5b3 (patch)
treed51c14f091120b30d4354f6e0ab4aeef1b94bc7f
parent0a72135f4a43727b6ee8c9b6e3bbd24b395da638 (diff)
downloadteachos-45e7b24f19b3c4557f98996a44d8857d750ca5b3.tar.xz
teachos-45e7b24f19b3c4557f98996a44d8857d750ca5b3.zip
Adjust comments and constant
-rw-r--r--arch/x86_64/CMakeLists.txt2
-rw-r--r--arch/x86_64/include/arch/memory/cpu/control_register.hpp70
-rw-r--r--arch/x86_64/include/arch/memory/cpu/cr3.hpp27
-rw-r--r--arch/x86_64/include/arch/memory/cpu/msr.hpp47
-rw-r--r--arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp10
-rw-r--r--arch/x86_64/src/memory/cpu/control_register.cpp66
-rw-r--r--arch/x86_64/src/memory/cpu/cr3.cpp23
-rw-r--r--arch/x86_64/src/memory/cpu/msr.cpp18
-rw-r--r--arch/x86_64/src/memory/cpu/tlb.cpp7
9 files changed, 185 insertions, 85 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt
index 9fa8181..ee0141e 100644
--- a/arch/x86_64/CMakeLists.txt
+++ b/arch/x86_64/CMakeLists.txt
@@ -53,7 +53,7 @@ target_sources("_memory" PRIVATE
"src/memory/paging/active_page_table.cpp"
"src/memory/paging/inactive_page_table.cpp"
"src/memory/cpu/tlb.cpp"
- "src/memory/cpu/cr3.cpp"
+ "src/memory/cpu/control_register.cpp"
)
#[============================================================================[
diff --git a/arch/x86_64/include/arch/memory/cpu/control_register.hpp b/arch/x86_64/include/arch/memory/cpu/control_register.hpp
new file mode 100644
index 0000000..b48e48c
--- /dev/null
+++ b/arch/x86_64/include/arch/memory/cpu/control_register.hpp
@@ -0,0 +1,70 @@
+#ifndef TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP
+#define TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP
+
+#include <cstdint>
+
+namespace teachos::arch::memory::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 2 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 cr2_flags : uint32_t
+ {
+ PROTECTED_MODE_ENABLED = 1U << 0U, ///< System is in protected moe else 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.
+ *
+ * @note The cr3 register value 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.
+ *
+ * @return Physical address the level 4 page table is located at.
+ */
+
+ /**
+ * @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) -> std::size_t;
+
+ /**
+ * @brief Writes the given value into the given control 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, std::size_t new_value) -> void;
+} // namespace teachos::arch::memory::cpu
+
+#endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP
diff --git a/arch/x86_64/include/arch/memory/cpu/cr3.hpp b/arch/x86_64/include/arch/memory/cpu/cr3.hpp
deleted file mode 100644
index 51d5055..0000000
--- a/arch/x86_64/include/arch/memory/cpu/cr3.hpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP
-
-#include "arch/memory/allocator/physical_frame.hpp"
-
-namespace teachos::arch::memory::cpu
-{
- /**
- * @brief Reads the value of the cr3 register.
- *
- * @note The cr3 register value 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.
- *
- * @return Physical address the level 4 page table is located at.
- */
- auto read_cr3_register() -> allocator::physical_address;
-
- /**
- * @brief Writes the given value into the cr3 register.
- *
- * @param new_p4_table_address Physical address the newly kernel mapped level 4 page table is located at.
- */
- auto write_cr3_register(allocator::physical_address new_p4_table_address) -> void;
-} // namespace teachos::arch::memory::cpu
-
-#endif // TEACHOS_ARCH_X86_64_MEMORY_CPU_CR3_HPP
diff --git a/arch/x86_64/include/arch/memory/cpu/msr.hpp b/arch/x86_64/include/arch/memory/cpu/msr.hpp
index 662f3ac..1403995 100644
--- a/arch/x86_64/include/arch/memory/cpu/msr.hpp
+++ b/arch/x86_64/include/arch/memory/cpu/msr.hpp
@@ -6,63 +6,68 @@
namespace teachos::arch::memory::cpu
{
- constexpr uint32_t IA32_EFER = 0xC0000080;
-
- enum class msr_flags : uint64_t
+ /**
+ * @brief Important Flags that can be writen into the Extended Feature Enable Register (EFER).
+ *
+ * @note EFER is a model-specific register allowing to configure CPU extensions. Only the most important extensions
+ * are listed below, the rest are excluded for brevity. See https://en.wikipedia.org/wiki/Control_register#EFER for
+ * more information.
+ */
+ enum class efer_flags : uint64_t
{
- SCE = 1U << 0ULL, ///< System Call Extensions
- LME = 1U << 8ULL, ///< Long Mode Enabled
- LMA = 1U << 10ULL, ///< Long Mode Active
- NXE = 1U << 11ULL, ///< No-Execute Enable
- SVME = 1U << 12ULL, ///< Secure Virtual Machine Enable
- LMSLE = 1U << 13ULL, ///< Secure Virtual Machine Enable
- FFXSR = 1U << 14ULL, ///< fast FXSAVE/FXSTOR
- TCE = 1U << 15ULL, ///< Translation Cache Extension
+ SCE = 1UL << 0UL, ///< System Call Extensions
+ LME = 1UL << 8UL, ///< Long Mode Enabled
+ LMA = 1UL << 10UL, ///< Long Mode Active
+ NXE = 1UL << 11UL, ///< No-Execute Enable
+ SVME = 1UL << 12UL, ///< Secure Virtual Machine Enable
+ LMSLE = 1UL << 13UL, ///< Long Mode Segment Limit Enable
+ FFXSR = 1UL << 14UL, ///< Fast FXSAVE/FXSTOR
+ TCE = 1UL << 15UL, ///< Translation Cache Extension
};
/**
* @brief Reads a 64-bit Model-Specific Register (MSR).
*
- * This function reads the value of an MSR specified by the given address. It
+ * @note This function reads the value of an MSR specified by the given address. It
* combines the lower and upper 32-bits of the MSR value and returns it as a
* 64-bit unsigned integer.
*
* @param msr The address of the MSR to read.
* @return The 64-bit value read from the MSR.
*/
- uint64_t read_msr(uint32_t msr);
+ auto read_msr(uint32_t msr) -> void;
/**
* @brief Writes a 64-bit value to a Model-Specific Register (MSR).
*
- * This function writes a 64-bit value to the MSR specified by the given address.
+ * @note This function writes a 64-bit value to the MSR specified by the given address.
* It splits the 64-bit value into two 32-bit parts and writes them using the
* `wrmsr` instruction.
*
* @param msr The address of the MSR to write to.
- * @param value The 64-bit value to write to the MSR.
+ * @param new_value The 64-bit value to write to the MSR.
*/
- void write_msr(uint32_t msr, uint64_t value);
+ auto write_msr(uint32_t msr, uint64_t new_value) -> void;
/**
- * @brief Sets a specific bit in the MSR register.
+ * @brief Sets a specific bit in the Extended Feature Enable Register (EFER) Model-Specific Register (MSR) register.
*
- * This function reads the current value of the EFER register, ORs the specified
+ * @note This function reads the current value of the EFER register, ORs the specified
* bit with the current value, and writes the updated value back to the EFER register.
*
* @param flag The flag to set in the EFER register.
*/
- void set_msr_bit(msr_flags flag);
+ auto set_efer_bit(efer_flags flag) -> void;
/**
* @brief Enables the No-Execute Enable (NXE) bit in the Extended Feature Enable Register (EFER).
*
- * This function reads the current value of the EFER register, enables the NXE bit
+ * @note This function reads the current value of the EFER register, enables the NXE bit
* (bit 11), and writes the updated value back to the EFER register. Enabling the NXE
* bit allows the processor to support No-Execute memory regions, which are required
* for certain memory protection features like Data Execution Prevention (DEP).
*/
- void enable_nxe_bit();
+ auto enable_nxe_bit() -> void;
} // namespace teachos::arch::memory::cpu
diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp
index 5e51c64..53284b6 100644
--- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp
+++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp
@@ -1,7 +1,7 @@
#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP
#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP
-#include "arch/memory/cpu/cr3.hpp"
+#include "arch/memory/cpu/control_register.hpp"
#include "arch/memory/paging/active_page_table.hpp"
#include "arch/memory/paging/inactive_page_table.hpp"
#include "arch/memory/paging/temporary_page.hpp"
@@ -74,7 +74,8 @@ namespace teachos::arch::memory::paging
auto remap_elf_kernel_sections(inactive_page_table inactive_table, temporary_page & temporary_page,
active_page_table & active_table) -> void
{
- auto const backup = allocator::physical_frame::containing_address(cpu::read_cr3_register());
+ auto const backup =
+ allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3));
auto page_table_level4 = temporary_page.map_table_frame(backup, active_table);
active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE);
@@ -95,11 +96,12 @@ namespace teachos::arch::memory::paging
*/
auto switch_active_page_table(inactive_page_table new_table) -> inactive_page_table
{
- auto const backup = allocator::physical_frame::containing_address(cpu::read_cr3_register());
+ auto const backup =
+ allocator::physical_frame::containing_address(cpu::read_control_register(cpu::control_register::CR3));
auto const old_table = inactive_page_table{backup};
auto const new_address = new_table.page_table_level_4_frame.start_address();
- cpu::write_cr3_register(new_address);
+ cpu::write_control_register(cpu::control_register::CR3, new_address);
return old_table;
}
diff --git a/arch/x86_64/src/memory/cpu/control_register.cpp b/arch/x86_64/src/memory/cpu/control_register.cpp
new file mode 100644
index 0000000..38a887c
--- /dev/null
+++ b/arch/x86_64/src/memory/cpu/control_register.cpp
@@ -0,0 +1,66 @@
+#include "arch/memory/cpu/control_register.hpp"
+
+#include "arch/exception_handling/assert.hpp"
+
+namespace teachos::arch::memory::cpu
+{
+ auto read_control_register(control_register cr) -> std::size_t
+ {
+ std::size_t current_value;
+ switch (cr)
+ {
+ case control_register::CR0:
+ asm volatile("movq %%cr0, %[output]" : [output] "=r"(current_value));
+ break;
+ case control_register::CR2:
+ asm volatile("movq %%cr2, %[output]" : [output] "=r"(current_value));
+ break;
+ case control_register::CR3:
+ asm volatile("movq %%cr3, %[output]" : [output] "=r"(current_value));
+ break;
+ case control_register::CR4:
+ asm volatile("movq %%cr4, %[output]" : [output] "=r"(current_value));
+ break;
+ default:
+ exception_handling::assert(false,
+ "[Control Register] Attempted to read non-existent or reserved control register");
+ break;
+ }
+ return current_value;
+ }
+
+ auto write_control_register(control_register cr, std::size_t new_value) -> void
+ {
+ switch (cr)
+ {
+ case control_register::CR0:
+ asm volatile("movq %[input], %%cr0"
+ : /* no output from call */
+ : [input] "r"(new_value)
+ : "memory");
+ break;
+ case control_register::CR2:
+ asm volatile("movq %[input], %%cr2"
+ : /* no output from call */
+ : [input] "r"(new_value)
+ : "memory");
+ break;
+ case control_register::CR3:
+ asm volatile("movq %[input], %%cr3"
+ : /* no output from call */
+ : [input] "r"(new_value)
+ : "memory");
+ break;
+ case control_register::CR4:
+ asm volatile("movq %[input], %%cr4"
+ : /* no output from call */
+ : [input] "r"(new_value)
+ : "memory");
+ break;
+ default:
+ exception_handling::assert(false,
+ "[Control Register] Attempted to write non-existent or reserved control register");
+ break;
+ }
+ }
+} // namespace teachos::arch::memory::cpu
diff --git a/arch/x86_64/src/memory/cpu/cr3.cpp b/arch/x86_64/src/memory/cpu/cr3.cpp
deleted file mode 100644
index 7e48d40..0000000
--- a/arch/x86_64/src/memory/cpu/cr3.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "arch/memory/cpu/cr3.hpp"
-
-#include "arch/exception_handling/assert.hpp"
-
-namespace teachos::arch::memory::cpu
-{
- auto read_cr3_register() -> allocator::physical_address
- {
- allocator::physical_address cr3;
- asm volatile("movq %%cr3, %[output]" : [output] "=r"(cr3) : /* no input into call */ : "memory");
- return cr3;
- }
-
- auto write_cr3_register(allocator::physical_address new_p4_table_address) -> void
- {
- exception_handling::assert(new_p4_table_address % allocator::PAGE_FRAME_SIZE == 0U,
- "[CR3] Physical address to be written into register must be page aligned");
- asm volatile("movq %[input], %%cr3"
- : /* no output from call */
- : [input] "r"(new_p4_table_address)
- : "memory");
- }
-} // namespace teachos::arch::memory::cpu
diff --git a/arch/x86_64/src/memory/cpu/msr.cpp b/arch/x86_64/src/memory/cpu/msr.cpp
index 3a917c9..6e3d1d3 100644
--- a/arch/x86_64/src/memory/cpu/msr.cpp
+++ b/arch/x86_64/src/memory/cpu/msr.cpp
@@ -2,14 +2,19 @@
namespace teachos::arch::memory::cpu
{
- uint64_t read_msr(uint32_t msr)
+ namespace
+ {
+ constexpr uint32_t IA32_EFER_ADDRESS = 0xC0000080;
+ }
+
+ auto read_msr(uint32_t msr) -> uint64_t
{
uint32_t low, high;
asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
return (static_cast<uint64_t>(high) << 32) | low;
}
- void write_msr(uint32_t msr, uint64_t value)
+ auto write_msr(uint32_t msr, uint64_t value) -> void
{
uint32_t low = value & 0xFFFFFFFF;
uint32_t high = value >> 32;
@@ -18,12 +23,11 @@ namespace teachos::arch::memory::cpu
: "c"(msr), "a"(low), "d"(high));
}
- void set_msr_bit(msr_flags flag)
+ auto set_efer_bit(efer_flags flag) -> void
{
- uint64_t efer = read_msr(IA32_EFER);
- write_msr(IA32_EFER, static_cast<uint64_t>(flag) | efer);
+ uint64_t const efer = read_msr(IA32_EFER_ADDRESS);
+ write_msr(IA32_EFER_ADDRESS, static_cast<uint64_t>(flag) | efer);
}
- void enable_nxe_bit() { set_msr_bit(msr_flags::NXE); }
-
+ auto enable_nxe_bit() -> void { set_efer_bit(efer_flags::NXE); }
} // namespace teachos::arch::memory::cpu
diff --git a/arch/x86_64/src/memory/cpu/tlb.cpp b/arch/x86_64/src/memory/cpu/tlb.cpp
index 1663e80..591d9fc 100644
--- a/arch/x86_64/src/memory/cpu/tlb.cpp
+++ b/arch/x86_64/src/memory/cpu/tlb.cpp
@@ -1,6 +1,6 @@
#include "arch/memory/cpu/tlb.hpp"
-#include "arch/memory/cpu/cr3.hpp"
+#include "arch/memory/cpu/control_register.hpp"
namespace teachos::arch::memory::cpu
{
@@ -9,5 +9,8 @@ namespace teachos::arch::memory::cpu
asm volatile("invlpg (%[input])" : /* no output from call */ : [input] "r"(address) : "memory");
}
- auto tlb_flush_all() -> void { write_cr3_register(read_cr3_register()); }
+ auto tlb_flush_all() -> void
+ {
+ write_control_register(cpu::control_register::CR3, read_control_register(cpu::control_register::CR3));
+ }
} // namespace teachos::arch::memory::cpu