diff options
| author | Matteo Gmür <matteo.gmuer1@ost.ch> | 2025-03-27 09:40:32 +0000 |
|---|---|---|
| committer | Matteo Gmür <matteo.gmuer1@ost.ch> | 2025-03-27 09:40:32 +0000 |
| commit | a6c5f6a273d0c5c4161f600fca6d4fe49858c23c (patch) | |
| tree | bf02711f9d3e0424dccef4dc1299b5a70c9f839a /arch | |
| parent | db555089dea369d9dd3010d1853077e7a4118b90 (diff) | |
| download | teachos-a6c5f6a273d0c5c4161f600fca6d4fe49858c23c.tar.xz teachos-a6c5f6a273d0c5c4161f600fca6d4fe49858c23c.zip | |
Attempt to fix crash in far jump. WIP does not return from call to assembler method
Diffstat (limited to 'arch')
9 files changed, 37 insertions, 32 deletions
diff --git a/arch/x86_64/include/arch/boot/pointers.hpp b/arch/x86_64/include/arch/boot/pointers.hpp index 2a43f22..5bcb792 100644 --- a/arch/x86_64/include/arch/boot/pointers.hpp +++ b/arch/x86_64/include/arch/boot/pointers.hpp @@ -11,7 +11,7 @@ namespace teachos::arch::boot extern "C" size_t const multiboot_information_pointer; /** - * @brief Address pointing to the start of the multiboot information structure. + * @brief Address pointing to the method that clears all segment registers. */ extern "C" size_t const segment_register_reload_pointer; diff --git a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp index c31e2d0..73cd176 100644 --- a/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp +++ b/arch/x86_64/include/arch/context_switching/interrupt_descriptor_table/segment_selector.hpp @@ -43,7 +43,8 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table /** * @brief Constructor. * - * @param index Index into the local or global descriptor table. + * @param index Index into the local or global descriptor table. Processor multiplies the index value by 16 (number + * of bytes in segment descriptor) and adds the result to the base address. * @param flags Allows to set flags for the flags field using the unscoped enum contained in this class, used to * allow for direct integer conversion. */ @@ -66,8 +67,10 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table auto operator<=>(segment_selector const & other) const -> std::strong_ordering = default; private: - uint8_t _flags : 3 = {}; ///< Underlying bits used to read the flags from. - uint16_t _index : 13 = {}; ///< Index into the local or global descriptor table. + uint8_t _flags : 3 = {}; ///< Underlying bits used to read the flags from. + uint16_t _index : 13 = + {}; ///< Index into the local or global descriptor table. Processor multiplies the index value by 16 (number of + ///< bytes in segment descriptor) and adds the result to the base address. }; } // namespace teachos::arch::context_switching::interrupt_descriptor_table diff --git a/arch/x86_64/include/arch/kernel/cpu/if.hpp b/arch/x86_64/include/arch/kernel/cpu/if.hpp index 51f5d9a..48707dc 100644 --- a/arch/x86_64/include/arch/kernel/cpu/if.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/if.hpp @@ -9,6 +9,13 @@ namespace teachos::arch::kernel::cpu */ auto set_interrupt_flag() -> void; + /** + * @brief Clears the interrupt flag (IF) in the EFLAGS register. + * This will stop the processor to respond to maskable hardware interrupts and needs to be done before changing the + * Interrupt Descriptor Table with lidt. + */ + auto clear_interrupt_flag() -> void; + } // namespace teachos::arch::kernel::cpu #endif // TEACHOS_ARCH_X86_64_KERNEL_CPU_IF_HPP diff --git a/arch/x86_64/include/arch/kernel/cpu/jmp.hpp b/arch/x86_64/include/arch/kernel/cpu/jmp.hpp index 666174c..5bc7d07 100644 --- a/arch/x86_64/include/arch/kernel/cpu/jmp.hpp +++ b/arch/x86_64/include/arch/kernel/cpu/jmp.hpp @@ -1,6 +1,8 @@ #ifndef TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP #define TEACHOS_ARCH_X86_64_KERNEL_CPU_JMP_HPP +#include "arch/context_switching/interrupt_descriptor_table/segment_selector.hpp" + #include <cstdint> namespace teachos::arch::kernel::cpu @@ -10,14 +12,15 @@ namespace teachos::arch::kernel::cpu */ struct [[gnu::packed]] far_pointer { - uint64_t offset; ///< Selector of the segment in which the jump occurs. - uint16_t segment; ///< Address to jump to within the segment. + uint64_t offset; ///< Selector of the segment in which the jump occurs. (0- 63) + context_switching::interrupt_descriptor_table::segment_selector + selector; ///< Address to jump to within the segment. (64 - 79) }; /** * @brief Near jump - A jump to an instruction within the current code segment. * - * @param address to jump to. + * @param address Address we want to jump to. */ auto jmp(uint64_t address) -> void; @@ -25,10 +28,9 @@ namespace teachos::arch::kernel::cpu * @brief Far jump - A jump to an instruction located in a different segment than the current code segment but at the * same privilege level. * - * @param segment in which the jump occurs. - * @param offset to jump to. + * @param pointer 64-bit operand size far pointer that we should jump too. */ - auto jmp(uint64_t segment, uint64_t offset) -> void; + auto jmp(far_pointer pointer) -> void; } // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/src/boot/boot.s b/arch/x86_64/src/boot/boot.s index 4fb23e5..35a6121 100644 --- a/arch/x86_64/src/boot/boot.s +++ b/arch/x86_64/src/boot/boot.s @@ -366,7 +366,7 @@ segment_register_reload_pointer: ret _transition_to_long_mode: - call segment_register_reload_pointer + //call segment_register_reload_pointer xor %rax, %rax mov %rax, %ss 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 0555e4c..ddc098e 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 @@ -9,22 +9,12 @@ namespace teachos::arch::context_switching::interrupt_descriptor_table { auto create_interrupt_descriptor_table() -> interrupt_descriptor_table { - interrupt_descriptor_table idt{}; - - // Define basic exception handlers (at least for CPU exceptions 0x00-0x1F) - for (uint8_t vector = 0; vector < 32; ++vector) - { - uint64_t offset = reinterpret_cast<uint64_t>(default_exception_handler); // Use a real handler function - segment_selector selector{0U, segment_selector::REQUEST_LEVEL_KERNEL}; - ist_offset ist{0U}; // Default stack offset (can be updated for IST) - idt_flags flags{idt_flags::DESCRIPTOR_LEVEL_KERNEL | idt_flags::TRAP_GATE}; - - idt.push_back(gate_descriptor{selector, ist, flags, offset}); - } - - // Additional entries for hardware interrupts (IRQs) and syscalls can be added here - - return idt; + uint64_t offset = 0U; + segment_selector selector{0U, segment_selector::REQUEST_LEVEL_KERNEL}; + ist_offset ist{0U}; + idt_flags flags{idt_flags::DESCRIPTOR_LEVEL_KERNEL}; + gate_descriptor gate_descriptor{selector, ist, flags, offset}; + return interrupt_descriptor_table{gate_descriptor}; } } // namespace diff --git a/arch/x86_64/src/context_switching/main.cpp b/arch/x86_64/src/context_switching/main.cpp index 95a25e0..c3c0cf0 100644 --- a/arch/x86_64/src/context_switching/main.cpp +++ b/arch/x86_64/src/context_switching/main.cpp @@ -13,7 +13,10 @@ namespace teachos::arch::context_switching decltype(auto) global_descriptor_table = segment_descriptor_table::initialize_global_descriptor_table(); decltype(auto) interrupt_descriptor_table = interrupt_descriptor_table::initialize_interrupt_descriptor_table(); - kernel::cpu::jmp((uint64_t)&global_descriptor_table.at(1), boot::segment_register_reload_pointer); + interrupt_descriptor_table::segment_selector segment_selector{ + 1U, interrupt_descriptor_table::segment_selector::REQUEST_LEVEL_KERNEL}; + kernel::cpu::far_pointer pointer{boot::segment_register_reload_pointer, segment_selector}; + kernel::cpu::jmp(pointer); // 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 * 16) = 80 diff --git a/arch/x86_64/src/kernel/cpu/if.cpp b/arch/x86_64/src/kernel/cpu/if.cpp index 2a25df5..60a90a3 100644 --- a/arch/x86_64/src/kernel/cpu/if.cpp +++ b/arch/x86_64/src/kernel/cpu/if.cpp @@ -2,4 +2,6 @@ namespace teachos::arch::kernel::cpu { auto set_interrupt_flag() -> void { asm volatile("sti"); } + auto clear_interrupt_flag() -> void { asm volatile("cli"); } + } // namespace teachos::arch::kernel::cpu diff --git a/arch/x86_64/src/kernel/cpu/jmp.cpp b/arch/x86_64/src/kernel/cpu/jmp.cpp index 009981b..205c4a9 100644 --- a/arch/x86_64/src/kernel/cpu/jmp.cpp +++ b/arch/x86_64/src/kernel/cpu/jmp.cpp @@ -7,10 +7,8 @@ namespace teachos::arch::kernel::cpu asm volatile("jmp *%[input]" : /* no output from call */ : [input] "r"(address)); } - auto jmp(uint64_t segment, uint64_t offset) -> void + auto jmp(far_pointer pointer) -> void { - far_pointer far_pointer = {offset, static_cast<uint16_t>(segment)}; - asm volatile("jmp *%0" : : "m"(far_pointer)); + asm volatile("jmp *%[input]" : /* no output from call */ : [input] "m"(pointer)); } - } // namespace teachos::arch::kernel::cpu |
