diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2025-11-24 13:16:35 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2025-11-24 13:16:35 +0100 |
| commit | 9ee028e52bd60affded3b90ea8dcd20c93bb5025 (patch) | |
| tree | 672259a63205ed8efed5dcfc34415c8257577306 | |
| parent | 7f935cdc3e57d80c4ef83760e1a616c33684271d (diff) | |
| download | teachos-9ee028e52bd60affded3b90ea8dcd20c93bb5025.tar.xz teachos-9ee028e52bd60affded3b90ea8dcd20c93bb5025.zip | |
x86-64/kapi: reimplement ia32_efer support
| -rw-r--r-- | .vscode/settings.json | 5 | ||||
| -rw-r--r-- | arch/x86_64/include/x86_64/cpu/impl/model_specific_register.hpp | 112 | ||||
| -rw-r--r-- | arch/x86_64/include/x86_64/cpu/registers.hpp | 3 | ||||
| -rw-r--r-- | arch/x86_64/src/kapi/memory.cpp | 3 |
4 files changed, 119 insertions, 4 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json index 8cee879..dcf1d1a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -23,11 +23,14 @@ }, "cSpell.words": [ "crtc", + "efer", "invlpg", "kapi", "kstd", "NOLINTNEXTLINE", + "rdmsr", "rvalues", - "TeachOS" + "TeachOS", + "wrmsr" ] }
\ No newline at end of file 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 new file mode 100644 index 0000000..8a41a8a --- /dev/null +++ b/arch/x86_64/include/x86_64/cpu/impl/model_specific_register.hpp @@ -0,0 +1,112 @@ +#ifndef TEACHOS_X86_64_CPU_IMPL_MODEL_SPECIFIC_REGISTER_HPP +#define TEACHOS_X86_64_CPU_IMPL_MODEL_SPECIFIC_REGISTER_HPP + +#include <bit> +#include <cstdint> +#include <type_traits> + +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, + }; + + constexpr auto operator|(ia32_efer_flags lhs, ia32_efer_flags rhs) -> ia32_efer_flags + { + return static_cast<ia32_efer_flags>(static_cast<std::underlying_type_t<ia32_efer_flags>>(lhs) | + static_cast<std::underlying_type_t<ia32_efer_flags>>(rhs)); + } + + constexpr auto operator|=(ia32_efer_flags & lhs, ia32_efer_flags rhs) -> ia32_efer_flags & + { + lhs = lhs | rhs; + return lhs; + } + + constexpr auto operator&(ia32_efer_flags lhs, ia32_efer_flags rhs) -> ia32_efer_flags + { + return static_cast<ia32_efer_flags>(static_cast<std::underlying_type_t<ia32_efer_flags>>(lhs) & + static_cast<std::underlying_type_t<ia32_efer_flags>>(rhs)); + } + + constexpr auto operator&=(ia32_efer_flags & lhs, ia32_efer_flags rhs) -> ia32_efer_flags & + { + lhs = lhs & rhs; + return lhs; + } + + constexpr auto operator~(ia32_efer_flags lhs) -> ia32_efer_flags + { + // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange) + return static_cast<ia32_efer_flags>(~static_cast<std::underlying_type_t<ia32_efer_flags>>(lhs)); + } + + } // namespace impl + + using i32_efer = impl::model_specific_register<impl::ia32_efer_number, impl::ia32_efer_flags>; + +} // namespace teachos::cpu::x86_64 + +#endif
\ No newline at end of file diff --git a/arch/x86_64/include/x86_64/cpu/registers.hpp b/arch/x86_64/include/x86_64/cpu/registers.hpp index 7f71b95..97cba19 100644 --- a/arch/x86_64/include/x86_64/cpu/registers.hpp +++ b/arch/x86_64/include/x86_64/cpu/registers.hpp @@ -1,6 +1,7 @@ #ifndef TEACHOS_X86_64_CPU_REGISTERS_HPP #define TEACHOS_X86_64_CPU_REGISTERS_HPP -#include "x86_64/cpu/impl/control_registers.hpp" // IWYU pragma: export +#include "x86_64/cpu/impl/control_registers.hpp" // IWYU pragma: export +#include "x86_64/cpu/impl/model_specific_register.hpp" // IWYU pragma: export #endif
\ No newline at end of file diff --git a/arch/x86_64/src/kapi/memory.cpp b/arch/x86_64/src/kapi/memory.cpp index 6102bee..d0d966b 100644 --- a/arch/x86_64/src/kapi/memory.cpp +++ b/arch/x86_64/src/kapi/memory.cpp @@ -6,7 +6,6 @@ #include "x86_64/boot/boot.hpp" #include "x86_64/boot/ld.hpp" -#include "x86_64/cpu/impl/control_registers.hpp" #include "x86_64/cpu/registers.hpp" #include "x86_64/memory/region_allocator.hpp" @@ -50,7 +49,7 @@ namespace teachos::memory auto enable_cpu_protections() -> void { cpu::x86_64::cr0::set(cpu::x86_64::cr0::flags::write_protect); - // set_efer_bit(efer_flags::NXE); + cpu::x86_64::i32_efer::set(cpu::x86_64::i32_efer::flags::execute_disable_bit_enable); } } // namespace |
