From 2b8e6e7e10f084a9a9ba5c0b79a041f4d1ac459b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 15 Mar 2025 11:29:26 +0000 Subject: implement loading of gdtr register --- .../descriptor_table/access_byte.cpp | 10 +++--- .../descriptor_table/gdt_flags.cpp | 14 +++++--- .../descriptor_table/global_descriptor_table.cpp | 40 +++++++++++++--------- .../global_descriptor_table_pointer.cpp | 12 +++++++ .../descriptor_table/segment_descriptor.cpp | 17 +++------ .../descriptor_table/type_field.cpp | 12 ------- arch/x86_64/src/kernel/cpu/lgdt.cpp | 13 ++++--- arch/x86_64/src/kernel/cpu/ss.cpp | 8 ++--- arch/x86_64/src/kernel/main.cpp | 13 ++----- .../src/memory/heap/linked_list_allocator.cpp | 2 +- arch/x86_64/src/shared/mutex.cpp | 16 --------- arch/x86_64/src/stl/mutex.cpp | 16 +++++++++ 12 files changed, 86 insertions(+), 87 deletions(-) create mode 100644 arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table_pointer.cpp delete mode 100644 arch/x86_64/src/context_switching/descriptor_table/type_field.cpp delete mode 100644 arch/x86_64/src/shared/mutex.cpp create mode 100644 arch/x86_64/src/stl/mutex.cpp (limited to 'arch/x86_64/src') diff --git a/arch/x86_64/src/context_switching/descriptor_table/access_byte.cpp b/arch/x86_64/src/context_switching/descriptor_table/access_byte.cpp index 4e5459f..6b54451 100644 --- a/arch/x86_64/src/context_switching/descriptor_table/access_byte.cpp +++ b/arch/x86_64/src/context_switching/descriptor_table/access_byte.cpp @@ -2,14 +2,14 @@ namespace teachos::arch::context_switching::descriptor_table { - access_byte::access_byte(uint8_t flags, uint8_t type_field) + access_byte::access_byte(uint8_t flags) : _flags(flags) - , _type(type_field) { // Nothing to do. } - auto access_byte::contains_flags(std::bitset<4U> other) const -> bool { return (_flags & other) == other; } - - auto access_byte::get_type_field() const -> type_field { return _type; } + auto access_byte::contains_flags(std::bitset<8U> other) const -> bool + { + return (std::bitset<8U>{_flags} & other) == other; + } } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp b/arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp index 65f2e90..9e95182 100644 --- a/arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp +++ b/arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp @@ -1,14 +1,18 @@ #include "arch/context_switching/descriptor_table/gdt_flags.hpp" -#include "arch/exception_handling/assert.hpp" - namespace teachos::arch::context_switching::descriptor_table { - gdt_flags::gdt_flags(uint8_t flags) - : _flags(flags) + 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 (_flags & other) == other; } + auto gdt_flags::contains_flags(std::bitset<4U> other) const -> bool + { + return (std::bitset<4U>{_flags} & other) == other; + } + + auto descriptor_table::gdt_flags::get_limit() const -> std::bitset<4U> { return std::bitset<4U>{_limit_2}; } } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table.cpp b/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table.cpp index f4ea61b..c5554a7 100644 --- a/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table.cpp +++ b/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table.cpp @@ -1,6 +1,7 @@ #include "arch/context_switching/descriptor_table/global_descriptor_table.hpp" #include "arch/context_switching/descriptor_table/segment_descriptor.hpp" +#include "arch/exception_handling/assert.hpp" #include "arch/kernel/cpu/lgdt.hpp" #include "arch/stl/vector.hpp" @@ -10,33 +11,32 @@ namespace teachos::arch::context_switching::descriptor_table { segment_descriptor null_segment{0}; + std::bitset<20U> limit{0xFFFFF}; // Kernel space code segment access_byte kernel_code_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_KERNEL | - access_byte::CODE_OR_DATA_SEGMENT, - type_field::CODE_SEGMENT | type_field::READABLE}; - gdt_flags kernel_code_gdt_flags{gdt_flags::GRANULARITY | gdt_flags::LENGTH}; - segment_descriptor kernel_code_segment{kernel_code_access_byte, kernel_code_gdt_flags, 0, 0xFFFFF}; + access_byte::CODE_OR_DATA_SEGMENT | access_byte::CODE_SEGMENT | + access_byte::READABLE}; + gdt_flags kernel_code_gdt_flags{gdt_flags::GRANULARITY | gdt_flags::LENGTH, limit}; + segment_descriptor kernel_code_segment{kernel_code_access_byte, kernel_code_gdt_flags, 0, limit}; // Kernel space data segment access_byte kernel_data_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_KERNEL | - access_byte::CODE_OR_DATA_SEGMENT, - type_field::WRITABLE}; - gdt_flags kernel_data_gdt_flags{gdt_flags::GRANULARITY | gdt_flags::UPPER_BOUND}; - segment_descriptor kernel_data_segment{kernel_data_access_byte, kernel_data_gdt_flags, 0, 0xFFFFF}; + access_byte::CODE_OR_DATA_SEGMENT | access_byte::WRITABLE}; + gdt_flags kernel_data_gdt_flags{gdt_flags::GRANULARITY | gdt_flags::UPPER_BOUND, limit}; + segment_descriptor kernel_data_segment{kernel_data_access_byte, kernel_data_gdt_flags, 0, limit}; // User space code segment access_byte user_code_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_USER | - access_byte::CODE_OR_DATA_SEGMENT, - type_field::CODE_SEGMENT | type_field::READABLE}; - gdt_flags user_code_gdt_flags{gdt_flags::GRANULARITY | gdt_flags::LENGTH}; - segment_descriptor user_code_segment{user_code_access_byte, user_code_gdt_flags, 0, 0xFFFFF}; + access_byte::CODE_OR_DATA_SEGMENT | access_byte::CODE_SEGMENT | + access_byte::READABLE}; + gdt_flags user_code_gdt_flags{gdt_flags::GRANULARITY | gdt_flags::LENGTH, limit}; + segment_descriptor user_code_segment{user_code_access_byte, user_code_gdt_flags, 0, limit}; // User space data segment access_byte user_data_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_USER | - access_byte::CODE_OR_DATA_SEGMENT, - type_field::WRITABLE}; - gdt_flags user_data_gdt_flags{gdt_flags::GRANULARITY | gdt_flags::UPPER_BOUND}; - segment_descriptor user_data_segment{user_data_access_byte, user_data_gdt_flags, 0, 0xFFFFF}; + access_byte::CODE_OR_DATA_SEGMENT | access_byte::WRITABLE}; + gdt_flags user_data_gdt_flags{gdt_flags::GRANULARITY | gdt_flags::UPPER_BOUND, limit}; + segment_descriptor user_data_segment{user_data_access_byte, user_data_gdt_flags, 0, limit}; stl::vector global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, user_code_segment, user_data_segment}; @@ -46,8 +46,14 @@ namespace teachos::arch::context_switching::descriptor_table auto initialize_global_descriptor_table() -> global_descriptor_table { decltype(auto) gdt = create_global_descriptor_table(); - global_descriptor_table_pointer gdt_pointer{gdt.size() - 1, &gdt}; + global_descriptor_table_pointer gdt_pointer{static_cast(gdt.size() - 1), &gdt}; kernel::cpu::load_global_descriptor_table(gdt_pointer); + + auto 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."); + return gdt; } } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table_pointer.cpp b/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table_pointer.cpp new file mode 100644 index 0000000..f552496 --- /dev/null +++ b/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table_pointer.cpp @@ -0,0 +1,12 @@ +#include "arch/context_switching/descriptor_table/global_descriptor_table_pointer.hpp" + +namespace teachos::arch::context_switching::descriptor_table +{ + global_descriptor_table_pointer::global_descriptor_table_pointer(uint16_t table_length, + global_descriptor_table * address) + : table_length(table_length) + , address(address) + { + // Nothing to do. + } +} // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/context_switching/descriptor_table/segment_descriptor.cpp b/arch/x86_64/src/context_switching/descriptor_table/segment_descriptor.cpp index a743ad2..c1a46a6 100644 --- a/arch/x86_64/src/context_switching/descriptor_table/segment_descriptor.cpp +++ b/arch/x86_64/src/context_switching/descriptor_table/segment_descriptor.cpp @@ -5,9 +5,8 @@ namespace teachos::arch::context_switching::descriptor_table segment_descriptor::segment_descriptor(uint128_t flags) : _limit_1(flags << 112U) , _base_1((flags >> 16U) << 88U) - , _access((flags >> 44U) << 80U, (flags >> 40U) << 84U) - , _limit_2((flags >> 48U) << 72U) - , _flag((flags >> 52U) << 72U) + , _access((flags >> 40U) << 80U) + , _flag((flags >> 52U) << 72U, (flags >> 48U) << 72U) , _base_2((flags >> 56U) << 32U) , _reserved(flags >> 96U) { @@ -16,10 +15,9 @@ namespace teachos::arch::context_switching::descriptor_table segment_descriptor::segment_descriptor(access_byte access_byte, gdt_flags flags, uint64_t base, std::bitset<20U> limit) - : _limit_1((limit.to_ulong() << 4U) >> 16U) + : _limit_1(limit.to_ulong()) , _base_1((base << 40U) >> 40U) , _access(access_byte) - , _limit_2(limit.to_ulong() >> 16U) , _flag(flags) , _base_2(base >> 24U) , _reserved(0U) @@ -33,12 +31,7 @@ namespace teachos::arch::context_switching::descriptor_table { return segment_descriptor_type::SYSTEM_SEGMENT; } - - if (_access.get_type_field().contains_flags(type_field::CODE_SEGMENT)) - { - return segment_descriptor_type::CODE_SEGMENT; - } - - return segment_descriptor_type::DATA_SEGMENT; + return _access.contains_flags(access_byte::CODE_SEGMENT) ? segment_descriptor_type::CODE_SEGMENT + : segment_descriptor_type::DATA_SEGMENT; } } // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/context_switching/descriptor_table/type_field.cpp b/arch/x86_64/src/context_switching/descriptor_table/type_field.cpp deleted file mode 100644 index d967a97..0000000 --- a/arch/x86_64/src/context_switching/descriptor_table/type_field.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "arch/context_switching/descriptor_table/type_field.hpp" - -namespace teachos::arch::context_switching::descriptor_table -{ - type_field::type_field(uint8_t flags) - : _flags(flags) - { - // Nothing to do. - } - - auto type_field::contains_flags(std::bitset<4U> other) const -> bool { return (_flags & other) == other; } -} // namespace teachos::arch::context_switching::descriptor_table diff --git a/arch/x86_64/src/kernel/cpu/lgdt.cpp b/arch/x86_64/src/kernel/cpu/lgdt.cpp index 70a48dd..386914f 100644 --- a/arch/x86_64/src/kernel/cpu/lgdt.cpp +++ b/arch/x86_64/src/kernel/cpu/lgdt.cpp @@ -4,14 +4,17 @@ namespace teachos::arch::kernel::cpu { + auto store_global_descriptor_table() -> context_switching::descriptor_table::global_descriptor_table_pointer + { + context_switching::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::descriptor_table::global_descriptor_table_pointer const & gdt_pointer) -> void { - // TODO: build lgdt argument from global_descriptor_table_pointer (don't know how yet) - // asm volatile("lgdt (%0)" : : "r"(gdt_pointer)); - if (gdt_pointer.table_length) - { - } + asm volatile("lgdt %[input]" : /* no output from call */ : [input] "m"(gdt_pointer)); } } // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/src/kernel/cpu/ss.cpp b/arch/x86_64/src/kernel/cpu/ss.cpp index 9c8dd61..1f28e7f 100644 --- a/arch/x86_64/src/kernel/cpu/ss.cpp +++ b/arch/x86_64/src/kernel/cpu/ss.cpp @@ -19,15 +19,15 @@ namespace teachos::arch::kernel::cpu auto read_ss() -> uint16_t { - uint16_t ss; - asm volatile("mov %%ss, %0" : "=r"(ss)); - return ss; + uint16_t segment_selector; + asm volatile("mov %%ss, %[output]" : [output] "=r"(segment_selector)); + return segment_selector; } auto write_ss(segment_selector selector) -> void { uint16_t ss = selector.to_uint16(); - asm volatile("mov %0, %%ss" ::"r"(ss)); + asm volatile("mov %[input], %%ss" : /* no output from call */ : [input] "r"(ss)); } } // namespace teachos::arch::kernel::cpu \ No newline at end of file diff --git a/arch/x86_64/src/kernel/main.cpp b/arch/x86_64/src/kernel/main.cpp index 4db9599..2c0b6c8 100644 --- a/arch/x86_64/src/kernel/main.cpp +++ b/arch/x86_64/src/kernel/main.cpp @@ -1,6 +1,7 @@ #include "arch/kernel/main.hpp" #include "arch/context_switching/descriptor_table/global_descriptor_table.hpp" +#include "arch/kernel/cpu/lgdt.hpp" #include "arch/memory/heap/bump_allocator.hpp" #include "arch/memory/heap/global_heap_allocator.hpp" #include "arch/memory/main.hpp" @@ -60,16 +61,8 @@ namespace teachos::arch::kernel heap_test(); - context_switching::descriptor_table::global_descriptor_table global_descriptor_table{ - context_switching::descriptor_table::initialize_global_descriptor_table()}; - - decltype(auto) x = global_descriptor_table.at(1); - if (global_descriptor_table.size() == 0) - { - } - if (x.get_segment_type() == context_switching::descriptor_table::segment_descriptor_type::CODE_SEGMENT) - { - } + auto global_descriptor_table = context_switching::descriptor_table::initialize_global_descriptor_table(); + (void)global_descriptor_table.at(1); video::vga::text::write("GDT FILLED", video::vga::text::common_attributes::green_on_black); } } // namespace teachos::arch::kernel diff --git a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp index a824c8a..5101ab2 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -11,7 +11,7 @@ namespace teachos::arch::memory::heap : heap_start(heap_start) , heap_end(heap_end) , first(nullptr) - , mutex{shared::mutex{}} + , mutex{stl::mutex{}} { auto const heap_size = heap_end - heap_start; exception_handling::assert( diff --git a/arch/x86_64/src/shared/mutex.cpp b/arch/x86_64/src/shared/mutex.cpp deleted file mode 100644 index 6598255..0000000 --- a/arch/x86_64/src/shared/mutex.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "arch/shared/mutex.hpp" - -namespace teachos::arch::shared -{ - auto mutex::lock() -> void - { - while (!try_lock()) - { - // Nothing to do - } - } - - auto mutex::try_lock() -> bool { return !locked.exchange(true, std::memory_order_acquire); } - - auto mutex::unlock() -> void { locked.store(false, std::memory_order_release); } -} // namespace teachos::arch::shared diff --git a/arch/x86_64/src/stl/mutex.cpp b/arch/x86_64/src/stl/mutex.cpp new file mode 100644 index 0000000..232a11c --- /dev/null +++ b/arch/x86_64/src/stl/mutex.cpp @@ -0,0 +1,16 @@ +#include "arch/stl/mutex.hpp" + +namespace teachos::arch::stl +{ + auto mutex::lock() -> void + { + while (!try_lock()) + { + // Nothing to do + } + } + + auto mutex::try_lock() -> bool { return !locked.exchange(true, std::memory_order_acquire); } + + auto mutex::unlock() -> void { locked.store(false, std::memory_order_release); } +} // namespace teachos::arch::stl -- cgit v1.2.3