diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2024-10-17 13:12:29 +0200 |
|---|---|---|
| committer | Matteo Gmür <matteo.gmuer1@ost.ch> | 2024-10-17 13:12:29 +0200 |
| commit | b865b36b38d951de28cc4df5fa67338b8245a1c3 (patch) | |
| tree | 694825047086e18855bdb34fc24698292f6258ff | |
| parent | d539ed1f4f26a42959bcae6ea3050b7f99f5f872 (diff) | |
| download | teachos-b865b36b38d951de28cc4df5fa67338b8245a1c3.tar.xz teachos-b865b36b38d951de28cc4df5fa67338b8245a1c3.zip | |
Implement support for `std::terminate` via `::abort`
| -rw-r--r-- | arch/x86_64/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/exception_handling/assert.hpp | 7 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/exception_handling/panic.hpp | 13 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/kernel/halt.hpp | 9 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/video/vga/text.hpp | 5 | ||||
| -rw-r--r-- | arch/x86_64/src/boot/boot.s | 13 | ||||
| -rw-r--r-- | arch/x86_64/src/exception_handling/abort.cpp | 17 | ||||
| -rw-r--r-- | arch/x86_64/src/exception_handling/assert.cpp | 16 | ||||
| -rw-r--r-- | arch/x86_64/src/exception_handling/panic.cpp | 23 | ||||
| -rw-r--r-- | arch/x86_64/src/kernel/main.cpp | 3 | ||||
| -rw-r--r-- | arch/x86_64/src/video/vga/text.cpp | 22 | ||||
| -rw-r--r-- | src/kernel/main.cpp | 8 |
12 files changed, 119 insertions, 19 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index 603393c..3f67d71 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -51,7 +51,9 @@ target_sources("_memory" PRIVATE #]============================================================================] target_sources("_exception" PRIVATE + "src/exception_handling/abort.cpp" "src/exception_handling/assert.cpp" + "src/exception_handling/panic.cpp" ) #[============================================================================[ diff --git a/arch/x86_64/include/arch/exception_handling/assert.hpp b/arch/x86_64/include/arch/exception_handling/assert.hpp index eba43ac..f355a61 100644 --- a/arch/x86_64/include/arch/exception_handling/assert.hpp +++ b/arch/x86_64/include/arch/exception_handling/assert.hpp @@ -1,3 +1,6 @@ +#ifndef TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_ASSERT_HPP +#define TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_ASSERT_HPP + namespace teachos::arch::exception_handling { /** @@ -8,4 +11,6 @@ namespace teachos::arch::exception_handling * @param message */ auto assert(bool condition, char const * message) -> void; -} // namespace teachos::arch::exception_handling
\ No newline at end of file +} // namespace teachos::arch::exception_handling + +#endif
\ No newline at end of file diff --git a/arch/x86_64/include/arch/exception_handling/panic.hpp b/arch/x86_64/include/arch/exception_handling/panic.hpp new file mode 100644 index 0000000..9566159 --- /dev/null +++ b/arch/x86_64/include/arch/exception_handling/panic.hpp @@ -0,0 +1,13 @@ +#ifndef TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_PANIC_HPP +#define TEACHOS_ARCH_X86_64_EXCEPTION_HANDLING_PANIC_HPP + +namespace teachos::arch::exception_handling +{ + /** + * @brief Print a kernel panic message and then halt the system. + */ + [[noreturn]] auto panic(char const * reason) -> void; + [[noreturn]] auto panic(char const * prefix, char const * reason) -> void; +} // namespace teachos::arch::exception_handling + +#endif
\ No newline at end of file diff --git a/arch/x86_64/include/arch/kernel/halt.hpp b/arch/x86_64/include/arch/kernel/halt.hpp new file mode 100644 index 0000000..6c58938 --- /dev/null +++ b/arch/x86_64/include/arch/kernel/halt.hpp @@ -0,0 +1,9 @@ +#ifndef TEACHOS_ARCH_X86_64_KERNEL_HALT_HPP +#define TEACHOS_ARCH_X86_64_KERNEL_HALT_HPP + +namespace teachos::arch::kernel +{ + extern "C" [[noreturn]] auto halt() -> void; +} + +#endif
\ No newline at end of file diff --git a/arch/x86_64/include/arch/video/vga/text.hpp b/arch/x86_64/include/arch/video/vga/text.hpp index cfafce0..690f4aa 100644 --- a/arch/x86_64/include/arch/video/vga/text.hpp +++ b/arch/x86_64/include/arch/video/vga/text.hpp @@ -100,6 +100,11 @@ namespace teachos::arch::video::vga::text auto cursor(bool enabled) -> void; /** + * @brief Move the cursor to a new line, scrolling the buffer if necessary. + */ + auto newline() -> void; + + /** * @brief Write a string of code points to the VGA text buffer. * * @note This function also updates the text mode buffer pointer. diff --git a/arch/x86_64/src/boot/boot.s b/arch/x86_64/src/boot/boot.s index 2aa30c6..710d4ce 100644 --- a/arch/x86_64/src/boot/boot.s +++ b/arch/x86_64/src/boot/boot.s @@ -82,6 +82,7 @@ global_descriptor_table_pointer: * We are going to print some messages in case we panic during boot, so we are * going to store them here as well */ +.global message_prefix_panic message_prefix_panic: .string "TeachOS Panic: " message_not_loaded_by_multiboot2: @@ -109,6 +110,12 @@ vga_buffer_pointer: .long 0xb8000 .align 16 .code32 +.global halt +halt: +1: + hlt + jmp 1b + /** * Print a given panic message and then halt the machine. * @@ -129,7 +136,7 @@ _panic: call _print add $8, %esp - hlt + call halt /** * Print a message via the VGA buffer. @@ -189,7 +196,7 @@ _start: lgdt (global_descriptor_table_pointer) jmp $global_descriptor_table_code,$_transition_to_long_mode - hlt + call halt /** * Assert that the CPU supports going into long mode. @@ -354,4 +361,4 @@ _transition_to_long_mode: call _init call kernel_main - hlt + call halt diff --git a/arch/x86_64/src/exception_handling/abort.cpp b/arch/x86_64/src/exception_handling/abort.cpp new file mode 100644 index 0000000..dc40008 --- /dev/null +++ b/arch/x86_64/src/exception_handling/abort.cpp @@ -0,0 +1,17 @@ +#include "arch/exception_handling/panic.hpp" + +#include <cstdlib> + +namespace teachos::arch::exception_handling +{ + + /** + * @brief Override for the newlib abort function. + * + * newlib defines @p ::abort as a weak symbol, thus allowing implementations to override it by simply providing a + * matching implementation. Since the default implemenatation calls a number of functions the kernel does not + * currently implement, @p ::abort gets overridden to simply panic. + */ + extern "C" auto abort() -> void { panic("Terminate was called, possibly due to an unhandled exception"); } + +} // namespace teachos::arch::exception_handling
\ No newline at end of file diff --git a/arch/x86_64/src/exception_handling/assert.cpp b/arch/x86_64/src/exception_handling/assert.cpp index b55da49..86696f8 100644 --- a/arch/x86_64/src/exception_handling/assert.cpp +++ b/arch/x86_64/src/exception_handling/assert.cpp @@ -1,4 +1,6 @@ -#include "arch/video/vga/text.hpp" +#include "arch/exception_handling/assert.hpp" + +#include "arch/exception_handling/panic.hpp" namespace teachos::arch::exception_handling { @@ -9,16 +11,6 @@ namespace teachos::arch::exception_handling return; } - video::vga::text::write("Assert failed: ", video::vga::text::common_attributes::green_on_black); - video::vga::text::write(message, video::vga::text::common_attributes::green_on_black); - for (;;) - { - // Trick the compiler into thinking the variable is changes at run time, - // to prevent the while loop being optimized away - // See - // https://stackoverflow.com/questions/9495856/how-to-prevent-g-from-optimizing-out-a-loop-controlled-by-a-variable-that-can - // for more information. - asm volatile("" : "+g"(condition)); - } + panic("Assertion Violation: ", message); } } // namespace teachos::arch::exception_handling
\ No newline at end of file diff --git a/arch/x86_64/src/exception_handling/panic.cpp b/arch/x86_64/src/exception_handling/panic.cpp new file mode 100644 index 0000000..56edfd5 --- /dev/null +++ b/arch/x86_64/src/exception_handling/panic.cpp @@ -0,0 +1,23 @@ +#include "arch/exception_handling/panic.hpp" + +#include "arch/kernel/halt.hpp" +#include "arch/video/vga/text.hpp" + +namespace teachos::arch::exception_handling +{ + + extern "C" char const message_prefix_panic[]; + + auto panic(char const * reason) -> void { panic(message_prefix_panic, reason); } + + auto panic(char const * prefix, char const * reason) -> void + { + using video::vga::text::common_attributes::white_on_red; + + video::vga::text::newline(); + video::vga::text::write(prefix, white_on_red); + video::vga::text::write(reason, white_on_red); + + kernel::halt(); + }; +} // namespace teachos::arch::exception_handling
\ 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 12498d0..babe251 100644 --- a/arch/x86_64/src/kernel/main.cpp +++ b/arch/x86_64/src/kernel/main.cpp @@ -165,7 +165,6 @@ namespace teachos::arch::kernel auto allocator = arch::memory::area_frame_allocator(kernel_start, kernel_end, multiboot_start, multiboot_end, memory_areas, area_count); - // WATCH OUT: using optional::value() crashes the build... I think its because of missing exception handling auto last_allocated = allocator.allocate_frame(); auto allocated = last_allocated; do @@ -174,6 +173,6 @@ namespace teachos::arch::kernel allocated = allocator.allocate_frame(); } while (allocated.has_value()); video::vga::text::write("Allocated Frames", video::vga::text::common_attributes::green_on_black); - video::vga::text::write_number(allocated->frame_number, video::vga::text::common_attributes::green_on_black); + video::vga::text::write_number(allocated.value().frame_number, video::vga::text::common_attributes::green_on_black); } } // namespace teachos::arch::kernel diff --git a/arch/x86_64/src/video/vga/text.cpp b/arch/x86_64/src/video/vga/text.cpp index a613c3b..c14de16 100644 --- a/arch/x86_64/src/video/vga/text.cpp +++ b/arch/x86_64/src/video/vga/text.cpp @@ -13,6 +13,8 @@ namespace teachos::arch::video::vga::text namespace { auto constexpr default_text_buffer_address = 0xb8000; + auto constexpr default_text_buffer_width = 80; + auto constexpr default_text_buffer_height = 25; extern "C" std::pair<char, attribute> * vga_buffer_pointer; auto constinit text_buffer = teachos::memory::asm_pointer{vga_buffer_pointer}; @@ -32,6 +34,26 @@ namespace teachos::arch::video::vga::text crtc::data_port::write(vga::crtc::data_port::read() | cursor_disable_byte); } + auto newline() -> void + { + auto base = reinterpret_cast<decltype(text_buffer)::pointer>(default_text_buffer_address); + auto & raw_buffer = *text_buffer; + auto current_line = (raw_buffer - base) / default_text_buffer_width; + auto next_line = current_line + 1; + + if (next_line >= default_text_buffer_height) + { + auto begin = base + default_text_buffer_width; + auto end = base + default_text_buffer_width * default_text_buffer_height; + std::ranges::move(begin, end, base); + raw_buffer = base + current_line * default_text_buffer_width; + } + else + { + raw_buffer = base + next_line * default_text_buffer_width; + } + } + auto write_char(char code_point, attribute attribute) -> void { auto & p = *text_buffer; diff --git a/src/kernel/main.cpp b/src/kernel/main.cpp index 4799b29..36c6d92 100644 --- a/src/kernel/main.cpp +++ b/src/kernel/main.cpp @@ -1,3 +1,9 @@ #include "arch/kernel/main.hpp" -extern "C" auto kernel_main() -> void { teachos::arch::kernel::main(); } +#include "arch/exception_handling/panic.hpp" + +extern "C" auto kernel_main() -> void +{ + teachos::arch::kernel::main(); + teachos::arch::exception_handling::panic("Architecture specific main returned!"); +} |
