diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-01-16 17:39:23 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-01-16 17:39:23 +0100 |
| commit | 7ba274d0838e5cd4e48e85f81557bbb837ed4349 (patch) | |
| tree | b792f550634b856e3401ea42dd0ee7089494be28 /arch/x86_64/pre/src | |
| parent | f7fc4cb67c8c7c6ec1833f6ac6f0ad3a2837251d (diff) | |
| download | teachos-7ba274d0838e5cd4e48e85f81557bbb837ed4349.tar.xz teachos-7ba274d0838e5cd4e48e85f81557bbb837ed4349.zip | |
x86_64/cpu: port GDT reload procedure
Diffstat (limited to 'arch/x86_64/pre/src')
9 files changed, 0 insertions, 385 deletions
diff --git a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/access_byte.cpp b/arch/x86_64/pre/src/context_switching/segment_descriptor_table/access_byte.cpp deleted file mode 100644 index fcc72cf..0000000 --- a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/access_byte.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "arch/context_switching/segment_descriptor_table/access_byte.hpp" - -namespace teachos::arch::context_switching::segment_descriptor_table -{ - access_byte::access_byte(uint8_t flags) - : _flags(flags) - { - // Nothing to do. - } - - auto access_byte::contains_flags(std::bitset<8U> other) const -> bool - { - return (std::bitset<8U>{_flags} & other) == other; - } - - auto access_byte::operator|=(std::bitset<8U> other) -> void - { - _flags |= other.to_ulong(); - } -} // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/gdt_flags.cpp b/arch/x86_64/pre/src/context_switching/segment_descriptor_table/gdt_flags.cpp deleted file mode 100644 index ad1366a..0000000 --- a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/gdt_flags.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "arch/context_switching/segment_descriptor_table/gdt_flags.hpp" - -namespace teachos::arch::context_switching::segment_descriptor_table -{ - gdt_flags::gdt_flags(uint8_t flags, std::bitset<20U> limit) - : _limit_2(limit.to_ulong() >> 16U) - , _flags(flags) - { - // Nothing to do. - } - - auto gdt_flags::contains_flags(std::bitset<4U> other) const -> bool - { - return (std::bitset<4U>{_flags} & other) == other; - } - - auto gdt_flags::get_limit() const -> std::bitset<4U> - { - return std::bitset<4U>{_limit_2}; - } - - auto gdt_flags::operator|=(std::bitset<4U> other) -> void - { - _flags |= other.to_ulong(); - } -} // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp b/arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp deleted file mode 100644 index 1c4729f..0000000 --- a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "arch/context_switching/segment_descriptor_table/global_descriptor_table.hpp" - -#include "arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp" -#include "arch/exception_handling/assert.hpp" -#include "arch/kernel/cpu/gdtr.hpp" -#include "arch/kernel/cpu/tr.hpp" - -namespace teachos::arch::context_switching::segment_descriptor_table -{ - namespace - { - auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_byte access_level) - -> segment_descriptor_base - { - constexpr uint64_t BASE = 0x0; - constexpr std::bitset<20U> LIMIT{0xFFFFF}; - gdt_flags flags{gdt_flags::GRANULARITY, LIMIT}; - - access_level |= access_byte::PRESENT | access_byte::CODE_OR_DATA_SEGMENT; - if (segment_descriptor_type == segment_descriptor_type::CODE_SEGMENT) - { - flags |= gdt_flags::LONG_MODE; - access_level |= access_byte::CODE_SEGMENT | access_byte::READABLE; - } - else if (segment_descriptor_type == segment_descriptor_type::DATA_SEGMENT) - { - access_level |= access_byte::WRITABLE; - } - - segment_descriptor_base const segment_descriptor_base{access_level, flags, BASE, LIMIT}; - return segment_descriptor_base; - } - - auto create_tss_descriptor(task_state_segment * tss) -> segment_descriptor_extension - { - constexpr uint64_t TSS_LIMIT = sizeof(task_state_segment) - 1; - access_byte const tss_access_byte{access_byte::PRESENT | access_byte::DESCRIPTOR_LEVEL_KERNEL | - access_byte::TASK_STATE_SEGMENT_AVAILABLE}; - gdt_flags const tss_gdt_flags{0U, TSS_LIMIT}; - segment_descriptor_extension const tss_descriptor{tss_access_byte, tss_gdt_flags, reinterpret_cast<uint64_t>(tss), - TSS_LIMIT}; - return tss_descriptor; - } - - auto create_gdt() -> global_descriptor_table - { - segment_descriptor_base const null_segment{0}; - segment_descriptor_base const kernel_code_segment = - create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL); - segment_descriptor_base const kernel_data_segment = - create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL); - segment_descriptor_base const user_code_segment = - create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_USER); - segment_descriptor_base const user_data_segment = - create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_byte::DESCRIPTOR_LEVEL_USER); - - // Task State Segment needs to be kept alive - auto static tss = new task_state_segment(); - segment_descriptor_extension const tss_descriptor = create_tss_descriptor(tss); - - global_descriptor_table global_descriptor_table{null_segment, - kernel_code_segment, - kernel_data_segment, - user_code_segment, - user_data_segment, - tss_descriptor.get_first_gdt_entry(), - tss_descriptor.get_second_gdt_entry()}; - return global_descriptor_table; - } - } // namespace - - auto get_or_create_gdt() -> global_descriptor_table & - { - // Global Descriptor Table needs to be kept alive - global_descriptor_table static gdt = create_gdt(); - return gdt; - } - - auto update_gdtr() -> void - { - decltype(auto) gdt = get_or_create_gdt(); - - // Calculate the size of the gdt in bytes - 1. This subtraction occurs because the maximum value of Size is 65535, - // while the GDT can be up to 65536 bytes in length (8192 entries). Further, no GDT can have a size of 0 bytes. - uint16_t gdt_size = static_cast<uint16_t>((gdt.size() * sizeof(segment_descriptor_base)) - 1); - global_descriptor_table_pointer gdt_pointer{gdt_size, gdt.data()}; - kernel::cpu::load_global_descriptor_table(gdt_pointer); - - auto const stored_gdt_pointer = kernel::cpu::store_global_descriptor_table(); - arch::exception_handling::assert( - gdt_pointer == stored_gdt_pointer, - "[Global Descriptor Table] Loaded GDTR value is not the same as the stored value."); - } - - auto update_tss_register() -> void - { - decltype(auto) gdt = get_or_create_gdt(); - - // Load task state segment descriptor from the last element in the global descriptor table, done by calculating - // offset in bytes to the start of the segment descriptor (5 * 8) = 40 - uint16_t tss_selector = (gdt.size() * sizeof(segment_descriptor_base)) - sizeof(segment_descriptor_extension); - kernel::cpu::load_task_register(tss_selector); - - auto const stored_task_register = kernel::cpu::store_task_register(); - arch::exception_handling::assert(tss_selector == stored_task_register, - "[Global Descriptor Table] Loaded TR value is not the same as the stored value."); - } - -} // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp b/arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp deleted file mode 100644 index 79088b8..0000000 --- a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/global_descriptor_table_pointer.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp" - -namespace teachos::arch::context_switching::segment_descriptor_table -{ - global_descriptor_table_pointer::global_descriptor_table_pointer(uint16_t table_length, uint64_t * address) - : table_length(table_length) - , address(address) - { - // Nothing to do. - } -} // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_base.cpp b/arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_base.cpp deleted file mode 100644 index c3a03fc..0000000 --- a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_base.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "arch/context_switching/segment_descriptor_table/segment_descriptor_base.hpp" - -namespace teachos::arch::context_switching::segment_descriptor_table -{ - segment_descriptor_base::segment_descriptor_base(uint64_t flags) - : _limit_1(flags) - , _base_1(flags >> 16U) - , _access(flags >> 40U) - , _flag(flags >> 52U, flags >> 48U) - , _base_2(flags >> 56U) - { - // Nothing to do. - } - - segment_descriptor_base::segment_descriptor_base(access_byte access_byte, gdt_flags flags, uint32_t base, - std::bitset<20U> limit) - : _limit_1(limit.to_ulong()) - , _base_1(base) - , _access(access_byte) - , _flag(flags) - , _base_2(base >> 24U) - { - // Nothing to do - } - - auto segment_descriptor_base::get_segment_type() const -> segment_descriptor_type - { - if (!_access.contains_flags(access_byte::CODE_OR_DATA_SEGMENT)) - { - return segment_descriptor_type::SYSTEM_SEGMENT; - } - return _access.contains_flags(access_byte::CODE_SEGMENT) ? segment_descriptor_type::CODE_SEGMENT - : segment_descriptor_type::DATA_SEGMENT; - } - - segment_descriptor_base::operator uint64_t() const - { - return *reinterpret_cast<uint64_t const *>(this); - } - -} // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_extension.cpp b/arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_extension.cpp deleted file mode 100644 index 5ea0d8a..0000000 --- a/arch/x86_64/pre/src/context_switching/segment_descriptor_table/segment_descriptor_extension.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "arch/context_switching/segment_descriptor_table/segment_descriptor_extension.hpp" - -namespace teachos::arch::context_switching::segment_descriptor_table -{ - segment_descriptor_extension::segment_descriptor_extension(uint128_t flags) - : _base(flags) - , _base_3(flags >> 64U) - { - // Nothing to do. - } - - segment_descriptor_extension::segment_descriptor_extension(access_byte access_byte, gdt_flags flags, uint64_t base, - std::bitset<20U> limit) - : _base(access_byte, flags, base, limit) - , _base_3(base >> 32U) - { - // Nothing to do - } - - auto segment_descriptor_extension::get_first_gdt_entry() const -> segment_descriptor_base - { - return _base; - } - - auto segment_descriptor_extension::get_second_gdt_entry() const -> uint64_t - { - return _base_3; - } - -} // namespace teachos::arch::context_switching::segment_descriptor_table diff --git a/arch/x86_64/pre/src/kernel/cpu/gdtr.cpp b/arch/x86_64/pre/src/kernel/cpu/gdtr.cpp deleted file mode 100644 index 74a4e1c..0000000 --- a/arch/x86_64/pre/src/kernel/cpu/gdtr.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "arch/kernel/cpu/gdtr.hpp" - -#include "arch/context_switching/segment_descriptor_table/global_descriptor_table_pointer.hpp" - -namespace teachos::arch::kernel::cpu -{ - auto store_global_descriptor_table() -> context_switching::segment_descriptor_table::global_descriptor_table_pointer - { - context_switching::segment_descriptor_table::global_descriptor_table_pointer current_value{}; - asm("sgdt %[output]" : [output] "=m"(current_value)); - return current_value; - } - - auto load_global_descriptor_table( - context_switching::segment_descriptor_table::global_descriptor_table_pointer const & gdt_pointer) -> void - { - asm volatile("lgdt %[input]" : /* no output from call */ : [input] "m"(gdt_pointer)); - } -} // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/pre/src/kernel/cpu/msr.cpp b/arch/x86_64/pre/src/kernel/cpu/msr.cpp deleted file mode 100644 index 9d6a318..0000000 --- a/arch/x86_64/pre/src/kernel/cpu/msr.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "arch/kernel/cpu/msr.hpp" - -namespace teachos::arch::kernel::cpu -{ - namespace - { - constexpr auto IA32_EFER_ADDRESS = 0xC000'0080; - } - - 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; - } - - auto write_msr(uint32_t msr, uint64_t value) -> void - { - uint32_t low = value; - uint32_t high = value >> 32; - asm volatile("wrmsr" - : /* no output from call */ - : "c"(msr), "a"(low), "d"(high)); - } - - auto set_efer_bit(efer_flags flag) -> void - { - auto const efer = read_msr(IA32_EFER_ADDRESS); - write_msr(IA32_EFER_ADDRESS, static_cast<std::underlying_type<efer_flags>::type>(flag) | efer); - } -} // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/pre/src/kernel/cpu/segment_register.cpp b/arch/x86_64/pre/src/kernel/cpu/segment_register.cpp deleted file mode 100644 index b08c9c4..0000000 --- a/arch/x86_64/pre/src/kernel/cpu/segment_register.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "arch/kernel/cpu/segment_register.hpp" - -#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" -#include "arch/exception_handling/assert.hpp" - -namespace teachos::arch::kernel::cpu -{ - auto reload_data_segment_registers() -> void - { - asm volatile("xor %%rax, %%rax\n" - "mov %%rax, %%ss\n" - "mov %%rax, %%ds\n" - "mov %%rax, %%es\n" - "mov %%rax, %%fs\n" - "mov %%rax, %%gs\n" - : /* no output from call */ - : /* no input to call */ - : "rax"); - } - - auto set_data_segment_registers(context_switching::interrupt_descriptor_table::segment_selector data_segment) -> void - { - asm volatile("xor %%rax, %%rax\n" - "mov %[input], %%ax\n" - "mov %%rax, %%ds\n" - "mov %%rax, %%es\n" - "mov %%rax, %%fs\n" - "mov %%rax, %%gs\n" - : /* no output from call */ - : [input] "m"(data_segment) - : "rax"); - } - - auto read_code_segment_register() -> context_switching::interrupt_descriptor_table::segment_selector - { - context_switching::interrupt_descriptor_table::segment_selector current_value{}; - asm volatile("mov %%cs, %[output]" : [output] "=r"(current_value)); - return current_value; - } - - auto validate_data_segment_registers(context_switching::interrupt_descriptor_table::segment_selector data_segment) - -> void - { - context_switching::interrupt_descriptor_table::segment_selector ss{}; - context_switching::interrupt_descriptor_table::segment_selector ds{}; - context_switching::interrupt_descriptor_table::segment_selector es{}; - context_switching::interrupt_descriptor_table::segment_selector fs{}; - context_switching::interrupt_descriptor_table::segment_selector gs{}; - - asm volatile( - "mov %%ss, %[ss_output]\n" - "mov %%ds, %[ds_output]\n" - "mov %%es, %[es_output]\n" - "mov %%fs, %[fs_output]\n" - "mov %%gs, %[gs_output]\n" - : [ss_output] "=r"(ss), [ds_output] "=r"(ds), [es_output] "=r"(es), [fs_output] "=r"(fs), [gs_output] "=r"(gs)); - - auto result = (ss == ds && ss == es && ss == fs && ss == gs); - exception_handling::assert(result, "[Segment Register] Values in data register are not the same."); - result = (ss == data_segment); - exception_handling::assert( - result, "[Segment Register] Expected Data Segment is not the same as the value in the Stack Segment register."); - } - - auto validate_code_segment_register(context_switching::interrupt_descriptor_table::segment_selector code_segment) - -> void - { - auto const cs = read_code_segment_register(); - exception_handling::assert( - cs == code_segment, - "[Segment Register] Expected Code Segment is not the same as the value in the Code Segment register."); - } - - auto validate_segment_registers(context_switching::interrupt_descriptor_table::segment_selector data_segment, - context_switching::interrupt_descriptor_table::segment_selector code_segment) -> void - { - validate_data_segment_registers(data_segment); - validate_code_segment_register(code_segment); - } - - auto set_code_segment_register(context_switching::interrupt_descriptor_table::segment_selector data_segment, - context_switching::interrupt_descriptor_table::segment_selector code_segment, - uint64_t address) -> void - { - asm volatile("mov %%rsp, %%rax\n" - "push %[data_segment]\n" - "push %%rax\n" - "pushfq\n" - "push %[code_segment]\n" - "mov %[return_function], %%rax\n" - "push %%rax\n" - "iretq\n" - : /* no output from call */ - : [data_segment] "m"(data_segment), [code_segment] "m"(code_segment), [return_function] "r"(address) - : "rax"); - } - -} // namespace teachos::arch::kernel::cpu |
