From 8d14c729c43ee555c240a043e3909617e4fa5043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Thu, 27 Feb 2025 09:24:17 +0000 Subject: Add files to cmake and implement gdt flags --- arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp (limited to 'arch/x86_64/src/context_switching') 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 new file mode 100644 index 0000000..8a05956 --- /dev/null +++ b/arch/x86_64/src/context_switching/descriptor_table/gdt_flags.cpp @@ -0,0 +1,6 @@ +#include "arch/context_switching/descriptor_table/gdt_flags.hpp" + +namespace teachos::arch::context_switching::descriptor_table +{ + auto gdt_flags::contains_flags(std::bitset<4U> other) const -> bool { return (flags & other) == other; } +} // namespace teachos::arch::context_switching::descriptor_table -- cgit v1.2.3 From d8a8efe3e8d90ec83069d1c934ff319626e87a2d Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 27 Feb 2025 10:13:35 +0000 Subject: add descriptor_table access_byte --- .../src/context_switching/descriptor_table/access_byte.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 arch/x86_64/src/context_switching/descriptor_table/access_byte.cpp (limited to 'arch/x86_64/src/context_switching') 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 new file mode 100644 index 0000000..15a0947 --- /dev/null +++ b/arch/x86_64/src/context_switching/descriptor_table/access_byte.cpp @@ -0,0 +1,14 @@ +#include "arch/context_switching/descriptor_table/access_byte.hpp" + +#include + +namespace teachos::arch::context_switching::descriptor_table +{ + auto access_byte::contains_flags(std::bitset<8U> other) const -> bool { return (flags & other) == other; } + + auto access_byte::get_privilege_level() const -> privilege_level + { + constexpr uint8_t PRIVILEGE_MASK = 0b0110'0000; + return static_cast(flags.to_ulong() & PRIVILEGE_MASK); + } +} // namespace teachos::arch::context_switching::descriptor_table -- cgit v1.2.3 From c5151739698620e77622423c109e638f903f01c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 10 Mar 2025 13:42:38 +0000 Subject: Adjust register segment descriptors to possible states --- .../descriptor_table/access_byte.cpp | 15 +++++++------- .../descriptor_table/gdt_flags.cpp | 24 +++++++++++++++++++++- .../descriptor_table/type_field.cpp | 12 +++++++++++ 3 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 arch/x86_64/src/context_switching/descriptor_table/type_field.cpp (limited to 'arch/x86_64/src/context_switching') 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 15a0947..7a2b0b0 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 @@ -1,14 +1,15 @@ #include "arch/context_switching/descriptor_table/access_byte.hpp" -#include - namespace teachos::arch::context_switching::descriptor_table { - auto access_byte::contains_flags(std::bitset<8U> other) const -> bool { return (flags & other) == other; } - - auto access_byte::get_privilege_level() const -> privilege_level + access_byte::access_byte(uint8_t flags) + : _flags(flags) + , _type(flags) { - constexpr uint8_t PRIVILEGE_MASK = 0b0110'0000; - return static_cast(flags.to_ulong() & PRIVILEGE_MASK); + // 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; } } // 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 8a05956..8e1e939 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,6 +1,28 @@ #include "arch/context_switching/descriptor_table/gdt_flags.hpp" +#include "arch/exception_handling/assert.hpp" + namespace teachos::arch::context_switching::descriptor_table { - auto gdt_flags::contains_flags(std::bitset<4U> other) const -> bool { return (flags & other) == other; } + gdt_flags::gdt_flags(uint8_t flags, segment_descriptor_type type) + : _flags(flags << 5U) + { + switch (type) + { + case segment_descriptor_type::SYSTEM_SEGMENT: + _flags.set(2, false); + _flags.set(3, false); + break; + case segment_descriptor_type::DATA_SEGMENT: + _flags.set(3, false); + break; + case segment_descriptor_type::CODE_SEGMENT: + exception_handling::assert((contains_flags(LENGTH) && !contains_flags(DEFAULT_LENGTH)) || + !contains_flags(LENGTH), + "[GDT] Flags of code segment descriptor has both "); + break; + } + } + + auto gdt_flags::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/context_switching/descriptor_table/type_field.cpp b/arch/x86_64/src/context_switching/descriptor_table/type_field.cpp new file mode 100644 index 0000000..d967a97 --- /dev/null +++ b/arch/x86_64/src/context_switching/descriptor_table/type_field.cpp @@ -0,0 +1,12 @@ +#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 -- cgit v1.2.3 From 52fffdf2c76def4a875e0328eb45d74c6e97e805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 10 Mar 2025 16:05:31 +0000 Subject: Adjust segment descriptor to use defined helpers --- .../descriptor_table/segment_descriptor.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 arch/x86_64/src/context_switching/descriptor_table/segment_descriptor.cpp (limited to 'arch/x86_64/src/context_switching') 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 new file mode 100644 index 0000000..fb9c034 --- /dev/null +++ b/arch/x86_64/src/context_switching/descriptor_table/segment_descriptor.cpp @@ -0,0 +1,13 @@ +#include "arch/context_switching/descriptor_table/segment_descriptor.hpp" + +namespace teachos::arch::context_switching::descriptor_table +{ + segment_descriptor::segment_descriptor(uint128_t flags) + : _reserved(flags) + , _access(flags) + , _flag(flags, segment_descriptor_type::SYSTEM_SEGMENT) + , _base(flags) + , _limit(flags) + { + } +} // namespace teachos::arch::context_switching::descriptor_table -- cgit v1.2.3 From 569cf73d1fa14ec11afbb37464d2c356d55d64b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 10 Mar 2025 16:35:01 +0000 Subject: Implement segment descriptor --- .../descriptor_table/gdt_flags.cpp | 18 ++---------------- .../descriptor_table/segment_descriptor.cpp | 21 ++++++++++++++++----- 2 files changed, 18 insertions(+), 21 deletions(-) (limited to 'arch/x86_64/src/context_switching') 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 8e1e939..8fbf869 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 @@ -4,24 +4,10 @@ namespace teachos::arch::context_switching::descriptor_table { - gdt_flags::gdt_flags(uint8_t flags, segment_descriptor_type type) + gdt_flags::gdt_flags(uint8_t flags) : _flags(flags << 5U) { - switch (type) - { - case segment_descriptor_type::SYSTEM_SEGMENT: - _flags.set(2, false); - _flags.set(3, false); - break; - case segment_descriptor_type::DATA_SEGMENT: - _flags.set(3, false); - break; - case segment_descriptor_type::CODE_SEGMENT: - exception_handling::assert((contains_flags(LENGTH) && !contains_flags(DEFAULT_LENGTH)) || - !contains_flags(LENGTH), - "[GDT] Flags of code segment descriptor has both "); - break; - } + // Nothing to do. } auto gdt_flags::contains_flags(std::bitset<4U> other) const -> bool { return (_flags & other) == other; } 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 fb9c034..57564f2 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 @@ -3,11 +3,22 @@ namespace teachos::arch::context_switching::descriptor_table { segment_descriptor::segment_descriptor(uint128_t flags) - : _reserved(flags) - , _access(flags) - , _flag(flags, segment_descriptor_type::SYSTEM_SEGMENT) - , _base(flags) - , _limit(flags) + : _reserved(flags >> 96U) + , _access((flags >> 40U) << 80U) + , _flag((flags >> 52U) << 72U) + , _base(((flags >> 64U) << 32U) << 32U | ((flags >> 56U) << 64U) << 24U | (flags >> 16U) << 88U) + , _limit(((flags >> 48U) << 72U) << 16U | flags << 112U) { + // Nothing to do. + } + + auto segment_descriptor::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.get_type_field().contains_flags(type_field::CODE_SEGMENT) ? segment_descriptor_type::CODE_SEGMENT + : segment_descriptor_type::DATA_SEGMENT; } } // namespace teachos::arch::context_switching::descriptor_table -- cgit v1.2.3 From b8a0024ee71a64ec0e87a1e2d0c0c7280dc954e6 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 13 Mar 2025 09:36:00 +0000 Subject: create GDT and fix segment descriptor bit order --- .../descriptor_table/access_byte.cpp | 4 ++-- .../descriptor_table/gdt_flags.cpp | 2 +- .../descriptor_table/segment_descriptor.cpp | 22 +++++++++++++++++++--- 3 files changed, 22 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/src/context_switching') 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 7a2b0b0..4e5459f 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,9 +2,9 @@ namespace teachos::arch::context_switching::descriptor_table { - access_byte::access_byte(uint8_t flags) + access_byte::access_byte(uint8_t flags, uint8_t type_field) : _flags(flags) - , _type(flags) + , _type(type_field) { // Nothing to do. } 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 8fbf869..65f2e90 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 @@ -5,7 +5,7 @@ namespace teachos::arch::context_switching::descriptor_table { gdt_flags::gdt_flags(uint8_t flags) - : _flags(flags << 5U) + : _flags(flags) { // Nothing to do. } 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 57564f2..ab8eaba 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 @@ -4,7 +4,7 @@ namespace teachos::arch::context_switching::descriptor_table { segment_descriptor::segment_descriptor(uint128_t flags) : _reserved(flags >> 96U) - , _access((flags >> 40U) << 80U) + , _access((flags >> 44U) << 80U, (flags >> 40U) << 84U) , _flag((flags >> 52U) << 72U) , _base(((flags >> 64U) << 32U) << 32U | ((flags >> 56U) << 64U) << 24U | (flags >> 16U) << 88U) , _limit(((flags >> 48U) << 72U) << 16U | flags << 112U) @@ -12,13 +12,29 @@ namespace teachos::arch::context_switching::descriptor_table // Nothing to do. } + segment_descriptor::segment_descriptor(access_byte access_byte, gdt_flags flags, uint64_t base, + std::bitset<20U> limit) + : _reserved(0U) + , _access(access_byte) + , _flag(flags) + , _base(base) + , _limit(limit) + { + // Nothing to do + } + auto segment_descriptor::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.get_type_field().contains_flags(type_field::CODE_SEGMENT) ? segment_descriptor_type::CODE_SEGMENT - : segment_descriptor_type::DATA_SEGMENT; + + if (_access.get_type_field().contains_flags(type_field::CODE_SEGMENT)) + { + return segment_descriptor_type::CODE_SEGMENT; + } + + return segment_descriptor_type::DATA_SEGMENT; } } // namespace teachos::arch::context_switching::descriptor_table -- cgit v1.2.3 From 34c36096e55ac678e29c58f7336b419647e805b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Thu, 13 Mar 2025 10:00:42 +0000 Subject: Fix segment descriptor bit order of private members --- .../descriptor_table/segment_descriptor.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/src/context_switching') 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 ab8eaba..a743ad2 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 @@ -3,22 +3,26 @@ namespace teachos::arch::context_switching::descriptor_table { segment_descriptor::segment_descriptor(uint128_t flags) - : _reserved(flags >> 96U) + : _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) - , _base(((flags >> 64U) << 32U) << 32U | ((flags >> 56U) << 64U) << 24U | (flags >> 16U) << 88U) - , _limit(((flags >> 48U) << 72U) << 16U | flags << 112U) + , _base_2((flags >> 56U) << 32U) + , _reserved(flags >> 96U) { // Nothing to do. } segment_descriptor::segment_descriptor(access_byte access_byte, gdt_flags flags, uint64_t base, std::bitset<20U> limit) - : _reserved(0U) + : _limit_1((limit.to_ulong() << 4U) >> 16U) + , _base_1((base << 40U) >> 40U) , _access(access_byte) + , _limit_2(limit.to_ulong() >> 16U) , _flag(flags) - , _base(base) - , _limit(limit) + , _base_2(base >> 24U) + , _reserved(0U) { // Nothing to do } -- cgit v1.2.3 From 2e4cbd473ff3bb7ac7371af39becf830b4fb753b Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 13 Mar 2025 14:05:45 +0000 Subject: IN_PROGRESS implement gdt initialization --- .../descriptor_table/global_descriptor_table.cpp | 57 ++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table.cpp (limited to 'arch/x86_64/src/context_switching') 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 new file mode 100644 index 0000000..1cba13c --- /dev/null +++ b/arch/x86_64/src/context_switching/descriptor_table/global_descriptor_table.cpp @@ -0,0 +1,57 @@ +#include "global_descriptor_table.hpp" + +#include "arch/stl/vector.hpp" + +#include "segment_descriptor.hpp" + +namespace teachos::arch::context_switching::descriptor_table +{ + auto create_global_descriptor_table() -> global_descriptor_table + { + segment_descriptor null_segment{0}; + + // 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}; + + // 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}; + + // 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}; + + // 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}; + + stl::vector global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, + user_code_segment, user_data_segment}; + return global_descriptor_table; + } + + auto load_global_descriptor_table(global_descriptor_table_pointer gdt_pointer) -> void + { + // + } + + auto initialize_global_descriptor_table() -> global_descriptor_table + { + global_descriptor_table gdt{create_global_descriptor_table()}; + global_descriptor_table_pointer gdt_pointer{gdt.size() - 1, &gdt}; + load_global_descriptor_table(gdt_pointer); + } +} // namespace teachos::arch::context_switching::descriptor_table \ No newline at end of file -- cgit v1.2.3 From 11db9338dac611ea32e202add5ce5055b54ebb58 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 13 Mar 2025 15:46:16 +0000 Subject: fixup typing and continue adding gdt --- .../descriptor_table/global_descriptor_table.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'arch/x86_64/src/context_switching') 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 1cba13c..ca3d7ff 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,9 +1,9 @@ -#include "global_descriptor_table.hpp" +#include "arch/context_switching/descriptor_table/global_descriptor_table.hpp" +#include "arch/context_switching/descriptor_table/segment_descriptor.hpp" +#include "arch/kernel/cpu/lgdt.hpp" #include "arch/stl/vector.hpp" -#include "segment_descriptor.hpp" - namespace teachos::arch::context_switching::descriptor_table { auto create_global_descriptor_table() -> global_descriptor_table @@ -43,15 +43,14 @@ namespace teachos::arch::context_switching::descriptor_table return global_descriptor_table; } - auto load_global_descriptor_table(global_descriptor_table_pointer gdt_pointer) -> void - { - // - } - auto initialize_global_descriptor_table() -> global_descriptor_table { global_descriptor_table gdt{create_global_descriptor_table()}; + + // TODO: Second argument does not work yet (because pointer hpp) global_descriptor_table_pointer gdt_pointer{gdt.size() - 1, &gdt}; - load_global_descriptor_table(gdt_pointer); + kernel::cpu::load_global_descriptor_table(gdt_pointer); + + return gdt; } } // namespace teachos::arch::context_switching::descriptor_table \ No newline at end of file -- cgit v1.2.3 From f2b9ac8f0f22354241e9b78e47aa7cb94e5ef511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Fri, 14 Mar 2025 14:20:24 +0000 Subject: Fix header recursion problem --- .../context_switching/descriptor_table/global_descriptor_table.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'arch/x86_64/src/context_switching') 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 ca3d7ff..f4ea61b 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 @@ -45,12 +45,9 @@ namespace teachos::arch::context_switching::descriptor_table auto initialize_global_descriptor_table() -> global_descriptor_table { - global_descriptor_table gdt{create_global_descriptor_table()}; - - // TODO: Second argument does not work yet (because pointer hpp) + decltype(auto) gdt = create_global_descriptor_table(); global_descriptor_table_pointer gdt_pointer{gdt.size() - 1, &gdt}; kernel::cpu::load_global_descriptor_table(gdt_pointer); - return gdt; } -} // namespace teachos::arch::context_switching::descriptor_table \ No newline at end of file +} // namespace teachos::arch::context_switching::descriptor_table -- cgit v1.2.3 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 ------- 6 files changed, 54 insertions(+), 51 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 (limited to 'arch/x86_64/src/context_switching') 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 -- cgit v1.2.3 From 5a332c90f79e6d10de1a8cd478c4dbef82f4d74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 15 Mar 2025 14:48:29 +0000 Subject: Use empty bit field to implement reserved --- .../src/context_switching/descriptor_table/segment_descriptor.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/x86_64/src/context_switching') 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 c1a46a6..3e93823 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 @@ -8,7 +8,6 @@ namespace teachos::arch::context_switching::descriptor_table , _access((flags >> 40U) << 80U) , _flag((flags >> 52U) << 72U, (flags >> 48U) << 72U) , _base_2((flags >> 56U) << 32U) - , _reserved(flags >> 96U) { // Nothing to do. } @@ -20,7 +19,6 @@ namespace teachos::arch::context_switching::descriptor_table , _access(access_byte) , _flag(flags) , _base_2(base >> 24U) - , _reserved(0U) { // Nothing to do } -- cgit v1.2.3 From ecb67842d3578dfc8c7d685b0cd168efd24505e6 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sat, 15 Mar 2025 14:56:12 +0000 Subject: create TSS descriptor --- .../descriptor_table/global_descriptor_table.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch/x86_64/src/context_switching') 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 c5554a7..6474739 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 @@ -12,6 +12,7 @@ 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 | access_byte::CODE_SEGMENT | @@ -38,6 +39,15 @@ namespace teachos::arch::context_switching::descriptor_table 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}; + // Task state segment + // TODO: Create TSS + access_byte tss_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_KERNEL | + access_byte::TASK_STATE_SEGMENT_AVAILABLE}; + gdt_flags tss_gdt_flags{0U, limit}; + uint64_t tss_address = 0; // &TSS + uint64_t tss_limit = 0U; // sizeof(TSS) - 1 + segment_descriptor task_state_segment{tss_access_byte, tss_gdt_flags, tss_address, tss_limit}; + stl::vector global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, user_code_segment, user_data_segment}; return global_descriptor_table; -- cgit v1.2.3 From 36758071881088b27a52cee4e5653f6cf6a79a78 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 16 Mar 2025 12:41:09 +0000 Subject: start implementing TSS --- .../descriptor_table/global_descriptor_table.cpp | 108 ++++++++++++++------- 1 file changed, 71 insertions(+), 37 deletions(-) (limited to 'arch/x86_64/src/context_switching') 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 6474739..2b399f8 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,61 +1,87 @@ #include "arch/context_switching/descriptor_table/global_descriptor_table.hpp" #include "arch/context_switching/descriptor_table/segment_descriptor.hpp" +#include "arch/context_switching/descriptor_table/task_state_segment.hpp" #include "arch/exception_handling/assert.hpp" -#include "arch/kernel/cpu/lgdt.hpp" +#include "arch/kernel/cpu/gdtr.hpp" +#include "arch/kernel/cpu/tr.hpp" #include "arch/stl/vector.hpp" namespace teachos::arch::context_switching::descriptor_table { + auto create_segment_descriptor(segment_descriptor_type segment_descriptor_type, access_level access_level) + -> segment_descriptor + { + uint8_t access_level_bitset = access_byte::PRESENT | access_byte::CODE_OR_DATA_SEGMENT; + if (access_level == access_level::KERNEL) + { + access_level_bitset |= access_byte::ACCESS_LEVEL_KERNEL; + } + else if (access_level == access_level::USER) + { + access_level_bitset = access_byte::ACCESS_LEVEL_USER; + } + + uint8_t gdt_flags_bitset = gdt_flags::GRANULARITY; + if (segment_descriptor_type == segment_descriptor_type::CODE_SEGMENT) + { + gdt_flags_bitset |= gdt_flags::LENGTH; + access_level_bitset |= access_byte::CODE_SEGMENT | access_byte::READABLE; + } + else if (segment_descriptor_type == segment_descriptor_type::DATA_SEGMENT) + { + gdt_flags_bitset |= gdt_flags::UPPER_BOUND; + access_level_bitset |= access_byte::WRITABLE; + } + + std::bitset<20U> limit{0xFFFFF}; + access_byte access_byte{access_level_bitset}; + gdt_flags gdt_flags{gdt_flags_bitset, limit}; + segment_descriptor code_segment{access_byte, gdt_flags, 0, limit}; + + return code_segment; + } + auto create_global_descriptor_table() -> global_descriptor_table { segment_descriptor null_segment{0}; + segment_descriptor kernel_code_segment = + create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_level::KERNEL); + segment_descriptor kernel_data_segment = + create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_level::KERNEL); + segment_descriptor user_code_segment = + create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_level::USER); + segment_descriptor user_data_segment = + create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_level::USER); - std::bitset<20U> limit{0xFFFFF}; + stl::vector global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, + user_code_segment, user_data_segment}; + return global_descriptor_table; + } - // Kernel space code segment - access_byte kernel_code_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_KERNEL | - 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 | 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 | 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 | 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}; - - // Task state segment - // TODO: Create TSS + auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor + { + std::bitset<20U> limit{0xFFFFF}; access_byte tss_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_KERNEL | access_byte::TASK_STATE_SEGMENT_AVAILABLE}; gdt_flags tss_gdt_flags{0U, limit}; - uint64_t tss_address = 0; // &TSS - uint64_t tss_limit = 0U; // sizeof(TSS) - 1 - segment_descriptor task_state_segment{tss_access_byte, tss_gdt_flags, tss_address, tss_limit}; + uint64_t tss_address = reinterpret_cast(tss); + constexpr uint64_t tss_limit = sizeof(task_state_segment) - 1; + segment_descriptor tss_descriptor{tss_access_byte, tss_gdt_flags, tss_address, tss_limit}; - stl::vector global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, - user_code_segment, user_data_segment}; - return global_descriptor_table; + return tss_descriptor; } auto initialize_global_descriptor_table() -> global_descriptor_table { - decltype(auto) gdt = create_global_descriptor_table(); + auto gdt = create_global_descriptor_table(); + + // Add TSS segment descriptor to GDT + auto tss = new task_state_segment(); + auto tss_descriptor = create_task_state_segment_descriptor(tss); + gdt.push_back(tss_descriptor); + + // Load GDT into GDTR global_descriptor_table_pointer gdt_pointer{static_cast(gdt.size() - 1), &gdt}; kernel::cpu::load_global_descriptor_table(gdt_pointer); @@ -64,6 +90,14 @@ namespace teachos::arch::context_switching::descriptor_table gdt_pointer == stored_gdt_pointer, "[Global Descriptor Table] Loaded GDTR value is not the same as the stored value."); + // Load Task Register (LTR) using the index of TSS descriptor + uint16_t tss_selector = (gdt.size() - 1) * sizeof(segment_descriptor); + kernel::cpu::load_task_register(tss_selector); + + auto 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."); + return gdt; } } // namespace teachos::arch::context_switching::descriptor_table -- cgit v1.2.3 From 5d1fbaba03f411b93281ef6934166d897cd0713e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 16 Mar 2025 13:42:44 +0000 Subject: Move base value out into variable --- .../context_switching/descriptor_table/global_descriptor_table.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/x86_64/src/context_switching') 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 2b399f8..77bd3e9 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 @@ -34,10 +34,11 @@ namespace teachos::arch::context_switching::descriptor_table access_level_bitset |= access_byte::WRITABLE; } + uint64_t base = 0x0; std::bitset<20U> limit{0xFFFFF}; access_byte access_byte{access_level_bitset}; gdt_flags gdt_flags{gdt_flags_bitset, limit}; - segment_descriptor code_segment{access_byte, gdt_flags, 0, limit}; + segment_descriptor code_segment{access_byte, gdt_flags, base, limit}; return code_segment; } @@ -54,8 +55,8 @@ namespace teachos::arch::context_switching::descriptor_table segment_descriptor user_data_segment = create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_level::USER); - stl::vector global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, - user_code_segment, user_data_segment}; + global_descriptor_table global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, + user_code_segment, user_data_segment}; return global_descriptor_table; } -- cgit v1.2.3 From c56a8a74bc4e9662469db33a85c12586f202985a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 17 Mar 2025 09:38:39 +0000 Subject: Fix issue in vector --- .../descriptor_table/global_descriptor_table.cpp | 27 ++++++++++------------ 1 file changed, 12 insertions(+), 15 deletions(-) (limited to 'arch/x86_64/src/context_switching') 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 77bd3e9..21a76e8 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 @@ -54,9 +54,12 @@ namespace teachos::arch::context_switching::descriptor_table create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_level::USER); segment_descriptor user_data_segment = create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_level::USER); + // Task State Segment needs to be kept alive + static auto tss = new task_state_segment(); + segment_descriptor tss_descriptor = create_task_state_segment_descriptor(tss); - global_descriptor_table global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, - user_code_segment, user_data_segment}; + global_descriptor_table global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, + user_code_segment, user_data_segment, tss_descriptor}; return global_descriptor_table; } @@ -67,20 +70,15 @@ namespace teachos::arch::context_switching::descriptor_table access_byte::TASK_STATE_SEGMENT_AVAILABLE}; gdt_flags tss_gdt_flags{0U, limit}; uint64_t tss_address = reinterpret_cast(tss); - constexpr uint64_t tss_limit = sizeof(task_state_segment) - 1; - segment_descriptor tss_descriptor{tss_access_byte, tss_gdt_flags, tss_address, tss_limit}; - + constexpr uint64_t TSS_LIMIT = sizeof(task_state_segment) - 1; + segment_descriptor tss_descriptor{tss_access_byte, tss_gdt_flags, tss_address, TSS_LIMIT}; return tss_descriptor; } - auto initialize_global_descriptor_table() -> global_descriptor_table + auto initialize_global_descriptor_table() -> global_descriptor_table & { - auto gdt = create_global_descriptor_table(); - - // Add TSS segment descriptor to GDT - auto tss = new task_state_segment(); - auto tss_descriptor = create_task_state_segment_descriptor(tss); - gdt.push_back(tss_descriptor); + // Global Descriptor Table needs to be kept alive + static auto gdt = create_global_descriptor_table(); // Load GDT into GDTR global_descriptor_table_pointer gdt_pointer{static_cast(gdt.size() - 1), &gdt}; @@ -91,14 +89,13 @@ namespace teachos::arch::context_switching::descriptor_table gdt_pointer == stored_gdt_pointer, "[Global Descriptor Table] Loaded GDTR value is not the same as the stored value."); - // Load Task Register (LTR) using the index of TSS descriptor - uint16_t tss_selector = (gdt.size() - 1) * sizeof(segment_descriptor); + // Calculate the offset of the gdt in bytes to the TSS descriptor + uint16_t const tss_selector = (gdt.size() - 1) * sizeof(segment_descriptor); kernel::cpu::load_task_register(tss_selector); auto 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."); - return gdt; } } // namespace teachos::arch::context_switching::descriptor_table -- cgit v1.2.3 From 3c01f820a064f3120a46aa3afdd9f88ce9e00db3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 17 Mar 2025 14:51:24 +0000 Subject: Debug and adjust load task register assembly call. WIP --- .../descriptor_table/global_descriptor_table.cpp | 42 ++++++++++------------ .../descriptor_table/segment_descriptor.cpp | 2 +- 2 files changed, 20 insertions(+), 24 deletions(-) (limited to 'arch/x86_64/src/context_switching') 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 21a76e8..b338d9d 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 @@ -34,44 +34,41 @@ namespace teachos::arch::context_switching::descriptor_table access_level_bitset |= access_byte::WRITABLE; } - uint64_t base = 0x0; - std::bitset<20U> limit{0xFFFFF}; - access_byte access_byte{access_level_bitset}; - gdt_flags gdt_flags{gdt_flags_bitset, limit}; - segment_descriptor code_segment{access_byte, gdt_flags, base, limit}; - + uint64_t const base = 0x0; + std::bitset<20U> const limit{0xFFFFF}; + access_byte const access_byte{access_level_bitset}; + gdt_flags const gdt_flags{gdt_flags_bitset, limit}; + segment_descriptor const code_segment{access_byte, gdt_flags, base, limit}; return code_segment; } auto create_global_descriptor_table() -> global_descriptor_table { - segment_descriptor null_segment{0}; - segment_descriptor kernel_code_segment = + segment_descriptor const null_segment{0}; + segment_descriptor const kernel_code_segment = create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_level::KERNEL); - segment_descriptor kernel_data_segment = + segment_descriptor const kernel_data_segment = create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_level::KERNEL); - segment_descriptor user_code_segment = + segment_descriptor const user_code_segment = create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_level::USER); - segment_descriptor user_data_segment = + segment_descriptor const user_data_segment = create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_level::USER); // Task State Segment needs to be kept alive static auto tss = new task_state_segment(); - segment_descriptor tss_descriptor = create_task_state_segment_descriptor(tss); + segment_descriptor const tss_descriptor = create_task_state_segment_descriptor(tss); - global_descriptor_table global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, - user_code_segment, user_data_segment, tss_descriptor}; + global_descriptor_table const global_descriptor_table{null_segment, kernel_code_segment, kernel_data_segment, + user_code_segment, user_data_segment, tss_descriptor}; return global_descriptor_table; } auto create_task_state_segment_descriptor(task_state_segment * tss) -> segment_descriptor { - std::bitset<20U> limit{0xFFFFF}; - access_byte tss_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_KERNEL | - access_byte::TASK_STATE_SEGMENT_AVAILABLE}; - gdt_flags tss_gdt_flags{0U, limit}; - uint64_t tss_address = reinterpret_cast(tss); constexpr uint64_t TSS_LIMIT = sizeof(task_state_segment) - 1; - segment_descriptor tss_descriptor{tss_access_byte, tss_gdt_flags, tss_address, TSS_LIMIT}; + access_byte const tss_access_byte{access_byte::PRESENT | access_byte::ACCESS_LEVEL_KERNEL | + access_byte::TASK_STATE_SEGMENT_AVAILABLE}; + gdt_flags const tss_gdt_flags{0U, TSS_LIMIT}; + segment_descriptor const tss_descriptor{tss_access_byte, tss_gdt_flags, reinterpret_cast(tss), TSS_LIMIT}; return tss_descriptor; } @@ -80,11 +77,10 @@ namespace teachos::arch::context_switching::descriptor_table // Global Descriptor Table needs to be kept alive static auto gdt = create_global_descriptor_table(); - // Load GDT into GDTR 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(); + 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."); @@ -93,7 +89,7 @@ namespace teachos::arch::context_switching::descriptor_table uint16_t const tss_selector = (gdt.size() - 1) * sizeof(segment_descriptor); kernel::cpu::load_task_register(tss_selector); - auto stored_task_register = kernel::cpu::store_task_register(); + 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."); return gdt; 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 3e93823..2385c58 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 @@ -15,7 +15,7 @@ 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()) - , _base_1((base << 40U) >> 40U) + , _base_1(base) , _access(access_byte) , _flag(flags) , _base_2(base >> 24U) -- cgit v1.2.3 From fd557fb19c4ad25fbcb1368a73fddd91921496fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 18 Mar 2025 10:48:24 +0000 Subject: Fix invalid bit values in access byte and typo in create_segment_descriptor method --- .../src/context_switching/descriptor_table/global_descriptor_table.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/context_switching') 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 b338d9d..578e264 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 @@ -19,7 +19,7 @@ namespace teachos::arch::context_switching::descriptor_table } else if (access_level == access_level::USER) { - access_level_bitset = access_byte::ACCESS_LEVEL_USER; + access_level_bitset |= access_byte::ACCESS_LEVEL_USER; } uint8_t gdt_flags_bitset = gdt_flags::GRANULARITY; -- cgit v1.2.3 From 7a98b1dcb1f4436664a8f1a5d6e71ab2c65378f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 18 Mar 2025 14:39:53 +0000 Subject: Attempt to add calls that Reload code segment and data segment register --- .../descriptor_table/global_descriptor_table.cpp | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'arch/x86_64/src/context_switching') 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 578e264..dccce6b 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 @@ -94,4 +94,35 @@ namespace teachos::arch::context_switching::descriptor_table "[Global Descriptor Table] Loaded TR value is not the same as the stored value."); return gdt; } + + auto reload_cs_register(uint16_t gdt_data_offset) -> void + { + asm volatile("mov %[input], %%ax\n" + "mov %%ax %%ds\n" // Data Segment + "mov %%ax %%es\n" // Extra Segment (used for string operations) + "mov %%ax %%fs\n" // General-purpose Segment + "mov %%ax %%gs\n" // General-purpose Segment + "mov %%ax %%ss\n" // Stack Segment + : /* no output from call */ + : [input] "r"(gdt_data_offset) + : "ax"); + } + + auto reload_segment_register(uint16_t gdt_code_offset, uint16_t gdt_data_offset) -> void + { + /* + Whatever you do with the GDT has no effect on the CPU until you load new Segment Selectors into Segment Registers. + For most of these registers, the process is as simple as using MOV instructions, but changing the CS register + requires code resembling a jump or call to elsewhere, as this is the only way its value is meant to be changed. + */ + auto function = [gdt_data_offset] { reload_cs_register(gdt_data_offset); }; + + asm volatile("push %[input]\n" + "lea %[func], %%rax\n" + "push %%rax\n" + "retfq\n" + : /* no output from call */ + : [input] "r"(gdt_code_offset), [func] "r"(&function) + : "rax"); + } } // namespace teachos::arch::context_switching::descriptor_table -- cgit v1.2.3 From b6ee8bec7ed23fd0c544f67f735e96b2bfe67682 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Thu, 20 Mar 2025 15:30:18 +0000 Subject: begin implementation of IDT --- .../descriptor_table/gate_descriptor.cpp | 5 +++ .../descriptor_table/global_descriptor_table.cpp | 42 ++-------------------- .../descriptor_table/initialization.cpp | 38 ++++++++++++++++++++ .../interrupt_descriptor_table.cpp | 10 ++++++ .../interrupt_descriptor_table_pointer.cpp | 13 +++++++ 5 files changed, 69 insertions(+), 39 deletions(-) create mode 100644 arch/x86_64/src/context_switching/descriptor_table/gate_descriptor.cpp create mode 100644 arch/x86_64/src/context_switching/descriptor_table/initialization.cpp create mode 100644 arch/x86_64/src/context_switching/descriptor_table/interrupt_descriptor_table.cpp create mode 100644 arch/x86_64/src/context_switching/descriptor_table/interrupt_descriptor_table_pointer.cpp (limited to 'arch/x86_64/src/context_switching') diff --git a/arch/x86_64/src/context_switching/descriptor_table/gate_descriptor.cpp b/arch/x86_64/src/context_switching/descriptor_table/gate_descriptor.cpp new file mode 100644 index 0000000..ee91e53 --- /dev/null +++ b/arch/x86_64/src/context_switching/descriptor_table/gate_descriptor.cpp @@ -0,0 +1,5 @@ +#include "arch/context_switching/descriptor_table/gate_descriptor.hpp" + +namespace teachos::arch::context_switching::descriptor_table +{ +} // 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 dccce6b..639b079 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 @@ -38,8 +38,8 @@ namespace teachos::arch::context_switching::descriptor_table std::bitset<20U> const limit{0xFFFFF}; access_byte const access_byte{access_level_bitset}; gdt_flags const gdt_flags{gdt_flags_bitset, limit}; - segment_descriptor const code_segment{access_byte, gdt_flags, base, limit}; - return code_segment; + segment_descriptor const segment_descriptor{access_byte, gdt_flags, base, limit}; + return segment_descriptor; } auto create_global_descriptor_table() -> global_descriptor_table @@ -53,6 +53,7 @@ namespace teachos::arch::context_switching::descriptor_table create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_level::USER); segment_descriptor const user_data_segme