diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-04-16 10:29:30 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-04-29 09:05:04 +0200 |
| commit | 1b964278762dde86b0b737bd9a34fec569339f54 (patch) | |
| tree | 7fe0f4707e05f46461f03744d178f413b7bbca28 /arch/x86_64/include | |
| parent | d906d70c94c2a40d5fc6fd26056c7bc57d540002 (diff) | |
| download | teachos-1b964278762dde86b0b737bd9a34fec569339f54.tar.xz teachos-1b964278762dde86b0b737bd9a34fec569339f54.zip | |
x86_64: use p1204 project layout
Diffstat (limited to 'arch/x86_64/include')
32 files changed, 0 insertions, 1941 deletions
diff --git a/arch/x86_64/include/arch/boot/boot.hpp b/arch/x86_64/include/arch/boot/boot.hpp deleted file mode 100644 index 7df61c4..0000000 --- a/arch/x86_64/include/arch/boot/boot.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef TEACHOS_X86_64_BOOT_BOOT_HPP -#define TEACHOS_X86_64_BOOT_BOOT_HPP - -#ifdef __ASSEMBLER__ -// clang-format off - -//! The number of huge pages to map during bootstrap. -#define HUGE_PAGES_TO_MAP (16) - -//! The magic value to be set in eax by the multiboot 2 loader. -#define MULTIBOOT2_MAGIC (0x36d76289) - -//! The "A" bit in a GDT entry. -#define GDT_ACCESSED (1 << 40) - -//! The "R/W" bit in a GDT entry -#define GDT_READ_WRITE (1 << 41) - -//! The "E" bit in a GDT entry. -#define GDT_EXECUTABLE (1 << 43) - -//! The "S" bit in a GDT entry. -#define GDT_DESCRIPTOR_TYPE (1 << 44) - -//! The "P" bit in a GDT entry. -#define GDT_PRESENT (1 << 47) - -//! The "L" bit in a GDT entry. -#define GDT_LONG_MODE (1 << 53) - -// clang-format on -#else - -#include <kapi/boot.hpp> // IWYU pragma: export - -#include <multiboot2/information.hpp> - -#include <cstddef> - -namespace kapi::boot -{ - - struct information - { - //! A pointer to the loader provided Multiboot2 Information structure. - multiboot2::information_view const * mbi; - - //! The index of the next character to be written in the VGA text buffer after handoff. - std::size_t vga_buffer_index; - }; - -} // namespace kapi::boot - -#endif - -#endif diff --git a/arch/x86_64/include/arch/boot/ld.hpp b/arch/x86_64/include/arch/boot/ld.hpp deleted file mode 100644 index 988723d..0000000 --- a/arch/x86_64/include/arch/boot/ld.hpp +++ /dev/null @@ -1,61 +0,0 @@ -//! @file -//! The interface to linker script defined symbols. -//! -//! This header provides declarations for symbols that are defined in the linker script itself. The symbols declared -//! here provide important information, for example the start and end of the kernel image in virtual and physical -//! memory. -//! -//! Any variables defined in this file must not be read themselves, but rather their address shall be taken, yielding a -//! pointer to the memory location the represent. -//! -//! @note The symbols declared in this header are declared using C-language linkage in order to suppress name mangling. -//! -//! @see arch/x86_64/scripts/kernel.ld - -#ifndef TEACHOS_X86_64_BOOT_LD_HPP -#define TEACHOS_X86_64_BOOT_LD_HPP - -#include <cstddef> - -namespace arch::boot -{ - - extern "C" - { - //! The beginning of the kernel image in physical memory - //! - //! This symbol marks the start of the kernel image in physical memory. - //! - //! @see _end_physical - extern std::byte _start_physical; - - //! The first byte after the loaded kernel image. - //! - //! This symbol marks the end of the kernel image in physical memory. - //! - //! @see _start_physical - extern std::byte _end_physical; - - //! The first byte of the loaded kernel image in the virtual address space. - //! - //! This symbol and marks the start of the kernel image in virtual memory. - //! - //! @see _end_virtual - extern std::byte _start_virtual; - - //! The first byte after the loaded kernel image in the virtual address space. - //! - //! This symbol marks the end of the kernel image in virtual memory. - //! - //! @see _start_virtual - extern std::byte _end_virtual; - - //! The first byte of the kernel's virtual address space. - //! - //! This symbol marks beginning of the kernel virtual address space. - extern std::byte TEACHOS_VMA; - } - -} // namespace arch::boot - -#endif diff --git a/arch/x86_64/include/arch/bus/isa.hpp b/arch/x86_64/include/arch/bus/isa.hpp deleted file mode 100644 index e56f56a..0000000 --- a/arch/x86_64/include/arch/bus/isa.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef TEACHOS_X86_64_BUS_ISA_HPP -#define TEACHOS_X86_64_BUS_ISA_HPP - -#include <kapi/devices/bus.hpp> - -#include <cstddef> - -namespace arch::bus -{ - - struct isa final : public kapi::devices::bus - { - isa(std::size_t major); - }; - -} // namespace arch::bus - -#endif // TEACHOS_X86_64_BUS_ISA_HPP diff --git a/arch/x86_64/include/arch/cpu/control_register.hpp b/arch/x86_64/include/arch/cpu/control_register.hpp deleted file mode 100644 index 9cedc35..0000000 --- a/arch/x86_64/include/arch/cpu/control_register.hpp +++ /dev/null @@ -1,249 +0,0 @@ -#ifndef TEACHOS_X86_64_CPU_CONTROL_REGISTERS_HPP -#define TEACHOS_X86_64_CPU_CONTROL_REGISTERS_HPP - -// IWYU pragma: private, include <arch/cpu/registers.hpp> - -#include <kapi/memory.hpp> - -#include <kstd/ext/bitfield_enum> - -#include <cstdint> -#include <string_view> -#include <type_traits> -#include <utility> - -namespace arch::cpu -{ - namespace impl - { - //! The assembler templates used to access (r/w) CR0; - constexpr auto static cr0_asm = std::pair<std::string_view, std::string_view>{"mov %%cr0, %0", "mov %0, %%cr0"}; - - //! The assembler templates used to access (r/w) CR2; - constexpr auto static cr2_asm = std::pair<std::string_view, std::string_view>{"mov %%cr2, %0", "mov %0, %%cr2"}; - - //! The assembler templates used to access (r/w) CR3; - constexpr auto static cr3_asm = std::pair<std::string_view, std::string_view>{"mov %%cr3, %0", "mov %0, %%cr3"}; - } // namespace impl - - //! The flags that can be set on CR0 configuration register. - enum struct cr0_flags : uint64_t - { - //! Enable protected mode. - protection_enable = 1uz << 0, - //! Enable wait-monitoring of the coprocessor after task switching. - monitor_coprocessor = 1uz << 1, - //! Emulate floating point coprocessor. - emulation = 1uz << 2, - //! Marks that a task switch has occurred. - task_switched = 1uz << 3, - //! Marks Intel 387 DX math coprocessor as available - extension_type = 1uz << 4, - //! Numeric error handling mode. - numeric_error = 1uz << 5, - //! Disable writing to read-only marked memory. - write_protect = 1uz << 16, - //! Enable Ring-3 alignment checks - alignment_check = 1uz << 18, - //! Disable write through - not_write_through = 1uz << 29, - //! Disable caching of memory accesses - cache_disable = 1uz << 30, - //! Enable paging - paging = 1uz << 31 - }; - - enum struct cr3_flags : std::uint64_t - { - page_level_write_through = 1uz << 0, - page_level_cache_disable = 1uz << 1, - }; -} // namespace arch::cpu - -namespace kstd::ext -{ - template<> - struct is_bitfield_enum<arch::cpu::cr0_flags> : std::true_type - { - }; - - template<> - struct is_bitfield_enum<arch::cpu::cr3_flags> : std::true_type - { - }; -} // namespace kstd::ext - -namespace arch::cpu -{ - //! 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, 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. - template<typename Derived, typename ValueType, typename = void> - struct control_register_with_flags - { - private: - constexpr control_register_with_flags() noexcept = default; - friend Derived; - }; - - //! @copydoc control_register_with_flags - //! - //! @note This specialization provides the implementation for the case in which the value type of the control register - //! is an enum. - template<typename Derived, typename ValueType> - struct control_register_with_flags<Derived, ValueType, std::enable_if_t<kstd::ext::bitfield_enum<ValueType>>> - { - //! The type of the flags used by this control register - using flags = ValueType; - - //! Set one or more flags in this control register. - //! - //! @warning This function is to be considered **UNSAFE**. Setting flags in a control 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 value One or a combination of flags to be set in the control register. - auto static set(ValueType value) -> void - { - auto current = Derived::read(); - current |= value; - Derived::write(current); - } - - //! Clear one or more flags in this control register. - //! - //! @warning This function is to be considered **UNSAFE**. Clearing flags in a control 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 value One or a combination of flags to be cleared in the control register. - auto static clear(ValueType value) -> void - { - auto current = Derived::read(); - current &= ~value; - Derived::write(current); - } - }; - - //! A CPU control register. - //! - //! CPU control registers are used to configure builtin features of the CPU, for example memory protection and FPU - //! error reporting. Writing to a control register is inherently dangerous, since a misconfiguration can leave the CPU - //! in an invalid/undefined state. - template<typename ValueType, auto AssemblerTemplates> - struct control_register : control_register_with_flags<control_register<ValueType, AssemblerTemplates>, ValueType> - { - //! Read the current value of the control register. - //! - //! @return The currently set value of the control register. - [[nodiscard]] auto static read() -> ValueType - { - auto value = ValueType{}; - asm volatile((AssemblerTemplates->first) : "=r"(value)); - return value; - } - - //! Write a new value to the control register. - //! - //! @warning This function should be considered **UNSAFE**. Writing values to a control 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 value The new value to write to the control register. - auto static write(ValueType value) -> void - { - asm volatile((AssemblerTemplates->second) : : "r"(value)); - } - }; - - //! The value type of the CR3 control register. - //! - //! The CR3 control register holds the root configuration of the virtual memory protection mechanism. It contains the - //! page aligned physical address of the root page map, as well as the root paging configuration flags. - struct cr3_value - { - //! Contstruct a 0-value CR3 value. - constexpr cr3_value() = default; - - //! Construct a CR3 value using the given root page map address and flags. - //! - //! @param address The physical address of the root page map - //! @param flags The root configuration flags of the paging system. - constexpr cr3_value(kapi::memory::physical_address address, cr3_flags flags = static_cast<cr3_flags>(0)) - : m_flags{static_cast<std::uint64_t>(flags)} - , m_address{static_cast<std::uint64_t>(address.raw())} - {} - - //! Extract the physical address of the root page map from this value. - //! - //! @return The physical address of the root page map. - [[nodiscard]] constexpr auto address() const -> kapi::memory::physical_address - { - constexpr auto address_shift = 12uz; - return kapi::memory::physical_address{m_address << address_shift}; - } - - //! Encode the frame aligned physical address of the root page map into this value. - //! - //! @param frame The frame containing a PML4. - constexpr auto frame(kapi::memory::frame frame) -> void - { - m_address = static_cast<std::uint64_t>(frame.number()); - } - - //! Extract the root paging configuration flags from this value. - //! - //! @return The root paging configuration flags. - [[nodiscard]] constexpr auto flags() const -> cr3_flags - { - return static_cast<cr3_flags>(m_flags); - } - - //! Encode the root paging configuration flags into this value. - //! - //! @param flags The root paging configuration flags. - constexpr auto flags(cr3_flags flags) -> void - { - m_flags = static_cast<std::uint64_t>(flags); - } - - //! Add the given flags to the current set of encoded root configuration flags of this value. - //! - //! @param flags The root configuration flags to add. - //! @return A reference to this value. - constexpr auto operator|=(cr3_flags flags) -> cr3_value & - { - m_flags |= static_cast<std::uint64_t>(flags); - return *this; - } - - //! Mask the root configuration flags of this value. - //! - //! @param mask The mask to apply to the root configuration flags. - //! @return A reference to this value. - constexpr auto operator&=(cr3_flags mask) -> cr3_value & - { - m_flags &= static_cast<std::uint64_t>(mask); - return *this; - } - - private: - //! Reserved bits. - std::uint64_t : 3; - //! The root paging configuration flags. - std::uint64_t m_flags : 2 {}; - //! Reserved bits. - std::uint64_t : 7; - //! The page aligned physical address of the root page map. - std::uint64_t m_address : 52 {}; - }; - - static_assert(sizeof(cr3_value) == sizeof(std::uint64_t)); - -} // namespace arch::cpu - -#endif
\ No newline at end of file diff --git a/arch/x86_64/include/arch/cpu/global_descriptor_table.hpp b/arch/x86_64/include/arch/cpu/global_descriptor_table.hpp deleted file mode 100644 index b17c509..0000000 --- a/arch/x86_64/include/arch/cpu/global_descriptor_table.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef TEACHOS_X86_64_GLOBAL_DESCRIPTOR_TABLE_HPP -#define TEACHOS_X86_64_GLOBAL_DESCRIPTOR_TABLE_HPP - -#include <arch/cpu/segment_descriptor.hpp> - -#include <kapi/memory.hpp> - -#include <algorithm> -#include <array> -#include <bit> -#include <concepts> -#include <cstddef> -#include <cstdint> -#include <utility> - -namespace arch::cpu -{ - - template<std::size_t Size> - struct global_descriptor_table; - - struct [[gnu::packed]] global_descriptor_table_pointer - { - template<std::size_t GdtSize> - global_descriptor_table_pointer(global_descriptor_table<GdtSize> const & gdt) - : size{GdtSize * sizeof(segment_descriptor) - 1} - , address{kapi::memory::physical_address{std::bit_cast<std::uintptr_t>(&gdt)}.raw()} - {} - - auto load() -> void - { - asm volatile("lgdt %0" : : "m"(*this)); - } - - std::uint16_t size{}; - std::uint64_t address{}; - }; - - static_assert(sizeof(global_descriptor_table_pointer) == sizeof(std::uint16_t) + sizeof(std::uint64_t)); - - template<std::size_t SizeInBytes> - struct global_descriptor_table - { - template<std::derived_from<segment_descriptor>... SegmentDescriptors> - constexpr global_descriptor_table(SegmentDescriptors const &... descriptors) - : m_descriptors{} - { - auto descriptor_data = std::array{ - std::pair{std::bit_cast<std::byte const *>(&descriptors), sizeof(descriptors)} - ... - }; - auto written_size = 0uz; - std::ranges::for_each(descriptor_data, [&written_size, this](auto entry) { - std::ranges::copy(entry.first, entry.first + entry.second, m_descriptors.begin() + written_size); - written_size += entry.second; - }); - } - - auto load(std::size_t code_segment_index, std::size_t data_segment_index) const -> void - { - auto pointer = global_descriptor_table_pointer{*this}; - pointer.load(); - - asm volatile("push %0\n" - "lea 1f(%%rip), %%rax\n" - "push %%rax\n" - "lretq\n" - "1:\n" - "mov %1, %%rax\n" - "mov %%rax, %%ss\n" - "mov %%rax, %%ds\n" - "mov %%rax, %%es\n" - "mov %%rax, %%fs\n" - "mov %%rax, %%gs\n" - : - : "X"(code_segment_index * sizeof(segment_descriptor)), - "X"(data_segment_index * sizeof(segment_descriptor)) - : "rax"); - } - - private: - std::array<std::byte, SizeInBytes> m_descriptors; - }; - - template<std::derived_from<segment_descriptor>... SegmentDescriptors> - global_descriptor_table(SegmentDescriptors const &... descriptors) - -> global_descriptor_table<(sizeof(SegmentDescriptors) + ...)>; - -} // namespace arch::cpu - -#endif
\ No newline at end of file diff --git a/arch/x86_64/include/arch/cpu/initialization.hpp b/arch/x86_64/include/arch/cpu/initialization.hpp deleted file mode 100644 index 564c544..0000000 --- a/arch/x86_64/include/arch/cpu/initialization.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_CPU_INITIALIZATION_HPP -#define TEACHOS_ARCH_X86_64_CPU_INITIALIZATION_HPP - -namespace arch::cpu -{ - auto initialize_descriptors() -> void; - - auto initialize_legacy_interrupts() -> void; - -} // namespace arch::cpu - -#endif diff --git a/arch/x86_64/include/arch/cpu/interrupts.hpp b/arch/x86_64/include/arch/cpu/interrupts.hpp deleted file mode 100644 index 6162f56..0000000 --- a/arch/x86_64/include/arch/cpu/interrupts.hpp +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef TEACHOS_X86_64_CPU_INTERRUPTS_HPP -#define TEACHOS_X86_64_CPU_INTERRUPTS_HPP - -#include <arch/cpu/segment_selector.hpp> - -#include <kapi/memory.hpp> - -#include <array> -#include <cstdint> -#include <type_traits> - -namespace arch::cpu -{ - - //! The types of supported gates. - enum struct gate_type : std::uint8_t - { - //! A gate entered through the @p INT instruction. - interrupt_gate = 0b1110, - //! A gate entered via an exception. - trap_gate = 0b1111, - }; - - struct alignas(std::uint64_t) gate_descriptor - { - //! The lowest 16 bits of the address of this gate's handler function. - std::uint16_t offset_low : 16; - //! The code segment used when handling the respective interrupt. - segment_selector m_code_segment; - //! The index into the Interrupt Stack Table naming the stack to use. - std::uint8_t interrupt_stack_table_selector : 3; - //! Reserved - std::uint8_t : 5; - //! The type of this gate. - enum gate_type gate_type : 4; - //! Reserved - std::uint8_t : 1; - //! The privilege level required to enter through this gate. - std::uint8_t descriptor_privilege_level : 2; - //! Whether this gate is present or not. - std::uint8_t present : 1; - //! The middle 16 bits of the address of this gate's handler function. - std::uint16_t offset_middle : 16; - //! The highest 32 bits of the address of this gate's handler function. - std::uint32_t offset_high : 32; - //! Reserved - std::uint32_t : 32; - }; - - static_assert(sizeof(gate_descriptor) == 2 * sizeof(std::uint64_t)); - static_assert(std::is_aggregate_v<gate_descriptor>); - - //! The stack frame as established by the low-level assembly interrupt stubs. - //! - //! @note The layout of this struct is reverse than what would reasonably be expected. The reason for this reversal is - //! that fact that it represents a stack frame. Stack frames on x86_64 grow towards lower addresses, meaning the first - //! item on the stack is the last item in C++ memory layout order. - struct interrupt_frame - { - struct - { - std::uint64_t r15{}; - std::uint64_t r14{}; - std::uint64_t r13{}; - std::uint64_t r12{}; - std::uint64_t r11{}; - std::uint64_t r10{}; - std::uint64_t r9{}; - std::uint64_t r8{}; - std::uint64_t rdi{}; - std::uint64_t rsi{}; - std::uint64_t rbp{}; - std::uint64_t rdx{}; - std::uint64_t rcx{}; - std::uint64_t rbx{}; - std::uint64_t rax{}; - } handler_saved; - - struct - { - std::uint64_t number{}; - std::uint64_t error_code{}; - } interrupt; - - struct - { - kapi::memory::linear_address rip{}; - std::uint64_t cs{}; - std::uint64_t rflags{}; - kapi::memory::linear_address rsp{}; - std::uint64_t ss{}; - } cpu_saved; - }; - - struct interrupt_descriptor_table - { - interrupt_descriptor_table() noexcept; - - auto load() const -> void; - - private: - std::array<gate_descriptor, 256> m_descriptors{}; - }; - - struct [[gnu::packed]] interrupt_descriptor_table_register - { - std::uint16_t limit; - gate_descriptor const * base; - - auto load() const -> void; - auto static read() -> interrupt_descriptor_table_register; - }; - -} // namespace arch::cpu - -#endif
\ No newline at end of file diff --git a/arch/x86_64/include/arch/cpu/legacy_pic.hpp b/arch/x86_64/include/arch/cpu/legacy_pic.hpp deleted file mode 100644 index 56ca9c4..0000000 --- a/arch/x86_64/include/arch/cpu/legacy_pic.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef TEACHOS_X86_64_CPU_LEGACY_PIC_HPP -#define TEACHOS_X86_64_CPU_LEGACY_PIC_HPP - -#include <arch/device_io/port_io.hpp> - -#include <cstdint> - -namespace arch::cpu -{ - using pic_master_control_port = io::port<0x20, std::uint8_t, io::port_read, io::port_write>; - using pic_master_data_port = io::port<0x21, std::uint8_t, io::port_read, io::port_write>; - using pic_slave_control_port = io::port<0xa0, std::uint8_t, io::port_read, io::port_write>; - using pic_slave_data_port = io::port<0xa1, std::uint8_t, io::port_read, io::port_write>; - - constexpr auto pic_end_of_interrupt = std::uint8_t{0x20}; - -} // namespace arch::cpu - -#endif
\ No newline at end of file diff --git a/arch/x86_64/include/arch/cpu/model_specific_register.hpp b/arch/x86_64/include/arch/cpu/model_specific_register.hpp deleted file mode 100644 index bd4aff9..0000000 --- a/arch/x86_64/include/arch/cpu/model_specific_register.hpp +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef TEACHOS_X86_64_CPU_MODEL_SPECIFIC_REGISTER_HPP -#define TEACHOS_X86_64_CPU_MODEL_SPECIFIC_REGISTER_HPP - -// IWYU pragma: private, include <x86_64/cpu/registers.hpp> - -#include <kstd/ext/bitfield_enum> - -#include <bit> -#include <cstdint> -#include <type_traits> - -namespace arch::cpu -{ - - //! 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 arch::cpu - -namespace kstd::ext -{ - - template<> - struct is_bitfield_enum<arch::cpu::ia32_efer_flags> : std::true_type - { - }; - -} // namespace kstd::ext - -namespace arch::cpu -{ - //! 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 - { - private: - constexpr model_specific_register_with_flags() noexcept = default; - friend Derived; - }; - - //! @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. |
