From e8fb1d771d9aa4d1cb5b18cd0483c7e5731aeecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 31 Mar 2025 13:18:56 +0000 Subject: Improve create_segment readability --- .../interrupt_descriptor_table/idt_flags.cpp | 2 + .../interrupt_descriptor_table.cpp | 28 ++++++---- .../segment_selector.cpp | 2 + arch/x86_64/src/context_switching/main.cpp | 2 - .../segment_descriptor_table/access_byte.cpp | 2 + .../segment_descriptor_table/gdt_flags.cpp | 2 + .../global_descriptor_table.cpp | 62 ++++++++++++---------- 7 files changed, 60 insertions(+), 40 deletions(-) (limited to 'arch/x86_64/src/context_switching') diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp index e7379ef..d36a4c1 100644 --- a/arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp +++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/idt_flags.cpp @@ -12,4 +12,6 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table { return (std::bitset<8U>{_flags} & other) == other; } + + auto idt_flags::operator|=(std::bitset<8U> other) -> void { _flags |= other.to_ulong(); } } // namespace teachos::arch::context_switching::interrupt_descriptor_table diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp index 62b116b..db3351e 100644 --- a/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp +++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/interrupt_descriptor_table.cpp @@ -6,18 +6,28 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table { - auto get_or_create_interrupt_descriptor_table() -> interrupt_descriptor_table & + namespace { - // @MTO: This address resolution is most certainly wrong -> numbers in dbg seem off (offset_3 = 0) - uint64_t offset = reinterpret_cast(&interrupt_handling::generic_interrupt_handler); - segment_selector selector{0U, segment_selector::REQUEST_LEVEL_KERNEL}; - ist_offset ist{0U}; - idt_flags flags{idt_flags::DESCRIPTOR_LEVEL_KERNEL | idt_flags::PRESENT}; - gate_descriptor descriptor{selector, ist, flags, offset}; + auto create_interrupt_descriptor_table() -> interrupt_descriptor_table + { + // @MTO: This address resolution is most certainly wrong -> numbers in dbg seem off (offset_3 = 0) + uint64_t offset = reinterpret_cast(&interrupt_handling::generic_interrupt_handler); + segment_selector selector{0U, segment_selector::REQUEST_LEVEL_KERNEL}; + ist_offset ist{0U}; + idt_flags flags{idt_flags::DESCRIPTOR_LEVEL_KERNEL | idt_flags::PRESENT}; + gate_descriptor descriptor{selector, ist, flags, offset}; + + // Interrupt Descriptor Table needs to be kept alive + static interrupt_descriptor_table interrupt_descriptor_table{descriptor}; + return interrupt_descriptor_table; + } + } // namespace + auto get_or_create_interrupt_descriptor_table() -> interrupt_descriptor_table & + { // Interrupt Descriptor Table needs to be kept alive - static interrupt_descriptor_table interrupt_descriptor_table{descriptor}; - return interrupt_descriptor_table; + static interrupt_descriptor_table idt = create_interrupt_descriptor_table(); + return idt; } auto update_interrupt_descriptor_table_register() -> void diff --git a/arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp b/arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp index 494e50f..62aed9b 100644 --- a/arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp +++ b/arch/x86_64/src/context_switching/interrupt_descriptor_table/segment_selector.cpp @@ -13,4 +13,6 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table { return (std::bitset<3U>{_flags} & other) == other; } + + auto segment_selector::operator|=(std::bitset<3U> other) -> void { _flags |= other.to_ulong(); } } // namespace teachos::arch::context_switching::interrupt_descriptor_table diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index db04b52..2b853ec 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -24,8 +24,6 @@ namespace teachos::arch::context_switching // FIXME: We currently cannot enable interrupts, since for some reason, we will later run into what looks like a GP // and triple fault. - // @MTO: SOMETIMES i get past a breakpoint here???? seems to happen when i actually pause before (f.e. inside the - // idt). NEVER happened when stepping through quickly. Can you reproduce this? kernel::cpu::set_interrupt_flag(); descriptor_tables tables = {segment_descriptor_table::get_or_create_global_descriptor_table(), diff --git a/arch/x86_64/src/context_switching/segment_descriptor_table/access_byte.cpp b/arch/x86_64/src/context_switching/segment_descriptor_table/access_byte.cpp index 34a10f1..e31e021 100644 --- a/arch/x86_64/src/context_switching/segment_descriptor_table/access_byte.cpp +++ b/arch/x86_64/src/context_switching/segment_descriptor_table/access_byte.cpp @@ -12,4 +12,6 @@ namespace teachos::arch::context_switching::segment_descriptor_table { 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/src/context_switching/segment_descriptor_table/gdt_flags.cpp b/arch/x86_64/src/context_switching/segment_descriptor_table/gdt_flags.cpp index 9885bda..e444a24 100644 --- a/arch/x86_64/src/context_switching/segment_descriptor_table/gdt_flags.cpp +++ b/arch/x86_64/src/context_switching/segment_descriptor_table/gdt_flags.cpp @@ -15,4 +15,6 @@ namespace teachos::arch::context_switching::segment_descriptor_table } 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/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp b/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp index 346db9e..a497632 100644 --- a/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp +++ b/arch/x86_64/src/context_switching/segment_descriptor_table/global_descriptor_table.cpp @@ -11,28 +11,26 @@ 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 { - uint8_t access_level_bits = - access_byte::PRESENT | access_byte::CODE_OR_DATA_SEGMENT | *reinterpret_cast(&access_level); - uint8_t gdt_flags_bits = gdt_flags::GRANULARITY | gdt_flags::LONG_MODE; + uint64_t const base = 0x0; + std::bitset<20U> const 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) { - access_level_bits |= access_byte::CODE_SEGMENT | access_byte::READABLE; + flags |= gdt_flags::LONG_MODE; + access_level |= access_byte::CODE_SEGMENT | access_byte::READABLE; } else if (segment_descriptor_type == segment_descriptor_type::DATA_SEGMENT) { - gdt_flags_bits |= gdt_flags::UPPER_BOUND; - access_level_bits |= access_byte::WRITABLE; + flags |= gdt_flags::UPPER_BOUND; + access_level |= access_byte::WRITABLE; } - uint64_t const base = 0x0; - std::bitset<20U> const limit{0xFFFFF}; - access_byte const access_byte{access_level_bits}; - gdt_flags const gdt_flags{gdt_flags_bits, limit}; - segment_descriptor const segment_descriptor{access_byte, gdt_flags, base, limit}; + segment_descriptor const segment_descriptor{access_level, flags, base, limit}; return segment_descriptor; } @@ -46,28 +44,34 @@ namespace teachos::arch::context_switching::segment_descriptor_table TSS_LIMIT}; return tss_descriptor; } + + auto create_global_descriptor_table() -> global_descriptor_table + { + segment_descriptor const null_segment{0}; + segment_descriptor const kernel_code_segment = + create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL); + segment_descriptor const kernel_data_segment = + create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL); + segment_descriptor const user_code_segment = + create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_USER); + segment_descriptor 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 + static auto tss = new task_state_segment(); + 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}; + return global_descriptor_table; + } } // namespace auto get_or_create_global_descriptor_table() -> global_descriptor_table & { - segment_descriptor const null_segment{0}; - segment_descriptor const kernel_code_segment = - create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL); - segment_descriptor const kernel_data_segment = - create_segment_descriptor(segment_descriptor_type::DATA_SEGMENT, access_byte::DESCRIPTOR_LEVEL_KERNEL); - segment_descriptor const user_code_segment = - create_segment_descriptor(segment_descriptor_type::CODE_SEGMENT, access_byte::DESCRIPTOR_LEVEL_USER); - segment_descriptor 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 - static auto tss = new task_state_segment(); - segment_descriptor const tss_descriptor = create_task_state_segment_descriptor(tss); - // Global Descriptor Table needs to be kept alive - static 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; + static global_descriptor_table gdt = create_global_descriptor_table(); + return gdt; } auto update_global_descriptor_table_register() -> void -- cgit v1.2.3