From 3a2efa4ebc6b07a2304416262d5032a32dcddd8b Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 14 Jul 2025 13:06:17 +0000 Subject: x86_64: fix syscall error code reading --- arch/x86_64/src/context_switching/syscall/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86_64/src/context_switching/syscall/main.cpp b/arch/x86_64/src/context_switching/syscall/main.cpp index e291c10..b4ab468 100644 --- a/arch/x86_64/src/context_switching/syscall/main.cpp +++ b/arch/x86_64/src/context_switching/syscall/main.cpp @@ -27,7 +27,7 @@ namespace teachos::arch::context_switching::syscall asm volatile("mov %%r9, %[output]" : [output] "=m"(values.arg_5)); error error_code{}; - asm volatile("mov %%rax, %[output]" : [output] "=m"(error_code)); + asm volatile("mov %%al, %[output]" : [output] "=m"(error_code)); return {error_code, values}; } -- cgit v1.2.3 From d275ced60d63b1618169d755d228a860dfd23237 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 14 Jul 2025 13:06:47 +0000 Subject: memory: adapt to changes memory layout --- arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 81ac0cb..3afb54b 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -127,8 +127,8 @@ namespace teachos::arch::memory::paging std::array constexpr USER_SECTION_BASES = { 0x102000, // .boot_bss (Contains statically allocated variables) 0x209000, // .stl_text (Contains code for custom std implementations and standard library code) - 0x218000, // .user_text (Contains the actual user code executed) - 0x21F000, // .user_data (Contains static user variables) + 0x217000, // .user_text (Contains the actual user code executed) + 0x21E000, // .user_data (Contains static user variables) 0x20A000 // .text (Necessary, because symbols for all template standard library features are placed here if // they were first used in the Kernel Code Section) -- cgit v1.2.3 From 9bfd5652e865505ae73f5ae3ba70f384d7418e84 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 14 Jul 2025 13:07:01 +0000 Subject: build: upgrade x86-64 toolchain --- .vscode/launch.json | 2 +- cmake/Platforms/x86_64.cmake | 78 ++++++++++++++++++++++++++++++-------------- 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index e522ad5..3b53048 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,7 +11,7 @@ "gdbpath": "x86_64-pc-elf-gdb", "cwd": "${workspaceFolder}", "preLaunchTask": "QEMU (gdb)", - "executable": "${command:cmake.buildDirectory}/bin/${command:cmake.buildType}/_kernel", + "executable": "${command:cmake.buildDirectory}/bin/${command:cmake.buildType}/_kernel.elf", "autorun": [ "-enable-pretty-printing", "-break-insert _start" diff --git a/cmake/Platforms/x86_64.cmake b/cmake/Platforms/x86_64.cmake index e0518b5..29af020 100644 --- a/cmake/Platforms/x86_64.cmake +++ b/cmake/Platforms/x86_64.cmake @@ -1,35 +1,65 @@ -execute_process(COMMAND "x86_64-pc-elf-g++" "-mno-red-zone" "-print-file-name=crtbegin.o" - OUTPUT_VARIABLE CRT_BEGIN - ERROR_QUIET -) -string(STRIP "${CRT_BEGIN}" CRT_BEGIN) -mark_as_advanced(CRT_BEGIN) +include_guard(GLOBAL) -string(REGEX REPLACE "/crtbegin.o" "" CMAKE_SYSROOT "${CRT_BEGIN}") -mark_as_advanced(CMAKE_SYSROOT) +macro(find_compiler_file NAME OUTPUT_VARIABLE) + execute_process(COMMAND + "${CMAKE_CXX_COMPILER}" + "-mno-red-zone" + "-print-file-name=${NAME}" + OUTPUT_STRIP_TRAILING_WHITESPACE + OUTPUT_VARIABLE "${OUTPUT_VARIABLE}" + ERROR_QUIET + ) + mark_as_advanced("${OUTPUT_VARIABLE}") +endmacro() -set(SYSTEM_NAME "Generic") +set(PLATFORM_TARGET "x86_64-pc-elf") set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") -set(CMAKE_C_COMPILER "x86_64-pc-elf-gcc") -set(CMAKE_CXX_COMPILER "x86_64-pc-elf-g++") +set(CMAKE_SYSTEM_NAME "Generic-ELF") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_ASM_COMPILER_TARGET "${PLATFORM_TARGET}") +set(CMAKE_CXX_COMPILER_TARGET "${PLATFORM_TARGET}") + +find_program(CMAKE_ASM_COMPILER "${CMAKE_ASM_COMPILER_TARGET}-gcc" REQUIRED) +find_program(CMAKE_CXX_COMPILER "${CMAKE_CXX_COMPILER_TARGET}-g++" REQUIRED) + +set(CMAKE_CXX_FLAGS_INIT +"-mno-red-zone \ +-mcmodel=large \ +-fno-rtti \ +-fno-exceptions \ +-ffunction-sections \ +-fdata-sections" +) -set(CMAKE_CXX_FLAGS_INIT "-m64 -mno-red-zone -mcmodel=large -fno-rtti -fno-exceptions -ffunction-sections -fdata-sections") set(CMAKE_CXX_FLAGS_DEBUG "-ggdb3") set(CMAKE_ASM_FLAGS_DEBUG "-ggdb3") -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-ggdb3") -set(CMAKE_ASM_FLAGS_RELWITHDEBINFO "-ggdb3") + +set(CMAKE_ASM_FLAGS_MINSIZEREL "-Os -DNDEBUG -ggdb3") +set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG -ggdb3") + +set(CMAKE_ASM_FLAGS_RELEASE "-O3 -DNDEBUG -ggdb3") +set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -ggdb3") + +set(CMAKE_ASM_FLAGS_RELWITHDEBINFO "-O2 -DNDEBUG -ggdb3") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -DNDEBUG -ggdb3") + set(CMAKE_EXE_LINKER_FLAGS_INIT "-nostartfiles -Wl,--gc-sections") + +find_compiler_file("crtbegin.o" CRT_BEGIN_PATH) +find_compiler_file("crtend.o" CRT_END_PATH) + set(CMAKE_CXX_LINK_EXECUTABLE - " \ - \ - \ - \ - ${CMAKE_SYSROOT}/crtbegin.o \ - \ - -o \ - \ - -lgcc \ - ${CMAKE_SYSROOT}/crtend.o" +" \ + \ + \ + \ +${CRT_BEGIN_PATH} \ + \ +-o \ + \ +-lgcc \ +${CRT_END_PATH}" ) -- cgit v1.2.3 From 22fbbf849497c32f5b237ab70e9ed8aef63e54cf Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 14 Jul 2025 15:21:32 +0000 Subject: libs: extract multiboot library --- CMakeLists.txt | 6 + arch/x86_64/CMakeLists.txt | 4 + libs/multiboot2/CMakeLists.txt | 26 ++++ libs/multiboot2/include/multiboot2/constants.hpp | 20 +++ libs/multiboot2/include/multiboot2/impl/data.hpp | 130 +++++++++++++++++ libs/multiboot2/include/multiboot2/impl/ids.hpp | 79 ++++++++++ .../include/multiboot2/impl/iterator.hpp | 63 ++++++++ libs/multiboot2/include/multiboot2/impl/tag.hpp | 113 +++++++++++++++ libs/multiboot2/include/multiboot2/information.hpp | 160 +++++++++++++++++++++ 9 files changed, 601 insertions(+) create mode 100644 libs/multiboot2/CMakeLists.txt create mode 100644 libs/multiboot2/include/multiboot2/constants.hpp create mode 100644 libs/multiboot2/include/multiboot2/impl/data.hpp create mode 100644 libs/multiboot2/include/multiboot2/impl/ids.hpp create mode 100644 libs/multiboot2/include/multiboot2/impl/iterator.hpp create mode 100644 libs/multiboot2/include/multiboot2/impl/tag.hpp create mode 100644 libs/multiboot2/include/multiboot2/information.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c0e45f8..8fef2f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,6 +77,12 @@ add_compile_options( "$<$:-pedantic-errors>" ) +#[============================================================================[ +# Global Libraries +#]============================================================================] + +add_subdirectory("libs/multiboot2" EXCLUDE_FROM_ALL SYSTEM) + #[============================================================================[ # Global Directories #]============================================================================] diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index 57b3a60..bd06ea7 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -69,6 +69,10 @@ target_sources("_memory" PRIVATE "src/memory/heap/global_heap_allocator.cpp" ) +target_link_libraries("_memory" PUBLIC + "multiboot2::multiboot2" +) + #[============================================================================[ # The STL Library #]============================================================================] diff --git a/libs/multiboot2/CMakeLists.txt b/libs/multiboot2/CMakeLists.txt new file mode 100644 index 0000000..af56d5a --- /dev/null +++ b/libs/multiboot2/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION "3.27") + +project("multiboot2" + LANGUAGES CXX + VERSION "1.0.0" +) + +add_library("multiboot2" INTERFACE) +add_library("multiboot2::multiboot2" ALIAS "multiboot2") + +target_sources("multiboot2" INTERFACE + FILE_SET HEADERS + BASE_DIRS "include" + FILES + "include/multiboot2/constants.hpp" + "include/multiboot2/information.hpp" + + "include/multiboot2/impl/data.hpp" + "include/multiboot2/impl/ids.hpp" + "include/multiboot2/impl/iterator.hpp" + "include/multiboot2/impl/tag.hpp" +) + +target_include_directories("multiboot2" INTERFACE + "include" +) diff --git a/libs/multiboot2/include/multiboot2/constants.hpp b/libs/multiboot2/include/multiboot2/constants.hpp new file mode 100644 index 0000000..30d52d0 --- /dev/null +++ b/libs/multiboot2/include/multiboot2/constants.hpp @@ -0,0 +1,20 @@ +#ifndef MULTIBOOT2_CONSTANTS_HPP +#define MULTIBOOT2_CONSTANTS_HPP + +#include "impl/ids.hpp" // IWYU pragma: export + +#include + +namespace multiboot2 +{ + + using impl::architecture_id; + using impl::information_id; + using impl::memory_type; + using impl::tag_id; + + auto constexpr inline header_magic = std::uint32_t{0xe85250d6}; + +} // namespace multiboot2 + +#endif diff --git a/libs/multiboot2/include/multiboot2/impl/data.hpp b/libs/multiboot2/include/multiboot2/impl/data.hpp new file mode 100644 index 0000000..367e8cb --- /dev/null +++ b/libs/multiboot2/include/multiboot2/impl/data.hpp @@ -0,0 +1,130 @@ +#ifndef MULTIBOOT2_IMPL_DATA_HPP +#define MULTIBOOT2_IMPL_DATA_HPP + +#include "multiboot2/impl/ids.hpp" + +#include + +namespace multiboot2::impl +{ + template + struct tag_data + { + auto constexpr inline static id = Id; + }; + + /** + * @brief Basic system memory information + */ + struct basic_memory_data : tag_data + { + /** + * @brief Amount of lower memory (below 1MiB) available to the system. + * + * The maximum possible value for this field is 640 KiB. + */ + std::uint32_t const lower_KiB; + + /** + * @brief Amount of upper memory (above 1MiB) available to the system. + * + * The maximum possible value for this field is the address of the first upper memory hole minus 1MiB. + */ + std::uint32_t const upper_KiB; + }; + + /** + * @brief Device the image got loaded from + */ + struct bios_boot_device_data : tag_data + { + /** + * @brief BIOS device number as understood by INT 13h. + */ + std::uint32_t device_number; + + /** + * @brief Number of the primary partition. + */ + std::uint32_t partition_number; + + /** + * @brief Number the sub-partion on the primary partition. + */ + std::uint32_t sub_partition_number; + }; + + /** + * @brief Supplied image command line + */ + struct command_line_data : tag_data + { + /* This struct intentionally left blank. */ + }; + + /** + * @brief ELF symbols of the image + */ + struct elf_symbols_data : tag_data + { + std::uint32_t count; + std::uint32_t entry_size; + std::uint32_t string_table_index; + }; + + /** + * @brief Name of the boot loader + */ + struct loader_name_data : tag_data + { + /* This struct intentionally left blank. */ + }; + + /** + * @brief Detailed map of the memory regions present in the system + * + */ + struct memory_map_data : tag_data + { + /** + * @brief A region of memory + */ + struct region + { + /** + * @brief Check if the memory described by this region is available for use. + */ + auto constexpr available() const noexcept { return type == memory_type::AVAILABLE; } + + /** + * @brief Start address of this region + */ + std::uint64_t const base; + + /** + * @brief Size of this region in bytes. + */ + std::uint64_t const size_in_B; + + /** + * @brief Type of this region. + */ + memory_type const type; + + std::uint32_t : 0; + }; + + /** + * @brief Size of each entry present in the map + */ + std::uint32_t const entry_size; + + /** + * @brief Version of each entry present in the map + */ + std::uint32_t const entry_version; + }; + +} // namespace multiboot2::impl + +#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/impl/ids.hpp b/libs/multiboot2/include/multiboot2/impl/ids.hpp new file mode 100644 index 0000000..3a7215e --- /dev/null +++ b/libs/multiboot2/include/multiboot2/impl/ids.hpp @@ -0,0 +1,79 @@ +#ifndef MULTIBOOT2_IMPL_IDS_HPP +#define MULTIBOOT2_IMPL_IDS_HPP + +#include + +namespace multiboot2::impl +{ + + /** + * @brief Information tag IDs. + */ + enum struct information_id : std::uint32_t + { + END, ///< Signals final tag for the multiboot2 information structure. + CMDLINE, ///< Contains the command line string. + BOOT_LOADER_NAME, ///< Contains the name of the boot loader booting the kernel. + MODULE, ///< Indicates the boot module which was loaded along the kernel image. + BASIC_MEMORY_INFO, ///< Contains the amount of lower (0MB start address) and upper memory (1MB start address). + BOOTDEV, ///< Indicates which BIOS disk device the hoot loader has loaded the OS image from. + MEMORY_MAP, ///< Describes the memory layout of the system with individual areas and their flags. + VBE_INFO, ///< Includes information to access and utilize the device GPU. + FRAMEBUFFER, ///< VBE framebuffer information. + ELF_SECTIONS, ///< Includes list of all section headers from the loaded ELF kernel. + APM_INFO, ///< Advanced Power Management information. + EFI32, ///< EFI 32 bit system table pointer. + EFI64, ///< EFI 64 bit system table pointer. + SMBIOS, ///< Contains copy of all Sytem Management BIOS tables. + ACPI_OLD, ///< Contains copy of RSDP as defined per ACPI1.0 specification. + ACPI_NEW, ///< Contains copy of RSDP as defined per ACPI2.0 or later specification. + NETWORK, ///< Contains network information specified specified as DHCP. + EFI_MEMORY_MAP, ///< Contains EFI memory map. + EFI_BS_NOT_TERMINATED, ///< Indicated ExitBootServies wasn't called. + EFI32_IMAGE_HANDLE, ///< EFI 32 bit image handle pointer. + EFI64_IMAGE_HANDLE, ///< EFI 64 bit imae handle pointer. + LOAD_BASE_ADDRESS ///< Contains image load base physical address. + }; + + /** + * @brief Header tag IDs. + */ + enum struct tag_id : std::uint32_t + { + END, + INFORMATION_REQUEST, + ADDRESSES, + ENTRY_ADDRESS, + CONSOLE_FLAGS, + PREFERRED_FRAMEBUFFER_MODE, + PAGE_ALIGN_MODULES, + EFI_BOOT_SERVICES_SUPPORTED, + EFI32_ENTRY_ADDRESS, + EFI64_ENTRY_ADDRESS, + RELOCATABLE, + }; + + /** + * @brief System architecture IDs. + */ + enum struct architecture_id : std::uint32_t + { + I386 = 0, + MIPS32 = 4, + }; + + /** + * @brief Memory type IDs. + */ + enum struct memory_type : std::uint32_t + { + AVAILABLE = 1, + RESERVED, + ACPI_RECLAIMABLE, + NON_VOLATILE_STORAGE, + BAD_RAM, + }; + +} // namespace multiboot2::impl + +#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/impl/iterator.hpp b/libs/multiboot2/include/multiboot2/impl/iterator.hpp new file mode 100644 index 0000000..b84ef2c --- /dev/null +++ b/libs/multiboot2/include/multiboot2/impl/iterator.hpp @@ -0,0 +1,63 @@ +#ifndef MULTIBOOT2_IMPL_INFORMATION_ITERATOR_HPP +#define MULTIBOOT2_IMPL_INFORMATION_ITERATOR_HPP + +#include "multiboot2/impl/ids.hpp" +#include "multiboot2/impl/tag.hpp" + +#include +#include +#include + +namespace multiboot2::impl +{ + + struct information_iterator + { + using iterator_category = std::forward_iterator_tag; + using value_type = impl::tag_header; + using pointer = value_type const *; + using reference = value_type const &; + using difference_type = std::ptrdiff_t; + + constexpr information_iterator() = default; + + constexpr explicit information_iterator(impl::tag_header const * offset) + : m_current(offset) + { + } + + auto constexpr operator==(information_iterator const &) const noexcept -> bool = default; + + auto constexpr operator*() const noexcept -> reference { return *(m_current.value()); } + + auto constexpr operator->() const noexcept -> pointer { return m_current.value(); } + + auto constexpr operator++() noexcept -> information_iterator & + { + if (m_current) + { + if (auto next = m_current.value()->next(); next->information_id() != information_id::END) + { + m_current = next; + } + m_current.reset(); + } + return *this; + } + + auto constexpr operator++(int) noexcept -> information_iterator + { + auto copy = *this; + ++(*this); + return copy; + } + + private: + std::optional m_current{}; + }; + + static_assert(std::input_or_output_iterator); + +} // namespace multiboot2::impl + +#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/impl/tag.hpp b/libs/multiboot2/include/multiboot2/impl/tag.hpp new file mode 100644 index 0000000..f7471a4 --- /dev/null +++ b/libs/multiboot2/include/multiboot2/impl/tag.hpp @@ -0,0 +1,113 @@ +#ifndef MULTIBOOT2_IMPL_TAG_HPP +#define MULTIBOOT2_IMPL_TAG_HPP + +#include "multiboot2/impl/ids.hpp" + +#include +#include +#include + +namespace multiboot2::impl +{ + + /** + * @brief Header data and functionality shared by all tags. + */ + struct tag_header + { + tag_header() + : m_id{} + , m_size{} + { + } + + tag_header(tag_header const * data) + : tag_header{*data} + { + } + + auto full_size() const noexcept -> std::size_t { return (m_size + 7) & (~7); } + + auto information_id() const noexcept -> impl::information_id const & { return m_id; } + + auto next() const noexcept -> tag_header const * + { + return std::bit_cast(std::bit_cast(this) + full_size()); + } + + auto unaligned_size() const noexcept -> std::uint32_t { return m_size; } + + protected: + impl::information_id const m_id; + std::uint32_t const m_size; + }; + + /** + * @brief A tag containing no variable length array data. + */ + template + struct tag : tag_header, Data + { + tag() + : tag_header{} + , Data{} + { + } + + explicit tag(tag_header const * header) + requires(sizeof(tag) > sizeof(tag_header)) + : tag_header{header} + , Data{*std::bit_cast(header + 1)} + { + } + + explicit tag(tag_header const * header) + requires(sizeof(tag) == sizeof(tag_header)) + : tag_header{header} + , Data{} + { + } + }; + + /** + * @brief A tag containing variable length array data. + */ + template typename Range> + struct vla_tag : tag + { + using range_type = Range; + + vla_tag() + : tag{} + , m_vla{} + { + } + + explicit vla_tag(tag_header const * header) + : tag{header} + , m_vla{vla_start(header), vla_size(header)} + { + } + + protected: + auto static vla_start(tag_header const * header) noexcept -> VlaData * + { + auto raw = std::bit_cast(header); + auto start = raw + sizeof(tag); + return std::bit_cast(start); + } + + auto static vla_size(tag_header const * header) noexcept -> std::size_t + { + auto size = (header->unaligned_size() - sizeof(tag) - + std::is_same_v> * 1) / + sizeof(VlaData); + return size; + } + + range_type const m_vla; + }; + +} // namespace multiboot2::impl + +#endif \ No newline at end of file diff --git a/libs/multiboot2/include/multiboot2/information.hpp b/libs/multiboot2/include/multiboot2/information.hpp new file mode 100644 index 0000000..04ba183 --- /dev/null +++ b/libs/multiboot2/include/multiboot2/information.hpp @@ -0,0 +1,160 @@ +#ifndef JOS_MULTIBOOT2_INFORMATION_HPP +#define JOS_MULTIBOOT2_INFORMATION_HPP + +#include "impl/data.hpp" +#include "impl/iterator.hpp" +#include "impl/tag.hpp" + +#include +#include +#include +#include +#include +#include + +namespace multiboot2 +{ + + /** + * @copydoc multiboot2::impl::basic_memory_data + */ + struct basic_memory : impl::tag + { + using tag::tag; + }; + + /** + * @copydoc multiboot2::impl::bios_boot_device_data + */ + struct bios_boot_device : impl::tag + { + using tag::tag; + }; + + /** + * @copydoc multiboot2::impl::command_line_data + */ + struct command_line : impl::vla_tag + { + using vla_tag::vla_tag; + + /** + * @brief The command line string + */ + auto string() const noexcept -> range_type { return m_vla; } + }; + + /** + * @copydoc multiboot2::impl::elf_symbols_data + */ + struct elf_symbols : impl::vla_tag + { + using vla_tag::vla_tag; + + using iterator = range_type::iterator; + + auto data() const noexcept -> range_type { return m_vla; } + }; + + /** + * @copydoc multiboot2::impl::loader_name_data + */ + struct loader_name : impl::vla_tag + { + using vla_tag::vla_tag; + + /** + * @brief The name of the bootloader + */ + auto string() const noexcept -> std::string_view { return m_vla; } + }; + + /** + * @copydoc multiboot2::impl::memory_map_data + */ + struct memory_map : impl::vla_tag + { + using vla_tag::vla_tag; + + using iterator = range_type::iterator; + + auto begin() const noexcept -> iterator { return regions().begin(); } + + auto end() const noexcept -> iterator { return regions().end(); } + + /** + * @brief The available memory regions + */ + auto regions() const noexcept -> range_type { return m_vla; } + }; + + struct information_view + { + using iterator = impl::information_iterator; + using value_type = impl::information_iterator::value_type; + using pointer = impl::information_iterator::pointer; + using reference = impl::information_iterator::reference; + + auto size_bytes() const noexcept -> std::size_t { return m_size; } + + // Range access + + auto begin() const noexcept -> iterator { return iterator{&m_tags}; } + + auto end() const noexcept -> iterator { return iterator{}; } + + // Tag access + + template + auto has() const noexcept -> bool + { + return get().has_value(); + } + + auto maybe_basic_memory() const noexcept -> std::optional { return get(); } + + auto basic_memory() const -> basic_memory { return maybe_basic_memory().value(); } + + auto maybe_bios_boot_device() const noexcept -> std::optional + { + return get(); + } + + auto bios_boot_device() const -> bios_boot_device { return maybe_bios_boot_device().value(); } + + auto maybe_command_line() const noexcept -> std::optional { return get(); } + + auto command_line() const -> command_line { return maybe_command_line().value(); } + + auto maybe_elf_symbols() const noexcept -> std::optional { return get(); } + + auto elf_symbols() const -> elf_symbols { return maybe_elf_symbols().value(); } + + auto maybe_loader_name() const noexcept -> std::optional { return get(); } + + auto loader_name() const -> loader_name { return maybe_loader_name().value(); } + + auto maybe_memory_map() const noexcept -> std::optional { return get(); } + + auto memory_map() const -> memory_map { return maybe_memory_map().value(); } + + private: + template + auto constexpr get() const noexcept -> std::optional + { + if (auto found = std::ranges::find_if(*this, [](auto tag) { return tag.information_id() == Tag::id; }); + found != end()) + { + return Tag{&*found}; + } + return std::nullopt; + } + + [[maybe_unused]] uint32_t const m_size{}; + uint32_t : 32; + impl::tag_header const m_tags{}; + }; + +} // namespace multiboot2 + +#endif \ No newline at end of file -- cgit v1.2.3 From e7eedd234954509f4f5ec52b2d62cbc4a1723936 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 14 Jul 2025 15:39:09 +0000 Subject: libs: begin extraction of kernel std --- CMakeLists.txt | 9 +- arch/x86_64/CMakeLists.txt | 13 +- .../arch/memory/heap/linked_list_allocator.hpp | 5 +- .../arch/memory/heap/user_heap_allocator.hpp | 5 +- .../arch/memory/multiboot/elf_symbols_section.hpp | 41 ++-- arch/x86_64/include/arch/memory/multiboot/info.hpp | 64 ------ .../include/arch/memory/multiboot/memory_map.hpp | 53 ----- .../include/arch/memory/multiboot/reader.hpp | 19 +- arch/x86_64/include/arch/stl/mutex.hpp | 60 ----- .../src/memory/heap/linked_list_allocator.cpp | 2 +- arch/x86_64/src/memory/multiboot/reader.cpp | 250 +++++++++++---------- arch/x86_64/src/stl/mutex.cpp | 16 -- libs/kstd/CMakeLists.txt | 24 ++ libs/kstd/include/kstd/mutex.hpp | 60 +++++ libs/kstd/src/mutex.cpp | 16 ++ 15 files changed, 273 insertions(+), 364 deletions(-) delete mode 100644 arch/x86_64/include/arch/memory/multiboot/info.hpp delete mode 100644 arch/x86_64/include/arch/memory/multiboot/memory_map.hpp delete mode 100644 arch/x86_64/include/arch/stl/mutex.hpp delete mode 100644 arch/x86_64/src/stl/mutex.cpp create mode 100644 libs/kstd/CMakeLists.txt create mode 100644 libs/kstd/include/kstd/mutex.hpp create mode 100644 libs/kstd/src/mutex.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fef2f5..75ac1b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,7 @@ add_compile_options( # Global Libraries #]============================================================================] +add_subdirectory("libs/kstd" EXCLUDE_FROM_ALL SYSTEM) add_subdirectory("libs/multiboot2" EXCLUDE_FROM_ALL SYSTEM) #[============================================================================[ @@ -133,13 +134,6 @@ add_library("teachos::interrupt_handling" ALIAS "_interrupt_handling") # https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#index-interrupt-function-attribute_002c-x86 target_compile_options("_interrupt_handling" PRIVATE "-mgeneral-regs-only") -#[============================================================================[ -# The Stub Standard Library -#]============================================================================] - -add_library("_stl" OBJECT) -add_library("teachos::stl" ALIAS "_stl") - #[============================================================================[ # The Kernel #]============================================================================] @@ -154,7 +148,6 @@ target_link_libraries("_kernel" PRIVATE "teachos::video" "teachos::memory" "teachos::exception" - "teachos::stl" "teachos::context_switching" "teachos::interrupt_handling" ) diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index bd06ea7..511fe43 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -71,14 +71,7 @@ target_sources("_memory" PRIVATE target_link_libraries("_memory" PUBLIC "multiboot2::multiboot2" -) - -#[============================================================================[ -# The STL Library -#]============================================================================] - -target_sources("_stl" PRIVATE - "src/stl/mutex.cpp" + "libs::kstd" ) #[============================================================================[ @@ -115,6 +108,10 @@ target_sources("_context" PRIVATE "src/context_switching/interrupt_descriptor_table/segment_selector.cpp" ) +target_link_libraries("_context" PUBLIC + "libs::kstd" +) + #[============================================================================[ # The Interrupt Handlers #]============================================================================] diff --git a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp index 582b4af..bbbad19 100644 --- a/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/linked_list_allocator.hpp @@ -3,7 +3,8 @@ #include "arch/memory/heap/heap_allocator.hpp" #include "arch/memory/heap/memory_block.hpp" -#include "arch/stl/mutex.hpp" + +#include namespace teachos::arch::memory::heap { @@ -112,7 +113,7 @@ namespace teachos::arch::memory::heap std::size_t size) -> void; memory_block * first; ///< First free entry in our memory. - stl::mutex mutex; ///< Mutex to ensure only one thread calls allocate or deallocate at once. + kstd::mutex mutex; ///< Mutex to ensure only one thread calls allocate or deallocate at once. }; } // namespace teachos::arch::memory::heap diff --git a/arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp b/arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp index 6b1b7bb..3b47f15 100644 --- a/arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp +++ b/arch/x86_64/include/arch/memory/heap/user_heap_allocator.hpp @@ -2,8 +2,9 @@ #define TEACHOS_ARCH_X86_64_MEMORY_HEAP_USER_HEAP_ALLOCATOR_HPP #include "arch/memory/heap/memory_block.hpp" -#include "arch/stl/mutex.hpp" +// #include +#include #include namespace teachos::arch::memory::heap @@ -141,7 +142,7 @@ namespace teachos::arch::memory::heap std::size_t size) -> void; memory_block * first = {}; ///< First free entry in our memory. - stl::mutex mutex = {}; ///< Mutex to ensure only one thread calls allocate or deallocate at once. + kstd::mutex mutex = {}; ///< Mutex to ensure only one thread calls allocate or deallocate at once. }; } // namespace teachos::arch::memory::heap diff --git a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp index 0a25ca9..348c159 100644 --- a/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/elf_symbols_section.hpp @@ -1,9 +1,9 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP #define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP -#include "arch/memory/multiboot/info.hpp" -#include "arch/stl/container.hpp" -#include "arch/stl/contiguous_pointer_iterator.hpp" +// #include "arch/memory/multiboot/info.hpp" +// #include "arch/stl/container.hpp" +// #include "arch/stl/contiguous_pointer_iterator.hpp" #include #include @@ -145,24 +145,25 @@ namespace teachos::arch::memory::multiboot auto is_null() const -> bool; }; - /** - * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type - * multi_boot_tag_type::ELF_SECTIONS. - * - * @note The first section in the sections array will always be INACTIVE, there can only ever be one DYNAMIC section - * and only either one DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE. - */ - struct elf_symbols_section_header - { - tag info; ///< Basic multi_boot_tag information. - uint32_t number_of_sections; ///< Number of sections in the sections array. - uint32_t entry_size; ///< Size of each entry in the sections array. - uint32_t section_index; ///< Index to the string table used for symbol names. - std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data. - ///< contained in the section, to ensure byte alignment is actually 4 byte. - }; + // /** + // * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type + // * multi_boot_tag_type::ELF_SECTIONS. + // * + // * @note The first section in the sections array will always be INACTIVE, there can only ever be one DYNAMIC + // section + // * and only either one DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE. + // */ + // struct elf_symbols_section_header + // { + // tag info; ///< Basic multi_boot_tag information. + // uint32_t number_of_sections; ///< Number of sections in the sections array. + // uint32_t entry_size; ///< Size of each entry in the sections array. + // uint32_t section_index; ///< Index to the string table used for symbol names. + // std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data. + // ///< contained in the section, to ensure byte alignment is actually 4 byte. + // }; - using elf_section_header_container = stl::container>; + // using elf_section_header_container = stl::container>; } // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/include/arch/memory/multiboot/info.hpp b/arch/x86_64/include/arch/memory/multiboot/info.hpp deleted file mode 100644 index a9abf12..0000000 --- a/arch/x86_64/include/arch/memory/multiboot/info.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP - -#include - -namespace teachos::arch::memory::multiboot -{ - /** - * @brief Defines all possible types a multiboot2 tag structure can have. - * - * @note See - * https://github.com/rhboot/grub2/blob/fedora-39/include/multiboot2.h for more information on the structure of the - * tag headers and see https://github.com/rhboot/grub2/blob/fedora-39/include/multiboot.h for more information on the - * actual header contents and their following data. - */ - enum struct tag_type : uint32_t - { - END, ///< Signals final tag for the multiboot2 information structure. - CMDLINE, ///< Contains the command line string. - BOOT_LOADER_NAME, ///< Contains the name of the boot loader booting the kernel. - MODULE, ///< Indicates the boot module which was loaded along the kernel image. - BASIC_MEMORY_INFO, ///< Contains the amount of lower (0MB start address) and upper memory (1MB start address). - BOOTDEV, ///< Indicates which BIOS disk device the hoot loader has loaded the OS image from. - MEMORY_MAP, ///< Describes the memory layout of the system with individual areas and their flags. - VBE_INFO, ///< Includes information to access and utilize the device GPU. - FRAMEBUFFER, ///< VBE framebuffer information. - ELF_SECTIONS, ///< Includes list of all section headers from the loaded ELF kernel. - APM_INFO, ///< Advanced Power Management information. - EFI32, ///< EFI 32 bit system table pointer. - EFI64, ///< EFI 64 bit system table pointer. - SMBIOS, ///< Contains copy of all Sytem Management BIOS tables. - ACPI_OLD, ///< Contains copy of RSDP as defined per ACPI1.0 specification. - ACPI_NEW, ///< Contains copy of RSDP as defined per ACPI2.0 or later specification. - NETWORK, ///< Contains network information specified specified as DHCP. - EFI_MEMORY_MAP, ///< Contains EFI memory map. - EFI_BS_NOT_TERMINATED, ///< Indicated ExitBootServies wasn't called. - EFI32_IMAGE_HANDLE, ///< EFI 32 bit image handle pointer. - EFI64_IMAGE_HANDLE, ///< EFI 64 bit imae handle pointer. - LOAD_BASE_ADDRESS ///< Contains image load base physical address. - }; - - /** - * @brief Basic structure that every entry in the multi_boot_tag array of the multi_boot_info struct has to begin - * with. - */ - struct tag - { - tag_type type; ///< Specific type of this multi_boot_tag entry, used to differentiate handling. - uint32_t size; ///< Total size of this multi_boot_tag entry with all fields of the actual type. - }; - - /** - * @brief Basic structure the multiboot_information_pointer points too and which contains all information of - * multiboot2 in the tags array of different types. The start as well as the content has to be 8 byte aligned. - */ - struct info_header - { - uint32_t total_size; ///< Total size of all multiboot::tags and their data. - alignas(8) struct tag tags; ///< Specific tags. - }; - -} // namespace teachos::arch::memory::multiboot - -#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_INFO_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp b/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp deleted file mode 100644 index 68394c8..0000000 --- a/arch/x86_64/include/arch/memory/multiboot/memory_map.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP - -#include "arch/memory/multiboot/info.hpp" -#include "arch/stl/container.hpp" -#include "arch/stl/contiguous_pointer_iterator.hpp" - -#include - -namespace teachos::arch::memory::multiboot -{ - /** - * @brief Defines all memory area types possible that the memory region can be in. - */ - enum struct memory_area_type : uint32_t - { - AVAILABLE = 1, ///< Region is available for use by the OS. - RESERVED, ///< Region is reserved by firmware or bootloader and should not be used by OS. - ACPI_AVAILABLE, ///< Region is reclaimable by OS after ACPI event. - RESERVED_HIBERNATION, ///< Region is used for Non-volatile Storage (NVS). - DEFECTIVE ///< Region is defective or unusable. - }; - - /** - * @brief Defines an entry in the entries array of the memory_map struct. - * - * @note Last value needs to be padded, because the size of the entry needs to be - * exactly 24 bytes and not one byte more. - */ - struct memory_area - { - uint64_t base_address; ///< Base address the memory region starts at. - uint64_t area_length; ///< Size of the memory region, added to base_address results in the final address. - alignas(8) memory_area_type type; ///< Specific type of memory the region can contain. - }; - - /** - * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type - * multi_boot_tag_type::MEMORY_MAP. - */ - struct memory_map_header - { - tag info; ///< Basic multi_boot_tag information. - uint32_t entry_size; ///< Size of each entry in the memory_area array. Guaranteed multiple of 8. - uint32_t entry_version; ///< Version of the entries, currently 0. - struct memory_area entries; ///< Specific memory regions. - }; - - using memory_area_container = stl::container>; - -} // namespace teachos::arch::memory::multiboot - -#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_MEMORY_MAP_HPP diff --git a/arch/x86_64/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/include/arch/memory/multiboot/reader.hpp index bda0c43..c5464cb 100644 --- a/arch/x86_64/include/arch/memory/multiboot/reader.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/reader.hpp @@ -1,10 +1,14 @@ #ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP #define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP +// #include "arch/memory/multiboot/elf_symbols_section.hpp" +// #include "arch/memory/multiboot/memory_map.hpp" + #include "arch/memory/multiboot/elf_symbols_section.hpp" -#include "arch/memory/multiboot/memory_map.hpp" #include +#include +#include namespace teachos::arch::memory::multiboot { @@ -14,12 +18,13 @@ namespace teachos::arch::memory::multiboot */ struct memory_information { - std::size_t kernel_start; ///< Start address of the kernel code in memory. - std::size_t kernel_end; ///< End address of the kernel code in memory. - elf_section_header_container sections; ///< Contains non-owning pointers to all kernel sections. - std::size_t multiboot_start; ///< Start address of the multiboot code in memory. - std::size_t multiboot_end; ///< End address of the multiboot code in memory. - memory_area_container areas; ///< Contains non-owning pointers to all memory areas. + std::size_t kernel_start; ///< Start address of the kernel code in memory. + std::size_t kernel_end; ///< End address of the kernel code in memory. + multiboot2::elf_symbols; ///< Contains non-owning pointers to all kernel sections. + std::size_t multiboot_start; ///< Start address of the multiboot code in memory. + std::size_t multiboot_end; ///< End address of the multiboot code in memory. + // std::sp + // memory_area_container areas; ///< Contains non-owning pointers to all memory areas. }; /** diff --git a/arch/x86_64/include/arch/stl/mutex.hpp b/arch/x86_64/include/arch/stl/mutex.hpp deleted file mode 100644 index a7d297d..0000000 --- a/arch/x86_64/include/arch/stl/mutex.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_STL_MUTEX_HPP -#define TEACHOS_ARCH_X86_64_STL_MUTEX_HPP - -#include - -namespace teachos::arch::stl -{ - /** - * @brief Custom mutex implementation, that simply wraps an atomic boolean to keep track if the mutex is already in - * use by another thread or not. - */ - struct mutex - { - /** - * @brief Defaulted constructor. - */ - mutex() = default; - - /** - * @brief Defaulted destructor. - */ - ~mutex() = default; - - /** - * @brief Deleted copy constructor. - */ - mutex(const mutex &) = delete; - - /** - * @brief Deleted assignment operator. - */ - mutex & operator=(const mutex &) = delete; - - /** - * @brief Lock the mutex (blocks for as long as it is not available). - */ - [[gnu::section(".stl_text")]] - auto lock() -> void; - - /** - * @brief Try to lock the mutex (non-blocking). - * - * @return True if lock has been acquired and false otherwise. - */ - [[gnu::section(".stl_text")]] - auto try_lock() -> bool; - - /** - * @brief Unlock the mutex. - */ - [[gnu::section(".stl_text")]] - auto unlock() -> void; - - private: - std::atomic locked = {false}; // Atomic boolean to track if mutex is locked or not. - }; - -} // namespace teachos::arch::stl - -#endif // TEACHOS_ARCH_X86_64_STL_MUTEX_HPP 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 63a6111..00ca366 100644 --- a/arch/x86_64/src/memory/heap/linked_list_allocator.cpp +++ b/arch/x86_64/src/memory/heap/linked_list_allocator.cpp @@ -9,7 +9,7 @@ namespace teachos::arch::memory::heap { linked_list_allocator::linked_list_allocator(std::size_t heap_start, std::size_t heap_end) : first(nullptr) - , mutex{stl::mutex{}} + , mutex{kstd::mutex{}} { auto const heap_size = heap_end - heap_start; exception_handling::assert( diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index 2bf5b25..b05e6b3 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -2,130 +2,134 @@ #include "arch/boot/pointers.hpp" #include "arch/exception_handling/assert.hpp" -#include "arch/memory/multiboot/elf_symbols_section.hpp" -#include "arch/memory/multiboot/info.hpp" +#include "multiboot2/information.hpp" +// #include "arch/memory/multiboot/elf_symbols_section.hpp" +// #include "arch/memory/multiboot/info.hpp" #include #include -namespace teachos::arch::memory::multiboot -{ - namespace - { - template - requires std::is_pointer::value - auto align_to_8_byte_boundary(T ptr, uint32_t size) -> T - { - return reinterpret_cast(reinterpret_cast(ptr) + ((size + 7) & ~7)); - } - - auto process_memory_map(memory_map_header * mminfo) -> memory_area_container - { - auto const expected_entry_size = mminfo->entry_size; - auto constexpr actual_entry_size = sizeof(memory_area); - exception_handling::assert(expected_entry_size == actual_entry_size, - "[Multiboot Reader] Unexpected memory area entry size"); - - auto const total_size = mminfo->info.size; - auto const total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size; - auto const number_of_entries = total_entries_size / actual_entry_size; - - auto const begin = memory_area_container::iterator{&mminfo->entries}; - auto const end = begin + number_of_entries; - return memory_area_container{begin, end}; - } - - auto process_elf_sections(elf_symbols_section_header * symbol, std::size_t & kernel_start, - std::size_t & kernel_end) -> elf_section_header_container - { - auto const expected_entry_size = symbol->entry_size; - auto constexpr actual_entry_size = sizeof(elf_section_header); - exception_handling::assert(expected_entry_size == actual_entry_size, - "[Multiboot Reader] Unexpected elf section header entry size"); - - auto const expected_total_size = symbol->info.size; - auto const actual_total_entry_size = actual_entry_size * symbol->number_of_sections; - auto constexpr actual_total_section_size = sizeof(elf_symbols_section_header) - sizeof(uint32_t); - auto const actual_total_size = actual_total_entry_size + actual_total_section_size; - exception_handling::assert(expected_total_size == actual_total_size, - "[Multiboot Reader] Unexpected elf symbols section header total size"); - - auto const begin = elf_section_header_container::iterator{reinterpret_cast(&symbol->end)}; - auto const end = begin + symbol->number_of_sections; - exception_handling::assert(begin->is_null(), - "[Multiboot Reader] Elf symbols section not starting with SHT_NULL section"); - - elf_section_header_container sections{begin, end}; - - auto allocated_sections = sections | std::views::filter([](auto const & section) { - return section.flags.contains_flags(elf_section_flags::OCCUPIES_MEMORY); - }); - - auto const elf_section_with_lowest_physical_address = std::ranges::min_element( - allocated_sections, [](auto const & a, auto const & b) { return a.physical_address < b.physical_address; }); - - auto const elf_section_with_highest_physical_address = - std::ranges::max_element(allocated_sections, [](auto const & a, auto const & b) { - auto a_physical_address_end = a.physical_address + a.section_size; - auto b_physical_address_end = b.physical_address + b.section_size; - return a_physical_address_end < b_physical_address_end; - }); - - auto const symbol_table_section_count = std::ranges::count_if(sections, [](auto const & section) { - return section.type == elf_section_type::DYNAMIC_SYMBOL_TABLE || section.type == elf_section_type::SYMBOL_TABLE; - }); - auto const dynamic_section_count = std::ranges::count_if( - sections, [](auto const & section) { return section.type == elf_section_type::DYNAMIC; }); - - exception_handling::assert( - symbol_table_section_count == 1U, - "[Multiboot Reader] ELF Specifications allows only (1) symbol table section, but got more"); - exception_handling::assert( - dynamic_section_count <= 1U, - "[Multiboot Reader] ELF Specifications allows only (1) or less dynamic sections, but got more"); - - auto const lowest_elf_section = *elf_section_with_lowest_physical_address; - kernel_start = lowest_elf_section.physical_address; - - auto const highest_elf_section = *elf_section_with_highest_physical_address; - kernel_end = highest_elf_section.physical_address + highest_elf_section.section_size; - - return sections; - } - } // namespace - - auto read_multiboot2() -> memory_information - { - memory_information mem_info{UINT64_MAX, - 0U, - elf_section_header_container{}, - boot::multiboot_information_pointer, - 0U, - memory_area_container{}}; - - auto const multiboot_information_pointer = reinterpret_cast(boot::multiboot_information_pointer); - auto const multiboot_tag = &multiboot_information_pointer->tags; - mem_info.multiboot_end = mem_info.multiboot_start + multiboot_information_pointer->total_size; - - for (auto tag = multiboot_tag; tag->type != tag_type::END; tag = align_to_8_byte_boundary(tag, tag->size)) - { - switch (tag->type) - { - case tag_type::ELF_SECTIONS: { - auto const symbol = reinterpret_cast(tag); - mem_info.sections = process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end); - break; - } - case tag_type::MEMORY_MAP: { - auto const mminfo = reinterpret_cast(tag); - mem_info.areas = process_memory_map(mminfo); - break; - } - default: - // All other cases are not important and can be ignored. - break; - } - } - return mem_info; - } -} // namespace teachos::arch::memory::multiboot +// namespace teachos::arch::memory::multiboot +// { +// namespace +// { +// template +// requires std::is_pointer::value +// auto align_to_8_byte_boundary(T ptr, uint32_t size) -> T +// { +// return reinterpret_cast(reinterpret_cast(ptr) + ((size + 7) & ~7)); +// } + +// auto process_memory_map(memory_map_header * mminfo) -> memory_area_container +// { +// auto const expected_entry_size = mminfo->entry_size; +// auto constexpr actual_entry_size = sizeof(memory_area); +// exception_handling::assert(expected_entry_size == actual_entry_size, +// "[Multiboot Reader] Unexpected memory area entry size"); + +// auto const total_size = mminfo->info.size; +// auto const total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size; +// auto const number_of_entries = total_entries_size / actual_entry_size; + +// auto const begin = memory_area_container::iterator{&mminfo->entries}; +// auto const end = begin + number_of_entries; +// return memory_area_container{begin, end}; +// } + +// auto process_elf_sections(elf_symbols_section_header * symbol, std::size_t & kernel_start, std::size_t & +// kernel_end) +// -> elf_section_header_container +// { +// auto const expected_entry_size = symbol->entry_size; +// auto constexpr actual_entry_size = sizeof(elf_section_header); +// exception_handling::assert(expected_entry_size == actual_entry_size, +// "[Multiboot Reader] Unexpected elf section header entry size"); + +// auto const expected_total_size = symbol->info.size; +// auto const actual_total_entry_size = actual_entry_size * symbol->number_of_sections; +// auto constexpr actual_total_section_size = sizeof(elf_symbols_section_header) - sizeof(uint32_t); +// auto const actual_total_size = actual_total_entry_size + actual_total_section_size; +// exception_handling::assert(expected_total_size == actual_total_size, +// "[Multiboot Reader] Unexpected elf symbols section header total size"); + +// auto const begin = elf_section_header_container::iterator{reinterpret_cast(&symbol->end)}; auto const end = begin + symbol->number_of_sections; +// exception_handling::assert(begin->is_null(), +// "[Multiboot Reader] Elf symbols section not starting with SHT_NULL section"); + +// elf_section_header_container sections{begin, end}; + +// auto allocated_sections = sections | std::views::filter([](auto const & section) { +// return section.flags.contains_flags(elf_section_flags::OCCUPIES_MEMORY); +// }); + +// auto const elf_section_with_lowest_physical_address = std::ranges::min_element( +// allocated_sections, [](auto const & a, auto const & b) { return a.physical_address < b.physical_address; +// }); + +// auto const elf_section_with_highest_physical_address = +// std::ranges::max_element(allocated_sections, [](auto const & a, auto const & b) { +// auto a_physical_address_end = a.physical_address + a.section_size; +// auto b_physical_address_end = b.physical_address + b.section_size; +// return a_physical_address_end < b_physical_address_end; +// }); + +// auto const symbol_table_section_count = std::ranges::count_if(sections, [](auto const & section) { +// return section.type == elf_section_type::DYNAMIC_SYMBOL_TABLE || section.type == +// elf_section_type::SYMBOL_TABLE; +// }); +// auto const dynamic_section_count = std::ranges::count_if( +// sections, [](auto const & section) { return section.type == elf_section_type::DYNAMIC; }); + +// exception_handling::assert( +// symbol_table_section_count == 1U, +// "[Multiboot Reader] ELF Specifications allows only (1) symbol table section, but got more"); +// exception_handling::assert( +// dynamic_section_count <= 1U, +// "[Multiboot Reader] ELF Specifications allows only (1) or less dynamic sections, but got more"); + +// auto const lowest_elf_section = *elf_section_with_lowest_physical_address; +// kernel_start = lowest_elf_section.physical_address; + +// auto const highest_elf_section = *elf_section_with_highest_physical_address; +// kernel_end = highest_elf_section.physical_address + highest_elf_section.section_size; + +// return sections; +// } +// } // namespace + +// auto read_multiboot2() -> memory_information +// { +// memory_information mem_info{UINT64_MAX, +// 0U, +// elf_section_header_container{}, +// boot::multiboot_information_pointer, +// 0U, +// memory_area_container{}}; + +// auto const multiboot_information_pointer = reinterpret_cast(boot::multiboot_information_pointer); +// auto const multiboot_tag = &multiboot_information_pointer->tags; +// mem_info.multiboot_end = mem_info.multiboot_start + multiboot_information_pointer->total_size; + +// for (auto tag = multiboot_tag; tag->type != tag_type::END; tag = align_to_8_byte_boundary(tag, tag->size)) +// { +// switch (tag->type) +// { +// case tag_type::ELF_SECTIONS: { +// auto const symbol = reinterpret_cast(tag); +// mem_info.sections = process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end); +// break; +// } +// case tag_type::MEMORY_MAP: { +// auto const mminfo = reinterpret_cast(tag); +// mem_info.areas = process_memory_map(mminfo); +// break; +// } +// default: +// // All other cases are not important and can be ignored. +// break; +// } +// } +// return mem_info; +// } +// } // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/src/stl/mutex.cpp b/arch/x86_64/src/stl/mutex.cpp deleted file mode 100644 index 232a11c..0000000 --- a/arch/x86_64/src/stl/mutex.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#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 diff --git a/libs/kstd/CMakeLists.txt b/libs/kstd/CMakeLists.txt new file mode 100644 index 0000000..06083f3 --- /dev/null +++ b/libs/kstd/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION "3.27") + +project("kstd" + LANGUAGES CXX + VERSION "1.0.0" +) + +add_library("kstd" STATIC) +add_library("libs::kstd" ALIAS "kstd") + +target_sources("kstd" PRIVATE + "src/mutex.cpp" +) + +target_sources("kstd" PUBLIC + FILE_SET HEADERS + BASE_DIRS "include" + FILES + "include/kstd/mutex.hpp" +) + +target_include_directories("kstd" PUBLIC + "include" +) diff --git a/libs/kstd/include/kstd/mutex.hpp b/libs/kstd/include/kstd/mutex.hpp new file mode 100644 index 0000000..cf8549f --- /dev/null +++ b/libs/kstd/include/kstd/mutex.hpp @@ -0,0 +1,60 @@ +#ifndef KSTD_MUTEX_HPP +#define KSTD_MUTEX_HPP + +#include + +namespace kstd +{ + /** + * @brief Custom mutex implementation, that simply wraps an atomic boolean to keep track if the mutex is already in + * use by another thread or not. + */ + struct mutex + { + /** + * @brief Defaulted constructor. + */ + mutex() = default; + + /** + * @brief Defaulted destructor. + */ + ~mutex() = default; + + /** + * @brief Deleted copy constructor. + */ + mutex(const mutex &) = delete; + + /** + * @brief Deleted assignment operator. + */ + mutex & operator=(const mutex &) = delete; + + /** + * @brief Lock the mutex (blocks for as long as it is not available). + */ + [[gnu::section(".stl_text")]] + auto lock() -> void; + + /** + * @brief Try to lock the mutex (non-blocking). + * + * @return True if lock has been acquired and false otherwise. + */ + [[gnu::section(".stl_text")]] + auto try_lock() -> bool; + + /** + * @brief Unlock the mutex. + */ + [[gnu::section(".stl_text")]] + auto unlock() -> void; + + private: + std::atomic locked = {false}; // Atomic boolean to track if mutex is locked or not. + }; + +} // namespace kstd + +#endif \ No newline at end of file diff --git a/libs/kstd/src/mutex.cpp b/libs/kstd/src/mutex.cpp new file mode 100644 index 0000000..cfb1c84 --- /dev/null +++ b/libs/kstd/src/mutex.cpp @@ -0,0 +1,16 @@ +#include "kstd/mutex.hpp" + +namespace kstd +{ + auto mutex::lock() -> void + { + while (!try_lock()) + { + asm volatile("nop"); + } + } + + 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 kstd -- cgit v1.2.3 From 1b603d1145b9ee10b1b12a0f765bd2bc1ebe2b3c Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 14 Jul 2025 15:39:59 +0000 Subject: libs: rename multiboot alias --- arch/x86_64/CMakeLists.txt | 2 +- libs/multiboot2/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index 511fe43..c8ff216 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -70,8 +70,8 @@ target_sources("_memory" PRIVATE ) target_link_libraries("_memory" PUBLIC - "multiboot2::multiboot2" "libs::kstd" + "libs::multiboot2" ) #[============================================================================[ diff --git a/libs/multiboot2/CMakeLists.txt b/libs/multiboot2/CMakeLists.txt index af56d5a..386a127 100644 --- a/libs/multiboot2/CMakeLists.txt +++ b/libs/multiboot2/CMakeLists.txt @@ -6,7 +6,7 @@ project("multiboot2" ) add_library("multiboot2" INTERFACE) -add_library("multiboot2::multiboot2" ALIAS "multiboot2") +add_library("libs::multiboot2" ALIAS "multiboot2") target_sources("multiboot2" INTERFACE FILE_SET HEADERS -- cgit v1.2.3 From 25483b7af8df6b08d460f807fda04c6d409bd44e Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Mon, 14 Jul 2025 16:02:43 +0000 Subject: ide: start large-scale restructuring --- CMakeLists.txt | 268 +++++++++++++++++++++++-------------------- arch/CMakeLists.txt | 17 +++ arch/include/arch/io.hpp | 9 ++ arch/include/arch/memory.hpp | 9 ++ arch/include/arch/system.hpp | 9 ++ cmake/Platforms/x86_64.cmake | 1 - kern/CMakeLists.txt | 16 +++ kern/include/kern/error.hpp | 13 +++ kern/include/kern/print.hpp | 26 +++++ kern/src/abort.cpp | 3 + kern/src/error.cpp | 19 +++ kern/src/main.cpp | 11 ++ kern/src/print.cpp | 76 ++++++++++++ libs/CMakeLists.txt | 2 + src/kernel/main.cpp | 9 -- 15 files changed, 352 insertions(+), 136 deletions(-) create mode 100644 arch/CMakeLists.txt create mode 100644 arch/include/arch/io.hpp create mode 100644 arch/include/arch/memory.hpp create mode 100644 arch/include/arch/system.hpp create mode 100644 kern/CMakeLists.txt create mode 100644 kern/include/kern/error.hpp create mode 100644 kern/include/kern/print.hpp create mode 100644 kern/src/abort.cpp create mode 100644 kern/src/error.cpp create mode 100644 kern/src/main.cpp create mode 100644 kern/src/print.cpp create mode 100644 libs/CMakeLists.txt delete mode 100644 src/kernel/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 75ac1b5..e10da55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,138 +22,154 @@ set(CMAKE_CXX_STANDARD_REQUIRED YES) set(CMAKE_CXX_EXTENSIONS NO) #[============================================================================[ -# Documentation -#]============================================================================] - -find_package("Doxygen") - -set(DOXYGEN_GENERATE_HTML YES) -set(DOXYGEN_GENERATE_XML YES) -set(DOXYGEN_EXCLUDE_PATTERNS "*.cpp") -set(DOXYGEN_OUTPUT_DIRECTORY "doxygen") -set(DOXYGEN_QUIET YES) - -file(GLOB_RECURSE DOXYGEN_SOURCES CONFIGURE_DEPENDS "*.hpp") - -message(STATUS "${SPHINX_SOURCES}") - -doxygen_add_docs("docs_xml" - ${DOXYGEN_SOURCES} - ALL - USE_STAMP_FILE - COMMENT "Generating deve