aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2025-12-12 10:52:38 +0100
committerFelix Morgner <felix.morgner@ost.ch>2025-12-12 10:52:38 +0100
commit822b17b852cdc8933881132dd7b862ee74117973 (patch)
tree6c31e3cb9ad6d5c7523e49cc5d3daf41af381793
parent4bb59ebf68351754ab97e722914e0434c4d347fd (diff)
downloadteachos-822b17b852cdc8933881132dd7b862ee74117973.tar.xz
teachos-822b17b852cdc8933881132dd7b862ee74117973.zip
x86_64/cpu: update documentation and structure
-rw-r--r--.vscode/settings.json2
-rw-r--r--arch/x86_64/include/x86_64/cpu/impl/control_registers.hpp5
-rw-r--r--arch/x86_64/include/x86_64/cpu/impl/model_specific_register.hpp195
3 files changed, 129 insertions, 73 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index c0f3e5d..1bd7db0 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -25,6 +25,7 @@
"acpi",
"crtc",
"efer",
+ "initializable",
"interprocedural",
"invlpg",
"iwyu",
@@ -35,6 +36,7 @@
"nolintnextline",
"rdmsr",
"rvalues",
+ "sysret",
"teachos",
"wrmsr"
]
diff --git a/arch/x86_64/include/x86_64/cpu/impl/control_registers.hpp b/arch/x86_64/include/x86_64/cpu/impl/control_registers.hpp
index c2ad3e7..1f8c690 100644
--- a/arch/x86_64/include/x86_64/cpu/impl/control_registers.hpp
+++ b/arch/x86_64/include/x86_64/cpu/impl/control_registers.hpp
@@ -1,7 +1,7 @@
#ifndef TEACHOS_X86_64_CPU_IMPL_CONTROL_REGISTERS_HPP
#define TEACHOS_X86_64_CPU_IMPL_CONTROL_REGISTERS_HPP
-// IWYU pragma: private
+// IWYU pragma: private, include "x86_64/cpu/registers.hpp"
#include "kapi/memory/address.hpp"
@@ -77,8 +77,7 @@ namespace teachos::cpu::x86_64
//! A mixin for flag-oriented control registers.
//!
//! This mixin provides additional functionality for flag-oriented, or partially flag-oriented, control registers. A
- //! control register is flag-oriented, when it's comprises is a bitfield and zero or more additional non-bitfield
- //! parts.
+ //! control register is flag-oriented, if it comprises a bitfield and zero or more additional non-bitfield parts.
//!
//! @tparam Derived The class deriving from this mixin.
//! @tparam ValueType The value type of the class deriving from this mixin.
diff --git a/arch/x86_64/include/x86_64/cpu/impl/model_specific_register.hpp b/arch/x86_64/include/x86_64/cpu/impl/model_specific_register.hpp
index ff2c8ad..080b280 100644
--- a/arch/x86_64/include/x86_64/cpu/impl/model_specific_register.hpp
+++ b/arch/x86_64/include/x86_64/cpu/impl/model_specific_register.hpp
@@ -1,7 +1,7 @@
#ifndef TEACHOS_X86_64_CPU_IMPL_MODEL_SPECIFIC_REGISTER_HPP
#define TEACHOS_X86_64_CPU_IMPL_MODEL_SPECIFIC_REGISTER_HPP
-// IWYU pragma: private
+// IWYU pragma: private, include "x86_64/cpu/registers.hpp"
#include <kstd/ext/bitfield_enum>
@@ -11,75 +11,19 @@
namespace teachos::cpu::x86_64
{
- namespace impl
- {
- constexpr auto ia32_efer_number = 0xC000'0080u;
-
- template<typename Derived, typename ValueType, typename = void>
- struct model_specific_register_with_flags
- {
- };
-
- template<typename Derived, typename ValueType>
- struct model_specific_register_with_flags<Derived, ValueType, std::enable_if_t<std::is_enum_v<ValueType>>>
- {
- using flags = ValueType;
-
- auto static set(flags flag) -> void
- {
- auto current = Derived::read();
- current |= flag;
- Derived::write(current);
- }
-
- auto static clear(flags flag) -> void
- {
- auto current = Derived::read();
- current &= ~flag;
- Derived::write(current);
- }
-
- auto test(flags flag) -> void
- {
- return Derived::read() & flag;
- }
- };
-
- template<std::uint32_t Number, typename ValueType>
- struct model_specific_register
- : model_specific_register_with_flags<model_specific_register<Number, ValueType>, ValueType>
- {
- struct raw_value
- {
- std::uint32_t low_half;
- std::uint32_t high_half;
- };
-
- auto static read() -> ValueType
- {
- auto raw = raw_value{};
- asm volatile("rdmsr" : "=a"(raw.low_half), "=d"(raw.high_half) : "c"(Number));
- return static_cast<ValueType>(std::bit_cast<std::uint64_t>(raw));
- }
-
- auto static write(ValueType value) -> void
- {
- auto raw = std::bit_cast<raw_value>(static_cast<std::uint64_t>(value));
- asm volatile("wrmsr" : : "a"(raw.low_half), "d"(raw.high_half), "c"(Number));
- }
- };
- enum struct ia32_efer_flags : std::uint64_t
- {
- syscall_enable = 1uz << 0,
- ia32e_mode_enable = 1uz << 8,
- ia32e_mode_active = 1uz << 10,
- execute_disable_bit_enable = 1uz << 11,
- };
-
- } // namespace impl
-
- using i32_efer = impl::model_specific_register<impl::ia32_efer_number, impl::ia32_efer_flags>;
+ //! The flags of the IA32_EFER (Extended Features Enable Register) MSR.
+ enum struct ia32_efer_flags : std::uint64_t
+ {
+ //! Enable the syscall and sysret instructions.
+ syscall_enable = 1uz << 0,
+ //! Enable IA-32e mode operation.
+ ia32e_mode_enable = 1uz << 8,
+ //! Indicates IA-32e mode is active (read-only)
+ ia32e_mode_active = 1uz << 10,
+ //! Enable the use of the NX page table bit.
+ execute_disable_bit_enable = 1uz << 11,
+ };
} // namespace teachos::cpu::x86_64
@@ -87,10 +31,121 @@ namespace kstd::ext
{
template<>
- struct is_bitfield_enum<teachos::cpu::x86_64::impl::ia32_efer_flags> : std::true_type
+ struct is_bitfield_enum<teachos::cpu::x86_64::ia32_efer_flags> : std::true_type
{
};
} // namespace kstd::ext
+namespace teachos::cpu::x86_64
+{
+ //! The MSR number for the IA32_EFER MSR
+ constexpr auto ia32_efer_number = 0xC000'0080u;
+
+ //! A mixin for flag-oriented model specific registers.
+ //!
+ //! This mixin provides additional functionality for a flag-oriented model specific register. A models specific
+ //! register is flag-oriented, if it comprises a single field of bitfield.
+ //!
+ //! @tparam Derived The class deriving from this mixin.
+ //! @tparam ValueType The value type of the class deriving from this mixin.
+ template<typename Derived, typename ValueType, typename = void>
+ struct model_specific_register_with_flags
+ {
+ };
+
+ //! @copydoc model_specific_register_with_flags
+ //!
+ //! @note This specialization provides the implementation for the case in which the value type of the model specific
+ //! register is a bitfield enum.
+ template<typename Derived, typename ValueType>
+ struct model_specific_register_with_flags<Derived, ValueType, std::enable_if_t<kstd::ext::bitfield_enum<ValueType>>>
+ {
+ //! The of the flags used by this model specific register.
+ using flags = ValueType;
+
+ //! Set one or more flags in this model specific register.
+ //!
+ //! @warning This function is to be considered **UNSAFE**. Setting flags in a model specific register may lead to
+ //! unexpected CPU behavior if the prerequisites imposed by the CPU specification are not fulfilled. This function
+ //! will perform no additional checks, and may, by extension, crash the system.
+ //!
+ //! @param flag One or a combination of flags to be set in the model specific register.
+ auto static set(flags flag) -> void
+ {
+ auto current = Derived::read();
+ current |= flag;
+ Derived::write(current);
+ }
+
+ //! Clear one or more flags in this model specific register.
+ //!
+ //! @warning This function is to be considered **UNSAFE**. Clearing flags in a model specific register may lead to
+ //! unexpected CPU behavior if the prerequisites imposed by the CPU specification are not fulfilled. This function
+ //! will perform no additional checks, and may, by extension, crash the system.
+ //!
+ //! @param flag One or a combination of flags to be cleared in the model specific register.
+ auto static clear(flags flag) -> void
+ {
+ auto current = Derived::read();
+ current &= ~flag;
+ Derived::write(current);
+ }
+
+ //! Test one or more flags in this model specific register
+ //!
+ //! @param flag One or a combination of flags to test for.
+ auto test(flags flag) -> flags
+ {
+ return Derived::read() & flag;
+ }
+ };
+
+ //! A model specific register (MSR)
+ //!
+ //! Model specific register are used to configure CPU features that a not necessarily present on all CPUs generations.
+ //! In the past, some MSRs have been defined to be architectural, meaning all CPUs of a given architecture (x86-64 in
+ //! this case) support them. Writing to a MSR is inherently dangerous, since a misconfiguration cal leave the CPU in
+ //! an invalid/undefined state.
+ //!
+ //! @tparam Number The register number of this MSR
+ //! @tparam ValueType The value type of this MSR
+ template<std::uint32_t Number, typename ValueType>
+ struct model_specific_register
+ : model_specific_register_with_flags<model_specific_register<Number, ValueType>, ValueType>
+ {
+ //! A raw MSR value, comprising two halfs.
+ //!
+ //! MSRs have been 64-bit in size even in the 32-bit intel architecture, and are thus written in two halfs.
+ struct raw_value
+ {
+ std::uint32_t low_half; //!< The lower half of the register value
+ std::uint32_t high_half; //!< The upper half of the register value
+ };
+
+ //! Read the current value of this MSR.
+ //!
+ //! @return The current value of this MSR.
+ auto static read() -> ValueType
+ {
+ auto raw = raw_value{};
+ asm volatile("rdmsr" : "=a"(raw.low_half), "=d"(raw.high_half) : "c"(Number));
+ return static_cast<ValueType>(std::bit_cast<std::uint64_t>(raw));
+ }
+
+ //! Write a new value to this MSR.
+ //!
+ //! @param value The new value for this MSR.
+ auto static write(ValueType value) -> void
+ {
+ auto raw = std::bit_cast<raw_value>(static_cast<std::uint64_t>(value));
+ asm volatile("wrmsr" : : "a"(raw.low_half), "d"(raw.high_half), "c"(Number));
+ }
+ };
+
+ //! The I32_EFER (Extended Feature Enable Register) MSR
+ using i32_efer = model_specific_register<ia32_efer_number, ia32_efer_flags>;
+
+} // namespace teachos::cpu::x86_64
+
#endif \ No newline at end of file