diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2025-12-12 10:52:38 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2025-12-12 10:52:38 +0100 |
| commit | 822b17b852cdc8933881132dd7b862ee74117973 (patch) | |
| tree | 6c31e3cb9ad6d5c7523e49cc5d3daf41af381793 | |
| parent | 4bb59ebf68351754ab97e722914e0434c4d347fd (diff) | |
| download | teachos-822b17b852cdc8933881132dd7b862ee74117973.tar.xz teachos-822b17b852cdc8933881132dd7b862ee74117973.zip | |
x86_64/cpu: update documentation and structure
| -rw-r--r-- | .vscode/settings.json | 2 | ||||
| -rw-r--r-- | arch/x86_64/include/x86_64/cpu/impl/control_registers.hpp | 5 | ||||
| -rw-r--r-- | arch/x86_64/include/x86_64/cpu/impl/model_specific_register.hpp | 195 |
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 |
